线性八叉树_八叉树OcTree
在描述三维场景的过程中常常用到一种名为八叉树的数据结构。描述三维空间的八叉树和描述二维空间的四叉树有相似之处,二维空间中正方形可以被分为四个相同形状的正方形,而三维空间中正方体可以被分为八个形状相同的正方体。
八叉树的每个结点表示一个正方体的体积元素,每一个结点有八个子节点,这种用于描述三维空间的树装结构叫做八叉树。为了便利的点云操作,八叉树OcTree被封装在PCL库中。
八叉树的计算原理
1. 设定最大递归深度
2. 找出场景的最大尺寸,并以此尺寸建立第一个立方体
3. 依序将单位元元素丢入能包含且没有子节点的立方体
4. 若没达到最大递归深度,就进行细分八等份,再讲该立方体所装的单位元元素全部分组给八个子立方体
5. 若发现子立方体所分配到的单位元元素数量不为零且跟父立方体一样,则该子立方体停止细分
(因为根据空间分割理论,细分的空间所得到的分配必定较少,若是一样的数目,再怎么切,数目还是一样)
6. 重复3,知道到达最大递归深度
八叉树的数据结构
首先,八叉树是一种树(废话),所以可以分析它的结点,和枝干数量,这里枝干数量永远是8。假设原目标(点云)被一个大立方体包含,八叉树的作用就是细分该大立方体,每个结点对应一个立方体空间(这里类似于四叉树),八叉树的结点分为三类:
灰色结点:它对应的立方体部分被目标占据(非叶结点)
白色结点:它对应的立方体没有被目标占据(叶结点)
黑色结点:它对应的立方体完全被目标占据(叶结点)
对于非叶结点,数据结构以八元数法进行区分,分解为更小的子区块,每个区块有结点容量,当结点达到最大容量时结点停止分裂。
八叉树的存储结构
八叉树的存储结构一般分为三种:规则八叉树、线性八叉树和一对八式
规则八叉树,有九个字段,八个子叶结点,一个表征该结点灰白黑的结点,这种表示方式处于贮存空间考量,一般不使用。
线性八叉树,将八叉树转化为线性表,采用内存紧凑的方式进行表示。
一对八表示,使用指针表示,好处是顺序可以随机
八叉树的主要优缺点
优点,使用八叉树可以快速进行三维目标的集合运算,如交、并、补、差等,亦可快速进行最邻近区域或点的搜索。
缺点,存储空间消耗。
八叉树实现
虽然PCL中封装了八叉树OcTree类,但是我们也有不得不自己写的情况,下面代买是自己摘抄的(自己当然还是用PCL了)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
#include
usingnamespacestd;
//定义八叉树节点类
template
structOctreeNode
{
Tdata;//节点数据
Txmin,xmax;//节点坐标,即六面体个顶点的坐标
Tymin,ymax;
Tzmin,zmax;
OctreeNode*top_left_front,*top_left_back;//该节点的个子结点
OctreeNode*top_right_front,*top_right_back;
OctreeNode*bottom_left_front,*bottom_left_back;
OctreeNode*bottom_right_front,*bottom_right_back;
OctreeNode//节点类
(TnodeValue=T(),
TxminValue=T(),TxmaxValue=T(),
TyminValue=T(),TymaxValue=T(),
TzminValue=T(),TzmaxValue=T(),
OctreeNode*top_left_front_Node=NULL,
OctreeNode*top_left_back_Node=NULL,
OctreeNode*top_right_front_Node=NULL,
OctreeNode*top_right_back_Node=NULL,
OctreeNode*bottom_left_front_Node=NULL,
OctreeNode*bottom_left_back_Node=NULL,
OctreeNode*bottom_right_front_Node=NULL,
OctreeNode*bottom_right_back_Node=NULL)
:data(nodeValue),
xmin(xminValue),xmax(xmaxValue),
ymin(yminValue),ymax(ymaxValue),
zmin(zminValue),zmax(zmaxValue),
top_left_front(top_left_front_Node),
top_left_back(top_left_back_Node),
top_right_front(top_right_front_Node),
top_right_back(top_right_back_Node),
bottom_left_front(bottom_left_front_Node),
bottom_left_back(bottom_left_back_Node),
bottom_right_front(bottom_right_front_Node),
bottom_right_back(bottom_right_back_Node){}
};
//创建八叉树
template
voidcreateOctree(OctreeNode*&root,intmaxdepth,doublexmin,doublexmax,doubleymin,doubleymax,doublezmin,doublezmax)
{
//cout<
maxdepth=maxdepth-1;//每递归一次就将最大递归深度-1
if(maxdepth>=0)
{
root=newOctreeNode();
cout<
//root->data =9;//为节点赋值,可以存储节点信息,如物体可见性。由于是简单实现八叉树功能,简单赋值为9。
cin>>root->data;//为节点赋值
root->xmin=xmin;//为节点坐标赋值
root->xmax=xmax;
root->ymin=ymin;
root->ymax=ymax;
root->zmin=zmin;
root->zmax=zmax;
doublexm=(xmax-xmin)/2;//计算节点个维度上的半边长
doubleym=(ymax-ymin)/2;
doublezm=(ymax-ymin)/2;
//递归创建子树,根据每一个节点所处(是几号节点)的位置决定其子结点的坐标。
createOctree(root->top_left_front,maxdepth,xmin,xmax-xm,ymax-ym,ymax,zmax-zm,zmax);
createOctree(root->top_left_back,maxdepth,xmin,xmax-xm,ymin,ymax-ym,zmax-zm,zmax);
createOctree(root->top_right_front,maxdepth,xmax-xm,xmax,ymax-ym,ymax,zmax-zm,zmax);
createOctree(root->top_right_back,maxdepth,xmax-xm,xmax,ymin,ymax-ym,zmax-zm,zmax);
createOctree(root->bottom_left_front,maxdepth,xmin,xmax-xm,ymax-ym,ymax,zmin,zmax-zm);
createOctree(root->bottom_left_back,maxdepth,xmin,xmax-xm,ymin,ymax-ym,zmin,zmax-zm);
createOctree(root->bottom_right_front,maxdepth,xmax-xm,xmax,ymax-ym,ymax,zmin,zmax-zm);
createOctree(root->bottom_right_back,maxdepth,xmax-xm,xmax,ymin,ymax-ym,zmin,zmax-zm);
}
}
inti=1;
//先序遍历八叉树
template
voidpreOrder(OctreeNode*&p)
{
if(p)
{
cout<data<
cout<xmin<xmax;
cout<ymin<ymax;
cout<zmin<zmax;
i+=1;
cout<
preOrder(p->top_left_front);
preOrder(p->top_left_back);
preOrder(p->top_right_front);
preOrder(p->top_right_back);
preOrder(p->bottom_left_front);
preOrder(p->bottom_left_back);
preOrder(p->bottom_right_front);
preOrder(p->bottom_right_back);
cout<
}
}
//求八叉树的深度
template
intdepth(OctreeNode*&p)
{
if(p==NULL)
return-1;
inth=depth(p->top_left_front);
returnh+1;
}
//计算单位长度,为查找点做准备
intcal(intnum)
{
intresult=1;
if(1==num)
result=1;
else
{
for(inti=1;i
result=2*result;
}
returnresult;
}
//查找点
intmaxdepth=0;
inttimes=0;
staticdoublexmin=0,xmax=0,ymin=0,ymax=0,zmin=0,zmax=0;
inttmaxdepth=0;
doubletxm=1,tym=1,tzm=1;
template
voidfind(OctreeNode*&p,doublex,doubley,doublez)
{
doublexm=(p->xmax-p->xmin)/2;
doubleym=(p->ymax-p->ymin)/2;
doublezm=(p->ymax-p->ymin)/2;
times++;
if(x>xmax||xymax||yzmax||z
{
cout<
return;
}
if(x<=p->xmin+txm&&x>=p->xmax-txm&&y<=p->ymin+tym&&y>=p->ymax-tym&&z<=p->zmin+tzm&&z>=p->zmax-tzm)
{
cout<
cout<xmin<xmax;
cout<ymin<ymax;
cout<zmin<zmax;
cout<
cout<
}
elseif(xxmax-xm)&&yymax-ym)&&zzmax-zm))
{
cout<
cout<xmin<xmax;
cout<ymin<ymax;
cout<zmin<zmax;
cout<
find(p->bottom_left_back,x,y,z);
}
elseif(xxmax-xm)&&yymax-ym)&&z>(p->zmax-zm))
{
cout<
cout<xmin<xmax;
cout<ymin<ymax;
cout<zmin<zmax;
cout<
find(p->top_left_back,x,y,z);
}
elseif(x>(p->xmax-xm)&&yymax-ym)&&zzmax-zm))
{
cout<
cout<xmin<xmax;
cout<ymin<ymax;
cout<zmin<zmax;
cout<
find(p->bottom_right_back,x,y,z);
}
elseif(x>(p->xmax-xm)&&yymax-ym)&&z>(p->zmax-zm))
{
cout<
cout<xmin<xmax;
cout<ymin<ymax;
cout<zmin<zmax;
cout<
find(p->top_right_back,x,y,z);
}
elseif(xxmax-xm)&&y>(p->ymax-ym)&&zzmax-zm))
{
cout<
cout<xmin<xmax;
cout<ymin<ymax;
cout<zmin<zmax;
cout<
find(p->bottom_left_front,x,y,z);
}
elseif(xxmax-xm)&&y>(p->ymax-ym)&&z>(p->zmax-zm))
{
cout<
cout<xmin<xmax;
cout<ymin<ymax;
cout<zmin<zmax;
cout<
find(p->top_left_front,x,y,z);
}
elseif(x>(p->xmax-xm)&&y>(p->ymax-ym)&&zzmax-zm))
{
cout<
cout<xmin<xmax;
cout<ymin<ymax;
cout<zmin<zmax;
cout<
find(p->bottom_right_front,x,y,z);
}
elseif(x>(p->xmax-xm)&&y>(p->ymax-ym)&&z>(p->zmax-zm))
{
cout<
cout<xmin<xmax;
cout<ymin<ymax;
cout<zmin<zmax;
cout<
find(p->top_right_front,x,y,z);
}
}
//main函数
intmain()
{
OctreeNode*rootNode=NULL;
intchoiced=0;
while(true)
{
system("cls");
cout<
cout<
cout<
cout<
cin>>choiced;
if(choiced==0)
return0;
elseif(choiced==1)
{
system("cls");
cout<
cin>>maxdepth;
cout<
cin>>xmin>>xmax>>ymin>>ymax>>zmin>>zmax;
if(maxdepth>=0||xmax>xmin||ymax>ymin||zmax>zmin||xmin>0||ymin>0||zmin>0)
{
tmaxdepth=cal(maxdepth);
txm=(xmax-xmin)/tmaxdepth;
tym=(ymax-ymin)/tmaxdepth;
tzm=(zmax-zmin)/tmaxdepth;
createOctree(rootNode,maxdepth,xmin,xmax,ymin,ymax,zmin,zmax);
}
else
{
cout<
return0;
}
}
elseif(choiced==2)
{
system("cls");
cout<
i=1;
preOrder(rootNode);
cout<
system("pause");
}
elseif(choiced==3)
{
system("cls");
intdep=depth(rootNode);
cout<
system("pause");
}
elseif(choiced==4)
{
system("cls");
cout<
doublex,y,z;
cin>>x>>y>>z;
times=0;
cout<
find(rootNode,x,y,z);
system("pause");
}
else
{
system("cls");
cout<
system("pause");
}
}
}
线性八叉树_八叉树OcTree相关推荐
- 线性八叉树_八叉树 - chunlinge - 博客园
(一)基本原理 用八叉树来表示三维形体,并研究在这种表示下的各种操作及应用是在进入80年代后才比较全面地开展起来的.这种方法,既可以看成是四叉树方法在三维空间的推广,也可以认为是用三维体素阵列表示形体 ...
- 线性八叉树_八叉树模型(体素)分解简易程序
八叉树 维基释义:八叉树(Octree)是一种用于描述三维空间的树状数据结构.八叉树的每个节点表示一个正方体的体积元素,每个节点有八个子节点, 这八个子节点所表示的体积元素加在一起就等于父节点的体积. ...
- 线性八叉树_octree八叉树数据结构原理与实现
通过雷达.激光扫描.立体摄像机等三维测量设备获取的点云数据,具有数据量大.分布不均匀等特点.作为三维领域中一个重要的数据来源,点云数据主要是表征目标表面的海量点集合,并不具备传统网格数据的集合拓扑信息 ...
- C语言数据结构线性表上机实验报告,数据结构实验报告实验一线性表_图文
数据结构实验报告实验一线性表_图文 更新时间:2017/2/11 1:23:00 浏览量:763 手机版 数据结构实验报告 实验名称: 实验一 线性表 学生姓名: 班 级: 班内序号: 学 号: ...
- 线性八叉树_基于三维点云数据的线性八叉树编码压缩算法(权毓舒, 何明一,).pdf...
基于三维点云数据的线性八叉树编码压缩算法(权毓舒, 何明一,) ·70 · 计算机应用研究 2005 年 基于三维点云数据的线性八叉树编码压缩算法 * 权毓舒, 何明一 ( 西北工业大学 电子信息学院 ...
- CloudCompare源码分析_八叉树(Octree)算法基础CC中的八叉树结构
官方参考地址:CloudCompare octree - CloudCompareWiki CC的octree算法主要体现在DgmOctree.h和DgmOctree.cpp中,他采用了一种分级的结构 ...
- 线性八叉树_游戏场景管理的八叉树算法是怎样的?
最近正好在看吧.就谈一下数据结构. 八叉树特别适合进行空间划分.在需要邻近点信息做参考时,利用八叉树做搜索会非常高效. 八叉树必备的元素:尺寸:一般就是自己限定的空间(有的地方也叫bounding b ...
- 八叉树 java_八叉树(Octree)
转载自:http://www.cnblogs.com/21207-iHome/p/7098000.html 八叉树(Octree)是一种用于描述三维空间的树状数据结构.想象一个立方体,我们最少可以切成 ...
- 多变量线性相关分析_如何测量多个变量之间的“非线性相关性”?
多变量线性相关分析 现实世界中的数据科学 (Data Science in the Real World) This article aims to present two ways of calcu ...
最新文章
- Missing artifact com.microsoft.sqlserver:sqljdbc4:jar:4.0
- OpenResty简介
- 【Python】青少年蓝桥杯_每日一题_4.21_s=a+aa+aaa+aaaa的值
- java jsf_将Java 8日期时间API与JSF和Java EE 7结合使用
- 【渝粤教育】电大中专药事管理与法规 (2)作业 题库
- 服务器热修复,热修复探究,hotfix,patch
- WebSocket实践
- springmvc重定向之后取值的几种办法以及优劣比较
- 卢伟冰曝Redmi K50系列最新进展:天玑9000调校比较顺利
- Pytorch:函数的手动梯度计算方法
- 史上最全的微信小程序代码大全源码下载
- 人脸对齐—3DDFA
- 最优秀的数据可视化案例欣赏
- ad网络标号怎么用_altium designer网络标号的作用范围
- conda冗余package的清理(.conda/pkgs)
- ISP—图像调试实习生(第10天)
- 湿空气性质计算,随笔与学习记录(1.饱和水蒸气压力计算)
- 你看到的好片子,原来藏着这么多黑科技……
- Linux Zram的概念
- Go语言之禅 | Gopher Daily (2021.05.06) ʕ◔ϖ◔ʔ