C++实现八叉树
#include
#include
#define MAX_DEEP 5
#define BOX_SIDE 100
namespace KS
{
struct Point
{
double x;
double y;
double z;
Point(double x_, double y_, double z_):x(x_), y(y_), z(z_) {}
bool operator==(Point& point)
{
return point.x == x && point.y == y && point.z == z;
}
};
struct Node
{
double x, y, z;
double sideLength;
std::vector<Point> points;
struct Node* childs[8];
Node(double x_, double y_, double z_, double sideLength_):x(x_),y(y_),z(z_),sideLength(sideLength_) {}
};
class Octree
{
private:
struct Node* head = nullptr;
Node* init(int x, int y, int z, int side, int deep)
{
if (deep > MAX_DEEP)
{
return nullptr;
}
Node* root = new Node(x, y, z, side);
root->childs[0] = init(x - side / 4, y - side / 4, z + side / 4, side / 2, deep + 1);
root->childs[1] = init(x - side / 4, y + side / 4, z + side / 4, side / 2, deep + 1);
root->childs[2] = init(x + side / 4, y - side / 4, z + side / 4, side / 2, deep + 1);
root->childs[3] = init(x + side / 4, y + side / 4, z + side / 4, side / 2, deep + 1);
root->childs[4] = init(x - side / 4, y + side / 4, z - side / 4, side / 2, deep + 1);
root->childs[5] = init(x - side / 4, y - side / 4, z - side / 4, side / 2, deep + 1);
root->childs[6] = init(x + side / 4, y + side / 4, z - side / 4, side / 2, deep + 1);
root->childs[7] = init(x + side / 4, y - side / 4, z - side / 4, side / 2, deep + 1);
return root;
}
void uninit(Node* root, int deep)
{
if (deep > MAX_DEEP)
{
return;
}
for (int i = 0; i < 8; ++i)
{
uninit(root->childs[i], deep+1);
}
delete root;
}
void deepFind(Node* root, Point target, int deep, Node*& value)
{
if (root == nullptr)
{
return;
}
double side = root->sideLength;
double rootX = root->x;
double rootY = root->y;
double rootZ = root->z;
if (((rootX - side / 2 <= target.x && rootX + side / 2 >= target.x) ||
(rootY - side / 2 <= target.y && rootY + side / 2 >= target.y) ||
(rootZ - side / 2 <= target.z && rootZ + side / 2 >= target.z)) == false)
{
return;
}
if (deep == MAX_DEEP)
{
for (auto &&point : root->points)
{
if (point == target)
{
value = root;
return;
}
}
return;
}
for (int i = 0; i < 8; ++i)
{
deepFind(root->childs[i], target, deep + 1, value);
}
}
bool deepInsert(Node* root, Point target, int deep)
{
if (root == nullptr)
{
return false;
}
double side = root->sideLength;
double rootX = root->x;
double rootY = root->y;
double rootZ = root->z;
if (((rootX - side / 2 <= target.x&& rootX + side / 2 >= target.x) &&
(rootY - side / 2 <= target.y&& rootY + side / 2 >= target.y) &&
(rootZ - side / 2 <= target.z&& rootZ + side / 2 >= target.z)) == false)
{
return false;
}
if (deep == MAX_DEEP)
{
root->points.push_back(target);
return true;
}
bool value = false;
for (int i = 0; i < 8; ++i)
{
value = value || deepInsert(root->childs[i], target, deep + 1);
}
return value;
}
public:
Octree()
{
this->head = init(0, 0, 0, BOX_SIDE, 1);
return;
}
bool find(Point target)
{
Node* value = nullptr;
deepFind(this->head, target, 1, value);
if (value == nullptr)
{
return false;
}
else
{
return true;
}
}
bool insert(Point target)
{
return deepInsert(this->head, target, 1);
}
~Octree()
{
this->uninit(this->head, 1);
}
};
}