四叉树与八叉树

摘要:
四叉树广泛应用于图像处理、空间数据索引、2D中的快速碰撞检测、存储稀疏数据等,而八叉树主要应用于3D图形处理。本文着重于对四叉树与八叉树的原理与结构的介绍,帮助您在脑海中建立四叉树与八叉树的基本思想。本文并不对这两种数据结构同时进行详解,而只对四叉树进行详解,因为八叉树的建立可由四叉树的建立推得。较之四叉树,八叉树将场景从二维空间延伸到了三维空间。

前序

四叉树或四元树也被称为Q树(Q-Tree)。四叉树广泛应用于图像处理、空间数据索引、2D中的快速碰撞检测、存储稀疏数据等,而八叉树(Octree)主要应用于3D图形处理。对游戏编程,这会很有用。本文着重于对四叉树与八叉树的原理与结构的介绍,帮助您在脑海中建立四叉树与八叉树的基本思想。本文并不对这两种数据结构同时进行详解,而只对四叉树进行详解,因为八叉树的建立可由四叉树的建立推得。若有不足之处,望能不吝指出,以改进之。^_^ 欢迎Email:zhanxinhang@gmail.com

四叉树与八叉树的结构与原理

四叉树(Q-Tree)是一种树形数据结构。四叉树的定义是:它的每个节点下至多可以有四个子节点,通常把一部分二维空间细分为四个象限或区域并把 该区域里的相关信息存入到四叉树节点中。这个区域可以是正方形、矩形或是任意形状。以下为四叉树的二维空间结构(左)和存储结构(右)示意图(注意节点颜 色与网格边框颜色):

四叉树与八叉树第1张

四叉树的每一个节点代表一个矩形区域(如上图黑色的根节点代表最外围黑色边框的矩形区域),每一个矩形区域又可划分为四个小矩形区域,这四个小矩形区域作为四个子节点所代表的矩形区域。

较之四叉树,八叉树将场景从二维空间延伸到了三维空间。八叉树(Octree)的定义是:若不为空树的话,树中任一节点的子节点恰好只会有八个,或零个,也就是子节点不会有0与8以外的数目。那么,这要用来做什么?想象一个立方体,我们最少可以切成多少个相同等分的小立方体?答案就是8个如下八叉树的结构示意图所示:

四叉树与八叉树第2张

四叉树存储结构的c语言描述:

  1. /*一个矩形区域的象限划分::
  2. UL(1)|UR(0)
  3. ----------|-----------
  4. LL(2)|LR(3)
  5. 以下对该象限类型的枚举
  6. */
  7. typedefenum
  8. {
  9. UR=0,
  10. UL=1,
  11. LL=2,
  12. LR=3
  13. }QuadrantEnum;
  14. /*矩形结构*/
  15. typedefstructquadrect_t
  16. {
  17. doubleleft,
  18. top,
  19. right,
  20. bottom;
  21. }quadrect_t;
  22. /*四叉树节点类型结构*/
  23. typedefstructquadnode_t
  24. {
  25. quadrect_trect;//节点所代表的矩形区域
  26. list_t*lst_object;//节点数据,节点类型一般为链表,可存储多个对象
  27. structquadnode_t*sub[4];//指向节点的四个孩子
  28. }quadnode_t;
  29. /*四叉树类型结构*/
  30. typedefstructquadtree_t
  31. {
  32. quadnode_t*root;
  33. intdepth;//四叉树的深度
  34. }quadtree_t;

四叉树的建立

1、利用四叉树分网格,如本文的第一张图<四层完全四叉树结构示意图>,根据左图的网格图形建立如右图所示的完全四叉树。

伪码:

Funtion QuadTreeBuild ( depth, rect )

{

QuadTree->depth = depth;


/*创建分支,root树的根,depth深度,rect根节点代表的矩形区域*/

QuadCreateBranch ( root, depth, rect );

}


Funtion QuadCreateBranch ( n, depth,rect )

{

if ( depth!=0 )

{

n = new node; //开辟新节点

n ->rect = rect; //将该节点所代表的矩形区域存储到该节点中

将rect划成四份 rect[UR], rect[UL], rect[LL], rect[LR];


/*创建各孩子分支*/

QuadCreateBranch ( n->sub[UR], depth-1, rect [UR] );

QuadCreateBranch ( n->sub[UL], depth-1, rect [UL] );

QuadCreateBranch ( n->sub[LL], depth-1, rect [LL] );

QuadCreateBranch ( n->sub[LR], depth-1, rect [LR] );

}

}


2、假设在一个矩形区域里有N个对象,如下左图一个黑点代表一个对象,每个对象的坐标位置都是已知的,用四叉树的一个节点存储一个对象,构建成如下右图所示的四叉树。

四叉树与八叉树第3张

方法也是采用递归的方法对该矩形进行划分分区块,分完后再往里分,直到每一个子矩形区域里只包含一个对象为止。

伪码:

Funtion QuadtreeBuild()

{

Quadtree = {empty};
For (i = 1;i<n;i++) //遍历所有对象

{

QuadInsert(i, root);//将i对象插入四叉树

}

剔除多余的节点; //执行完上面循环后,四叉树中可能有数据为空的叶子节点需要剔除
}


Funtion QuadInsert(i,n) //该函数插入后四叉树中的每个节点所存储的对象数量不是1就是0

{

if(节点n有孩子)

{

通过划分区域判断i应该放置于n节点的哪一个孩子节点c;

QuadInsert(i,c);

}

else if(节点n存储了一个对象)

{

为n节点创建四个孩子;

将n节点中的对象移到它应该放置的孩子节点中;

通过划分区域判断i应该放置于n节点的哪一个孩子节点c;

QuadInsert(i,c);

}

else if(n节点数据为空)

{

将i存储到节点n中;

}

}


(以上两种建立方法作为举一反三之用)

用四叉树查找某一对象

1、采用盲目搜索,与二叉树的递归遍历类似,可采用后序遍历或前序遍历或中序遍历对其进行搜索某一对象,时间复杂度为O(n)。

2、根据对象在区域里的位置来搜索,采用分而治之思想,时间复杂度只与四叉树的深度有关。比起盲目搜索,这种搜索在区域里的对象越多时效果越明显

四叉树与八叉树第4张

伪码:

Funtionfind ( n, pos, )

{

If (n节点所存的对象位置为 pos所指的位置 )

Returnn;

If ( pos位于第一象限 )

temp = find ( n->sub[UR], pos );

else if ( pos位于第二象限)

temp = find ( n->sub[UL], pos );

else if ( pos位于第三象限 )

temp = find ( n->sub[LL], pos );

else //pos 位于第四象限

temp = find ( n->sub[LR], pos );

return temp;

}

结语:

熟话说:结构之法,算法之道。多一种数据结构就多一种解决问题的方法,多一种方法就多一种思维模式。祝君学习愉快!^_^

免责声明:文章转载自《四叉树与八叉树》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇nodeJS从入门到进阶一(基础部分)ABAP常用字符串操作收集整理下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

VC++通用控件编程

滑动条控制(Slider Control)也叫轨道条控制,其主要是用一个带有轨道和滑标的小窗口以及窗口上的刻度,来让用户选择一个离散数据或一个连续的数值区间。通过鼠标或键盘来进行数据的选择操作,这在WIN98/95中的很多应用程序中都可以看到,如控制面板中的鼠标等,滑动条既可以是水平方式的也可以是垂直方式的。滑动条控制的风格如下: TBS_HORZ 滑动条...

[ PyQt入门教程 ] Qt Designer工具的使用

Qt Designer是PyQt程序UI界面的实现工具,使用Qt Designer可以拖拽、点击完成GUI界面设计,并且设计完成的.ui程序可以转换成.py文件供python程序调用。本文主要通过用户登录需求描述Qt Designer工具开发界面的使用方法。 本文主要内容1、Qt Designer程序主界面窗口介绍。 2、Qt Designer程序实现界面...

ggplot2 theme相关设置—矩形设置(rect)

在主题设置中,rect设置主要用于设置图例和面板 element_rect(fill = NULL, colour = NULL, size = NULL, linetype = NULL, color = NULL) 参数也相对简单,基本上是常用的参数,从设置来看,灵活性还是很高的。 下面看些例子: library(ggplot2) p<-ggpl...

swift 画虚线

1. CAShapeLayer:适用于 动态显示 虚线, 通过控制添加虚线view的 ishidden 控制虚线的显示隐藏 ///绘制虚线 ///- Parameters: ///- lineView: 添加虚线的view ///- strokeColor: 虚线颜色 ///- lineWidth: 虚线宽度...

android应用程序中获取view的位置

android应用程序中获取view的位置_雨枫技术教程网  我们重点在获取view的y坐标,你懂的... 依次介绍以下四个方法:   1.getLocationInWindow   int[] position = new int[2];  textview.getLocationInWindow(position);  System.out.pr...

C语言Windows程序开发—CreateWindow函数介绍【第03天】

(一)CreateWindow函数的参数介绍: 1 HWND CreateWindow( 2 LPCTSTR lpClassName, //Windows窗口中预定义的控件结构体,包括:BUTTON(按钮),EDIT(文本框),LISTBOX(列表),MDICLIENT(子窗口),SCROLLBAR(滚动条),RICHEDIT(富文...