Yogurt是一名学GIS的学生,今天要跟大家分享的是四叉树这种空间索引方式的Morton编码方法,接下来我将在小课堂中简单介绍一下空间索引以及其几种编码方式~~

---------------------------------------------------------yogurt小课堂开课啦--------------------------------------------------------

GIS所涉及到的都是有关空间的数据信息,即也属于所谓的大数据了,那么怎么将客观的物体对象存储到计算机中,以及怎么从计算机中读取所需要的数据呢?

首先我们要知道计算机的存储器有内存和外存,内存空间小但是读写快,外存空间大却读写慢,访问外存所花费的时间是访问内存的十万倍以上!在GIS的实际应用中大量的数据都是存储在外存上的,想象一下如果这些数据全都杂乱无章的堆放在那里,那么每需要查询一个数据就需要扫描整个数据文件,这样访问磁盘的代价是非常大的,严重影响了系统效率!所以,我们必须记录好每个数据存放的位置,以便于组织和管理,在这个过程中就需要用到索引技术啦!

【(这里引自我老师的课件哈,低调低调!!!)

从传统的索引技术观点来看,可以把空间索引技术大致分为四大类:基于R树,基于Hashing,基于二叉树,基于空间填充。

在建立索引时,按照划分区域是否与空间对象的分布特征有关的标准,空间索引又可以分为两大类:无关的(网格索引、四叉树),有关的(BSP树、KD树、KDB树、R树及其变种树)。

我们来看看几种索引方法的实际应用:

(1)ESRI的ArcSDE采用的是固定格网索引;

(2)目前国内外主要的空间数据库如ESRI的ArcView,Mapinfo公司的Maoinfo和Informix的GeoSpatial DataBlade采用的是R树系列作为空间索引的方式;

(3)Oracle公司的Spatial同时采用固定格网索引以及R树索引;

(4)中国地质大学的MapGIS和中科院的SuperMap采用的是四叉树。

以上来自我的一个大牛老师的PPT~~】

好啦,既然今天要讲矩阵四叉树的Morton编码,那么接下来就介绍一下四叉树以及Morton码的编码规则吧:

【四叉树】:

区域型物体的四叉树表示方法最早出现在加拿大地理信息系统CGIS中,20世纪80年代以来,四叉树在图象分割、数据压缩、 地理信息系统等方面进行了大量的研究,对四叉树数据结构提出了许多编码方案。四叉树分为常规四叉树与线性四叉树,下图简单的说明了两者的区别:(不要嫌弃我字丑!!!)

编码规定:

【线性四叉树的编码方式】: 例如有这样一个矩阵线性四叉树,以红色圈中的9的编码为例,有自上而下的方法和自下而上的方法:

(1)基于深度和层次码线性四叉树编码:(自上而下的方法)

层次码:第一层(在位置2,用两位二进制表示为:10),第二层(在位置1,用两位二进制表示为:01),第三层(在位置2,用两位二进制表示为:10);

深度码:有3层深,(用四位二进制表示为:0011);

“9”的位置编码为:10 01 10 0011,该位置码的十进制为2^0+2^1+2^5+2^6+2^9=611.

(2)基于四进制的线性四叉树编码:

(自上而下的方法):第一层2,第二层1,第三层2,位置码:212

(自下而上的方法,说明四进制编码的过程):二进制的行列号Iyb、Ixb(从第0行0列开始),四进制编码M=2*Iyb+ Ixb;那么这里就是:第5行(101)第2列(010):M=2*101+10=212

(3)基于十进制的线性四叉树编码:

(自下而上的方法,说明四进制编码的过程):二进制的行列号Iyb、Ixb(从第0行0列开始),十进制编码M=奇数位用列号填充,偶数位用行号填充;那么这里就是:第5行(101)第2列(010):M=10 01 10

(4)在相邻四个码中若属性值相同,进行合并,除去最低位得到合并后的新编码。

-----------------------------------------------------------下课啦!!!--------------------------------------------------------------

编写该程序的思路:

第一步:读入矩阵四叉树,并将其输出;

第二步:利用four_decimal函数得到每一个位置的四进制M码,利用Change函数得到规定格式的三位四进制M码;最后利用checkcombine_four函数,将属性值一样的位置的M码合并,并输出;

第三步:同第二步类似,利用ten_decimal函数得到每一个位置的十进制M码,利用checkcombine_ten函数,将属性值一样的位置的M码合并,并输出。

具体实现过程:

(1)将十进制行列号转换为二进制:利用函数Tobinary :

(2)得到四进制M码:利用函数four_decimal:

(3)得到十进制M码:利用函数ten_decimal:(注意按位交错)

(4)对属性值一样的M码进行合并的处理操作checkcombine_ten:(以十进制为例)

在第二层里:(方法与第一层类似,只是合并条件变成了w==2)

最后输出数组即可,对于四进制的M码,由于合并时还要除去最低位的,所以需要特殊处理(便于输出):如在合并第一层时,给第二三位赋予标志值99999999:

合并第二层时,给第三位赋予标志值99999999:

输出时:

好啦,接下来是整体代码:

#include#include#includetypedefint newc[3];

typedefint ceng[2];void read(int a[][8]); //读入矩形四叉树

int Tobinary(int k); //将十进制的行列号k转换为二进制.

int eq(int m, int n); //判断m和n是否相等,相等则返回1,否则返回0.

void judge_four(int a[][8], newc b[][8], ceng c[4]);//判断数组c表示的矩形范围内的值是否一样,若一样就更新数组b.

void judge_ten(int a[][8], int b[][8], ceng c[4]);void checkcombine_four(int a[][8], newc b[][8]); //将属性值一样的单元进行合并.

void checkcombine_ten(int a[][8], int b[][8]);void Change(int m[][8], newc n[][8]); //将四进制的M码按照规定格式输出.

void four_decimal(int b[][8]); //四进制编码.

void ten_decimal(int c[][8]); //十进制编码.

void output_i(int a[][8]); //输出int型数组.

void output_c(newc a[][8]); //输出newc型数组.

voidmain()

{int a[8][8], b[8][8], c[8][8];

newc bb[8][8];

read(a);

printf("矩阵四叉树为:\n");

output_i(a);

four_decimal(b);

Change(b, bb);

checkcombine_four(a,bb);

printf("\n四叉树对应的四进制编码为:\n");

output_c(bb);

ten_decimal(c);

checkcombine_ten(a,c);

printf("\n四叉树对应的十进制编码为:\n");

output_i(c);

}void read(int a[][8])

{

FILE*fp = fopen("四叉树.txt","r");if (!fp)

exit;else

for (int i = 0; i < 8;i++)for (int j = 0; j < 8; j++)

fscanf(fp,"%d", &a[i][j]);

fclose(fp);

}int Tobinary(intk)

{int s[10],rem,i=0,t=0;do{

rem= k % 2;

k= k / 2;

s[i++] =rem;

}while (k != 0); //当十进制数是0时也要进行一遍此循环,所以必须用do……while循环,而不是while循环

for (int j = --i; j >= 0; j--)

{

t+= s[j] * pow(10.0, j);

}returnt;

}int eq(int m, intn)

{if (m ==n)return 1;else

return 0;

}void judge_four(int a[][8], newc b[][8], ceng c[4])

{for (int i = 0; i < 4; i++)

{int w = 0;for (int m = c[i][0]; m

w+= eq(a[m][n], a[m][n + 1]);if (w == 2)//4个值属性一样

{for (int m = c[i][0]; m

{*b[m][n] = *b[(c[i][0])][(c[i][1])];*(b[m][n] + 1) = *(b[(c[i][0])][(c[i][1])] + 1);*(b[m][n] + 2) = 99999999;

}

}

}

}void judge_ten(int a[][8], int b[][8], ceng c[4])

{for (int i = 0; i < 4; i++)

{int w = 0;for (int m = c[i][0]; m

w+= eq(a[m][n], a[m][n + 1]);if (w == 2)//4个值属性一样

{for (int m = c[i][0]; m

{

b[m][n]= b[(c[i][0])][(c[i][1])];

}

}

}

}void checkcombine_ten(int a[][8], int b[][8])

{//第一层

ceng c[4] = { { 0, 0 }, { 0, 4 }, { 4, 0 }, { 4, 4} };for (int i = 0; i < 4; i++)

{int w = 0;for (int m = c[i][0]; m < 4; m++)for (int n = c[i][1]; n < 3; n++)

w+= eq(a[m][n], a[m][n + 1]);if (w == 12)//16个值属性一样

{for (int m = c[i][0]; m < c[i][0] + 4; m++)for (int n = c[i][1]; n < c[i][1] + 4; n++)

{

b[m][n]= b[(c[i][0])][(c[i][1])];

}

}

}//第二层

ceng d[4] = { { 0, 0 }, { 0, 2 }, { 2, 0 }, { 2, 2} },

e[4] = { { 0, 4 }, { 0, 6 }, { 2, 4 }, { 2, 6} },

f[4] = { { 4, 0 }, { 4, 2 }, { 6, 0 }, { 6, 2} },

g[4] = { { 4, 4 }, { 4, 6 }, { 6, 4 }, { 6, 6} };

judge_ten(a, b, d);

judge_ten(a, b, e);

judge_ten(a, b, f);

judge_ten(a, b, g);

}void checkcombine_four(int a[][8], newc b[][8])

{//第一层

ceng c[4] = { { 0, 0 }, { 0, 4 }, { 4, 0 }, { 4, 4} };for (int i = 0; i < 4; i++)

{int w = 0;for (int m = c[i][0]; m < 4; m++)for (int n = c[i][1]; n < 3; n++)

w+= eq(a[m][n], a[m][n + 1]);if (w == 12)//16个值属性一样

{for (int m = c[i][0]; m < c[i][0] + 4; m++)for (int n = c[i][1]; n < c[i][1] + 4; n++)

{*b[m][n] =*b[(c[i][0])][(c[i][1])];*(b[m][n] + 1) =99999999;*(b[m][n] + 2) =99999999;

}

}

}//第二层

ceng d[4] = { { 0, 0 }, { 0, 2 }, { 2, 0 }, { 2, 2} },

e[4] = { { 0, 4 }, { 0, 6 }, { 2, 4 }, { 2, 6} },

f[4] = { { 4, 0 }, { 4, 2 }, { 6, 0 }, { 6, 2} },

g[4] = { { 4, 4 }, { 4, 6 }, { 6, 4 }, { 6, 6} };

judge_four(a, b, d);

judge_four(a, b, e);

judge_four(a, b, f);

judge_four(a, b, g);

}void Change(int m[][8], newc n[][8])

{int t[3];intq;for (int i = 0; i < 8;i++)for (int j = 0; j < 8; j++)

{

q=m[i][j];

t[0] = q / 100;

q= q % 100;

t[1] = q / 10;

q= q % 10;

t[2] =q;*n[i][j] = *t; //数组赋值,数组名称不能直接做左值

*(n[i][j] + 1) = *(t + 1);*(n[i][j] + 2) = *(t + 2);

}

}void four_decimal(int b[][8])

{for (int i = 0; i < 8;i++)for (int j = 0; j < 8;j++)

{int m=Tobinary(i);int n=Tobinary(j);

b[i][j]= 2 * m +n;

}

}void ten_decimal(int c[][8])

{for (int i = 0; i < 8; i++)for (int j = 0; j < 8; j++)

{int m =Tobinary(i);int n =Tobinary(j);int t[8];

t[0] = m / 1000;

m= m % 1000;

t[2] = m / 100;

m= m % 100;

t[4] = m / 10;

m= m % 10;

t[6] =m;

t[1] = n / 1000;

n= n % 1000;

t[3] = n / 100;

n= n % 100;

t[5] = n / 10;

n= n % 10;

t[7] =n;int y = 0;for (int w = 0; w < 8; w++)

{

y+= t[w] * pow(2.0,7-w);

}

c[i][j]=y;

}

}void output_i(int a[][8])

{for (int i = 0; i < 8; i++)

{for (int j = 0; j < 8; j++)

{

printf("%6d", a[i][j]);

}

printf("\n");

}

}void output_c(newc a[][8])

{for (int i = 0; i < 8; i++)

{for (int j = 0; j < 8; j++)if (*(a[i][j] + 1)==99999999&&*(a[i][j] + 2)==99999999)

printf("%6d", *a[i][j]);else if (*(a[i][j] + 2) == 99999999)

printf("%5d%d", *a[i][j], *(a[i][j] + 1));elseprintf("%4d%d%d", *a[i][j], *(a[i][j] + 1), *(a[i][j] + 2));

printf("\n");

}

}

View Code

最后结果:

morton码_求矩阵四叉树的四进制和十进制Morton码相关推荐

  1. 四进制加法(运算符重载)

    题目描述 定义一个四进制的类,重定义"+"号实现四进制数的累加. 输入 第一行输入所需要的四进制数的个数 第二行开始,依次输入四进制数 输出 所有输入四进制数累加的和 输入样例1  ...

  2. 进制转换【最全进制转换汇总】(整数_小数_正数_负数)正负数整数小数十进制转任意进制-正负数整数小数任意进制转十进制-正负数低进制转高进制-正负数高进制转低进制

    文章目录: 补充知识点:各进制符号表示及其关系--二进制(B).八进制(O).十进制(D).十六进制(前缀OX,后缀H) 扩展:在线进制转换 第一部分:正数 一:[整数]正数十进制转任意进制:辗转相除 ...

  3. 【数电】(一) 进制转换编码 原码,反码,补码

    文章目录 前提知识 计算机发展史 集成电路(Integrated Circuit) 数字集成电路 0 1思维 1Bit 机器码 加法器 二进制与十进制之间的转换 BCD编码 原码,反码,补码 原码 反 ...

  4. 同步四进制加减法可逆计数器设计(D触发器+74153)

    好久没更新博客了, 很高兴今天又与大家见面了. 昨天有朋友问道这样一个问题"该如何使用最少数量的D触发器和四选一数据选择器74153接成同步四进制加减法可逆计数器": 从这个问题中 ...

  5. 二十四进制 加法计数器 并用数码管显示

    二十四进制 (BCD码)加法计数器 并用数码管显示 `timescale 1ns / 1ps // // Company: // Engineer: // // Create Date: 2020/1 ...

  6. 二进制转四进制计算机,二进制换算(进制转换计算器)

    二进制数01011010扩大2倍之后是多少?急求~ 先把它转换成为 10进制 变成90 变180 然后再转换成为2进制 10110100 我看了一下像是一道二进制的题 有谁知道答案帮帮忙 谢谢了 问着 ...

  7. 经典同步时序逻辑电路分析汇总(第六道)(同步四进制可逆加减法计数器)

    题: 分析该时序逻辑电路 的功能, 写出电路的驱动方程.状态方程和输出方程, 画出电路的状态转换图和时序图. 分析: 第一步, 根据电路逻辑图写出驱动方程和输出方程. (由于书中Y的接法不合理, 我将 ...

  8. day017:Java进制转换、原码反码补码、位运算、位移运算符

    一.进制介绍: 1.进制:指进位制,表示某一位置上的数,运算时是逢X进一. 十进制就是逢十进一,二进制就是逢二进一,八进制就是逢八进一. 2.Java中默认的数值都是十进制,如果要输入其他进制,在数值 ...

  9. 进制转换,原码补码反码--学习笔记--03

    一. 进制转换 1.其他进制到十进制的转换 比如: 十进制 十进制 123=100+20+3 =1* 10^2 + 2 *10^1 +3 * 10^0 =100+20+3 =123 八进制 十进制 1 ...

最新文章

  1. 票据自动处理系统著名研究团队
  2. inline hook __usercall 函数
  3. 数组实用类:Arrays
  4. python画两条曲线_查找在matplotlib中绘制的两条曲线之间的区域(在区域之间填充)...
  5. NetBeans中文乱码解决办法
  6. BZOJ1061 NOI2008 志愿者招募 线性规划、费用流
  7. 运用ffmpeg SDK解264码流(来源FFmpeg工程组)
  8. iOS 搭建XMPP环境时添加依赖库报错及解决
  9. iOS开发 - 动画实践系列
  10. spark to mysql date_[Spark][Python]Spark 访问 mysql , 生成 dataframe 的例子:
  11. 计算不确定度的小工具
  12. 收集一些Qt学习网站
  13. Windows 进程激活服务
  14. led拼接屏报价_液晶拼接屏报价大概多少钱一套?
  15. 【图形和图像】三原色
  16. 计算机考试怎么复制粘贴文件,复制粘贴,教您电脑复制粘贴不能用了怎么解决...
  17. [论文阅读]PointRend: Image Segmentation as Rendering
  18. 基础-02-日语中为何会有体言用言?
  19. Office激活了提示非正版!
  20. 金蝶eas系统服务器地址,金蝶eas服务器地址

热门文章

  1. java ascii码转字符_java中char对应的ASCII码的转化操作
  2. html在ie8下跳转新网址,ie8升级到ie11 单击“查看已安装更新”
  3. MMKV_荣登Github日榜!微信最新开源MMKV
  4. 超详细的Socket通信原理和实例讲解(学习走起~)
  5. 音频编辑软件Goldwave v6.68中文版,goldwave 2022最新版怎么来消除人声
  6. PHP之Zip扩展,解压缩文件,ZipArchive类
  7. linux tree显示乱码,Linux tree 命令乱码
  8. Android 10.0 ​默认允许未知来源权限安装
  9. matlab编程实现自适应均值滤波和自适应中值滤波
  10. 基于图像和激光的多模态点云融合与视觉定位