00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef _KDNODE_H_
00020 #define _KDNODE_H_
00021
00022 #include "Object.h"
00023 #include <stdio.h>
00024 #include <iostream>
00025 #include <math.h>
00026 #include "KDPoint.h"
00027 #include "KDPQueue.h"
00028
00029 namespace RobotFlow {
00030
00031 #define KDN_LOW 0
00032 #define KDN_HIGH 1
00033
00034
00035
00036
00037 template <class KDData>
00038 class KDNode : public FD::Object
00039 {
00040 public:
00041
00042
00043
00044
00045
00046 KDNode()
00047 : m_nPts(0), m_dimSize(0), m_bucket(NULL), m_bucketIdx(NULL)
00048 {
00049 m_children[KDN_LOW] = NULL;
00050 m_children[KDN_HIGH] = NULL;
00051 }
00052
00053
00054
00055
00056
00057
00058 KDNode(int i_cutDim, KDData i_cutVal, KDData i_lowVal,
00059 KDData i_highVal, KDNode *i_lowChild, KDNode *i_highChild)
00060 : m_cutDim(i_cutDim), m_cutVal(i_cutVal), m_nPts(0), m_dimSize(0),
00061 m_bucket(NULL), m_bucketIdx(NULL)
00062 {
00063 m_children[KDN_LOW] = i_lowChild;
00064 m_children[KDN_HIGH] = i_highChild;
00065 m_cutBnds[KDN_LOW] = i_lowVal;
00066 m_cutBnds[KDN_HIGH] = i_highVal;
00067 }
00068
00069
00070
00071
00072
00073
00074 KDNode(KDPoint<KDData> *i_dataPts, int *i_ptsIdx, int i_numPts, int i_dimSize)
00075 : m_nPts(i_numPts), m_dimSize(i_dimSize)
00076 {
00077 m_children[KDN_LOW] = NULL;
00078 m_children[KDN_HIGH] = NULL;
00079
00080 if (m_nPts == 0) {
00081 m_bucket = NULL;
00082 m_bucketIdx = NULL;
00083 return;
00084 }
00085
00086 m_bucket = new KDPoint<KDData>[m_nPts];
00087 m_bucketIdx = new int[m_nPts];
00088
00089 for (int i=0; i<m_nPts; ++i) {
00090 m_bucket[i] = i_dataPts[i_ptsIdx[i]];
00091 m_bucketIdx[i] = i_ptsIdx[i];
00092 }
00093 }
00094
00095
00096
00097
00098
00099
00100 KDNode(KDData **i_dataPts, int *i_ptsIdx, int i_numPts, int i_dimSize)
00101 : m_nPts(i_numPts), m_dimSize(i_dimSize)
00102 {
00103 m_children[KDN_LOW] = NULL;
00104 m_children[KDN_HIGH] = NULL;
00105
00106 if (m_nPts == 0) {
00107 m_bucket = NULL;
00108 m_bucketIdx = NULL;
00109 return;
00110 }
00111
00112 m_bucket = new KDPoint<KDData>[m_nPts](m_dimSize);
00113 m_bucketIdx = new int[m_nPts];
00114
00115 for (int i=0; i<m_nPts; ++i) {
00116 m_bucket[i].SetPoint(i_dataPts[i_ptsIdx[i]]);
00117 m_bucketIdx[i] = i_ptsIdx[i];
00118 }
00119 }
00120
00121
00122
00123
00124
00125
00126 ~KDNode()
00127 {
00128 delete [] m_bucket;
00129 delete [] m_bucketIdx;
00130 delete m_children[KDN_LOW];
00131 delete m_children[KDN_HIGH];
00132 }
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 KDNode<KDData> & operator =(const KDNode<KDData> &i_ref)
00146 {
00147
00148 if (&i_ref == this) {
00149 return *this;
00150 }
00151
00152 m_cutDim = i_ref.m_cutDim;
00153 m_cutVal = i_ref.m_cutVal;
00154 m_cutBnds[0] = i_ref.m_cutBnds[0];
00155 m_cutBnds[1] = i_ref.m_cutBnds[1];
00156 m_nPts = i_ref.m_nPts;
00157 m_dimSize = i_ref.m_dimSize;
00158
00159 if (m_bucket) {
00160 delete [] m_bucket;
00161 }
00162 m_bucket = new KDPoint<KDData>[m_nPts];
00163
00164 if (m_bucketIdx) {
00165 delete [] m_bucketIdx;
00166 }
00167 m_bucketIdx = new int[m_nPts];
00168
00169 for (int i=0; i<m_nPts; ++i) {
00170 m_bucket[i] = i_ref.m_bucket[i];
00171 m_bucketIdx[i] = i_ref.m_bucketIdx[i];
00172 }
00173
00174 m_children[0] = i_ref.m_children[0];
00175 m_children[1] = i_ref.m_children[1];
00176
00177 return *this;
00178 }
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188 void printOn(std::ostream &out) const
00189 {
00190 out << "<KDNode " << std::endl;
00191 if (m_children[KDN_LOW] == NULL &&
00192 m_children[KDN_HIGH] == NULL &&
00193 m_bucket != NULL) {
00194 out << "<Type Leaf " << std::endl;
00195 out << "<NumPts " << m_nPts << " >" << std::endl;
00196 out << "<DimSize " << m_dimSize << " >" << std::endl;
00197
00198 out << "<Bucket " << std::endl;
00199 for (int i=0; i<m_nPts; ++i) {
00200 m_bucket[i].printOn(out);
00201 }
00202 out << " >" << std::endl;
00203
00204 out << "<BucketIdx ";
00205 for (int i=0; i<m_nPts; ++i) {
00206 out << m_bucketIdx[i] << " ";
00207 }
00208 out << " >" << std::endl;
00209
00210 out << " >" << std::endl;
00211 out << " >" << std::endl;
00212 }
00213 else {
00214 out << "<Type Internal " << std::endl;
00215 out << "<CutDim " << m_cutDim << " >" << std::endl;
00216 out << "<CutVal " << m_cutVal << " >" << std::endl;
00217 out << "<CutBounds " << m_cutBnds[0] << " " << m_cutBnds[1]
00218 << " >" << std::endl;
00219
00220 if (m_children[KDN_LOW] != NULL) {
00221 out << "<LowChild " << std::endl;
00222 m_children[KDN_LOW]->printOn(out);
00223 out << " >" << std::endl;
00224 }
00225
00226 if (m_children[KDN_HIGH] != NULL) {
00227 out << "<HighChild " << std::endl;
00228 m_children[KDN_HIGH]->printOn(out);
00229 out << " >" << std::endl;
00230 }
00231
00232 out << " >" << std::endl;
00233 out << " >" << std::endl;
00234 }
00235
00236 out << " >" << std::endl;
00237 }
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247 void readFrom(std::istream &in)
00248 {
00249 std::string tag;
00250
00251 while (1) {
00252 char ch;
00253 in >> ch;
00254
00255 if (ch == '>') {
00256 break;
00257 }
00258 else if (ch != '<') {
00259 throw new FD::GeneralException ("KDNode::readFrom : Parse error: '<' expected",__FILE__,__LINE__);
00260 }
00261
00262 in >> tag;
00263
00264 if (tag == "KDNode") {
00265 continue;
00266 }
00267 else if (tag == "Type") {
00268 in >> tag;
00269 if (tag == "Internal") {
00270 try {
00271 readFromInternal(in);
00272 }
00273 catch (FD::GeneralException *e) {
00274 throw e;
00275 }
00276 }
00277 else if (tag == "Leaf") {
00278 try {
00279 readFromLeaf(in);
00280 }
00281 catch (FD::GeneralException *e) {
00282 throw e;
00283 }
00284 }
00285 else {
00286 throw new FD::GeneralException ("KDNode::readFrom : unknown KDNode type",__FILE__,__LINE__);
00287 }
00288 }
00289 else {
00290 throw new FD::GeneralException ("KDNode::readFrom : Unknown argument: " + tag,__FILE__,__LINE__);
00291 }
00292
00293 if (!in) {
00294 throw new FD::GeneralException ("KDNode::readFrom : Parse error trying to build " + tag,__FILE__,__LINE__);
00295 }
00296
00297 in >> tag;
00298 if (tag != ">") {
00299 throw new FD::GeneralException ("KDNode::readFrom : Parse error: '>' expected ",__FILE__,__LINE__);
00300 }
00301 }
00302 }
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324 void NNSearch(KDPoint<KDData> *i_qp, int i_maxNumNodes, int &io_numVisited,
00325 double i_maxErr, double io_bbDist, KDPQueue<double, int> *io_nnQueue)
00326 {
00327 if (m_children[KDN_LOW] == NULL &&
00328 m_children[KDN_HIGH] == NULL &&
00329 m_bucket != NULL) {
00330 NNBucketSearch(i_qp, io_numVisited, io_nnQueue);
00331 }
00332 else if (m_children[KDN_LOW] != NULL || m_children[KDN_HIGH] != NULL) {
00333 NNNodeSearch(i_qp, i_maxNumNodes, io_numVisited, i_maxErr, io_bbDist,
00334 io_nnQueue);
00335 }
00336 }
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358 void NNSearch(KDPoint<KDData> *i_qp, int i_maxNumNodes, int &io_numVisited,
00359 double i_maxErr, double io_bbDist, KDPQueue<double, KDPoint<KDData> > *io_nnQueue)
00360 {
00361 if (m_children[KDN_LOW] == NULL &&
00362 m_children[KDN_HIGH] == NULL &&
00363 m_bucket != NULL) {
00364 NNBucketSearch(i_qp, io_numVisited, io_nnQueue);
00365 }
00366 else if (m_children[KDN_LOW] != NULL || m_children[KDN_HIGH] != NULL) {
00367 NNNodeSearch(i_qp, i_maxNumNodes, io_numVisited, i_maxErr, io_bbDist,
00368 io_nnQueue);
00369 }
00370 }
00371
00372 private:
00373
00374
00375
00376
00377
00378
00379
00380
00381 void readFromInternal(std::istream &in)
00382 {
00383 std::string tag;
00384
00385 while (1) {
00386 char ch;
00387 in >> ch;
00388
00389 if (ch == '>') {
00390 break;
00391 }
00392 else if (ch != '<') {
00393 throw new FD::GeneralException ("KDNode::readFromInternal : Parse error: '<' expected",__FILE__,__LINE__);
00394 }
00395
00396 in >> tag;
00397
00398 if (tag == "CutDim") {
00399 in >> m_cutDim;
00400 }
00401 else if (tag == "CutVal") {
00402 in >> m_cutVal;
00403 }
00404 else if (tag == "CutBounds") {
00405 in >> m_cutBnds[0];
00406 in >> m_cutBnds[1];
00407 }
00408 else if (tag == "LowChild") {
00409 try {
00410
00411 m_children[KDN_LOW] = new KDNode<KDData>();
00412 m_children[KDN_LOW]->readFrom(in);
00413 }
00414 catch (FD::GeneralException *e) {
00415 throw e;
00416 }
00417 }
00418 else if (tag == "HighChild") {
00419 try {
00420
00421 m_children[KDN_HIGH] = new KDNode<KDData>();
00422 m_children[KDN_HIGH]->readFrom(in);
00423 }
00424 catch (FD::GeneralException *e) {
00425 throw e;
00426 }
00427 }
00428 else {
00429 throw new FD::GeneralException ("KDNode::readFromInternal : Unknown argument: " + tag,__FILE__,__LINE__);
00430 }
00431
00432 if (!in) {
00433 throw new FD::GeneralException ("KDNode::readFromInternal : Parse error trying to build " + tag,__FILE__,__LINE__);
00434 }
00435
00436 in >> tag;
00437 if (tag != ">") {
00438 throw new FD::GeneralException ("KDNode::readFromInternal : Parse error: '>' expected ",__FILE__,__LINE__);
00439 }
00440 }
00441 }
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451 void readFromLeaf(std::istream &in)
00452 {
00453 std::string tag;
00454
00455 while (1) {
00456 char ch;
00457 in >> ch;
00458
00459 if (ch == '>') {
00460 break;
00461 }
00462 else if (ch != '<') {
00463 throw new FD::GeneralException ("KDNode::readFromLeaf : Parse error: '<' expected",__FILE__,__LINE__);
00464 }
00465
00466 in >> tag;
00467
00468 if (tag == "NumPts") {
00469 in >> m_nPts;
00470 }
00471 else if (tag == "DimSize") {
00472 in >> m_dimSize;
00473 }
00474 else if (tag == "BucketIdx") {
00475
00476 m_bucketIdx = new int[m_nPts];
00477
00478 for (int i=0; i<m_nPts; ++i) {
00479 in >> m_bucketIdx[i];
00480 }
00481 }
00482 else if (tag == "Bucket") {
00483 try {
00484
00485 m_bucket = new KDPoint<KDData>[m_nPts];
00486
00487 for (int i=0; i<m_nPts; ++i) {
00488 m_bucket[i].readFrom(in);
00489 }
00490 }
00491 catch (FD::GeneralException *e) {
00492 throw e->add(new FD::GeneralException("In KDNode::readFromLeaf : ",__FILE__,__LINE__));
00493 }
00494 }
00495 else {
00496 throw new FD::GeneralException ("KDNode::readFromLeaf : Unknown argument: " + tag,__FILE__,__LINE__);
00497 }
00498
00499 if (!in) {
00500 throw new FD::GeneralException ("KDNode::readFromLeaf : Parse error trying to build " + tag,__FILE__,__LINE__);
00501 }
00502
00503 in >> tag;
00504 if (tag != ">") {
00505 throw new FD::GeneralException ("KDNode::readFromLeaf : Parse error: '>' expected ",__FILE__,__LINE__);
00506 }
00507 }
00508 }
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523 void NNBucketSearch(KDPoint<KDData> *i_qp, int &io_numVisited,
00524 KDPQueue<double, int> *io_nnQueue)
00525 {
00526 int d;
00527 double dist;
00528 double tmp;
00529 double minDist = io_nnQueue->GetMaxKey();
00530
00531
00532 for (int i=0; i<m_nPts; ++i) {
00533
00534 KDData *bktDataPtr = m_bucket[i].GetPoint();
00535 KDData *queryPtPtr = i_qp->GetPoint();
00536
00537 dist = 0.0;
00538
00539 for (d=0; d<m_dimSize; ++d) {
00540 tmp = (double)(*(bktDataPtr++)) - (double)(*(queryPtPtr++));
00541 dist += tmp*tmp;
00542
00543
00544 if (dist >= minDist) {
00545 break;
00546 }
00547 }
00548
00549
00550 if (d >= m_dimSize && dist < minDist) {
00551 io_nnQueue->Insert(dist, &(m_bucketIdx[i]));
00552 minDist = io_nnQueue->GetMaxKey();
00553 }
00554 }
00555
00556
00557 io_numVisited += m_nPts;
00558 }
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573 void NNBucketSearch(KDPoint<KDData> *i_qp, int &io_numVisited,
00574 KDPQueue<double, KDPoint<KDData> > *io_nnQueue)
00575 {
00576 int d;
00577 double dist;
00578 double tmp;
00579 double minDist = io_nnQueue->GetMaxKey();
00580
00581
00582 for (int i=0; i<m_nPts; ++i) {
00583
00584 KDData *bktDataPtr = m_bucket[i].GetPoint();
00585 KDData *queryPtPtr = i_qp->GetPoint();
00586
00587 dist = 0.0;
00588
00589 for (d=0; d<m_dimSize; ++d) {
00590 tmp = (double)(*(bktDataPtr++)) - (double)(*(queryPtPtr++));
00591 dist += tmp*tmp;
00592
00593
00594 if (dist >= minDist) {
00595 break;
00596 }
00597 }
00598
00599
00600 if (d >= m_dimSize && dist < minDist) {
00601 io_nnQueue->Insert(dist, &(m_bucket[i]));
00602 minDist = io_nnQueue->GetMaxKey();
00603 }
00604 }
00605
00606
00607 io_numVisited += m_nPts;
00608 }
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630 void NNNodeSearch(KDPoint<KDData> *i_qp, int i_maxNumNodes, int &io_numVisited,
00631 double i_maxErr, double io_bbDist, KDPQueue<double, int> *io_nnQueue)
00632 {
00633
00634
00635 if (i_maxNumNodes && io_numVisited >= i_maxNumNodes) {
00636 return;
00637 }
00638
00639 double cutDist = (double)(i_qp->GetCoord(m_cutDim)) - (double)m_cutVal;
00640
00641 if (cutDist < 0.0) {
00642
00643 if (m_children[KDN_LOW] != NULL) {
00644
00645 m_children[KDN_LOW]->NNSearch(i_qp, i_maxNumNodes, io_numVisited,
00646 i_maxErr, io_bbDist, io_nnQueue);
00647
00648 double bboxDiff = (double)(m_cutBnds[KDN_LOW]) - (double)(i_qp->GetCoord(m_cutDim));
00649
00650
00651 if (bboxDiff < 0.0) {
00652 bboxDiff = 0.0;
00653 }
00654
00655
00656 io_bbDist += cutDist*cutDist - bboxDiff*bboxDiff;
00657
00658 if (io_bbDist*i_maxErr < io_nnQueue->GetMaxKey()) {
00659
00660 m_children[KDN_HIGH]->NNSearch(i_qp, i_maxNumNodes, io_numVisited,
00661 i_maxErr, io_bbDist, io_nnQueue);
00662 }
00663 }
00664 }
00665 else {
00666
00667 if (m_children[KDN_HIGH] != NULL) {
00668
00669 m_children[KDN_HIGH]->NNSearch(i_qp, i_maxNumNodes, io_numVisited,
00670 i_maxErr, io_bbDist, io_nnQueue);
00671
00672 double bboxDiff = (double)(i_qp->GetCoord(m_cutDim)) - (double)(m_cutBnds[KDN_HIGH]);
00673
00674
00675 if (bboxDiff < 0.0) {
00676 bboxDiff = 0.0;
00677 }
00678
00679
00680 io_bbDist += cutDist*cutDist - bboxDiff*bboxDiff;
00681
00682 if (io_bbDist*i_maxErr < io_nnQueue->GetMaxKey()) {
00683
00684 m_children[KDN_LOW]->NNSearch(i_qp, i_maxNumNodes, io_numVisited,
00685 i_maxErr, io_bbDist, io_nnQueue);
00686 }
00687 }
00688 }
00689 }
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711 void NNNodeSearch(KDPoint<KDData> *i_qp, int i_maxNumNodes, int &io_numVisited,
00712 double i_maxErr, double io_bbDist, KDPQueue<double, KDPoint<KDData> > *io_nnQueue)
00713 {
00714
00715
00716 if (i_maxNumNodes && io_numVisited >= i_maxNumNodes) {
00717 return;
00718 }
00719
00720 double cutDist = (double)(i_qp->GetCoord(m_cutDim)) - (double)m_cutVal;
00721
00722 if (cutDist < 0.0) {
00723
00724 if (m_children[KDN_LOW] != NULL) {
00725
00726 m_children[KDN_LOW]->NNSearch(i_qp, i_maxNumNodes, io_numVisited,
00727 i_maxErr, io_bbDist, io_nnQueue);
00728
00729 double bboxDiff = (double)(m_cutBnds[KDN_LOW]) - (double)(i_qp->GetCoord(m_cutDim));
00730
00731
00732 if (bboxDiff < 0.0) {
00733 bboxDiff = 0.0;
00734 }
00735
00736
00737 io_bbDist += cutDist*cutDist - bboxDiff*bboxDiff;
00738
00739 if (io_bbDist*i_maxErr < io_nnQueue->GetMaxKey()) {
00740
00741 m_children[KDN_HIGH]->NNSearch(i_qp, i_maxNumNodes, io_numVisited,
00742 i_maxErr, io_bbDist, io_nnQueue);
00743 }
00744 }
00745 }
00746 else {
00747
00748 if (m_children[KDN_HIGH] != NULL) {
00749
00750 m_children[KDN_HIGH]->NNSearch(i_qp, i_maxNumNodes, io_numVisited,
00751 i_maxErr, io_bbDist, io_nnQueue);
00752
00753 double bboxDiff = (double)(i_qp->GetCoord(m_cutDim)) - (double)(m_cutBnds[KDN_HIGH]);
00754
00755
00756 if (bboxDiff < 0.0) {
00757 bboxDiff = 0.0;
00758 }
00759
00760
00761 io_bbDist += cutDist*cutDist - bboxDiff*bboxDiff;
00762
00763 if (io_bbDist*i_maxErr < io_nnQueue->GetMaxKey()) {
00764
00765 m_children[KDN_LOW]->NNSearch(i_qp, i_maxNumNodes, io_numVisited,
00766 i_maxErr, io_bbDist, io_nnQueue);
00767 }
00768 }
00769 }
00770 }
00771
00772 private:
00773
00774 int m_cutDim;
00775
00776 KDData m_cutVal;
00777
00778 KDData m_cutBnds[2];
00779
00780 KDNode *m_children[2];
00781
00782
00783 int m_nPts;
00784
00785 int m_dimSize;
00786
00787 KDPoint<KDData> *m_bucket;
00788
00789 int *m_bucketIdx;
00790 };
00791
00792 }
00793
00794 #endif