(九)OcTree教程一--OcTree原理介绍

OcTree原理介绍

八叉树是一种用于描述三维空间的树状数据结构。八叉树的每个节点表示一个正方体的体积元素,每个节点有八个子节点,将八个子节点所表示的体积元素加在一起就等于父节点的体积。八叉树是四叉树在三维空间上的扩展,二维上我们有四个象限,而三维上,我们有8个卦限。八叉树主要用于空间划分和最近邻搜索。

八叉树建立过程

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

八叉树和k-d树比较

八叉树算法的算法实现简单,但大数据量点云数据下,其使用比较困难的是最小粒度(叶节点)的确定,粒度较大时,有的节点数据量可能仍比较大,后续查询效率仍比较低,反之,粒度较小,八叉树的深度增加,需要的内存空间也比较大(每个非叶子节点需要八个指针),效率也降低。而等分的划分依据,使得在数据重心有偏斜的情况下,受划分深度限制,其效率不是太高。

k-d在邻域查找上比较有优势,但在大数据量的情况下,若划分粒度较小时,建树的开销也较大,但比八叉树灵活些。在小数据量的情况下,其搜索效率比较高,但在数据量增大的情况下,其效率会有一定的下降,一般是线性上升的规律。

也有将八叉树和k-d树结合起来的应用,应用八叉树进行大粒度的划分和查找,而后使用k-d树进行细分,效率会有一定的提升,但其搜索效率变化也与数据量的变化有一个线性关系。

叉树Octree是一种用于空间分割的数据结构,常用于计算机图形学、物理模拟等领域。其原理是将空间递归地分割成八个子空间,每个子空间又可以继续递归地分割成八个子空间,直到最小空间达到一定的大小。 C++中可以通过定义节点类和递归函数来实现叉树Octree。以下是一个简单的实现: ```c++ #include <iostream> #include <vector> #include <cmath> using namespace std; class Node { public: double x, y, z; // 三维坐标 double size; // 此节点所代表的空间大小 vector<Node*> children; // 子节点指针数组 Node(double x_, double y_, double z_, double size_) { x = x_; y = y_; z = z_; size = size_; children.resize(8, nullptr); } }; void insert(Node* node, double x, double y, double z, double size) { if (size <= node->size) { // 如果此节点的大小大于等于当前空间大小,则将此空间添加到此节点的子节点中 if (node->children[0] == nullptr) { // 如果当前节点还没有子节点,则创建 node->children[0] = new Node(node->x - node->size / 4, node->y - node->size / 4, node->z - node->size / 4, node->size / 2); node->children[1] = new Node(node->x + node->size / 4, node->y - node->size / 4, node->z - node->size / 4, node->size / 2); node->children[2] = new Node(node->x - node->size / 4, node->y + node->size / 4, node->z - node->size / 4, node->size / 2); node->children[3] = new Node(node->x + node->size / 4, node->y + node->size / 4, node->z - node->size / 4, node->size / 2); node->children[4] = new Node(node->x - node->size / 4, node->y - node->size / 4, node->z + node->size / 4, node->size / 2); node->children[5] = new Node(node->x + node->size / 4, node->y - node->size / 4, node->z + node->size / 4, node->size / 2); node->children[6] = new Node(node->x - node->size / 4, node->y + node->size / 4, node->z + node->size / 4, node->size / 2); node->children[7] = new Node(node->x + node->size / 4, node->y + node->size / 4, node->z + node->size / 4, node->size / 2); } for (int i = 0; i < 8; i++) { // 递归插入 insert(node->children[i], x, y, z, size / 2); } } } int main() { Node* root = new Node(0, 0, 0, 1); // 创建根节点 insert(root, 0.5, 0.5, 0.5, 0.1); // 插入一个大小为0.1的空间,其坐标为(0.5,0.5,0.5) return 0; } ``` 在这个简单的实现中,我们定义了一个节点类Node,包含了三维坐标和空间大小等属性,同时还有一个指向子节点的数组。我们通过递归函数insert来递归地插入新的空间,如果当前节点的大小大于等于要插入的空间大小,则将此空间插入到当前节点的子节点中,否则递归进入子节点。在main函数中,我们创建了一个根节点,并插入了一个大小为0.1的空间。 需要注意的是,此实现仅是一个简单的示例,实际应用中可能需要更复杂的节点类和插入函数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值