C语言实现一个四叉树quadtree
cheungmine
用C语言实现一个2维四叉树quadtree,具有一定的实际意义。你可以把几何图形的索引(用long型的id标识)放到这个树中(根据最小边界矩形)。quadtree可以用来快速区域查找图形,虽然不是那么精确,但是毕竟没有漏掉的。虽然quadtree的效率不如RTree?但是RTree的实现毕竟复杂了些,我会尽快收集整理出RTree的代码。RTree确实比QuadTree好的多?(起码RTree很时髦啊!)
头文件如下:
/*
*quadtree.h
*Quadtreestructure--forspatialquicksearching
*cheungmine
*Oct.5,2007.Allrightsreserved.
*/
#ifndefQUADTREE_H_INCLUDED
#defineQUADTREE_H_INCLUDED
#include"unistd.h"
#include"list.h"
#defineQUAD_SUBNODES4
#defineQBOX_OVERLAP_MAX0.4
#defineQBOX_OVERLAP_MIN0.02
#defineQTREE_DEPTH_MAX8
#defineQTREE_DEPTH_MIN4
#defineQUADRANT_BITS3
/*aquadrantdefinedbelow:
NW(1)|NE(0)
-----------|-----------
SW(2)|SE(3)
*/
typedefenum
{
NE=0,
NW=1,
SW=2,
SE=3
}QuadrantEnum;
/*aboxdefinedbelow:
_____max
|__|__|
|__|__|
min
*/
typedefstruct_quadbox_t
{
double_xmin,
_ymin,
_xmax,
_ymax;
}quadbox_t;
/*quadnode*/
typedefstruct_quadnode_t
{
quadbox_t_box;/*nodeboundbox*/
list_t*_lst;/*nodedatalist*/
struct_quadnode_t*_sub[QUAD_SUBNODES];/*pointertosubnodesofthisnode*/
}quadnode_t;
/*quadtree*/
typedefstruct_quadtree_t
{
quadnode_t*_root;
int_depth;/*maxdepthoftree:0-based*/
float_overlap;/*overlappedratioofquanbox*/
}quadtree_t;
/*=============================================================================
PublicFunctions
=============================================================================*/
/*createsaquadtreeandreturnsapointertoit*/
externquadtree_t*
quadtree_create(quadbox_tbox,
intdepth,/*4~8*/
floatoverlap/*0.02~0.4*/
);
/*destroysaquadtreeandfreeallmemory*/
externvoid
quadtree_destroy(INquadtree_t*qtree
);
/*insertsanodeidentifiedbynode_keyintoaquadtree,returnsthenodequadtreeencoding*/
externquadnode_t*
quadtree_insert(INquadtree_t*qtree,
INlongnode_key,
INquadbox_t*node_box
);
/*searchesnodesinsidesearch_box*/
externvoid
quadtree_search(INconstquadtree_t*qtree,
INquadbox_t*search_box,
OUTlist_t*results_list
);
#endif//QUADTREE_H_INCLUDED
实现文件如下:
/*
*quadtree.c
*Quadtreeimplementation--forspatialquicksearching
*cheungmine
*Oct.5,2007.Allrightsreserved.
*/
#include"quadtree.h"
#include<assert.h>
/*=============================================================================
PrivateFunctions
=============================================================================*/
staticBOOLquadbox_is_valid(quadbox_t*qb)
{
return(qb->_xmin<qb->_xmax&&qb->_ymin<qb->_ymax)?TRUE:FALSE;
}
staticdoublequadbox_width(constquadbox_t*qb)
{
return(qb->_xmax-qb->_xmin);
}
staticdoublequadbox_height(constquadbox_t*qb)
{
return(qb->_ymax-qb->_ymin);
}
staticvoidquadbox_init(quadbox_t*qb,
doublexmin,doubleymin,doublexmax,doubleymax)
{
qb->_xmin=xmin;qb->_ymin=ymin;qb->_xmax=xmax;qb->_ymax=ymax;
assert(quadbox_is_valid(qb));
}
staticvoidquadbox_inflate(quadbox_t*qb,doubledx,doubledy)
{
assert(dx>0&&dy>0);
qb->_xmin-=(dx/2);
qb->_xmax+=(dx/2);
qb->_ymin-=(dy/2);
qb->_ymax+=(dy/2);
}
/*splitsthequadrantsuchasbelow:
nw(0010)|ne(0001)
----------|----------
sw(0100)|se(1000)
*/
staticvoidquadbox_split(constquadbox_t*qb,
quadbox_t*ne,quadbox_t*nw,quadbox_t*se,quadbox_t*sw,
floatoverlap)
{
doubledx=quadbox_width(qb)*(1.0+overlap)/2;
doubledy=quadbox_height(qb)*(1.0+overlap)/2;
assert(overlap>=QBOX_OVERLAP_MIN-0.0001);
assert(overlap<=QBOX_OVERLAP_MAX+0.0001);
quadbox_init(ne,qb->_xmax-dx,qb->_ymax-dy,qb->_xmax,qb->_ymax);
quadbox_init(nw,qb->_xmin,qb->_ymax-dy,qb->_xmin+dx,qb->_ymax);
quadbox_init(sw,qb->_xmin,qb->_ymin,qb->_xmin+dx,qb->_ymin+dy);
quadbox_init(se,qb->_xmax-dx,qb->_ymin,qb->_xmax,qb->_ymin+dy);
}
/*returnsTRUEifthefirstisinsidethesenond*/
staticBOOLquadbox_is_inside(constquadbox_t*_first,constquadbox_t*_second)
{
return(_second->_xmin<_first->_xmin&&_second->_xmax>_first->_xmax&&
_second->_ymin<_first->_ymin&&_second->_ymax>_first->_ymax)?TRUE:FALSE;
}
/*returnsTRUEiftwoquad_boxisoverlapped*/
staticBOOLquadbox_is_overlapped(constquadbox_t*_first,constquadbox_t*_second)
{
return(_first->_xmin>_second->_xmax||_first->_xmax<_second->_xmin||
_first->_ymin>_second->_ymax||_first->_ymax<_second->_ymin)?FALSE:TRUE;
}
staticquadnode_t*quadnode_create(constquadbox_t*box)
{
quadnode_t*node=(quadnode_t*)calloc(1,sizeof(quadnode_t));
if(node)
memcpy(&(node->_box),box,sizeof(quadbox_t));
returnnode;
}
staticvoidquadnode_destroy(quadnode_t*node)
{
if(node->_sub[NE]!=0){
quadnode_destroy(node->_sub[NE]);
quadnode_destroy(node->_sub[NW]);
quadnode_destroy(node->_sub[SE]);
quadnode_destroy(node->_sub[SW]);
}
if(node->_lst)
list_destroy(node->_lst,NULL);
free(node);
}
staticvoidquadnode_create_child(quadnode_t*node,floatoverlap,intdepth)
{
quadbox_tne,nw,se,sw;
assert(node);
quadbox_split(&(node->_box),&ne,&nw,&se,&sw,overlap);
node->_sub[NE]=quadnode_create(&ne);
node->_sub[NW]=quadnode_create(&nw);
node->_sub[SW]=quadnode_create(&sw);
node->_sub[SE]=quadnode_create(&se);
}
staticBOOLquadnode_has_child(constquadnode_t*node)
{
return(node->_sub[NE]!=0);
}
staticBOOLquadnode_has_data(constquadnode_t*node)
{
return(node->_lst&&node->_lst->size>0)?TRUE:FALSE;
}
staticvoidquadnode_add_data(quadnode_t*node,longnode_key)
{
assert(node);
if(!node->_lst)node->_lst=list_create();
assert(node->_lst);
list_append_node(node->_lst,list_key_create(node_key));
}
/*insertsanodetoparentnodeoftree.returnspointertonode*/
staticquadnode_t*quadtree_insert_node(quadtree_t*tree,
quadnode_t*parent,
longnode_key,
quadbox_t*node_box,
int*depth
)
{
if(quadbox_is_inside(node_box,&(parent->_box)))
{
if(++(*depth)<tree->_depth)
{
if(!quadnode_has_child(parent))
quadnode_create_child(parent,tree->_overlap,(*depth));
if(quadbox_is_inside(node_box,&(parent->_sub[NE]->_box)))
returnquadtree_insert_node(tree,parent->_sub[NE],node_key,node_box,depth);
if(quadbox_is_inside(node_box,&(parent->_sub[NW]->_box)))
returnquadtree_insert_node(tree,parent->_sub[NW],node_key,node_box,depth);
if(quadbox_is_inside(node_box,&(parent->_sub[SW]->_box)))
returnquadtree_insert_node(tree,parent->_sub[SW],node_key,node_box,depth);
if(quadbox_is_inside(node_box,&(parent->_sub[SE]->_box)))
returnquadtree_insert_node(tree,parent->_sub[SE],node_key,node_box,depth);
}
/*insertsintothisnodesinceitcanNOTbeincludedinanysubnodes*/
quadnode_add_data(parent,node_key);
returnparent;
}
returnNULL;
}
/*searchedtreenodes*/
staticvoidquadtree_search_nodes(quadnode_t*current_node,
quadbox_t*search_box,
list_t*results_list
)
{
if(quadbox_is_overlapped(&(current_node->_box),search_box))
{
if(quadnode_has_data(current_node))
list_append_node(results_list,list_node_create(current_node));
if(quadnode_has_child(current_node))
{
quadtree_search_nodes(current_node->_sub[NE],search_box,results_list);
quadtree_search_nodes(current_node->_sub[NW],search_box,results_list);
quadtree_search_nodes(current_node->_sub[SW],search_box,results_list);
quadtree_search_nodes(current_node->_sub[SE],search_box,results_list);
}
}
}
/*=============================================================================
PublicFunctions
=============================================================================*/
quadtree_t*
quadtree_create(quadbox_tbox,
intdepth,/*4~8*/
floatoverlap/*0.02~0.4*/
)
{
quadtree_t*qt=NULL;
assert(depth>=QTREE_DEPTH_MIN-0.0001&&depth<=QTREE_DEPTH_MAX+0.0001);
assert(overlap>=QBOX_OVERLAP_MIN-0.0001&&overlap<=QBOX_OVERLAP_MAX+0.0001);
qt=(quadtree_t*)calloc(1,sizeof(quadtree_t));
if(qt)
{
qt->_depth=depth;
qt->_overlap=overlap;
quadbox_inflate(&box,quadbox_width(&box)*overlap,quadbox_height(&box)*overlap);
qt->_root=quadnode_create(&box);
assert(qt->_root);
if(!qt->_root)
{
free(qt);
qt=NULL;
}
}
assert(qt);
returnqt;
}
/*destroysaquadtree*/
void
quadtree_destroy(INquadtree_t*qtree)
{
assert(qtree&&qtree->_root);
quadnode_destroy(qtree->_root);
free(qtree);
}
/*insertsanodeintoquadtreeandreturnpointertonewnode*/
quadnode_t*
quadtree_insert(INquadtree_t*qtree,
INlongnode_key,
INquadbox_t*node_box
)
{
intdepth=-1;
returnquadtree_insert_node(qtree,qtree->_root,node_key,node_box,&depth);
}
/*searchesnodesinsidesearch_box*/
void
quadtree_search(INconstquadtree_t*qtree,
INquadbox_t*search_box,
OUTlist_t*results_list
)
{
quadtree_search_nodes(qtree->_root,search_box,results_list);
}
其中用到的文件(list.h,list.c,unistd.h)参考我的另一篇文章:
C语言实现一个简单的单向链表list
分享到:
相关推荐
creator 四叉树 Quadtree.ts 用于优化碰撞检测
使用c++实现一棵四叉树,每个叶节点最多只包含一个二维平面的点。四叉树可以进行遍历,删除,添加,查询操作。
这个代码是一个四叉树的C#实现,使用四叉树文成一个可视项目。四叉树是一种树结构可以用于编码和2D碰撞检测。多用在2D碰撞检测中,在大量的碰撞检测中可以提高效率,但结构略复杂。
matlab 图像分析 包括(边缘检测 ;微分算子 ;Log算子 ;Canny 算子 ;四叉树分解 ;四叉树分解 ;四叉树及相应的MATLAB 函数
四叉树这是Quadtree的Java实现,Quadtree是一种树数据结构,可用于存储2D位置数据。用法创建新的四叉树从点(0,0)开始以400 x 400尺寸初始化世界// init.Dimension dimension = new Dimension ( 400 , 400 ); ...
quadtree-js, 另一个用于javascript的四叉树实现 四叉树 js这是本教程中介绍的Java方法的JavaScript四叉树实现: http://gamedev.tutsplus.com/tutorials/implementation/quick-tip-use-quadtrees-to-
这是一个基于JavaScript方法JavaScript Quadtree实现,该实现基于在上描述的Java方法: 许多游戏需要使用碰撞检测算法来确定两个对象何时发生碰撞,但是这些算法通常是昂贵的操作,并且会大大降低游戏的速度。 一种...
四叉树分割图像中的点,左键点击 右键分割
四叉树是用于二维空间对象查找的一个数据结构,本实现包括了三个类:QuadTree,QuadTreeNode, QuadNodeItem。
从 QuadTree 中删除一个对象,并选择使用该对象的先前坐标。 四叉树:removeAllObjects() 从四叉树中删除所有对象 四叉树:更新对象(对象) 更新已在四叉树中的对象,将其从先前位置移动到当前位置。 四叉树:...
QuadTree(VC#2005) 四叉树算法C#实现 GDI+示例
四叉树Python 在Python3中实现四叉树算法。
四叉树是在二维图片中定位像素的唯一适合的算法。因为二维空间(图经常被描述的方式)中,平面像素可以重复的被分为四部分,树的深度由图片、计算机内存和图形的复杂度决定。四叉树可以用来在数据库中放置和定位文件...
一种基本的四叉树类型,用于检索潜在的碰撞 方法 用于插入和检索“对象”的数据类型定义为: object = {} object. left = _ object. top = _ object. width = _ object. height = _ Quadtree.create(left,top,...
Unity下的 四叉树Demo, 参考 https://github.com/CodingTrain/QuadTree
本文实例讲述了JS实现的四叉树算法。分享给大家供大家参考,具体如下: 最近在看canvas动画方面教程,里面提到了采用四叉树检测碰撞。之前也看到过四叉树这个名词,但是一直不是很懂。于是就又找了一些四叉树方面的...
C# 实现的四叉树源码,包括Demo,适用于空间数据管理
利用四叉树与哈夫曼编码,实现分形压缩的快速算法的matlab程序
用opengl实现的四叉树exe 想要代码的可以联系本人。
图像的Matlab用四叉树分解程序 可以自定义detfun函数以确定基于什么规则判断目标block需要继续分解或者不用继续分解 编辑encode函数可以改变分块的编码方式 test_codec函数为源码本身自带的编解码 test_split函数为...