在描述三维场景的过程中常常用到一种名为八叉树的数据结构。描述三维空间的八叉树和描述二维空间的四叉树有相似之处,二维空间中正方形可以被分为四个相同形状的正方形,而三维空间中正方体可以被分为八个形状相同的正方体。

八叉树的每个结点表示一个正方体的体积元素,每一个结点有八个子节点,这种用于描述三维空间的树装结构叫做八叉树。为了便利的点云操作,八叉树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相关推荐

  1. 线性八叉树_八叉树 - chunlinge - 博客园

    (一)基本原理 用八叉树来表示三维形体,并研究在这种表示下的各种操作及应用是在进入80年代后才比较全面地开展起来的.这种方法,既可以看成是四叉树方法在三维空间的推广,也可以认为是用三维体素阵列表示形体 ...

  2. 线性八叉树_八叉树模型(体素)分解简易程序

    八叉树 维基释义:八叉树(Octree)是一种用于描述三维空间的树状数据结构.八叉树的每个节点表示一个正方体的体积元素,每个节点有八个子节点, 这八个子节点所表示的体积元素加在一起就等于父节点的体积. ...

  3. 线性八叉树_octree八叉树数据结构原理与实现

    通过雷达.激光扫描.立体摄像机等三维测量设备获取的点云数据,具有数据量大.分布不均匀等特点.作为三维领域中一个重要的数据来源,点云数据主要是表征目标表面的海量点集合,并不具备传统网格数据的集合拓扑信息 ...

  4. C语言数据结构线性表上机实验报告,数据结构实验报告实验一线性表_图文

    数据结构实验报告实验一线性表_图文 更新时间:2017/2/11 1:23:00  浏览量:763  手机版 数据结构实验报告 实验名称: 实验一 线性表 学生姓名: 班 级: 班内序号: 学 号: ...

  5. 线性八叉树_基于三维点云数据的线性八叉树编码压缩算法(权毓舒, 何明一,).pdf...

    基于三维点云数据的线性八叉树编码压缩算法(权毓舒, 何明一,) ·70 · 计算机应用研究 2005 年 基于三维点云数据的线性八叉树编码压缩算法 * 权毓舒, 何明一 ( 西北工业大学 电子信息学院 ...

  6. CloudCompare源码分析_八叉树(Octree)算法基础CC中的八叉树结构

    官方参考地址:CloudCompare octree - CloudCompareWiki CC的octree算法主要体现在DgmOctree.h和DgmOctree.cpp中,他采用了一种分级的结构 ...

  7. 线性八叉树_游戏场景管理的八叉树算法是怎样的?

    最近正好在看吧.就谈一下数据结构. 八叉树特别适合进行空间划分.在需要邻近点信息做参考时,利用八叉树做搜索会非常高效. 八叉树必备的元素:尺寸:一般就是自己限定的空间(有的地方也叫bounding b ...

  8. 八叉树 java_八叉树(Octree)

    转载自:http://www.cnblogs.com/21207-iHome/p/7098000.html 八叉树(Octree)是一种用于描述三维空间的树状数据结构.想象一个立方体,我们最少可以切成 ...

  9. 多变量线性相关分析_如何测量多个变量之间的“非线性相关性”?

    多变量线性相关分析 现实世界中的数据科学 (Data Science in the Real World) This article aims to present two ways of calcu ...

最新文章

  1. Missing artifact com.microsoft.sqlserver:sqljdbc4:jar:4.0
  2. OpenResty简介
  3. 【Python】青少年蓝桥杯_每日一题_4.21_s=a+aa+aaa+aaaa的值
  4. java jsf_将Java 8日期时间API与JSF和Java EE 7结合使用
  5. 【渝粤教育】电大中专药事管理与法规 (2)作业 题库
  6. 服务器热修复,热修复探究,hotfix,patch
  7. WebSocket实践
  8. springmvc重定向之后取值的几种办法以及优劣比较
  9. 卢伟冰曝Redmi K50系列最新进展:天玑9000调校比较顺利
  10. Pytorch:函数的手动梯度计算方法
  11. 史上最全的微信小程序代码大全源码下载
  12. 人脸对齐—3DDFA
  13. 最优秀的数据可视化案例欣赏
  14. ad网络标号怎么用_altium designer网络标号的作用范围
  15. conda冗余package的清理(.conda/pkgs)
  16. ISP—图像调试实习生(第10天)
  17. 湿空气性质计算,随笔与学习记录(1.饱和水蒸气压力计算)
  18. 你看到的好片子,原来藏着这么多黑科技……
  19. Linux Zram的概念
  20. Go语言之禅 | Gopher Daily (2021.05.06) ʕ◔ϖ◔ʔ

热门文章

  1. 【IOS 开发学习总结-OC-60】ipad应用开发的一些知识
  2. 感谢万商网《万商访谈》栏目对我的专访报导
  3. okio 的使用及源码分析
  4. java中的IO、NIO、Okio
  5. 国内openstack桌面云领跑者机敏云桌面GPU性能评测
  6. android编译做cmcc分支宏
  7. 如何隐藏您在Apple App Store和Google Play上购买的应用程序
  8. VUE源码解析-1- 初始篇:vue定义路径查找
  9. Streamsets性能优化
  10. 3.4—4 Java final关键字、接口、数组