八叉树算法

转载 2013年10月20日 22:54:17

Octree的定义是:若不为空树的话,树中任一节点的子节点恰好只会有八个,或
零个,也就是子节点不会有0与8以外的数目。那么,这要用来做什么?想象一个
立方体,我们最少可以切成多少个相同等分的小立方体?答案就是8个。再想象
我们有一个房间,房间里某个角落藏着一枚金币,我们想很快的把金币找出来,
聪明的你会怎么做?我们可以把房间当成一个立方体,先切成八个小立方体,
然后排除掉没有放任何东西的小立方体,再把有可能藏金币的小立方体继续切八
等份….如此下去,平均在Log8(房间内的所有物品数)的时间内就可找到金币。
因此,Octree就是用在3D空间中的场景管理,可以很快地知道物体在3D场景中
的位置,或侦测与其它物体是否有碰撞以及是否在可视范围内。


2、实现Octree的原理
(1). 设定最大递归深度
(2). 找出场景的最大尺寸,并以此尺寸建立第一个立方体
(3). 依序将单位元元素丢入能被包含且没有子节点的立方体
(4). 若没有达到最大递归深度,就进行细分八等份,再将该立方体所装的单位元元素全部分担给八
个子立方体
(5). 若发现子立方体所分配到的单位元元素数量不为零且跟父立方体是一样的,则该子立方体停止
细分,因为跟据空间分割理论,细分的空间所得到的分配必定较少,若是一样数目,则再怎么切数目
还是一样,会造成无穷切割的情形。
(6). 重复3,直到达到最大递归深度。


4、BSP Tree和Octree对比
a) BSP Tree将场景分割为1个面,而Octree分割为3个面。
b) BSP Tree每个节点最多有2个子结点,而Octree最多有8个子结点
因此BSP Tree可以用在不论几唯的场景中,而Octree则常用于三维场景

  1. #include "stdafx.h"  
  2. #include <iostream>  
  3.   
  4. using namespace std;  
  5. //定义八叉树节点类  
  6. template<class T>  
  7. struct OctreeNode  
  8. {  
  9.     T data; //节点数据  
  10.     T xmin,xmax; //节点坐标,即六面体个顶点的坐标  
  11.     T ymin,ymax;  
  12.     T zmin,zmax;  
  13.     OctreeNode <T> *top_left_front,*top_left_back; //该节点的个子结点  
  14.     OctreeNode <T> *top_right_front,*top_right_back;  
  15.     OctreeNode <T> *bottom_left_front,*bottom_left_back;  
  16.     OctreeNode <T> *bottom_right_front,*bottom_right_back;  
  17.     OctreeNode //节点类  
  18.         (T nodeValue = T(),  
  19.         T xminValue = T(),T xmaxValue = T(),  
  20.         T yminValue = T(),T ymaxValue = T(),  
  21.         T zminValue = T(),T zmaxValue = T(),  
  22.         OctreeNode<T>* top_left_front_Node = NULL,  
  23.         OctreeNode<T>* top_left_back_Node = NULL,  
  24.         OctreeNode<T>* top_right_front_Node = NULL,  
  25.         OctreeNode<T>* top_right_back_Node = NULL,  
  26.         OctreeNode<T>* bottom_left_front_Node = NULL,  
  27.         OctreeNode<T>* bottom_left_back_Node = NULL,  
  28.         OctreeNode<T>* bottom_right_front_Node = NULL,  
  29.         OctreeNode<T>* bottom_right_back_Node = NULL )  
  30.         :data(nodeValue),  
  31.         xmin(xminValue),xmax(xmaxValue),  
  32.         ymin(yminValue),ymax(ymaxValue),  
  33.         zmin(zminValue),zmax(zmaxValue),  
  34.         top_left_front(top_left_front_Node),  
  35.         top_left_back(top_left_back_Node),  
  36.         top_right_front(top_right_front_Node),  
  37.         top_right_back(top_right_back_Node),  
  38.         bottom_left_front(bottom_left_front_Node),  
  39.         bottom_left_back(bottom_left_back_Node),  
  40.         bottom_right_front(bottom_right_front_Node),  
  41.         bottom_right_back(bottom_right_back_Node){}  
  42. };  
  43. //创建八叉树  
  44. template <class T>  
  45. void createOctree(OctreeNode<T> * &root,int maxdepth,double xmin,double xmax,double ymin,double ymax,double zmin,double zmax)  
  46. {  
  47.     cout<<"处理中,请稍候……"<<endl;  
  48.     maxdepth=maxdepth-1; //每递归一次就将最大递归深度-1  
  49.     if(maxdepth>=0)  
  50.     {  
  51.         root=new OctreeNode<T>();  
  52.         root->data = 9; //为节点赋值,可以存储节点信息,如物体可见性。由于是简单实现八叉树功能,简单赋值为。  
  53.         root->xmin=xmin; //为节点坐标赋值  
  54.         root->xmax=xmax;  
  55.         root->ymin=ymin;  
  56.         root->ymax=ymax;  
  57.         root->zmin=zmin;  
  58.         root->zmax=zmax;  
  59.         double xm=(xmax-xmin)/2;//计算节点个维度上的半边长  
  60.         double ym=(ymax-ymin)/2;  
  61.         double zm=(ymax-ymin)/2;  
  62.         //递归创建子树,根据每一个节点所处(是几号节点)的位置决定其子结点的坐标。  
  63.         createOctree(root->top_left_front,maxdepth,xmin,xmax-xm,ymax-ym,ymax,zmax-zm,zmax);  
  64.         createOctree(root->top_left_back,maxdepth,xmin,xmax-xm,ymin,ymax-ym,zmax-zm,zmax);  
  65.         createOctree(root->top_right_front,maxdepth,xmax-xm,xmax,ymax-ym,ymax,zmax-zm,zmax);  
  66.         createOctree(root->top_right_back,maxdepth,xmax-xm,xmax,ymin,ymax-ym,zmax-zm,zmax);  
  67.         createOctree(root->bottom_left_front,maxdepth,xmin,xmax-xm,ymax-ym,ymax,zmin,zmax-zm);  
  68.         createOctree(root->bottom_left_back,maxdepth,xmin,xmax-xm,ymin,ymax-ym,zmin,zmax-zm);  
  69.         createOctree(root->bottom_right_front,maxdepth,xmax-xm,xmax,ymax-ym,ymax,zmin,zmax-zm);  
  70.         createOctree(root->bottom_right_back,maxdepth,xmax-xm,xmax,ymin,ymax-ym,zmin,zmax-zm);  
  71.     }  
  72. }  
  73. int i=1;  
  74. //先序遍历八叉树  
  75. template <class T>  
  76. void preOrder( OctreeNode<T> * & p)  
  77. {  
  78.     if(p)  
  79.     {  
  80.         cout<<i<<".当前节点的值为:"<<p->data<<"/n坐标为:";  
  81.         cout<<" xmin: "<<p->xmin<<" xmax: "<<p->xmax;  
  82.         cout<<" ymin: "<<p->ymin<<" ymax: "<<p->ymax;  
  83.         cout<<" zmin: "<<p->zmin<<" zmax: "<<p->zmax;  
  84.         i+=1;  
  85.         cout<<endl;  
  86.         preOrder(p->top_left_front);  
  87.         preOrder(p->top_left_back);  
  88.         preOrder(p->top_right_front);  
  89.         preOrder(p->top_right_back);  
  90.         preOrder(p->bottom_left_front);  
  91.         preOrder(p->bottom_left_back);  
  92.         preOrder(p->bottom_right_front);  
  93.         preOrder(p->bottom_right_back);  
  94.         cout<<endl;  
  95.     }  
  96. }  
  97. //求八叉树的深度  
  98. template<class T>  
  99. int depth(OctreeNode<T> *& p)  
  100. {  
  101.     if(p == NULL)  
  102.         return -1;  
  103.     int h = depth(p->top_left_front);  
  104.     return h+1;  
  105. }  
  106. //计算单位长度,为查找点做准备  
  107. int cal(int num)  
  108. {  
  109.     int result=1;  
  110.     if(1==num)  
  111.         result=1;  
  112.     else  
  113.     {  
  114.         for(int i=1;i<num;i++)  
  115.             result=2*result;  
  116.     }  
  117.     return result;  
  118. }  
  119. //查找点  
  120. int maxdepth=0;  
  121. int times=0;  
  122. static double xmin=0,xmax=0,ymin=0,ymax=0,zmin=0,zmax=0;  
  123. int tmaxdepth=0;  
  124. double txm=1,tym=1,tzm=1;  
  125. template<class T>  
  126. void find(OctreeNode<T> *& p,double x,double y,double z)  
  127. {  
  128.     double xm=(p->xmax-p->xmin)/2;  
  129.     double ym=(p->ymax-p->ymin)/2;  
  130.     double zm=(p->ymax-p->ymin)/2;  
  131.     times++;  
  132.     if(x>xmax || x<xmin || y>ymax || y<ymin || z>zmax || z<zmin)  
  133.     {  
  134.         cout<<"该点不在场景中!"<<endl;  
  135.         return;  
  136.     }  
  137.     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 )  
  138.     {  
  139.         cout<<endl<<"找到该点!"<<"该点位于"<<endl;  
  140.         cout<<" xmin: "<<p->xmin<<" xmax: "<<p->xmax;  
  141.         cout<<" ymin: "<<p->ymin<<" ymax: "<<p->ymax;  
  142.         cout<<" zmin: "<<p->zmin<<" zmax: "<<p->zmax;  
  143.         cout<<"节点内!"<<endl;  
  144.         cout<<"共经过"<<times<<"次递归!"<<endl;  
  145.     }  
  146.     else if(x<(p->xmax-xm) && y<(p->ymax-ym) && z<(p->zmax-zm))  
  147.     {  
  148.         cout<<"当前经过节点坐标:"<<endl;  
  149.         cout<<" xmin: "<<p->xmin<<" xmax: "<<p->xmax;  
  150.         cout<<" ymin: "<<p->ymin<<" ymax: "<<p->ymax;  
  151.         cout<<" zmin: "<<p->zmin<<" zmax: "<<p->zmax;  
  152.         cout<<endl;  
  153.         find(p->bottom_left_back,x,y,z);  
  154.     }  
  155.     else if(x<(p->xmax-xm) && y<(p->ymax-ym) && z>(p->zmax-zm))  
  156.     {  
  157.         cout<<"当前经过节点坐标:"<<endl;  
  158.         cout<<" xmin: "<<p->xmin<<" xmax: "<<p->xmax;  
  159.         cout<<" ymin: "<<p->ymin<<" ymax: "<<p->ymax;  
  160.         cout<<" zmin: "<<p->zmin<<" zmax: "<<p->zmax;  
  161.         cout<<endl;  
  162.         find(p->top_left_back,x,y,z);  
  163.     }  
  164.     else if(x>(p->xmax-xm) && y<(p->ymax-ym) && z<(p->zmax-zm))  
  165.     {  
  166.         cout<<"当前经过节点坐标:"<<endl;  
  167.         cout<<" xmin: "<<p->xmin<<" xmax: "<<p->xmax;  
  168.         cout<<" ymin: "<<p->ymin<<" ymax: "<<p->ymax;  
  169.         cout<<" zmin: "<<p->zmin<<" zmax: "<<p->zmax;  
  170.         cout<<endl;  
  171.         find(p->bottom_right_back,x,y,z);  
  172.     }  
  173.     else if(x>(p->xmax-xm) && y<(p->ymax-ym) && z>(p->zmax-zm))  
  174.     {  
  175.         cout<<"当前经过节点坐标:"<<endl;  
  176.         cout<<" xmin: "<<p->xmin<<" xmax: "<<p->xmax;  
  177.         cout<<" ymin: "<<p->ymin<<" ymax: "<<p->ymax;  
  178.         cout<<" zmin: "<<p->zmin<<" zmax: "<<p->zmax;  
  179.         cout<<endl;  
  180.         find(p->top_right_back,x,y,z);  
  181.     }  
  182.     else if(x<(p->xmax-xm) && y>(p->ymax-ym) && z<(p->zmax-zm))  
  183.     {  
  184.         cout<<"当前经过节点坐标:"<<endl;  
  185.         cout<<" xmin: "<<p->xmin<<" xmax: "<<p->xmax;  
  186.         cout<<" ymin: "<<p->ymin<<" ymax: "<<p->ymax;  
  187.         cout<<" zmin: "<<p->zmin<<" zmax: "<<p->zmax;  
  188.         cout<<endl;  
  189.         find(p->bottom_left_front,x,y,z);  
  190.     }  
  191.     else if(x<(p->xmax-xm) && y>(p->ymax-ym) && z>(p->zmax-zm))  
  192.     {  
  193.         cout<<"当前经过节点坐标:"<<endl;  
  194.         cout<<" xmin: "<<p->xmin<<" xmax: "<<p->xmax;  
  195.         cout<<" ymin: "<<p->ymin<<" ymax: "<<p->ymax;  
  196.         cout<<" zmin: "<<p->zmin<<" zmax: "<<p->zmax;  
  197.         cout<<endl;  
  198.         find(p->top_left_front,x,y,z);  
  199.     }  
  200.     else if(x>(p->xmax-xm) && y>(p->ymax-ym) && z<(p->zmax-zm))  
  201.     {  
  202.         cout<<"当前经过节点坐标:"<<endl;  
  203.         cout<<" xmin: "<<p->xmin<<" xmax: "<<p->xmax;  
  204.         cout<<" ymin: "<<p->ymin<<" ymax: "<<p->ymax;  
  205.         cout<<" zmin: "<<p->zmin<<" zmax: "<<p->zmax;  
  206.         cout<<endl;  
  207.         find(p->bottom_right_front,x,y,z);  
  208.     }  
  209.     else if(x>(p->xmax-xm) && y>(p->ymax-ym) && z>(p->zmax-zm))  
  210.     {  
  211.         cout<<"当前经过节点坐标:"<<endl;  
  212.         cout<<" xmin: "<<p->xmin<<" xmax: "<<p->xmax;  
  213.         cout<<" ymin: "<<p->ymin<<" ymax: "<<p->ymax;  
  214.         cout<<" zmin: "<<p->zmin<<" zmax: "<<p->zmax;  
  215.         cout<<endl;  
  216.         find(p->top_right_front,x,y,z);  
  217.     }  
  218. }  
  219. //main函数  
  220. int main ()  
  221. {  
  222.     OctreeNode<double> * rootNode = NULL;  
  223.     int choiced = 0;  
  224.     while(true)  
  225.     {  
  226.         system("cls");  
  227.         cout<<"请选择操作:/n";  
  228.         cout<<"1.创建八叉树 2.先序遍历八叉树/n";  
  229.         cout<<"3.查看树深度 4.查找节点   /n";  
  230.         cout<<"0.退出/n/n";  
  231.         cin>>choiced;  
  232.         if(choiced == 0)  
  233.             return 0;  
  234.         else if(choiced == 1)  
  235.         {  
  236.             system("cls");  
  237.             cout<<"请输入最大递归深度:"<<endl;  
  238.             cin>>maxdepth;  
  239.             cout<<"请输入外包盒坐标,顺序如下:xmin,xmax,ymin,ymax,zmin,zmax"<<endl;  
  240.             cin>>xmin>>xmax>>ymin>>ymax>>zmin>>zmax;  
  241.             if(maxdepth>=0 || xmax>xmin || ymax>ymin || zmax>zmin || xmin>0 || ymin>0 ||zmin>0)  
  242.             {  
  243.                 tmaxdepth=cal(maxdepth);  
  244.                 txm=(xmax-xmin)/tmaxdepth;  
  245.                 tym=(ymax-ymin)/tmaxdepth;  
  246.                 tzm=(zmax-zmin)/tmaxdepth;  
  247.                 createOctree(rootNode,maxdepth,xmin,xmax,ymin,ymax,zmin,zmax);  
  248.             }  
  249.             else  
  250.             {  
  251.                 cout<<"输入错误!";  
  252.                 return 0;  
  253.             }  
  254.         }  
  255.         else if(choiced == 2)  
  256.         {  
  257.             system("cls");  
  258.             cout<<"先序遍历八叉树结果:/n";  
  259.             i=1;  
  260.             preOrder(rootNode);  
  261.             cout<<endl;  
  262.             system("pause");  
  263.         }  
  264.         else if(choiced == 3)  
  265.         {  
  266.             system("cls");  
  267.             int dep = depth(rootNode);  
  268.             cout<<"此八叉树的深度为"<<dep+1<<endl;  
  269.             system("pause");  
  270.         }  
  271.         else if(choiced == 4)  
  272.         {  
  273.             system("cls");  
  274.             cout<<"请输入您希望查找的点的坐标,顺序如下:x,y,z/n";  
  275.             double x,y,z;  
  276.             cin>>x>>y>>z;  
  277.             times=0;  
  278.             cout<<endl<<"开始搜寻该点……"<<endl;  
  279.             find(rootNode,x,y,z);  
  280.             system("pause");  
  281.         }  
  282.         else  
  283.         {  
  284.             system("cls");  
  285.             cout<<"/n/n错误选择!/n";  
  286.             system("pause");  
  287.         }  
  288.     }  
  289. }  

八叉树Octree

维基释义:八叉树(Octree)是一种用于描述三维空间的树状数据结构。八叉树的每个节点表示一个正方体的体积元素,每个节点有八个子节点,这八个子节点所表示的体积元素加在一起就等于父节点的体积。一般中心点...
  • Augusdi
  • Augusdi
  • 2014年06月30日 16:41
  • 12780

基于八叉树的网格生成算法剖析

前言  对于网格生成这个主题,之前的网格生成系列的三篇博客文章分别介绍了MC算法,SMC算法以及Cuberille算法三种方法。同时还有一篇介绍网格生成与种子点生长算法高效结合的算法。本篇文章继续这一...
  • Augusdi
  • Augusdi
  • 2014年07月01日 09:19
  • 13419

基于八叉树的网格生成算法剖析

前言   对于网格生成这个主题,之前的网格生成系列的三篇博客文章分别介绍了MC算法,SMC算法以及Cuberille算法三种方法。同时还有一篇介绍网格生成与种子点生长算法高效结合的算法。本篇文章...
  • wozhengtao
  • wozhengtao
  • 2016年05月17日 01:15
  • 1248

八叉树及K-D树的应用和实现

1. 八叉树、k-d树的原理2. 八叉树、k-d树的应用、优缺点3. 八叉树、k-d树的实现八叉树和k-d树都经常用来处理三维空间数据,k-d树的使用范围更宽泛些,适用于k维空间的数据,在Sift算法...
  • Augusdi
  • Augusdi
  • 2014年06月30日 20:46
  • 2264

八叉树算法

  • 2015年10月08日 16:28
  • 2.94MB
  • 下载

基于八叉树的区域增长点云分割算法

提出的问题 相关工作 提出的方案 粗分割 细化 达到的效果 认为的优点 可能的改进 提出的问题 激光雷达探测到城市环境的物体表面构成三维几何点,相应的点云分割技术常用于建筑物重建。由于建筑物的复...
  • cjx2lxj
  • cjx2lxj
  • 2016年01月16日 20:41
  • 5452

八叉树

在写Ambient Occlusion时需要进行射线与物体的各个三角形的碰撞检测 但是逐个三角形进行判断需要进行大量的无意义计算 可以通过一个八叉树管理物体的包围盒空间 通过八叉树对物体的包围盒进行空...
  • u010897187
  • u010897187
  • 2015年03月27日 22:02
  • 347

场景管理:八叉树算法C++实现

简单实现了场景管理八叉树算法 代码结构: object.h,object.cpp 被管理的对象类octree_node.h,octree_node.cpp 八叉树类main.cpp程序入口...
  • u012234115
  • u012234115
  • 2015年07月30日 21:06
  • 2945

基于八叉树的网格生成算法剖析

基于八叉树的网格生成算法剖析前言  对于网格生成这个主题,之前的网格生成系列的三篇博客文章分别介绍了MC算法,SMC算法以及Cuberille算法三种方法。同时还有一篇介绍网格生成与种子点生长算法高效...
  • Kaitiren
  • Kaitiren
  • 2016年03月11日 11:40
  • 2392

八叉树结构算法

  • 2014年09月20日 20:46
  • 362KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:八叉树算法
举报原因:
原因补充:

(最多只允许输入30个字)