Octree新 20210422

#pragma once
#include <vector>
#include <iostream>
#include <fstream>
#include <string>

#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/visualization/cloud_viewer.h>

#include <GL/GLU.h>


class Octree {
public:
	Octree() {}
	~Octree() { std::cout << "delete"; destory(root); }
	struct Point
	{
		float x, y, z;
		float r, g, b;
		void setPoint(float x, float y, float z) {
			this->x = x;
			this->y = y;
			this->z = z;
		}
		Point() {}
		Point(float x, float y, float z,float r=1,float g=1,float b=1) {
			this->x = x;
			this->y = y;
			this->z = z;
			this->r = r;
			this->g = g;
			this->b = b;
		}
		Point& operator = (const Point &b) {
			this->x = b.x;
			this->y = b.y;
			this->z = b.z;
			return *this;
		}
	};
	typedef struct Octree_Node {
		int count;
		int newCount;
		std::vector<Point> points;
		std::vector<Point> newPoints;
		Octree_Node *nodes[8];
		Point centel;
		float length;
		int level;

	}Octree_Node, *Octree_Struct;

	Octree_Struct root;
	std::vector<Point> pointCloud;
	std::vector<Point> resPointCloud;
	float octLength;
	bool oldPoint = true;

	bool created = false;

	Octree& operator+(const Octree &b) {
		Octree *newOctree = new Octree();
		newOctree->root = NULL;
		resPointCloud.clear();
		newOctree->octLength = this->octLength;
		for (auto it = this->pointCloud.begin(); it != this->pointCloud.end(); it++) {
			newOctree->insertPoint(newOctree->root, (*it));
			resPointCloud.push_back((*it));
		}
		newOctree->oldPoint = false;
		for (auto it = b.pointCloud.begin(); it != b.pointCloud.end(); it++) {
			newOctree->insertPoint(newOctree->root, (*it));
			resPointCloud.push_back((*it));
		}
		return *newOctree;
	}


	Octree& operator-(const Octree &b) {
		Octree *newOctree = new Octree();
		newOctree->root = NULL;
		resPointCloud.clear();
		newOctree->octLength = this->octLength;
		for (auto it = this->pointCloud.begin(); it != this->pointCloud.end(); it++) {
			newOctree->insertPoint(newOctree->root, (*it));
		}
		newOctree->oldPoint = false;
		for (auto it = b.pointCloud.begin(); it != b.pointCloud.end(); it++) {
			newOctree->insertPoint(newOctree->root, (*it));
		}
		getSubResault(*newOctree, newOctree->root);
		return *newOctree;
	}

	int subLimt = 20;
	void getSubResault(Octree &root, Octree::Octree_Struct node) {
		if (node->level > 1) {
			for (int i = 0; i < 8; i++) {
				if (node->nodes[i] != NULL) {
					getSubResault(root, node->nodes[i]);
				}
			}
		}
		else {
			if (node->newCount + subLimt <= node->count)
			{
				int size = node->points.size();
				for (int i = 0; i < size; i++) {
					root.resPointCloud.push_back(node->points.at(i));
				}
			}
		}
	}

	void insertPoint(Octree_Struct &root, Point point) {
		//第一个点
		if (root == NULL) {
			root = new Octree_Node();
			root->centel = point;
			root->length = octLength;
			root->level = 1;
			root->newCount = 0;
			root->count = 0;


			for (int i = 0; i < 8; i++) {
				root->nodes[i] = NULL;
			}
			if (oldPoint == true) {
				root->count = 1;
				root->points.push_back(point);
			}
			else {
				root->newCount = 1;
				root->newPoints.push_back(point);
			}

			pointCloud.push_back(point);
			return;
		}

		//如果point在root范围内
		bool inRoot = false;
		if (point.x <= root->centel.x + root->length && point.x > root->centel.x - root->length) {
			if (point.y <= root->centel.y + root->length && point.y > root->centel.y - root->length) {
				if (point.z <= root->centel.z + root->length && point.z > root->centel.z - root->length) {
					inRoot = true;
				}
			}
		}

		//在里面
		if (inRoot == true) {
			//最下面那层
			if (root->level == 1) {

				if (oldPoint == true) {
					root->count++;
					root->points.push_back(point);
				}
				else {
					root->newCount++;
					root->newPoints.push_back(point);
				}
				pointCloud.push_back(point);
			}
			//中间层
			else {
				int i = 0;
				Point centel;
				//不用=
				if (point.x > root->centel.x && point.y > root->centel.y &&point.z > root->centel.z) {
					i = 0;
					centel.x = root->centel.x + root->length / 2;
					centel.y = root->centel.y + root->length / 2;
					centel.z = root->centel.z + root->length / 2;
				}
				else if (point.x <= root->centel.x && point.y > root->centel.y &&point.z > root->centel.z) {
					i = 1;
					centel.x = root->centel.x - root->length / 2;
					centel.y = root->centel.y + root->length / 2;
					centel.z = root->centel.z + root->length / 2;
				}
				else if (point.x > root->centel.x && point.y <= root->centel.y &&point.z > root->centel.z) {
					i = 2;
					centel.x = root->centel.x + root->length / 2;
					centel.y = root->centel.y - root->length / 2;
					centel.z = root->centel.z + root->length / 2;
				}
				else if (point.x <= root->centel.x && point.y <= root->centel.y &&point.z > root->centel.z) {
					i = 3;
					centel.x = root->centel.x - root->length / 2;
					centel.y = root->centel.y - root->length / 2;
					centel.z = root->centel.z + root->length / 2;
				}
				else if (point.x > root->centel.x && point.y > root->centel.y &&point.z <= root->centel.z) {
					i = 4;
					centel.x = root->centel.x + root->length / 2;
					centel.y = root->centel.y + root->length / 2;
					centel.z = root->centel.z - root->length / 2;
				}
				else if (point.x <= root->centel.x && point.y > root->centel.y &&point.z <= root->centel.z) {
					i = 5;
					centel.x = root->centel.x - root->length / 2;
					centel.y = root->centel.y + root->length / 2;
					centel.z = root->centel.z - root->length / 2;
				}
				else if (point.x > root->centel.x && point.y <= root->centel.y &&point.z <= root->centel.z) {
					i = 6;
					centel.x = root->centel.x + root->length / 2;
					centel.y = root->centel.y - root->length / 2;
					centel.z = root->centel.z - root->length / 2;
				}
				else if (point.x <= root->centel.x && point.y <= root->centel.y &&point.z <= root->centel.z) {
					i = 7;
					centel.x = root->centel.x - root->length / 2;
					centel.y = root->centel.y - root->length / 2;
					centel.z = root->centel.z - root->length / 2;
				}

				if (root->nodes[i] == NULL) {
					root->nodes[i] = new Octree_Node();
					for (int j = 0; j < 8; j++) {
						root->nodes[i]->nodes[j] = NULL;
					}
					root->nodes[i]->centel = centel;
					root->nodes[i]->length = root->length / 2;
					root->nodes[i]->level = root->level - 1;
					root->nodes[i]->count = 0;
					root->nodes[i]->newCount = 0;
				}

				if (oldPoint == true) {
					root->count++;
				}
				else {
					root->newCount++;
				}

				insertPoint(root->nodes[i], point);

			}
		}
		else if (inRoot == false) {
			//      newRoot
			//     /               \
			//  root            insert
			Octree_Struct newRoot = new Octree_Node();
			for (int i = 0; i < 8; i++) {
				newRoot->nodes[i] = NULL;
			}
			newRoot->level = root->level + 1;
			newRoot->count = root->count;
			newRoot->newCount = root->newCount;

			Point centel;
			if (point.x > root->centel.x && point.y > root->centel.y &&point.z > root->centel.z) {
				centel = Point(root->centel.x + root->length, root->centel.y + root->length, root->centel.z + root->length);
			}
			else if (point.x < root->centel.x && point.y > root->centel.y &&point.z > root->centel.z) {
				centel = Point(root->centel.x - root->length, root->centel.y + root->length, root->centel.z + root->length);
			}
			else if (point.x > root->centel.x && point.y < root->centel.y &&point.z > root->centel.z) {
				centel = Point(root->centel.x + root->length, root->centel.y - root->length, root->centel.z + root->length);
			}
			else if (point.x < root->centel.x && point.y < root->centel.y &&point.z > root->centel.z) {
				centel = Point(root->centel.x - root->length, root->centel.y - root->length, root->centel.z + root->length);
			}
			else if (point.x > root->centel.x && point.y > root->centel.y &&point.z < root->centel.z) {
				centel = Point(root->centel.x + root->length, root->centel.y + root->length, root->centel.z - root->length);
			}
			else if (point.x < root->centel.x && point.y > root->centel.y &&point.z < root->centel.z) {
				centel = Point(root->centel.x - root->length, root->centel.y + root->length, root->centel.z - root->length);
			}
			else if (point.x > root->centel.x && point.y < root->centel.y &&point.z < root->centel.z) {
				centel = Point(root->centel.x + root->length, root->centel.y - root->length, root->centel.z - root->length);
			}
			else if (point.x < root->centel.x && point.y < root->centel.y &&point.z < root->centel.z) {
				centel = Point(root->centel.x - root->length, root->centel.y - root->length, root->centel.z - root->length);
			}

			newRoot->centel = centel;

			float length = root->length*2;

			newRoot->length = length;

			int i = 0;
			if (root->centel.x > newRoot->centel.x && root->centel.y > newRoot->centel.y &&root->centel.z > newRoot->centel.z) {
				i = 0;
			}
			else if (root->centel.x < newRoot->centel.x && root->centel.y > newRoot->centel.y &&root->centel.z > newRoot->centel.z) {
				i = 1;
			}
			else if (root->centel.x > newRoot->centel.x && root->centel.y < newRoot->centel.y &&root->centel.z > newRoot->centel.z) {
				i = 2;
			}
			else if (root->centel.x < newRoot->centel.x && root->centel.y < newRoot->centel.y &&root->centel.z > newRoot->centel.z) {
				i = 3;
			}
			else if (root->centel.x > newRoot->centel.x && root->centel.y > newRoot->centel.y &&root->centel.z < newRoot->centel.z) {
				i = 4;
			}
			else if (root->centel.x < newRoot->centel.x && root->centel.y > newRoot->centel.y &&root->centel.z < newRoot->centel.z) {
				i = 5;
			}
			else if (root->centel.x > newRoot->centel.x && root->centel.y < newRoot->centel.y &&root->centel.z < newRoot->centel.z) {
				i = 6;
			}
			else if (root->centel.x < newRoot->centel.x && root->centel.y < newRoot->centel.y &&root->centel.z < newRoot->centel.z) {
				i = 7;
			}
			newRoot->nodes[i] = root;
			root = newRoot;
			insertPoint(newRoot, point);
		}
	}

	void destory() {
		std::cout << "deleted";
		destory(root);
	}
	void destory(Octree_Struct &root) {
		if (created != true)return;
		if (root != NULL)
			for (int i = 0; i < 8; i++) {
				if (root->nodes[i] != NULL) {
					destory(root->nodes[i]);

				}
			}
		if (root != NULL)
			delete root;
	}

	

public://后添加
	struct drawOptions {
		enum showType { POINT };
		showType showOption;
		float pointSize;
		int drawPointCount;

		int newPointMoreSize;
		drawOptions(showType _showOption, float _pointSize, int _drawPointCount, int _newPointMoreSize) {
			showOption = _showOption;
			pointSize = _pointSize;
			drawPointCount = _drawPointCount;
			newPointMoreSize = _newPointMoreSize;
		}
	};
	void loadFile(const std::string str) {
		int x, y, z, color;
		FILE *fp;
		fp = fopen(str.c_str(), "r");
		if (!fp) {
			std::cout << "0.can't open " << std::endl;
			return;
		}
		while (feof(fp) == 0) {
			fscanf(fp, "%d %d %d %d", &x, &y, &z, &color);
			insertPoint(root, Octree::Point((float)x, (float)y, (float)z));
		}
		fclose(fp);
	}
	void loadPoints(pcl::PointCloud<pcl::PointXYZRGB>::Ptr src) {
		int size = src->size();
		for (int i = 0; i < size; i++) {
			Point point;
			point.x = src->at(i).x;
			point.y = src->at(i).y;
			point.z = src->at(i).z;
			point.r = src->at(i).r; 
			point.g = src->at(i).g;
			point.b = src->at(i).b;
			insertPoint(root,point);
		}
	}

	void getPointsFromOctree(pcl::PointCloud<pcl::PointXYZRGB>::Ptr &src, drawOptions drawOption) {
		getPointsFromOctree(root, src, drawOption);
	}
	void getPointsFromOctree(Octree_Struct root, pcl::PointCloud<pcl::PointXYZRGB>::Ptr &src, drawOptions drawOption) {
		if (root == NULL)return;

		if (root->level == 1){
			if(root->newCount<root->count)
			if(root->newCount<drawOption.newPointMoreSize)
			{
				pcl::PointXYZRGB point;
				if (root->count > 0)
				for (auto it = root->points.begin(); it != root->points.end(); it++) {
					point.x = (*it).x;
					point.y = (*it).y;
					point.z = (*it).z;
					point.r = (*it).r;
					point.g = (*it).g;
					point.b = (*it).b;
					src->push_back(point);
				}
				cout << root->points.size() << endl;
			}
		}

		for (int i = 0; i < 8; i++) {
			getPointsFromOctree(root->nodes[i],src, drawOption);
		}
	}

	
	void gglDrawOctree(drawOptions drawOption) {
		gglDrawOctree(root, drawOption);
	}
	void gglDrawOctree(Octree_Struct root, drawOptions drawOption) {
		if (root == NULL)return;

		if(root->level==1)
		if (root->points.size() >= drawOption.drawPointCount) 
		{
			std::cout << root->points.size() << std::endl;
			if (drawOption.showOption == drawOptions::POINT) {
				glPointSize(drawOption.pointSize);
				glBegin(GL_POINTS);

				for (auto it = root->points.begin(); it != root->points.end(); it++) {
					glColor3f((*it).r, (*it).g, (*it).b);
					glVertex3f((*it).x, (*it).y, (*it).z);
				}
				glEnd();
			}
		}

		for (int i = 0; i < 8; i++) {
			gglDrawOctree(root->nodes[i], drawOption);
		}
	}
};
oct.octLength  = 75;
oct.root       = NULL;
oct2.octLength = 75;
oct2.root      = NULL;

openFileSlot(src,"C:\\Users\\90182si\\Desktop\\dianyun2021\\zhangaiwu3.pcd");
openFileSlot(src2,"C:\\Users\\90182si\\Desktop\\dianyun2021\\bei-jing.pcd");
oct.oldPoint = true;
oct.loadPoints(src);
oct.oldPoint = false;
oct.loadPoints(src2);

oct.getPointsFromOctree(octPoint,Octree::drawOptions(Octree::drawOptions::POINT,3.0f,0,10));

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值