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]) {
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;
258 if(weights.empty()) {
259 this->
weight_.resize(weightNumber);
262 for(
int i = 0; i < weightNumber; i++) {
263 weight_.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;
343 if(weights.empty()) {
344 this->
weight_.resize(weightNumber);
347 for(
int i = 0; i < weightNumber; i++) {
348 weight_.push_back(weights[i][median_idx]);
352 if(idx_side.size() > 1) {
354 for(
int w = 0; w < weightNumber; w++) {
361 for(
int axis = 0; axis < dimension; axis++) {
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);
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);
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];
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];
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)