八叉树静态Octree(点云) C++代码

该代码为静态生成八叉树代码,一经创建,不可改变

step1:节点数据结构

//结构体
struct Point {
    double x;
	double y;
	double z;
	void setPoint(double x, double y, double z) {
		this->x = x;
		this->y = y;
		this->z = z;
	}
	Point() {}
	Point(double x, double y, double z) {
		this->x = x;
		this->y = y;
		this->z = z;
	}
};
typedef struct Octree_Node {
	int count;                    //该节点往下所包含点的个数
	std::vector<Point> points;    //用来在叶子节点保存点云
	Octree_Node *nodes[8];        //8个孩子节点
	Octree_Node *parent;          //父节点

	int level;                    //该节点在八叉树中的深度
	Point centel;                 //八叉树格子中心位置
	double length;                //八叉树小格子宽度

	//初始化八叉树节点(父节点,格子宽度,深度)
	void init(Octree_Node *parent, double length, int level) {
		this->parent = parent;
		for (int i = 0; i < 8; i++) {
			nodes[i] = NULL;
		}
		centel.setPoint(0, 0, 0);
		this->level = level;
		this->length = length;
	}

	//释放该节点
	void destory() {
		this->parent = NULL;
		for (int i = 0; i < 8; i++) {
			nodes[i] = NULL;
		}
	}

}Octree_Node, *Octree_Struct;

//类成员
Octree_Struct octree;                    //八叉树root节点
std::vector<Point> pointCloud;
double max_x;                            //八叉树包围盒大小
double max_z;
double max_y;
double octLength;

step2:初始化点云数据

for (int i = 0; i < 1000; i++) {
	Point point;
	point.setPoint(rand() % 1000, rand() % 1000, rand() % 1000);
	pointCloud.push_back(point);
}

step3: 根据点云规模创建相应大小的八叉树

//初始化八叉树(包围盒大小pointCloud)
void CreatOctreeByPointCloud() {

	this->max_x = pointCloud.at(0).x;
	this->max_y = pointCloud.at(0).y;
	this->max_z = pointCloud.at(0).z;

	std::vector<Point>::iterator it = pointCloud.begin();
	for (; it != pointCloud.end(); it++) {
		this->max_x = this->max_x < (*it).x ? (*it).x : this->max_x;
		this->max_y = this->max_y < (*it).y ? (*it).y : this->max_y;
		this->max_z = this->max_z < (*it).z ? (*it).z : this->max_z;
	}

	octree = new Octree_Node();
    //octLength为手动设置叶子节点格子大小,根据点云规模设置,越小八叉树分的越细
	double length = octLength;            
	double maxLength;
	int level = 1;
	maxLength = max_x > max_y ? max_x : max_y;
	maxLength = maxLength > max_z ? maxLength : max_z;
	while (length < maxLength) {    //maxLength为最小能包含所有点的边长
		length *= 2;                //但在八叉树中,每层都是子节点的两倍,
                                    //所以根节点的length要大于maxLength
		level++;
	}

    //根节点octree
    //length:根节点每个格子的宽度,格子为正方体
    //level:将要创建的八叉树的深度的最大值,
    //       比如深度为5的八叉树,根节点的level就是5,叶子节点为1
	octree->init(NULL, length, level);    //初始化根节点(该函数在Step1)

    //生成一个空的八叉树,不包含任何数据
	creat(octree);

    //把数据放到八叉树中,并把不包含数据的地方释放掉
	addPointCloud(pointCloud);
}
//递归生产八叉树空节点
void creat(Octree_Struct octree) {
	if (octree->level == 1) {
		return;
	}
	for (int i = 0; i < 8; i++) {
		octree->nodes[i] = new Octree_Node();
		octree->nodes[i]->init(octree, octree->length / 2, octree->level - 1);


		if (i == 0 || i == 1 || i == 4 || i == 5)
			octree->nodes[i]->centel.y = octree->centel.y + octree->length / 2;
		if (i == 2 || i == 3 || i == 6 || i == 7)
			octree->nodes[i]->centel.y = octree->centel.y - octree->length / 2;
		if (i == 0 || i == 2 || i == 4 || i == 6)
			octree->nodes[i]->centel.x = octree->centel.x + octree->length / 2;
		if (i == 1 || i == 3 || i == 5 || i == 7)
			octree->nodes[i]->centel.x = octree->centel.x - octree->length / 2;
		if (i == 0 || i == 1 || i == 2 || i == 3)
			octree->nodes[i]->centel.z = octree->centel.z + octree->length / 2;
		if (i == 4 || i == 5 || i == 6 || i == 7)
			octree->nodes[i]->centel.z = octree->centel.z - octree->length / 2;

		creat(octree->nodes[i]);
	}
}

把每个点放到它该在的位置(对应叶子节点中)

//添加点云到八叉树中
void addPointCloud(std::vector<Point> pointCloud) {
	std::vector<Point>::iterator it = pointCloud.begin();
	for (; it != pointCloud.end(); it++) {
		octree->count++;
		addNode(octree, *it);
	}
	addNodeEnd(octree);
}
void addNode(Octree_Struct octree, Point point) {
		if (octree->level == 1) {
			octree->points.push_back(point);
			return;
		}
		if (point.x >= octree->centel.x && point.y >= octree->centel.y && point.z >= octree->centel.z) {
			octree->nodes[0]->count++;
			addNode(octree->nodes[0], point);
		}
		else if (point.x < octree->centel.x && point.y >= octree->centel.y && point.z >= octree->centel.z) {
			octree->nodes[1]->count++;
			addNode(octree->nodes[1], point);
		}
		else if (point.x >= octree->centel.x && point.y < octree->centel.y && point.z >= octree->centel.z) {
			octree->nodes[2]->count++;
			addNode(octree->nodes[2], point);
		}
		else if (point.x < octree->centel.x && point.y < octree->centel.y && point.z >= octree->centel.z) {
			octree->nodes[3]->count++;
			addNode(octree->nodes[3], point);
		}
		else if (point.x >= octree->centel.x && point.y >= octree->centel.y && point.z < octree->centel.z) {
			octree->nodes[4]->count++;
			addNode(octree->nodes[4], point);
		}
		else if (point.x < octree->centel.x && point.y >= octree->centel.y && point.z < octree->centel.z) {
			octree->nodes[5]->count++;
			addNode(octree->nodes[5], point);
		}
		else if (point.x >= octree->centel.x && point.y < octree->centel.y && point.z < octree->centel.z) {
			octree->nodes[6]->count++;
			addNode(octree->nodes[6], point);
		}
		else if (point.x < octree->centel.x && point.y < octree->centel.y && point.z < octree->centel.z) {
			octree->nodes[7]->count++;
			addNode(octree->nodes[7], point);
		}
	}

当所有点都添加到八叉树中后,把空节点释放掉

void addNodeEnd(Octree_Struct octree) {
	for (int i = 0; i < 8; i++) {
		if (octree->nodes[i] != NULL) {
			addNodeEnd(octree->nodes[i]);
			if (octree->nodes[i]->count == 0) {
				octree->nodes[i]->parent = NULL;
				delete octree->nodes[i];
				octree->nodes[i] = NULL;
			}
		}
	}
}

至此,八叉树已经创建好了

Step4:销毁八叉树

void destory(Octree_Struct octree) {
	for (int i = 0; i < 8; i++) {
		if (octree->nodes[i] != NULL) {
			destory(octree->nodes[i]);
			octree->nodes[i]->parent = NULL;
			octree->nodes[i]->points.clear();
			delete octree->nodes[i];
		}
	}
	if (octree->parent == NULL) {
		pointCloud.clear();
		delete octree;
	}
}

完整代码:

#pragma once
#include <iostream>
#include <vector>
#include <math.h>

class Octree{
public:

	Octree() {}
	~Octree() { destory(octree); }

	struct Point {
		double x;
		double y;
		double z;
		void setPoint(double x, double y, double z) {
			this->x = x;
			this->y = y;
			this->z = z;
		}
		Point() {}
		Point(double x, double y, double z) {
			this->x = x;
			this->y = y;
			this->z = z;
		}
	};
	typedef struct Octree_Node {
		int count;
		std::vector<Point> points;
		Octree_Node *nodes[8];
		Octree_Node *parent;

		int level;
		Point centel;
		double length;

		void init(Octree_Node *parent, double length, int level) {
			this->parent = parent;
			for (int i = 0; i < 8; i++) {
				nodes[i] = NULL;
			}
			centel.setPoint(0, 0, 0);
			this->level = level;
			this->length = length;
		}

		void destory() {
			this->parent = NULL;
			for (int i = 0; i < 8; i++) {
				nodes[i] = NULL;
			}
		}
	}Octree_Node, *Octree_Struct;

	Octree_Struct octree;
	double octLength;
	std::vector<Point> pointCloud;
	double max_x;
	double max_z;
	double max_y;

	void setPoint(std::vector<Point> points) {
		int size = points.size();
		for (int i = 0; i < size; i++) {
			pointCloud.push_back(points[i]);
		}
	}

	void CreatOctreeByPointCloud() {
		this->max_x = pointCloud.at(0).x;
		this->max_y = pointCloud.at(0).y;
		this->max_z = pointCloud.at(0).z;

		//计算八叉树深度和宽度
		std::vector<Point>::iterator it = pointCloud.begin();
		for (; it != pointCloud.end(); it++) {
			this->max_x = this->max_x < (*it).x ? (*it).x : this->max_x;
			this->max_y = this->max_y < (*it).y ? (*it).y : this->max_y;
			this->max_z = this->max_z < (*it).z ? (*it).z : this->max_z;
		}
		
		double length = octLength;
		double maxLength;
		int level = 1;
		maxLength = max_x > max_y ? max_x : max_y;
		maxLength = maxLength > max_z ? maxLength : max_z;
		while (length < maxLength) {
			length *= 2;
			level++;
		}
		
		//初始化八叉树
		octree = new Octree_Node();
		octree->init(NULL, length, level);
				
		creat(octree);

		addPointCloud(pointCloud);
	}

	void creat(Octree_Struct octree) {
		if (octree->level == 1) {
			return;
		}
		for (int i = 0; i < 8; i++) {
			octree->nodes[i] = new Octree_Node();
			octree->nodes[i]->init(octree, octree->length / 2, octree->level - 1);

			if (i == 0 || i == 1 || i == 4 || i == 5)
				octree->nodes[i]->centel.y = octree->centel.y + octree->length / 2;
			if (i == 2 || i == 3 || i == 6 || i == 7)
				octree->nodes[i]->centel.y = octree->centel.y - octree->length / 2;
			if (i == 0 || i == 2 || i == 4 || i == 6)
				octree->nodes[i]->centel.x = octree->centel.x + octree->length / 2;
			if (i == 1 || i == 3 || i == 5 || i == 7)
				octree->nodes[i]->centel.x = octree->centel.x - octree->length / 2;
			if (i == 0 || i == 1 || i == 2 || i == 3)
				octree->nodes[i]->centel.z = octree->centel.z + octree->length / 2;
			if (i == 4 || i == 5 || i == 6 || i == 7)
				octree->nodes[i]->centel.z = octree->centel.z - octree->length / 2;

			creat(octree->nodes[i]);
		}
	}

	void addPointCloud(std::vector<Point> pointCloud) {
		std::vector<Point>::iterator it = pointCloud.begin();
		for (; it != pointCloud.end(); it++) {
			octree->count++;
			addNode(octree, *it);
		}
		addNodeEnd(octree);
	}

	void addNode(Octree_Struct octree, Point point) {
		if (octree->level == 1) {
			octree->points.push_back(point);
			return;
		}
		if (point.x >= octree->centel.x && point.y >= octree->centel.y && point.z >= octree->centel.z) {
			octree->nodes[0]->count++;
			addNode(octree->nodes[0], point);
		}
		else if (point.x < octree->centel.x && point.y >= octree->centel.y && point.z >= octree->centel.z) {
			octree->nodes[1]->count++;
			addNode(octree->nodes[1], point);
		}
		else if (point.x >= octree->centel.x && point.y < octree->centel.y && point.z >= octree->centel.z) {
			octree->nodes[2]->count++;
			addNode(octree->nodes[2], point);
		}
		else if (point.x < octree->centel.x && point.y < octree->centel.y && point.z >= octree->centel.z) {
			octree->nodes[3]->count++;
			addNode(octree->nodes[3], point);
		}
		else if (point.x >= octree->centel.x && point.y >= octree->centel.y && point.z < octree->centel.z) {
			octree->nodes[4]->count++;
			addNode(octree->nodes[4], point);
		}
		else if (point.x < octree->centel.x && point.y >= octree->centel.y && point.z < octree->centel.z) {
			octree->nodes[5]->count++;
			addNode(octree->nodes[5], point);
		}
		else if (point.x >= octree->centel.x && point.y < octree->centel.y && point.z < octree->centel.z) {
			octree->nodes[6]->count++;
			addNode(octree->nodes[6], point);
		}
		else if (point.x < octree->centel.x && point.y < octree->centel.y && point.z < octree->centel.z) {
			octree->nodes[7]->count++;
			addNode(octree->nodes[7], point);
		}
	}

	void addNodeEnd(Octree_Struct octree) {
		for (int i = 0; i < 8; i++) {
			if (octree->nodes[i] != NULL) {
				addNodeEnd(octree->nodes[i]);
				if (octree->nodes[i]->count == 0) {
					octree->nodes[i]->parent = NULL;
					delete octree->nodes[i];
					octree->nodes[i] = NULL;
				}
			}
		}
	}

	void destory(Octree_Struct octree) {
		for (int i = 0; i < 8; i++) {
			if (octree->nodes[i] != NULL) {
				destory(octree->nodes[i]);
				octree->nodes[i]->parent = NULL;
				octree->nodes[i]->points.clear();
				delete octree->nodes[i];
			}
		}
		if (octree->parent == NULL) {
			pointCloud.clear();
			delete octree;
		}
	}

};

main.cpp

#include "Octree3.h"

int main(int argc, char *argv[])
{
	int size = 10;
	std::vector<Octree::Point> pointCloud;
	for (int i = 0; i < size; i++) {
		pointCloud.push_back(Octree::Point(rand() % 1000 - 500, rand() % 1000 - 500, rand() % 1000 - 500));
	}

	Octree oct;
	oct.octLength = 10;
	oct.setPoint(pointCloud);
	oct.CreatOctreeByPointCloud();
}

八叉树可视化

 

  • 5
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值