File indexing completed on 2025-01-18 09:58:34
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068 template<typename PointT>
0069 G4KDNode_Base* G4KDTree::InsertMap(PointT* point)
0070 {
0071 auto node = new G4KDNode<PointT>(this, point, 0);
0072 this->__InsertMap(node);
0073 return node;
0074 }
0075
0076 template<typename PointT>
0077 G4KDNode_Base* G4KDTree::Insert(PointT* pos)
0078 {
0079 G4KDNode_Base* node = nullptr;
0080 if (!fRoot)
0081 {
0082 fRoot = new G4KDNode<PointT>(this, pos, nullptr);
0083 node = fRoot;
0084 fNbNodes = 0;
0085 fNbNodes++;
0086 fNbActiveNodes++;
0087 }
0088 else
0089 {
0090 if ((node = fRoot->Insert<PointT>(pos)))
0091 {
0092 fNbNodes++;
0093 fNbActiveNodes++;
0094 }
0095 }
0096
0097 if (fRect == nullptr)
0098 {
0099 fRect = new HyperRect(fDim);
0100 fRect->SetMinMax(*pos, *pos);
0101 }
0102 else
0103 {
0104 fRect->Extend(*pos);
0105 }
0106
0107 return node;
0108 }
0109
0110 template<typename PointT>
0111 G4KDNode_Base* G4KDTree::Insert(const PointT& pos)
0112 {
0113 G4KDNode_Base* node = nullptr;
0114 if (!fRoot)
0115 {
0116 fRoot = new G4KDNodeCopy<PointT>(this, pos, 0);
0117 node = fRoot;
0118 fNbNodes = 0;
0119 fNbNodes++;
0120 fNbActiveNodes++;
0121 }
0122 else
0123 {
0124 if ((node = fRoot->Insert<PointT>(pos)))
0125 {
0126 fNbNodes++;
0127 fNbActiveNodes++;
0128 }
0129 }
0130
0131 if (fRect == nullptr)
0132 {
0133 fRect = new HyperRect(fDim);
0134 fRect->SetMinMax(pos, pos);
0135 }
0136 else
0137 {
0138 fRect->Extend(pos);
0139 }
0140
0141 return node;
0142 }
0143
0144
0145 template<typename Position>
0146 G4int G4KDTree::__NearestInRange(G4KDNode_Base* node,
0147 const Position& pos,
0148 const double& range_sq,
0149 const double& range,
0150 G4KDTreeResult& list,
0151 G4int ordered,
0152 G4KDNode_Base *source_node)
0153 {
0154 if (!node) return 0;
0155
0156 G4double dist_sq(DBL_MAX), dx(DBL_MAX);
0157 G4int ret(-1), added_res(0);
0158
0159 if (node->IsValid() && node != source_node)
0160 {
0161 G4bool do_break = false;
0162 dist_sq = 0;
0163 for (std::size_t i = 0; i < fDim; ++i)
0164 {
0165 dist_sq += sqr((*node)[i] - pos[(G4int)i]);
0166 if (dist_sq > range_sq)
0167 {
0168 do_break = true;
0169 break;
0170 }
0171 }
0172 if (!do_break && dist_sq <= range_sq)
0173 {
0174 list.Insert(dist_sq, node);
0175 added_res = 1;
0176 }
0177 }
0178
0179 dx = pos[node->GetAxis()] - (*node)[node->GetAxis()];
0180
0181 ret = __NearestInRange(dx <= 0.0 ? node->GetLeft() : node->GetRight(), pos,
0182 range_sq, range, list, ordered, source_node);
0183 if (ret >= 0 && std::fabs(dx) <= range)
0184 {
0185 added_res += ret;
0186 ret = __NearestInRange(dx <= 0.0 ? node->GetRight() : node->GetLeft(),
0187 pos, range_sq, range, list, ordered, source_node);
0188 }
0189
0190 if (ret == -1)
0191 {
0192 return -1;
0193 }
0194 added_res += ret;
0195
0196 return added_res;
0197 }
0198
0199
0200 template<typename Position>
0201 void G4KDTree::__NearestToPosition(G4KDNode_Base *node,
0202 const Position &pos,
0203 G4KDNode_Base *&result,
0204 G4double *result_dist_sq,
0205 HyperRect* rect)
0206 {
0207 G4int dir = node->GetAxis();
0208 G4double dummy(0.), dist_sq(-1.);
0209 G4KDNode_Base* nearer_subtree(nullptr), *farther_subtree(nullptr);
0210 G4double *nearer_hyperrect_coord(nullptr), *farther_hyperrect_coord(nullptr);
0211
0212
0213 dummy = pos[dir] - (*node)[dir];
0214 if (dummy <= 0)
0215 {
0216 nearer_subtree = node->GetLeft();
0217 farther_subtree = node->GetRight();
0218
0219 nearer_hyperrect_coord = rect->GetMax() + dir;
0220 farther_hyperrect_coord = rect->GetMin() + dir;
0221 }
0222 else
0223 {
0224 nearer_subtree = node->GetRight();
0225 farther_subtree = node->GetLeft();
0226 nearer_hyperrect_coord = rect->GetMin() + dir;
0227 farther_hyperrect_coord = rect->GetMax() + dir;
0228 }
0229
0230 if (nearer_subtree)
0231 {
0232
0233 dummy = *nearer_hyperrect_coord;
0234 *nearer_hyperrect_coord = (*node)[dir];
0235
0236 __NearestToPosition(nearer_subtree, pos, result, result_dist_sq, rect);
0237
0238 *nearer_hyperrect_coord = dummy;
0239 }
0240
0241
0242
0243 if (node->IsValid())
0244 {
0245 dist_sq = 0;
0246 G4bool do_break = false;
0247 for (std::size_t i = 0; i < fDim; ++i)
0248 {
0249 dist_sq += sqr((*node)[i] - pos[(G4int)i]);
0250 if (dist_sq > *result_dist_sq)
0251 {
0252 do_break = true;
0253 break;
0254 }
0255 }
0256 if (!do_break && dist_sq < *result_dist_sq)
0257 {
0258 result = node;
0259 *result_dist_sq = dist_sq;
0260 }
0261 }
0262
0263 if (farther_subtree)
0264 {
0265
0266 dummy = *farther_hyperrect_coord;
0267 *farther_hyperrect_coord = (*node)[dir];
0268
0269
0270
0271 if (rect->CompareDistSqr(pos, result_dist_sq))
0272 {
0273
0274 __NearestToPosition(farther_subtree, pos, result, result_dist_sq, rect);
0275 }
0276
0277 *farther_hyperrect_coord = dummy;
0278 }
0279 }
0280
0281 template<typename Position>
0282 G4KDTreeResultHandle G4KDTree::Nearest(const Position& pos)
0283 {
0284
0285
0286 if (!fRect) return nullptr;
0287
0288 G4KDNode_Base *result(nullptr);
0289 G4double dist_sq = DBL_MAX;
0290
0291
0292 auto newrect = new HyperRect(*fRect);
0293
0294
0295
0296 __NearestToPosition(fRoot, pos, result, &dist_sq, newrect);
0297
0298
0299 delete newrect;
0300
0301
0302 if (result)
0303 {
0304 G4KDTreeResultHandle rset = new G4KDTreeResult(this);
0305 rset->Insert(dist_sq, result);
0306 rset->Rewind();
0307 return rset;
0308 }
0309
0310 return nullptr;
0311 }
0312
0313
0314 template<typename Position>
0315 void G4KDTree::__NearestToNode(G4KDNode_Base* source_node,
0316 G4KDNode_Base* node,
0317 const Position& pos,
0318 std::vector<G4KDNode_Base*>& result,
0319 G4double *result_dist_sq,
0320 HyperRect* rect,
0321 G4int& nbresult)
0322 {
0323 G4int dir = node->GetAxis();
0324 G4double dummy, dist_sq;
0325 G4KDNode_Base *nearer_subtree(nullptr), *farther_subtree(nullptr);
0326 G4double *nearer_hyperrect_coord(nullptr), *farther_hyperrect_coord(nullptr);
0327
0328
0329 dummy = pos[dir] - (*node)[dir];
0330 if (dummy <= 0)
0331 {
0332 nearer_subtree = node->GetLeft();
0333 farther_subtree = node->GetRight();
0334 nearer_hyperrect_coord = rect->GetMax() + dir;
0335 farther_hyperrect_coord = rect->GetMin() + dir;
0336 }
0337 else
0338 {
0339 nearer_subtree = node->GetRight();
0340 farther_subtree = node->GetLeft();
0341 nearer_hyperrect_coord = rect->GetMin() + dir;
0342 farther_hyperrect_coord = rect->GetMax() + dir;
0343 }
0344
0345 if (nearer_subtree)
0346 {
0347
0348 dummy = *nearer_hyperrect_coord;
0349 *nearer_hyperrect_coord = (*node)[dir];
0350
0351 __NearestToNode(source_node, nearer_subtree, pos, result, result_dist_sq,
0352 rect, nbresult);
0353
0354 *nearer_hyperrect_coord = dummy;
0355 }
0356
0357
0358
0359 if (node->IsValid() && node != source_node)
0360 {
0361 dist_sq = 0;
0362 G4bool do_break = false;
0363 for (std::size_t i = 0; i < fDim; ++i)
0364 {
0365 dist_sq += sqr((*node)[i] - pos[i]);
0366 if (dist_sq > *result_dist_sq)
0367 {
0368 do_break = true;
0369 break;
0370 }
0371 }
0372 if (!do_break)
0373 {
0374 if (dist_sq < *result_dist_sq)
0375 {
0376 result.clear();
0377 nbresult = 1;
0378 result.push_back(node);
0379 *result_dist_sq = dist_sq;
0380 }
0381 else if (dist_sq == *result_dist_sq)
0382 {
0383 result.push_back(node);
0384 nbresult++;
0385 }
0386 }
0387 }
0388
0389 if (farther_subtree)
0390 {
0391
0392 dummy = *farther_hyperrect_coord;
0393 *farther_hyperrect_coord = (*node)[dir];
0394
0395
0396
0397
0398 if (rect->CompareDistSqr(pos, result_dist_sq))
0399 {
0400
0401 __NearestToNode(source_node, farther_subtree, pos, result,
0402 result_dist_sq, rect, nbresult);
0403 }
0404
0405 *farther_hyperrect_coord = dummy;
0406 }
0407 }
0408
0409 template<typename Position>
0410 G4KDTreeResultHandle G4KDTree::NearestInRange(const Position& pos,
0411 const G4double& range)
0412 {
0413 G4int ret(-1);
0414
0415 const G4double range_sq = sqr(range);
0416
0417 G4KDTreeResultHandle rset = new G4KDTreeResult(this);
0418 if ((ret = __NearestInRange(fRoot, pos, range_sq, range, *(rset()), 0)) == -1)
0419 {
0420 rset = nullptr;
0421 return rset;
0422 }
0423 rset->Sort();
0424 rset->Rewind();
0425 return rset;
0426 }