#include <G4KDTree.hh>
Public Member Functions | |
G4KDTree (int dim=3) | |
virtual | ~G4KDTree () |
void | Clear () |
int | GetDim () |
void | SetDataDestructor (void(*fDestr)(void *)) |
int | GetNbNodes () |
G4KDNode * | GetRoot () |
G4KDNode * | Insert (const double *pos, void *data) |
G4KDNode * | Insert (const double &x, const double &y, const double &z, void *data) |
G4KDTreeResultHandle | Nearest (const double *pos) |
G4KDTreeResultHandle | Nearest (const double &x, const double &y, const double &z) |
G4KDTreeResultHandle | Nearest (G4KDNode *node) |
G4KDTreeResultHandle | NearestInRange (const double *pos, const double &range) |
G4KDTreeResultHandle | NearestInRange (const double &x, const double &y, const double &z, const double &range) |
G4KDTreeResultHandle | NearestInRange (G4KDNode *node, const double &range) |
Protected Member Functions | |
void | __Clear_Rec (G4KDNode *node) |
int | __NearestInRange (G4KDNode *node, const double *pos, const double &range_sq, const double &range, G4KDTreeResult &list, int ordered, G4KDNode *source_node=0) |
void | __NearestToPosition (G4KDNode *node, const double *pos, G4KDNode *&result, double *result_dist_sq, struct HyperRect *fRect) |
void | __NearestToNode (G4KDNode *source_node, G4KDNode *node, const double *pos, std::vector< G4KDNode * > &result, double *result_dist_sq, struct HyperRect *fRect, int &nbresult) |
Protected Attributes | |
G4KDNode * | fRoot |
Friends | |
class | G4KDNode |
Definition at line 60 of file G4KDTree.hh.
G4KDTree::G4KDTree | ( | int | dim = 3 |
) |
Definition at line 169 of file G4KDTree.cc.
References fRoot.
00170 { 00171 fDim = k; 00172 fRoot = 0; 00173 fDestr = 0; 00174 fRect = 0; 00175 fNbNodes = 0; 00176 }
G4KDTree::~G4KDTree | ( | ) | [virtual] |
Definition at line 178 of file G4KDTree.cc.
References __Clear_Rec(), and fRoot.
00179 { 00180 if(fRoot) __Clear_Rec(fRoot); 00181 fRoot = 0; 00182 00183 if (fRect) 00184 { 00185 delete fRect; 00186 fRect = 0; 00187 } 00188 }
void G4KDTree::__Clear_Rec | ( | G4KDNode * | node | ) | [protected] |
Definition at line 203 of file G4KDTree.cc.
References G4KDNode::GetData(), G4KDNode::GetLeft(), G4KDNode::GetRight(), and G4KDNode::SetData().
Referenced by Clear(), and ~G4KDTree().
00204 { 00205 if(!node) return; 00206 00207 if(node->GetLeft()) __Clear_Rec(node->GetLeft()); 00208 if(node->GetRight()) __Clear_Rec(node->GetRight()); 00209 00210 if(fDestr) 00211 { 00212 if(node->GetData()) 00213 { 00214 fDestr(node->GetData()); 00215 node->SetData(0); 00216 } 00217 } 00218 delete node; 00219 }
int G4KDTree::__NearestInRange | ( | G4KDNode * | node, | |
const double * | pos, | |||
const double & | range_sq, | |||
const double & | range, | |||
G4KDTreeResult & | list, | |||
int | ordered, | |||
G4KDNode * | source_node = 0 | |||
) | [protected] |
Definition at line 261 of file G4KDTree.cc.
References DBL_MAX, G4KDNode::GetAxis(), GetData(), G4KDNode::GetLeft(), G4KDNode::GetPosition(), G4KDNode::GetRight(), G4KDTreeResult::Insert(), and sqr().
Referenced by NearestInRange().
00263 { 00264 if(!node) return 0; 00265 00266 double dist_sq(DBL_MAX), dx(DBL_MAX); 00267 int ret(-1), added_res(0); 00268 00269 if(node-> GetData() && node != source_node) 00270 { 00271 bool do_break = false ; 00272 dist_sq = 0; 00273 for(int i=0; i<fDim; i++) 00274 { 00275 dist_sq += sqr(node->GetPosition()[i] - pos[i]); 00276 if(dist_sq > range_sq) 00277 { 00278 do_break = true; 00279 break; 00280 } 00281 } 00282 if(!do_break && dist_sq <= range_sq) 00283 { 00284 list.Insert(dist_sq, node); 00285 added_res = 1; 00286 } 00287 } 00288 00289 dx = pos[node->GetAxis()] - node->GetPosition()[node->GetAxis()]; 00290 00291 ret = __NearestInRange(dx <= 0.0 ? node->GetLeft() : node->GetRight(), pos, range_sq, range, list, ordered, source_node); 00292 if(ret >= 0 && fabs(dx) <= range) 00293 { 00294 added_res += ret; 00295 ret = __NearestInRange(dx <= 0.0 ? node->GetRight() : node->GetLeft(), pos, range_sq, range, list, ordered, source_node); 00296 } 00297 00298 if(ret == -1) 00299 { 00300 return -1; 00301 } 00302 added_res += ret; 00303 00304 return added_res; 00305 }
void G4KDTree::__NearestToNode | ( | G4KDNode * | source_node, | |
G4KDNode * | node, | |||
const double * | pos, | |||
std::vector< G4KDNode * > & | result, | |||
double * | result_dist_sq, | |||
struct HyperRect * | fRect, | |||
int & | nbresult | |||
) | [protected] |
Definition at line 420 of file G4KDTree.cc.
References HyperRect::CompareDistSqr(), G4KDNode::GetAxis(), G4KDNode::GetData(), G4KDNode::GetLeft(), HyperRect::GetMax(), HyperRect::GetMin(), G4KDNode::GetPosition(), G4KDNode::GetRight(), and sqr().
Referenced by Nearest().
00423 { 00424 int dir = node->GetAxis(); 00425 double dummy, dist_sq; 00426 G4KDNode *nearer_subtree (0), *farther_subtree (0); 00427 double *nearer_hyperrect_coord (0), *farther_hyperrect_coord (0); 00428 00429 /* Decide whether to go left or right in the tree */ 00430 dummy = pos[dir] - node->GetPosition()[dir]; 00431 if (dummy <= 0) 00432 { 00433 nearer_subtree = node->GetLeft(); 00434 farther_subtree = node->GetRight(); 00435 nearer_hyperrect_coord = rect->GetMax() + dir; 00436 farther_hyperrect_coord = rect->GetMin() + dir; 00437 } 00438 else 00439 { 00440 nearer_subtree = node->GetRight(); 00441 farther_subtree = node->GetLeft(); 00442 nearer_hyperrect_coord = rect->GetMin() + dir; 00443 farther_hyperrect_coord = rect->GetMax() + dir; 00444 } 00445 00446 if (nearer_subtree) 00447 { 00448 /* Slice the hyperrect to get the hyperrect of the nearer subtree */ 00449 dummy = *nearer_hyperrect_coord; 00450 *nearer_hyperrect_coord = node->GetPosition()[dir]; 00451 /* Recurse down into nearer subtree */ 00452 __NearestToNode(source_node, nearer_subtree, pos, result, result_dist_sq, rect, nbresult); 00453 /* Undo the slice */ 00454 *nearer_hyperrect_coord = dummy; 00455 } 00456 00457 /* Check the distance of the point at the current node, compare it 00458 * with our best so far */ 00459 if(node->GetData() && node != source_node) 00460 { 00461 dist_sq = 0; 00462 bool do_break = false; 00463 for(int i=0; i < fDim; i++) 00464 { 00465 dist_sq += sqr(node->GetPosition()[i] - pos[i]); 00466 if(dist_sq > *result_dist_sq) 00467 { 00468 do_break = true; 00469 break ; 00470 } 00471 } 00472 if(!do_break) 00473 { 00474 if (dist_sq < *result_dist_sq) 00475 { 00476 result.clear(); 00477 nbresult = 1 ; 00478 result.push_back(node); 00479 *result_dist_sq = dist_sq; 00480 } 00481 else if(dist_sq == *result_dist_sq) 00482 { 00483 result.push_back(node); 00484 nbresult++; 00485 } 00486 } 00487 } 00488 00489 if (farther_subtree) 00490 { 00491 /* Get the hyperrect of the farther subtree */ 00492 dummy = *farther_hyperrect_coord; 00493 *farther_hyperrect_coord = node->GetPosition()[dir]; 00494 /* Check if we have to recurse down by calculating the closest 00495 * point of the hyperrect and see if it's closer than our 00496 * minimum distance in result_dist_sq. */ 00497 // if (hyperrect_dist_sq(rect, pos) < *result_dist_sq) 00498 if (rect->CompareDistSqr(pos,result_dist_sq)) 00499 { 00500 /* Recurse down into farther subtree */ 00501 __NearestToNode(source_node, farther_subtree, pos, result, result_dist_sq, rect, nbresult); 00502 } 00503 /* Undo the slice on the hyperrect */ 00504 *farther_hyperrect_coord = dummy; 00505 } 00506 }
void G4KDTree::__NearestToPosition | ( | G4KDNode * | node, | |
const double * | pos, | |||
G4KDNode *& | result, | |||
double * | result_dist_sq, | |||
struct HyperRect * | fRect | |||
) | [protected] |
Definition at line 308 of file G4KDTree.cc.
References HyperRect::CompareDistSqr(), G4KDNode::GetAxis(), G4KDNode::GetData(), G4KDNode::GetLeft(), HyperRect::GetMax(), HyperRect::GetMin(), G4KDNode::GetPosition(), G4KDNode::GetRight(), and sqr().
Referenced by Nearest().
00310 { 00311 int dir = node->GetAxis(); 00312 int i; 00313 double dummy(0.), dist_sq(-1.); 00314 G4KDNode *nearer_subtree(0), *farther_subtree (0); 00315 double *nearer_hyperrect_coord(0),*farther_hyperrect_coord(0); 00316 00317 /* Decide whether to go left or right in the tree */ 00318 dummy = pos[dir] - node->GetPosition()[dir]; 00319 if (dummy <= 0) 00320 { 00321 nearer_subtree = node->GetLeft(); 00322 farther_subtree = node->GetRight(); 00323 00324 nearer_hyperrect_coord = rect->GetMax() + dir; 00325 farther_hyperrect_coord = rect->GetMin() + dir; 00326 } 00327 else 00328 { 00329 nearer_subtree = node->GetRight(); 00330 farther_subtree = node->GetLeft(); 00331 nearer_hyperrect_coord = rect->GetMin() + dir; 00332 farther_hyperrect_coord = rect->GetMax() + dir; 00333 } 00334 00335 if (nearer_subtree) 00336 { 00337 /* Slice the hyperrect to get the hyperrect of the nearer subtree */ 00338 dummy = *nearer_hyperrect_coord; 00339 *nearer_hyperrect_coord = node->GetPosition()[dir]; 00340 /* Recurse down into nearer subtree */ 00341 __NearestToPosition(nearer_subtree, pos, result, result_dist_sq, rect); 00342 /* Undo the slice */ 00343 *nearer_hyperrect_coord = dummy; 00344 } 00345 00346 /* Check the distance of the point at the current node, compare it 00347 * with our best so far */ 00348 if(node->GetData()) 00349 { 00350 dist_sq = 0; 00351 bool do_break = false ; 00352 for(i=0; i < fDim; i++) 00353 { 00354 dist_sq += sqr(node->GetPosition()[i] - pos[i]); 00355 if(dist_sq > *result_dist_sq) 00356 { 00357 do_break = true; 00358 break ; 00359 } 00360 } 00361 if (!do_break && dist_sq < *result_dist_sq) 00362 { 00363 result = node; 00364 *result_dist_sq = dist_sq; 00365 } 00366 } 00367 00368 if (farther_subtree) 00369 { 00370 /* Get the hyperrect of the farther subtree */ 00371 dummy = *farther_hyperrect_coord; 00372 *farther_hyperrect_coord = node->GetPosition()[dir]; 00373 /* Check if we have to recurse down by calculating the closest 00374 * point of the hyperrect and see if it's closer than our 00375 * minimum distance in result_dist_sq. */ 00376 if (rect->CompareDistSqr(pos,result_dist_sq)) 00377 { 00378 /* Recurse down into farther subtree */ 00379 __NearestToPosition(farther_subtree, pos, result, result_dist_sq, rect); 00380 } 00381 /* Undo the slice on the hyperrect */ 00382 *farther_hyperrect_coord = dummy; 00383 } 00384 }
void G4KDTree::Clear | ( | ) |
Definition at line 190 of file G4KDTree.cc.
References __Clear_Rec(), and fRoot.
00191 { 00192 __Clear_Rec(fRoot); 00193 fRoot = 0; 00194 fNbNodes = 0; 00195 00196 if (fRect) 00197 { 00198 delete fRect; 00199 fRect = 0; 00200 } 00201 }
int G4KDTree::GetDim | ( | ) | [inline] |
Definition at line 136 of file G4KDTree.hh.
References HyperRect::fDim.
Referenced by G4KDNode::GetDim(), and G4KDTreeResult::GetItem().
int G4KDTree::GetNbNodes | ( | ) | [inline] |
G4KDNode* G4KDTree::GetRoot | ( | ) | [inline] |
G4KDNode * G4KDTree::Insert | ( | const double & | x, | |
const double & | y, | |||
const double & | z, | |||
void * | data | |||
) |
Definition at line 251 of file G4KDTree.cc.
References Insert().
00252 { 00253 double buf[3]; 00254 buf[0] = x; 00255 buf[1] = y; 00256 buf[2] = z; 00257 return Insert(buf, data); 00258 }
G4KDNode * G4KDTree::Insert | ( | const double * | pos, | |
void * | data | |||
) |
Definition at line 221 of file G4KDTree.cc.
References HyperRect::Extend(), fRoot, G4KDNode, and G4KDNode::Insert().
Referenced by Insert().
00222 { 00223 G4KDNode* node = 0 ; 00224 if(!fRoot) 00225 { 00226 fRoot = new G4KDNode(this,pos,data,0, 0); 00227 node = fRoot; 00228 fNbNodes = 0; 00229 fNbNodes++; 00230 } 00231 else 00232 { 00233 if((node=fRoot->Insert(pos, data))) 00234 { 00235 fNbNodes++; 00236 } 00237 } 00238 00239 if (fRect == 0) 00240 { 00241 fRect = new HyperRect(fDim,pos,pos); 00242 } 00243 else 00244 { 00245 fRect->Extend(pos); 00246 } 00247 00248 return node; 00249 }
G4KDTreeResultHandle G4KDTree::Nearest | ( | G4KDNode * | node | ) |
Definition at line 508 of file G4KDTree.cc.
References __NearestToNode(), DBL_MAX, fRoot, G4cout, G4endl, and G4KDNode::GetPosition().
00509 { 00510 // G4cout << "Nearest(node)" << G4endl ; 00511 if (!fRect) 00512 { 00513 G4cout << "Tree empty" << G4endl ; 00514 return 0; 00515 } 00516 00517 const double* pos = node->GetPosition(); 00518 std::vector<G4KDNode*> result; 00519 double dist_sq = DBL_MAX; 00520 00521 /* Duplicate the bounding hyperrectangle, we will work on the copy */ 00522 HyperRect *newrect = new HyperRect(*fRect); 00523 00524 /* Search for the nearest neighbour recursively */ 00525 int nbresult = 0 ; 00526 00527 __NearestToNode(node, fRoot, pos, result, &dist_sq, newrect, nbresult); 00528 00529 /* Free the copy of the hyperrect */ 00530 delete newrect; 00531 00532 /* Store the result */ 00533 if (!result.empty()) 00534 { 00535 G4KDTreeResultHandle rset(new G4KDTreeResult(this)); 00536 int j = 0 ; 00537 while (j<nbresult) 00538 { 00539 rset->Insert(dist_sq, result[j]); 00540 j++; 00541 } 00542 rset->Rewind(); 00543 00544 return rset; 00545 } 00546 else 00547 { 00548 return 0; 00549 } 00550 }
G4KDTreeResultHandle G4KDTree::Nearest | ( | const double & | x, | |
const double & | y, | |||
const double & | z | |||
) |
Definition at line 552 of file G4KDTree.cc.
References Nearest().
00553 { 00554 double pos[3]; 00555 pos[0] = x; 00556 pos[1] = y; 00557 pos[2] = z; 00558 return Nearest(pos); 00559 }
G4KDTreeResultHandle G4KDTree::Nearest | ( | const double * | pos | ) |
Definition at line 386 of file G4KDTree.cc.
References __NearestToPosition(), DBL_MAX, and fRoot.
Referenced by Nearest().
00387 { 00388 // G4cout << "Nearest(pos)" << G4endl ; 00389 00390 if (!fRect) return 0; 00391 00392 G4KDNode *result(0); 00393 double dist_sq = DBL_MAX; 00394 00395 /* Duplicate the bounding hyperrectangle, we will work on the copy */ 00396 HyperRect *newrect = new HyperRect(*fRect); 00397 00398 /* Our first guesstimate is the root node */ 00399 /* Search for the nearest neighbour recursively */ 00400 __NearestToPosition(fRoot, pos, result, &dist_sq, newrect); 00401 00402 /* Free the copy of the hyperrect */ 00403 delete newrect; 00404 00405 /* Store the result */ 00406 if (result) 00407 { 00408 G4KDTreeResultHandle rset = new G4KDTreeResult(this); 00409 rset->Insert(dist_sq, result); 00410 rset -> Rewind(); 00411 return rset; 00412 } 00413 else 00414 { 00415 return 0; 00416 } 00417 }
G4KDTreeResultHandle G4KDTree::NearestInRange | ( | G4KDNode * | node, | |
const double & | range | |||
) |
Definition at line 590 of file G4KDTree.cc.
References __NearestInRange(), fRoot, G4KDNode::GetPosition(), and sqr().
00591 { 00592 if(!node) return 0 ; 00593 int ret(-1); 00594 00595 G4KDTreeResult *rset = new G4KDTreeResult(this); 00596 00597 const double range_sq = sqr(range) ; 00598 00599 if((ret = __NearestInRange(fRoot, node->GetPosition(), range_sq, range, *rset, 0, node)) == -1) 00600 { 00601 delete rset; 00602 return 0; 00603 } 00604 rset->Sort(); 00605 rset->Rewind(); 00606 return rset; 00607 }
G4KDTreeResultHandle G4KDTree::NearestInRange | ( | const double & | x, | |
const double & | y, | |||
const double & | z, | |||
const double & | range | |||
) |
Definition at line 578 of file G4KDTree.cc.
References NearestInRange().
00582 { 00583 double buf[3]; 00584 buf[0] = x; 00585 buf[1] = y; 00586 buf[2] = z; 00587 return NearestInRange(buf, range); 00588 }
G4KDTreeResultHandle G4KDTree::NearestInRange | ( | const double * | pos, | |
const double & | range | |||
) |
Definition at line 561 of file G4KDTree.cc.
References __NearestInRange(), fRoot, and sqr().
Referenced by NearestInRange().
00562 { 00563 int ret(-1); 00564 00565 const double range_sq = sqr(range) ; 00566 00567 G4KDTreeResultHandle rset = new G4KDTreeResult(this); 00568 if((ret = __NearestInRange(fRoot, pos, range_sq, range, *(rset()), 0)) == -1) 00569 { 00570 rset = 0; 00571 return rset; 00572 } 00573 rset->Sort(); 00574 rset->Rewind(); 00575 return rset; 00576 }
void G4KDTree::SetDataDestructor | ( | void(*)(void *) | fDestr | ) | [inline] |
friend class G4KDNode [friend] |
G4KDNode* G4KDTree::fRoot [protected] |
Definition at line 69 of file G4KDTree.hh.
Referenced by Clear(), G4KDTree(), GetRoot(), Insert(), Nearest(), NearestInRange(), and ~G4KDTree().