157 const int &dimension,
158 const std::vector<std::vector<dataType>> &weights,
159 const int &weightNumber,
160 const int &nodeNumber,
161 const bool &preciseBoundingBox) {
163 int createdNumberNode = 1;
164 int idGenerator = createdNumberNode - 1;
165 int maximumLevel = 0;
167 int correspondence_map_size = 0;
169 if(nodeNumber == -1) {
170 correspondence_map_size = ptNumber;
172 correspondence_map_size = nodeNumber;
173 maximumLevel = ceil(log2(nodeNumber + 1)) - 1;
176 KDTreeMap correspondence_map(correspondence_map_size);
178 if(preciseBoundingBox) {
181 dataType x_max = std::numeric_limits<dataType>::lowest();
182 dataType x_min = std::numeric_limits<dataType>::max();
183 dataType y_max = std::numeric_limits<dataType>::lowest();
184 dataType y_min = std::numeric_limits<dataType>::max();
185 dataType z_max = std::numeric_limits<dataType>::lowest();
186 dataType z_min = std::numeric_limits<dataType>::max();
188 for(
int i = 0; i < ptNumber * dimension; i += dimension) {
189 if(x_max < data[i]) {
192 if(x_min > data[i]) {
196 if(y_max < data[i + 1]) {
199 if(y_min > data[i + 1]) {
204 if(z_max < data[i + 2]) {
207 if(z_min > data[i + 2]) {
213 coords_min_[0] = x_min;
214 coords_max_[0] = x_max;
215 coords_min_[1] = y_min;
216 coords_max_[1] = y_max;
218 coords_min_[2] = z_min;
219 coords_max_[2] = z_max;
222 for(
int axis = 0; axis < dimension; axis++) {
223 coords_min_[axis] = std::numeric_limits<dataType>::lowest();
224 coords_max_[axis] = std::numeric_limits<dataType>::max();
228 std::vector<int> idx(ptNumber);
229 for(
int i = 0; i < ptNumber; i++) {
233 sort(idx.begin(), idx.end(), [&](
int i1,
int i2) {
234 return data[dimension * i1 + coords_number_]
235 < data[dimension * i2 + coords_number_];
237 int median_loc = (int)(ptNumber - 1) / 2;
238 int median_idx = idx[median_loc];
240 for(
int axis = 0; axis < dimension; axis++) {
241 coordinates_[axis] = data[dimension * median_idx + axis];
244 if(nodeNumber == -1) {
245 correspondence_map[median_idx] =
this;
248 correspondence_map[idGenerator] =
this;
255 this->weight_.clear();
256 this->min_subweights_.clear();
258 if(weights.empty()) {
259 this->weight_.resize(weightNumber);
260 this->min_subweights_.resize(weightNumber);
262 for(
int i = 0; i < weightNumber; i++) {
263 weight_.push_back(weights[i][median_idx]);
264 min_subweights_.push_back(weights[i][median_idx]);
268 if(((nodeNumber == -1) && (idx.size() > 2))
269 || ((nodeNumber != -1) && (createdNumberNode < nodeNumber))) {
271 std::vector<int> idx_left(median_loc);
272 for(
int i = 0; i < median_loc; i++) {
273 idx_left[i] = idx[i];
277 = std::make_unique<KDTree>(
this, (coords_number_ + 1) % dimension,
true);
278 this->left_->buildRecursive(data, idx_left, ptNumber, dimension,
this,
279 correspondence_map, nodeNumber, maximumLevel,
280 createdNumberNode, weights, weightNumber);
283 if(((nodeNumber == -1) && (idx.size() > 1))
284 || ((nodeNumber != -1) && (createdNumberNode < nodeNumber))) {
286 std::vector<int> idx_right(ptNumber - median_loc - 1);
287 for(
int i = 0; i < ptNumber - median_loc - 1; i++) {
288 idx_right[i] = idx[i + median_loc + 1];
291 = std::make_unique<KDTree>(
this, (coords_number_ + 1) % dimension,
false);
292 this->right_->buildRecursive(data, idx_right, ptNumber, dimension,
this,
293 correspondence_map, nodeNumber, maximumLevel,
294 createdNumberNode, weights, weightNumber);
297 return correspondence_map;
303 std::vector<int> &idx_side,
305 const int &dimension,
308 const int &nodeNumber,
309 const int &maximumLevel,
310 int &createdNumberNode,
311 const std::vector<std::vector<dataType>> &weights,
312 const int &weightNumber) {
315 int idGenerator = createdNumberNode - 1;
318 sort(idx_side.begin(), idx_side.end(), [&](
int i1,
int i2) {
319 return data[dimension * i1 + coords_number_]
320 < data[dimension * i2 + coords_number_];
322 int median_loc = (int)(idx_side.size() - 1) / 2;
323 int median_idx = idx_side[median_loc];
325 for(
int axis = 0; axis < dimension; axis++) {
326 coordinates_[axis] = data[dimension * median_idx + axis];
329 if(nodeNumber == -1) {
330 correspondence_map[median_idx] =
this;
333 correspondence_map[idGenerator] =
this;
338 level_ = parent->
level_ + 1;
340 this->weight_.clear();
341 this->min_subweights_.clear();
343 if(weights.empty()) {
344 this->weight_.resize(weightNumber);
345 this->min_subweights_.resize(weightNumber);
347 for(
int i = 0; i < weightNumber; i++) {
348 weight_.push_back(weights[i][median_idx]);
349 min_subweights_.push_back(weights[i][median_idx]);
352 if(idx_side.size() > 1) {
354 for(
int w = 0; w < weightNumber; w++) {
355 this->updateMinSubweight(w);
361 for(
int axis = 0; axis < dimension; axis++) {
362 coords_min_[axis] = parent_->coords_min_[axis];
363 coords_max_[axis] = parent_->coords_max_[axis];
365 if(is_left_ && !this->isRoot()) {
366 coords_max_[parent_->coords_number_]
367 = parent_->coordinates_[parent_->coords_number_];
368 }
else if(!is_left_ && !this->isRoot()) {
369 coords_min_[parent_->coords_number_]
370 = parent_->coordinates_[parent_->coords_number_];
373 if(((nodeNumber == -1) && (idx_side.size() > 2))
374 || ((nodeNumber != -1) && (level_ < maximumLevel)
375 && (createdNumberNode < nodeNumber))) {
377 std::vector<int> idx_left(median_loc);
378 for(
int i = 0; i < median_loc; i++) {
379 idx_left[i] = idx_side[i];
383 = std::make_unique<KDTree>(
this, (coords_number_ + 1) % dimension,
true);
384 this->left_->buildRecursive(data, idx_left, ptNumber, dimension,
this,
385 correspondence_map, nodeNumber, maximumLevel,
386 createdNumberNode, weights, weightNumber);
389 if(((nodeNumber == -1) && (idx_side.size() > 1))
390 || ((nodeNumber != -1) && (level_ < maximumLevel)
391 && (createdNumberNode < nodeNumber))) {
393 std::vector<int> idx_right(idx_side.size() - median_loc - 1);
394 for(
unsigned int i = 0; i < idx_side.size() - median_loc - 1; i++) {
395 idx_right[i] = idx_side[i + median_loc + 1];
398 = std::make_unique<KDTree>(
this, (coords_number_ + 1) % dimension,
false);
399 this->right_->buildRecursive(data, idx_right, ptNumber, dimension,
this,
400 correspondence_map, nodeNumber, maximumLevel,
401 createdNumberNode, weights, weightNumber);
407 const int weight_index) {
408 dataType new_min_subweight;
410 new_min_subweight = weight_[weight_index];
413 = std::min(right_->min_subweights_[weight_index], weight_[weight_index]);
416 = std::min(left_->min_subweights_[weight_index], weight_[weight_index]);
419 = std::min(std::min(left_->min_subweights_[weight_index],
420 right_->min_subweights_[weight_index]),
421 weight_[weight_index]);
424 if(new_min_subweight != min_subweights_[weight_index]) {
425 min_subweights_[weight_index] = new_min_subweight;
426 if(!this->isRoot()) {
427 parent_->updateMinSubweight(weight_index);
463 const unsigned int k,
464 const Container &coordinates,
466 std::vector<dataType> &costs,
467 const int weight_index,
468 const PowerFunc &power) {
471 dataType cost = this->getCost(coordinates, power);
472 cost += weight_[weight_index];
474 if(costs.size() < k) {
475 neighbours.push_back(
this);
476 costs.push_back(cost);
479 const auto idx_max_cost = std::distance(
480 costs.begin(), std::max_element(costs.begin(), costs.begin() + k));
481 const dataType max_cost = costs[idx_max_cost];
485 if(cost < max_cost) {
486 costs[idx_max_cost] = cost;
487 neighbours[idx_max_cost] =
this;
493 const dataType max_cost = *std::max_element(costs.begin(), costs.end());
494 const dataType min_subweight = left_->min_subweights_[weight_index];
495 const dataType d_min = this->distanceToBox(*left_, coordinates, power);
496 if(costs.size() < k || d_min + min_subweight < max_cost) {
499 left_->recursiveGetKClosest(
500 k, coordinates, neighbours, costs, weight_index, power);
505 const dataType max_cost = *std::max_element(costs.begin(), costs.end());
506 const dataType min_subweight = right_->min_subweights_[weight_index];
507 const dataType d_min = this->distanceToBox(*right_, coordinates, power);
508 if(costs.size() < k || d_min + min_subweight < max_cost) {
511 right_->recursiveGetKClosest(
512 k, coordinates, neighbours, costs, weight_index, power);
void buildRecursive(dataType *data, std::vector< int > &idx_side, const int &ptNumber, const int &dimension, KDTree< dataType, Container > *parent, KDTreeMap &correspondence_map, const int &nodeNumber, const int &maximumLevel, int &createdNumberNode, const std::vector< std::vector< dataType > > &weights={}, const int &weightNumber=1)