1 #ifndef _SPICA_KDTREE_DETAIL_H_
2 #define _SPICA_KDTREE_DETAIL_H_
7 #include "core/common.h"
8 #include "core/vector3d.h"
20 KdTree<Ty>::KdTree(
const KdTree& kdtree)
24 this->operator=(kdtree);
34 KdTree<Ty>& KdTree<Ty>::operator=(
const KdTree& kdtree) {
36 _numCopies = kdtree._numCopies;
38 _nodes = kdtree._nodes;
42 void KdTree<Ty>::release() {
43 if (_numCopies !=
nullptr) {
44 if (*_numCopies == 0) {
55 void KdTree<Ty>::add(
const Ty& point) {
56 _nodes = addRec(_nodes, point, 0);
60 typename KdTree<Ty>::KdTreeNode* KdTree<Ty>::addRec(KdTreeNode* node,
const Ty& point,
int dim) {
61 if (node ==
nullptr) {
62 KdTreeNode* ret =
new KdTreeNode;
67 if (point[dim] < node->point[dim]) {
68 node->left = addRec(node->left, point, (dim + 1) % 3);
70 node->right = addRec(node->right, point, (dim + 1) % 3);
77 void KdTree<Ty>::construct(
const std::vector<Ty>& points) {
79 const int numPoints =
static_cast<int>(points.size());
81 for (numNodes = 1; numNodes < numPoints; numNodes <<= 1) ;
83 _nodes =
new KdTreeNode[numNodes];
85 std::vector<const Ty*> pointers(numPoints);
86 for (
int i = 0; i < numPoints; i++) {
87 pointers[i] = &points[i];
89 constructRec(pointers, 0, 0, numPoints, 0);
90 _numCopies =
new int(0);
94 typename KdTree<Ty>::KdTreeNode* KdTree<Ty>::constructRec(std::vector<const Ty*>& points,
const int nodeID,
const int startID,
const int endID,
const int dim) {
95 if (startID >= endID) {
99 std::sort(points.begin() + startID, points.begin() + endID, AxisComparator(dim));
101 int mid = (startID + endID) / 2;
102 KdTreeNode* node = &_nodes[nodeID];
104 node->point = (*points[mid]);
105 node->left = constructRec(points, nodeID * 2 + 1, startID, mid, (dim + 1) % 3);
106 node->right = constructRec(points, nodeID * 2 + 2, mid + 1, endID, (dim + 1) % 3);
111 void KdTree<Ty>::knnSearch(
const Ty& point,
const KnnQuery& query, std::vector<Ty>* results)
const {
114 if ((qq.type & EPSILON_BALL) == 0) qq.epsilon = INFTY;
116 knnSearchRec(&_nodes[0], point, qq, &que);
118 while (!que.empty()) {
119 results->push_back(que.top().t);
125 void KdTree<Ty>::knnSearchRec(
typename KdTree<Ty>::KdTreeNode* node,
const Ty& point, KnnQuery& query, PriorityQueue* results)
const {
130 const double dist = distance(node->point, point);
131 if (dist < query.epsilon) {
132 results->push(OrderedType(dist, node->point));
133 if ((query.type & K_NEAREST) != 0 && results->size() > query.k) {
136 query.epsilon = distance(results->top().t, point);
140 int axis = node->axis;
141 double delta = point[axis] - node->point[axis];
143 knnSearchRec(node->left, point, query, results);
144 if (std::abs(delta) <= query.epsilon) {
145 knnSearchRec(node->right, point, query, results);
148 knnSearchRec(node->right, point, query, results);
149 if (std::abs(delta) <= query.epsilon) {
150 knnSearchRec(node->left, point, query, results);
156 double KdTree<Ty>::distance(
const Ty& p1,
const Ty& p2) {
157 return Ty::distance(p1, p2);
161 inline double KdTree<Vector3d>::distance(
const Vector3d& p1,
const Vector3d& p2) {
162 return (p1 - p2).norm();
167 #endif // _SPICA_KDTREE_DETAIL_H_