63 for (T i = 0; i < 64; ++i)
76 template<
typename T,
typename CloudType>
81 for (
int i = 0; i < v.size(); ++i)
93 template<
typename T,
typename Heap,
typename CloudType>
96 T minVal(std::numeric_limits<T>::max());
97 T maxVal(std::numeric_limits<T>::lowest());
101 const T val(cloud.coeff(dim, *it));
102 minVal = min(val, minVal);
103 maxVal = max(val, maxVal);
106 return make_pair(minVal, maxVal);
109 template<
typename T,
typename Heap,
typename CloudType>
112 const int count(last - first);
114 const unsigned pos(nodes.size());
117 if (count <=
int(bucketSize))
119 const uint32_t initBucketsSize(buckets.size());
121 for (
int i = 0; i < count; ++i)
123 const Index index(*(first+i));
124 assert(index < cloud.cols());
125 buckets.push_back(
BucketEntry(&cloud.coeff(0, index), index));
129 nodes.push_back(
Node(createDimChildBucketSize(dim, count),initBucketsSize));
134 const unsigned cutDim = argMax<T, CloudType>(maxValues - minValues);
135 const T idealCutVal((maxValues(cutDim) + minValues(cutDim))/2);
138 const pair<T,T> minMaxVals(getBounds(first, last, cutDim));
142 if (idealCutVal < minMaxVals.first)
143 cutVal = minMaxVals.first;
144 else if (idealCutVal > minMaxVals.second)
145 cutVal = minMaxVals.second;
147 cutVal = idealCutVal;
154 while (l < count && cloud.coeff(cutDim, *(first+l)) < cutVal)
156 while (r >= 0 && cloud.coeff(cutDim, *(first+r)) >= cutVal)
160 swap(*(first+l), *(first+r));
168 while (l < count && cloud.coeff(cutDim, *(first+l)) <= cutVal)
170 while (r >= br1 && cloud.coeff(cutDim, *(first+r)) > cutVal)
174 swap(*(first+l), *(first+r));
181 if (idealCutVal < minMaxVals.first)
183 else if (idealCutVal > minMaxVals.second)
185 else if (br1 > count / 2)
187 else if (br2 < count / 2)
190 leftCount = count / 2;
191 assert(leftCount > 0);
205 assert(leftCount < count);
208 Vector leftMaxValues(maxValues);
209 leftMaxValues[cutDim] = cutVal;
211 Vector rightMinValues(minValues);
212 rightMinValues[cutDim] = cutVal;
215 nodes.push_back(
Node(0, cutVal));
218 const unsigned _UNUSED leftChild = buildNodes(first, first + leftCount, minValues, leftMaxValues);
219 assert(leftChild == pos + 1);
220 const unsigned rightChild = buildNodes(first + leftCount, last, rightMinValues, maxValues);
223 nodes[pos].dimChildBucketSize = createDimChildBucketSize(cutDim, rightChild);
227 template<
typename T,
typename Heap,
typename CloudType>
230 bucketSize(additionalParameters.get<unsigned>(
"bucketSize", 8)),
232 dimMask((1<<dimBitCount)-1)
239 for (
int i = 0; i <
cloud.cols(); ++i)
245 const uint64_t maxNodeCount((0x1ULL << (32-
dimBitCount)) - 1);
247 if (estimatedNodeCount > maxNodeCount)
249 throw runtime_error(
"Cloud has a risk to have more nodes (" + std::to_string(estimatedNodeCount) +
") than the kd-tree allows (" + std::to_string(maxNodeCount) +
"). "
250 "The kd-tree has " + std::to_string(
dimBitCount) +
" bits for dimensions and " + std::to_string((32-
dimBitCount)) +
" bits for node indices");
255 buildPoints.reserve(
cloud.cols());
256 for (
int i = 0; i <
cloud.cols(); ++i)
259 buildPoints.push_back(i);
274 template<
typename T,
typename Heap,
typename CloudType>
277 checkSizesKnn(query, indices, dists2, k, optionFlags);
282 const T maxRadius2(maxRadius * maxRadius);
283 const T maxError2((1+epsilon)*(1+epsilon));
284 const int colCount(query.cols());
286 assert(nodes.size() > 0);
289 unsigned long leafTouchedCount(0);
295 std::vector<T> off(dim, 0);
297 #pragma omp for reduction(+:leafTouchedCount) schedule(guided,32)
298 for (
int i = 0; i < colCount; ++i)
300 leafTouchedCount += onePointKnn(query, indices, dists2, i, heap, off, maxError2, maxRadius2, allowSelfMatch, collectStatistics, sortResults);
303 return leafTouchedCount;
306 template<
typename T,
typename Heap,
typename CloudType>
309 checkSizesKnn(query, indices, dists2, k, optionFlags, &maxRadii);
314 const T maxError2((1+epsilon)*(1+epsilon));
315 const int colCount(query.cols());
317 assert(nodes.size() > 0);
319 unsigned long leafTouchedCount(0);
325 std::vector<T> off(dim, 0);
327 #pragma omp for reduction(+:leafTouchedCount) schedule(guided,32)
328 for (
int i = 0; i < colCount; ++i)
330 const T maxRadius(maxRadii[i]);
331 const T maxRadius2(maxRadius * maxRadius);
332 leafTouchedCount += onePointKnn(query, indices, dists2, i, heap, off, maxError2, maxRadius2, allowSelfMatch, collectStatistics, sortResults);
335 return leafTouchedCount;
338 template<
typename T,
typename Heap,
typename CloudType>
339 unsigned long KDTreeUnbalancedPtInLeavesImplicitBoundsStackOpt<T, Heap, CloudType>::onePointKnn(
const Matrix& query,
IndexMatrix& indices,
Matrix& dists2,
int i, Heap& heap, std::vector<T>& off,
const T maxError2,
const T maxRadius2,
const bool allowSelfMatch,
const bool collectStatistics,
const bool sortResults)
const
341 fill(off.begin(), off.end(),
static_cast<T
>(0));
343 unsigned long leafTouchedCount(0);
347 if (collectStatistics)
348 leafTouchedCount += recurseKnn<true, true>(&query.coeff(0, i), 0, 0, heap, off, maxError2, maxRadius2);
350 recurseKnn<true, false>(&query.coeff(0, i), 0, 0, heap, off, maxError2, maxRadius2);
354 if (collectStatistics)
355 leafTouchedCount += recurseKnn<false, true>(&query.coeff(0, i), 0, 0, heap, off, maxError2, maxRadius2);
357 recurseKnn<false, false>(&query.coeff(0, i), 0, 0, heap, off, maxError2, maxRadius2);
363 heap.getData(indices.col(i), dists2.col(i));
364 return leafTouchedCount;
367 template<
typename T,
typename Heap,
typename CloudType>
template<
bool allowSelfMatch,
bool collectStatistics>
370 const Node& node(nodes[n]);
373 if (cd == uint32_t(dim))
378 for (uint32_t i = 0; i < bucketSize; ++i)
384 const T* qPtr(query);
385 const T* dPtr(bucket->
pt);
386 for (
int i = 0; i < this->dim; ++i)
388 const T diff(*qPtr - *dPtr);
392 if ((dist <= maxRadius2) &&
393 (dist < heap.headValue()) &&
394 (allowSelfMatch || (dist > numeric_limits<T>::epsilon()))
396 heap.replaceHead(bucket->
index, dist);
399 return (
unsigned long)(bucketSize);
404 unsigned long leafVisitedCount(0);
407 const T old_off(offcd);
408 const T new_off(query[cd] - node.
cutVal);
411 if (collectStatistics)
412 leafVisitedCount += recurseKnn<allowSelfMatch, true>(query, rightChild, rd, heap, off, maxError2, maxRadius2);
414 recurseKnn<allowSelfMatch, false>(query, rightChild, rd, heap, off, maxError2, maxRadius2);
415 rd += - old_off*old_off + new_off*new_off;
416 if ((rd <= maxRadius2) &&
417 (rd * maxError2 < heap.headValue()))
420 if (collectStatistics)
421 leafVisitedCount += recurseKnn<allowSelfMatch, true>(query, n + 1, rd, heap, off, maxError2, maxRadius2);
423 recurseKnn<allowSelfMatch, false>(query, n + 1, rd, heap, off, maxError2, maxRadius2);
429 if (collectStatistics)
430 leafVisitedCount += recurseKnn<allowSelfMatch, true>(query, n+1, rd, heap, off, maxError2, maxRadius2);
432 recurseKnn<allowSelfMatch, false>(query, n+1, rd, heap, off, maxError2, maxRadius2);
433 rd += - old_off*old_off + new_off*new_off;
434 if ((rd <= maxRadius2) &&
435 (rd * maxError2 < heap.headValue()))
438 if (collectStatistics)
439 leafVisitedCount += recurseKnn<allowSelfMatch, true>(query, rightChild, rd, heap, off, maxError2, maxRadius2);
441 recurseKnn<allowSelfMatch, false>(query, rightChild, rd, heap, off, maxError2, maxRadius2);
445 return leafVisitedCount;