00001
00002 #include "boundingsphere.h"
00003 #include "object.h"
00004
00005 #ifdef _WIN32
00006 #include <glut.h>
00007 #else
00008 #include <GLUT/glut.h>
00009 #include <OpenGL/gl.h>
00010 #endif
00011
00012
00013
00014 const char* BoundingSphere::rcsid = "@(#) $Id: boundingsphere.cpp,v 1.30 2006/05/24 16:52:40 sean Exp $ $Copyright: (c)2001 National Biocomputation Center, Stanford University $";
00015
00016
00017 #define OLDUPDATE
00018 #ifdef OLDUPDATE
00019 BSLset BoundingSphereLeaf::sphereLeafSet;
00020 #else
00021 BSqueue BoundingSphere::spherePQ;
00022 #endif
00023 int bncount = 0;
00024
00025 int BoundingSphere::debug = 0;
00026 int BoundingSphere::return_first_collision_only = 0;
00027
00029
00031
00032 bool scompare::operator() (const BoundingSphere* s1,
00033 const BoundingSphere* s2) const
00034 { return (s1->level < s2->level); }
00035
00036 void swapptr(void **a, void **b)
00037 {
00038 void* temp = *a;
00039 *a = *b;
00040 *b = temp;
00041 }
00042
00043
00045
00047
00048
00049 BoundingSphere::BoundingSphere(BoundingSphere *parent_)
00050 {
00051 parent = parent_;
00052
00053 if (parent) level = parent->level + 1;
00054 else level = 0;
00055
00056
00057
00058 inQueue = false;
00059 enabled = 1;
00060 }
00061
00062
00063 BoundingSphere::~BoundingSphere()
00064 {
00065
00066 parent = NULL;
00067 center = Point3D(-1, -1, -1);
00068 radius = -1;
00069 level = -1;
00070 inQueue = false;
00071 }
00072
00073
00074
00075
00076 bool BoundingSphere::remainsValid(Point3D newCenter, double newRadius,
00077 double threshold)
00078 {
00079 if ((center.Dist(newCenter) + newRadius) > radius)
00080 return false;
00081
00082 double ratio = radius/newRadius;
00083
00084 if (ratio > threshold)
00085 return false;
00086
00087 return true;
00088 }
00089
00090
00091
00092 Node* BoundingSphere::findClosestNode(BoundingSphere *s, Point3D pt,
00093 double *thresh)
00094 {
00095 if (!s->isLeaf())
00096 return(((BoundingSphereNode *)s)->findClosestNode(pt, thresh));
00097 else
00098 return(((BoundingSphereLeaf *)s)->findClosestNode(pt, thresh));
00099 }
00100
00101 Node* BoundingSphereNode::findClosestNode(Point3D pt, double *thresh)
00102 {
00103
00104 double squaredSep = center.SquaredDist(pt);
00105 if (squaredSep >= (radius + *thresh)*(radius + *thresh))
00106 return(NULL);
00107
00108
00109 Node *nl = BoundingSphere::findClosestNode(left, pt, thresh);
00110
00111
00112 if (right) {
00113 Node *nr = BoundingSphere::findClosestNode(right, pt, thresh);
00114 if (nr)
00115 return(nr);
00116 }
00117 return(nl);
00118 }
00119
00120 Node* BoundingSphereLeaf::findClosestNode(Point3D pt, double *thresh)
00121 {
00122 Node *ret_node = NULL;
00123
00124
00125 double squaredSep = center.SquaredDist(pt);
00126 if (squaredSep >= (radius + *thresh)*(radius + *thresh))
00127 return(ret_node);
00128
00129
00130
00131 double squaredThresh = (*thresh)*(*thresh);
00132 switch (feature_type) {
00133 case tetra_ptr:
00134 squaredSep = pt.SquaredDist(getTetra()->getNodeLink(0)->p);
00135 if (squaredSep < squaredThresh) {
00136 ret_node = getTetra()->getNodeLink(0);
00137 *thresh = sqrt(squaredSep);
00138 squaredThresh = squaredSep;
00139 }
00140 squaredSep = pt.SquaredDist(getTetra()->getNodeLink(1)->p);
00141 if (squaredSep < squaredThresh) {
00142 ret_node = getTetra()->getNodeLink(1);
00143 *thresh = sqrt(squaredSep);
00144 squaredThresh = squaredSep;
00145 }
00146 squaredSep = pt.SquaredDist(getTetra()->getNodeLink(2)->p);
00147 if (squaredSep < squaredThresh) {
00148 ret_node = getTetra()->getNodeLink(2);
00149 *thresh = sqrt(squaredSep);
00150 squaredThresh = squaredSep;
00151 }
00152 squaredSep = pt.SquaredDist(getTetra()->getNodeLink(3)->p);
00153 if (squaredSep < squaredThresh) {
00154 ret_node = getTetra()->getNodeLink(2);
00155 *thresh = sqrt(squaredSep);
00156 squaredThresh = squaredSep;
00157 }
00158 break;
00159
00160 case face_ptr:
00161 squaredSep = pt.SquaredDist(getFace()->getNodeLink(0)->p);
00162 if (squaredSep < squaredThresh) {
00163 ret_node = getFace()->getNodeLink(0);
00164 *thresh = sqrt(squaredSep);
00165 squaredThresh = squaredSep;
00166 }
00167 squaredSep = pt.SquaredDist(getFace()->getNodeLink(1)->p);
00168 if (squaredSep < squaredThresh) {
00169 ret_node = getFace()->getNodeLink(1);
00170 *thresh = sqrt(squaredSep);
00171 squaredThresh = squaredSep;
00172 }
00173 squaredSep = pt.SquaredDist(getFace()->getNodeLink(2)->p);
00174 if (squaredSep < squaredThresh) {
00175 ret_node = getFace()->getNodeLink(2);
00176 *thresh = sqrt(squaredSep);
00177 squaredThresh = squaredSep;
00178 }
00179 break;
00180 case edge_ptr:
00181 squaredSep = pt.SquaredDist(getEdge()->getNodeLink(0)->p);
00182 if (squaredSep < squaredThresh) {
00183 ret_node = getEdge()->getNodeLink(0);
00184 *thresh = sqrt(squaredSep);
00185 squaredThresh = squaredSep;
00186 }
00187 squaredSep = pt.SquaredDist(getEdge()->getNodeLink(1)->p);
00188 if (squaredSep < squaredThresh) {
00189 ret_node = getEdge()->getNodeLink(1);
00190 *thresh = sqrt(squaredSep);
00191 squaredThresh = squaredSep;
00192 }
00193 break;
00194 case node_ptr:
00195 squaredSep = pt.SquaredDist(getNode()->p);
00196 if (squaredSep < squaredThresh) {
00197 ret_node = getNode();
00198 *thresh = sqrt(squaredSep);
00199 squaredThresh = squaredSep;
00200 }
00201 break;
00202 }
00203
00204
00205
00206 return(ret_node);
00207 }
00208
00209 int BoundingSphere::hasAncestor(BoundingSphere* b)
00210 {
00211 BoundingSphere* ptr = this;
00212
00213 while (ptr != NULL) {
00214 if (ptr == b) return(1);
00215 ptr = ptr->getParent();
00216 }
00217
00218
00219 return(0);
00220 }
00221
00222 int BoundingSphere::getDepth()
00223 {
00224 BoundingSphere* parent = getParent();
00225
00226 if (parent == NULL) return(1);
00227 else return ( 1+ parent->getDepth() );
00228 }
00229
00230 BoundingSphereNode* BoundingSphere::findCommonAncestor(BoundingSphere* b[],
00231 int num)
00232 {
00233 if (num <= 0) return(NULL);
00234
00235
00236 BoundingSphere* cur = b[0]->getParent();
00237
00238
00239 for (int i=0; i<num; i++) {
00240
00241 while (!b[i]->hasAncestor(cur) && (cur != NULL)) {
00242 cur = cur->getParent();
00243 }
00244 }
00245
00246 return((BoundingSphereNode*)cur);
00247 }
00248
00249
00250 void BoundingSphere::markTreeEnabled(int enabled_)
00251 {
00252
00253 enabled = enabled_;
00254
00255
00256 if (!isLeaf()) {
00257 BoundingSphereNode* me = (BoundingSphereNode*)this;
00258 BoundingSphere* my_left = me->getLeft();
00259 BoundingSphere* my_right = me->getRight();
00260 if (my_left) my_left->markTreeEnabled(enabled_);
00261 if (my_right) my_right->markTreeEnabled(enabled_);
00262 }
00263 }
00264
00265
00266 void BoundingSphere::propEnabled(int enabled_)
00267 {
00268
00269 enabled = enabled_;
00270
00271
00272 BoundingSphere* ptr = getParent();
00273 while (ptr) {
00274 ptr->enabled = enabled_;
00275 ptr = ptr->getParent();
00276 }
00277 }
00278
00279 int BoundingSphere::numLeafs()
00280 {
00281
00282 if (isLeaf())
00283 return(1);
00284
00285
00286 BoundingSphereNode* me = (BoundingSphereNode*)this;
00287
00288
00289 BoundingSphere* left = me->getLeft();
00290 BoundingSphere* right = me->getRight();
00291
00292
00293 int num = 0;
00294 if (left) num += left->numLeafs();
00295 if (right) num += right->numLeafs();
00296
00297
00298 return(num);
00299 }
00300
00301 int BoundingSphere::numEnabledLeafs()
00302 {
00303
00304 if (isLeaf())
00305 return( enabled );
00306
00307
00308 BoundingSphereNode* me = (BoundingSphereNode*)this;
00309
00310
00311 BoundingSphere* left = me->getLeft();
00312 BoundingSphere* right = me->getRight();
00313
00314
00315 int num = 0;
00316 if (left) num += left->numEnabledLeafs();
00317 if (right) num += right->numEnabledLeafs();
00318
00319
00320 return(num);
00321 }
00322
00323 int BoundingSphere::dist(BoundingSphere *sa, BoundingSphere *sb, double error,
00324 double init)
00325 {
00326 if (debug==2)
00327 cerr << " BoundingSphere::dist(" << sa << ", " << sb
00328 << ", " << error << ", " << init << ")\n";
00329
00330
00331 if (!sa || !sb) return(0);
00332
00333
00334 if (!sa->enabled) return(0);
00335 if (!sb->enabled) return(0);
00336
00337 if (!sa->isLeaf()) {
00338 if (debug==3) cerr << "sa is not a leaf" << endl;
00339 return (BoundingSphereNode::dist((BoundingSphereNode *)sa, sb, error,
00340 init));
00341 }
00342 if (debug==3) cerr << "sa is a leaf" << endl;
00343
00344 if (!sb->isLeaf()) {
00345 if (debug==3) cerr << "sb is not a leaf" << endl;
00346 return (BoundingSphereNode::dist((BoundingSphereNode *)sb, sa, error,
00347 init));
00348 }
00349 if (debug==3) cerr << "sb is a leaf" << endl;
00350
00351 return (BoundingSphereLeaf::dist((BoundingSphereLeaf *)sa,
00352 (BoundingSphereLeaf *)sb, error, init));
00353 }
00354
00355
00356
00357 int BoundingSphere::addLeaf(BoundingSphereLeaf *sa, BoundingSphere *sb)
00358 {
00359 if (debug==2) cerr << "BoundingSphere::addLeaf " << endl;
00360
00361 if (!sa->isLeaf()) {
00362 if (debug==3) cerr << "sa is not a leaf" << endl;
00363 return (0);
00364 }
00365
00366 if (!sb->isLeaf()) {
00367
00368 int split = 0;
00369
00370 const Point3D &acenter = sa->getCenter();
00371
00372 double sacenter[3];
00373 sacenter[0] = acenter.x;
00374 sacenter[1] = acenter.y;
00375 sacenter[2] = acenter.z;
00376
00377 const Point3D &bcenter = ((BoundingSphereNode*)sb)->getCenter();
00378
00379 double sbcenter[3];
00380 sbcenter[0] = bcenter.x;
00381 sbcenter[1] = bcenter.y;
00382 sbcenter[2] = bcenter.z;
00383
00384 if ((sbcenter[1] - sacenter[1]) > (sbcenter[split] - sacenter[split]))
00385 split = 1;
00386 if ((sbcenter[2] - sacenter[2]) > (sbcenter[split] - sacenter[split]))
00387 split = 2;
00388
00389 if (sacenter[split] < sbcenter[split]) {
00390 return(BoundingSphere::addLeaf(sa, ((BoundingSphereNode*)sb)->getLeft() ));
00391 }
00392 else {
00393 return(BoundingSphere::addLeaf(sa, ((BoundingSphereNode*)sb)->getRight() ));
00394 }
00395 }
00396
00397
00398
00399
00400 BoundingSphereNode* sc = ((BoundingSphereNode*)sb->parent);
00401
00402
00403
00404
00405 if ( sc->getLeft() == sb ) {
00406 BoundingSphereNode* mid = new BoundingSphereNode(sb,sa,sc);
00407 sc->setLeft(mid);
00408 mid->setParent(sc);
00409 }
00410 else {
00411 BoundingSphereNode* mid = new BoundingSphereNode(sa,sb,sc);
00412 sc->setRight(mid);
00413 mid->setParent(sc);
00414 }
00415
00416 return (1);
00417 }
00418
00419
00420 int BoundingSphere::removeLeaf(BoundingSphereLeaf *sa)
00421 {
00422 if (debug==1) cerr << "BoundingSphere::removeLeaf " << endl;
00423
00424 if (!sa->isLeaf()) {
00425 if (debug==1) cerr << "sa is not a leaf" << endl;
00426 return (0);
00427 }
00428
00429 BoundingSphereLeaf *buddy = NULL;
00430 BoundingSphereNode *oneUp = NULL;
00431 oneUp = (BoundingSphereNode*)sa->parent;
00432
00433 if (oneUp) {
00434 if (sa == oneUp->getLeft()){
00435 buddy = (BoundingSphereLeaf*)((BoundingSphereNode*)oneUp)->getRight();
00436 oneUp->setRight(NULL);
00437 }
00438 else {
00439 buddy = (BoundingSphereLeaf*)((BoundingSphereNode*)oneUp)->getLeft();
00440 oneUp->setLeft(NULL);
00441 }
00442
00443
00444 BoundingSphereNode *twoUp = NULL;
00445 twoUp = (BoundingSphereNode*)oneUp->parent;
00446
00447 if (twoUp) {
00448 if (oneUp == twoUp->getLeft()){
00449 twoUp->setLeft(buddy);
00450 buddy->setParent(twoUp);
00451 }
00452 else{
00453 twoUp->setRight(buddy);
00454 buddy->setParent(twoUp);
00455 }
00456 delete ((BoundingSphereNode *)oneUp);
00457 }
00458 else {
00459 if(buddy == NULL){
00460 delete ((BoundingSphereNode *)oneUp);
00461 return (1);
00462 } else {
00463 sa->getFeatureObject()->setBoundingSphereRoot((BoundingSphereNode *)buddy);
00464 buddy->setParent(NULL);
00465 delete ((BoundingSphereNode *)oneUp);
00466 return (1);
00467 }
00468 }
00469
00470 }
00471 else {
00472
00473 sa->getFeatureObject()->setBoundingSphereRoot(NULL);
00474 delete ((BoundingSphereLeaf *)sa);
00475 }
00476
00477 return (1);
00478
00479 }
00480
00481
00483
00485
00486
00487 void BoundingSphereNode::drawSubtree()
00488 {
00489
00490 if (left)
00491 if (left->isLeaf())
00492 ((BoundingSphereLeaf *)left)->draw();
00493 else
00494 ((BoundingSphereNode *)left)->drawSubtree();
00495 if (right)
00496 if (right->isLeaf())
00497 ((BoundingSphereLeaf *)right)->draw();
00498 else
00499 ((BoundingSphereNode *)right)->drawSubtree();
00500
00501
00502 glColor4f((level+1)%2, ((level+1)%3)/2.0, ((level+1)%5)/4.0, 0.2);
00503 glTranslated(center.x, center.y, center.z);
00504 glutSolidSphere(radius, 8, 8);
00505 glTranslated(-center.x, -center.y, -center.z);
00506 }
00507
00508
00509 BoundingSphereNode::BoundingSphereNode(BoundingSphere *left_,
00510 BoundingSphere *right_, BoundingSphere *parent_)
00511 : BoundingSphere(parent_)
00512 {
00513
00514
00515 left = left_;
00516 right = right_;
00517
00518 if (left) {
00519 left->parent = this;
00520 left->level = level + 1;
00521 }
00522 if (right) {
00523 right->parent = this;
00524 right->level = level + 1;
00525 }
00526
00527 bncount++;
00528 if (debug==3)
00529 cerr << "making node " << this << " with " << left << " and "
00530 << right << endl;
00531
00532 procChange();
00533 }
00534
00535
00536 BoundingSphereNode::BoundingSphereNode(BSlist &sphereList,
00537 BoundingSphere *parent_)
00538 : BoundingSphere(parent_)
00539 {
00540 bncount++;
00541 if (debug==3) {
00542 cerr << "making node " << this << " with " << sphereList.NumElements()
00543 << " children to be sorted" << endl;
00544 }
00545
00546
00547 BSlist leftList, rightList;
00548
00549 double min[3] = { LARGE, LARGE, LARGE};
00550 double max[3] = {-LARGE, -LARGE, -LARGE};
00551
00552 double mid;
00553
00554 int split = 0;
00555
00556 {
00557 for (int sphereIter=0; sphereIter<sphereList.NumElements(); sphereIter++) {
00558
00559 BoundingSphere *cur = sphereList[sphereIter];
00560 const Point3D ¢er = cur->getCenter();
00561
00562 double ncenter[3];
00563 ncenter[0] = center.x;
00564 ncenter[1] = center.y;
00565 ncenter[2] = center.z;
00566
00567 for (int i = 0; i < 3; i++) {
00568 if (ncenter[i] < min[i])
00569 min[i] = ncenter[i];
00570 if (ncenter[i] > max[i])
00571 max[i] = ncenter[i];
00572 }
00573 }
00574 }
00575
00576 if ((max[1] - min[1]) > (max[split] - min[split]))
00577 split = 1;
00578 if ((max[2] - min[2]) > (max[split] - min[split]))
00579 split = 2;
00580
00581 mid = (min[split] + max[split]) / 2;
00582
00583
00584
00585 for (int sphereIter=0; sphereIter < sphereList.NumElements(); sphereIter++) {
00586 BoundingSphere *cur = sphereList[sphereIter];
00587 const Point3D ¢er = cur->getCenter();
00588
00589 double ncenter[3];
00590 ncenter[0] = center.x;
00591 ncenter[1] = center.y;
00592 ncenter[2] = center.z;
00593
00594 if (ncenter[split] < mid) {
00595 leftList.Append(cur);
00596 } else {
00597 rightList.Append(cur);
00598 }
00599 }
00600
00601
00602 if ( leftList.NumElements() == 0 && rightList.NumElements() ) {
00603
00604 leftList.Append(rightList[0]);
00605 rightList.DeleteElement(rightList[0]);
00606 }
00607
00608
00609 if (leftList.NumElements() == 1) {
00610 left = leftList[0];
00611
00612 left->parent = this;
00613 left->level = level + 1;
00614 if (debug==2) cerr << "left: " << left << " parent: " << this << endl;
00615 }
00616 else
00617 left = new BoundingSphereNode(leftList, this);
00618
00619
00620 if (rightList.NumElements() == 1) {
00621 right = rightList[0];
00622
00623 right->parent = this;
00624 right->level = level + 1;
00625 if (debug==2) cerr << "right: " << right << " parent: " << this << endl;
00626 }
00627 else
00628 if (rightList.NumElements()) right = new BoundingSphereNode(rightList, this);
00629
00630 procChange();
00631 }
00632
00633
00634 BoundingSphereNode::~BoundingSphereNode()
00635 {
00636 if (left) {
00637 if (left->isLeaf())
00638 delete ((BoundingSphereLeaf *)left);
00639 else
00640 delete ((BoundingSphereNode *)left);
00641 }
00642 if (right) {
00643 if (right->isLeaf())
00644 delete ((BoundingSphereLeaf *)right);
00645 else
00646 delete ((BoundingSphereNode *)right);
00647 }
00648
00649 if (debug && !parent)
00650 cout << "deleting sphere tree\n";
00651
00652 left = NULL;
00653 right = NULL;
00654 }
00655
00656 int BoundingSphereNode::dist(BoundingSphereNode *sa, BoundingSphere *sb,
00657 double error, double init)
00658 {
00659 if (debug==2)
00660 cerr << " BoundingSphereNode::dist(" << sa << ", " << sb
00661 << ", " << error << ", " << init << ")\n";
00662
00663
00664 if (!sb->isLeaf() && (sa->getRadius() < sb->getRadius())) {
00665 swapptr((void **)&sa, (void **)&sb);
00666 }
00667
00668
00669 Point3D sa_center = sa->getCenter(); Point3D sb_center = sb->getCenter();
00670 double sa_radius = sa->getRadius(); double sb_radius = sb->getRadius();
00671 double squaredSep = sa_center.SquaredDist(sb_center);
00672
00673 if (debug==3) {
00674 cerr << "tester " << sa << " center " << sa_center << endl;
00675 cerr << "tester " << sa << " radius " << sa_radius << endl;
00676 cerr << "testee " << sb << " center " << sb_center << endl;
00677 cerr << "testee " << sb << " radius " << sb_radius << endl;
00678 cerr << "squaredSep " << squaredSep << endl;
00679 cerr << "test " << (squaredSep - (sa_radius + sb_radius)) << endl;
00680 }
00681
00682 double radius_sum = sa_radius + sb_radius;
00683 if (squaredSep > (radius_sum * radius_sum)) {
00684 if (debug==3) cerr << "earliest cut out " << endl;
00685 return 0;
00686 }
00687
00688
00689 int ldist = BoundingSphere::dist(sa->left, sb, error, init);
00690
00691
00692
00693 if (return_first_collision_only && ldist)
00694 return ldist;
00695
00696 if (debug==3) cerr << "returning control to dist2 testing right" << endl;
00697
00698
00699 int rdist = 0;
00700 if (sa->right) {
00701 rdist = BoundingSphere::dist(sa->right, sb, error, init);
00702
00703
00704
00705 if (return_first_collision_only && rdist)
00706 return rdist;
00707 }
00708
00709
00710 if (ldist || rdist) return 1;
00711 return 0;
00712 }
00713
00714 bool BoundingSphereNode::procChange()
00715 {
00716 if (debug)
00717 cerr << level << " BSN::procChange " << this << endl;
00718
00719
00720 Point3D lc = left->getCenter();
00721 double lr = left->getRadius();
00722
00723 if (debug==3) {
00724 cerr << left << " left center " << lc << " radius " << lr << endl;
00725 if (left->isLeaf()) cerr << "leaf index " <<
00726 ((BoundingSphereLeaf *)left)->getFeatureIndex()
00727 << endl;
00728 }
00729
00730
00731 double newRadius;
00732 Point3D newCenter;
00733
00734 if (right) {
00735 Point3D rc = right->getCenter();
00736 double rr = right->getRadius();
00737
00738 if (debug==3) {
00739 cerr << right << " right center " << rc << " radius " << rr << endl;
00740 if (right->isLeaf()) cerr << "leaf index " <<
00741 ((BoundingSphereLeaf *)right)->getFeatureIndex()
00742 << endl;
00743 }
00744
00745
00746 double dist = lc.Dist(rc);
00747
00748 if (debug==3) {
00749 cerr << " dist " << dist << endl;
00750 cerr << " dist plus left " << dist + lr << endl;
00751 cerr << " dist plus right " << dist + rr << endl;
00752 }
00753
00754
00755 if ( rr > (dist + lr) ) {
00756 if (debug==1) cerr << " left inside right sphere" << endl;
00757 newRadius = rr;
00758 newCenter = rc;
00759 }
00760 else if ( lr > (dist + rr) ) {
00761 if (debug==1) cerr << " right inside left sphere" << endl;
00762 newRadius = lr;
00763 newCenter = lc;
00764 }
00765 else {
00766 if (debug==3)
00767 cerr << " i'm not in either, just going to add them " << endl;
00768 newRadius = (dist + lr + rr) / 2.0;
00769
00770 if (dist != 0)
00771 newCenter.interp(lc, rc, (newRadius - lr) / dist);
00772 else {
00773 if (lr > rr) {
00774 newCenter = lc;
00775
00776
00777 newRadius = lr;
00778 }
00779 else {
00780 newCenter = rc;
00781 newRadius = rr;
00782 }
00783 }
00784 }
00785 }
00786 else {
00787 if (debug==3) cerr << "no right " << endl;
00788 newCenter = lc;
00789 newRadius = lr;
00790 }
00791
00792
00793 this->center = newCenter;
00794 this->radius = newRadius;
00795 if (debug==3)
00796 cerr << this << " my center " << center << " radius " << radius << endl;
00797
00798
00799 return true;
00800 }
00801
00802
00804
00806 BoundingSphereLeaf::BoundingSphereLeaf(Tetra *tetra_, BoundingSphere *parent_)
00807 : BoundingSphere(parent_)
00808 {
00809 if (debug == 2) {
00810 cout << "BoundingSphereLeaf" << endl;
00811 cout << "parent: " << parent << endl;
00812 }
00813
00814 feature_ptr.tetra = tetra_;
00815 feature_type = tetra_ptr;
00816 if (debug==2) cout << "tetra: " << feature_ptr.tetra << endl;
00817
00818 feature_ptr.tetra->setBoundingSphere(this);
00819
00820 setRadiusAndCenterFromFeature();
00821
00822 if (debug==3) {
00823 cout << "making leaf: " << this << endl;
00824 cout << "tetra: " << getFeatureIndex() << endl;
00825 cout << "radius: " << radius << endl;
00826 cout << "center: " << center << endl;
00827 }
00828
00829 inQueue = false;
00830 }
00831
00832 BoundingSphereLeaf::BoundingSphereLeaf(Face *face_, BoundingSphere *parent_)
00833 : BoundingSphere(parent_)
00834 {
00835 if (debug==2) cerr << "BoundingSphereLeaf" << endl;
00836
00837 feature_ptr.face = face_;
00838 feature_type = face_ptr;
00839 if (debug==2) cerr << "face: " << feature_ptr.face << endl;
00840
00841 feature_ptr.face->setBoundingSphere(this);
00842
00843 setRadiusAndCenterFromFeature();
00844
00845 if (debug==3) {
00846 cerr << "making leaf: " << this << endl;
00847 cerr << "face: " << getFeatureIndex() << endl;
00848 cerr << "radius: " << radius << endl;
00849 cerr << "center: " << center << endl;
00850 cerr << "feature:" << feature_ptr.face->getIndex() << endl;
00851 }
00852 }
00853
00854 BoundingSphereLeaf::BoundingSphereLeaf(Edge *edge_, BoundingSphere *parent_)
00855 : BoundingSphere(parent_)
00856 {
00857 if (debug==2) cerr << "BoundingSphereLeaf" << endl;
00858
00859 feature_ptr.edge = edge_;
00860 feature_type = edge_ptr;
00861 if (debug==2) cerr << "edge: " << feature_ptr.edge << endl;
00862
00863 feature_ptr.edge->setBoundingSphere(this);
00864
00865 setRadiusAndCenterFromFeature();
00866
00867 if (debug==3) {
00868 cerr << "making leaf: " << this << endl;
00869 cerr << "edge: " << getFeatureIndex() << endl;
00870 cerr << "radius: " << radius << endl;
00871 cerr << "center: " << center << endl;
00872 }
00873 }
00874
00875 BoundingSphereLeaf::BoundingSphereLeaf(Node *node_, BoundingSphere *parent_)
00876 : BoundingSphere(parent_)
00877 {
00878 if (debug==2) cerr << "BoundingSphereLeaf" << endl;
00879
00880 feature_ptr.node = node_;
00881 feature_type = node_ptr;
00882 if (debug==2) cerr << "node: " << feature_ptr.node << endl;
00883
00884 feature_ptr.node->setBoundingSphere(this);
00885
00886 setRadiusAndCenterFromFeature();
00887
00888 if (debug==3) {
00889 cerr << "making leaf: " << this << endl;
00890 cerr << "node: " << getFeatureIndex() << endl;
00891 cerr << "radius: " << radius << endl;
00892 cerr << "center: " << center << endl;
00893 }
00894 }
00895
00896
00897 BoundingSphereLeaf::~BoundingSphereLeaf()
00898 {
00899 feature_type = face_ptr;
00900 feature_ptr.face = NULL;
00901 sphereLeafSet.DeleteAll();
00902 }
00903
00904 void BoundingSphereLeaf::draw()
00905 {
00906
00907 glColor4f(1.0, 1.0, 1.0, 0.2);
00908 glTranslated(center.x, center.y, center.z);
00909 glutSolidSphere(radius, 8, 8);
00910 glTranslated(-center.x, -center.y, -center.z);
00911 }
00912
00913 int BoundingSphereLeaf::dist(BoundingSphereLeaf *sa, BoundingSphereLeaf *sb,
00914 double error, double init)
00915 {
00916 if (debug==2)
00917 cerr << " BoundingSphereLeaf::dist(" << sa << ", " << sb
00918 << ", " << error << ", " << init << ")\n";
00919
00920
00921 Point3D sbcent = sb->getCenter();
00922 double squared = sa->getCenter().SquaredDist(sbcent);
00923 double sarad = sa->getRadius(); double sbrad = sb->getRadius();
00924 if (squared > (sarad+sbrad)*(sarad+sbrad))
00925 return 0;
00926
00927
00928 Point3D int_p;
00929 int ret_val = 1;
00930 double dist = 0.0;
00931 double param1 = 0.0, param2 = 0.0;
00932 Point3D nearpt;
00933
00934
00935
00936
00937 if (sa->feature_type == face_ptr && sb->feature_type == face_ptr) {
00938
00939
00940 if (sa->getFeatureObject() == sb->getFeatureObject() &&
00941 (sa == sb || sa->getFace()->isAdjacent(sb->getFace())))
00942 return(0);
00943
00944
00945
00946
00947 if (error > 0.0)
00948 ret_val = 1;
00949 else
00950 ret_val = sa->feature_ptr.face->intersectsFace(sb->feature_ptr.face,
00951 &int_p);
00952
00953 if (!ret_val) return(0);
00954 }
00955
00956
00957
00958
00959 else if (sa->feature_type == edge_ptr && sb->feature_type == edge_ptr) {
00960 int i1 = sa->getEdge()->getIndex();
00961 int i2 = sb->getEdge()->getIndex();
00962 #define SEPARATION 3 // don't want edges closer than this to cause collisions
00963
00964 if (sa->getFeatureObject() == sb->getFeatureObject() &&
00965 i1 < i2+SEPARATION && i1 > i2-SEPARATION)
00966 return(0);
00967
00968
00969 dist = sa->feature_ptr.edge->EdgeDistanceToEdge(sb->feature_ptr.edge,
00970 ¶m1, ¶m2);
00971
00972
00973 if (dist > 0.5*(sa->getFeatureObject()->getEdgeThresh() +
00974 sb->getFeatureObject()->getEdgeThresh()))
00975 return(0);
00976 }
00977
00978
00979
00980
00981 else if ((sa->feature_type == face_ptr && sb->feature_type == edge_ptr) ||
00982 (sa->feature_type == edge_ptr && sb->feature_type == face_ptr)) {
00983
00984
00985
00986
00987 if (sa->feature_type == face_ptr)
00988 swapptr((void **)&sa, (void **)&sb);
00989
00990 dist = sa->feature_ptr.edge->EdgeDistanceToFaceNoIntersect
00991 (sb->feature_ptr.face, ¶m1, &nearpt);
00992
00993
00994 if (dist > 0.5*(sa->getFeatureObject()->getEdgeThresh()))
00995 return(0);
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005 }
01006
01007
01008 else {
01009 return(0);
01010 }
01011
01012
01013 Collision_pair pair;
01014 Object *myObj = sa->getFeatureObject();
01015 Object *otherObj = sb->getFeatureObject();
01016
01017
01018 if (sa->feature_type == edge_ptr && sb->feature_type == edge_ptr) {
01019 int append_flag = 1;
01020 if (myObj == otherObj) {
01021
01022
01023
01024
01025 int i1 = sa->getEdge()->getIndex();
01026 int i2 = sb->getEdge()->getIndex();
01027 for (int k = 0; k < myObj->CollisionPairGetNumElements(); k++) {
01028 int j1 =
01029 myObj->CollisionPairGet(k).mySphere->getEdge()->getIndex();
01030 int j2 =
01031 myObj->CollisionPairGet(k).otherSphere->getEdge()->getIndex();
01032 if ((i1 == j1 && i2 == j2) || (i1 == j2 && i2 == j1))
01033 append_flag = 0;
01034 }
01035 }
01036 if (append_flag) {
01037 pair.mySphere = sa;
01038 pair.otherSphere = sb;
01039 pair.near1 = param1;
01040 pair.near2 = param2;
01041 pair.dist = dist;
01042 myObj->CollisionPairAdd(pair);
01043 }
01044 if (myObj != otherObj) {
01045
01046 pair.mySphere = sb;
01047 pair.otherSphere = sa;
01048 pair.near1 = param2;
01049 pair.near2 = param1;
01050 pair.dist = dist;
01051 otherObj->CollisionPairAdd(pair);
01052 }
01053 }
01054
01055 else if (sa->feature_type == edge_ptr && sb->feature_type == face_ptr) {
01056 pair.mySphere = sa;
01057 pair.otherSphere = sb;
01058 pair.near1 = param1;
01059 pair.int_pt = nearpt;
01060 pair.dist = dist;
01061 myObj->CollisionPairAdd(pair);
01062
01063 pair.mySphere = sb;
01064 pair.otherSphere = sa;
01065 pair.near1 = param1;
01066 pair.int_pt = nearpt;
01067 pair.dist = dist;
01068 otherObj->CollisionPairAdd(pair);
01069 }
01070
01071
01072
01073 else {
01074
01075 pair.mySphere = sa;
01076 pair.otherSphere = sb;
01077 pair.int_pt = int_p;
01078 myObj->CollisionPairAdd(pair);
01079
01080
01081 pair.mySphere = sb;
01082 pair.otherSphere = sa;
01083 otherObj->CollisionPairAdd(pair);
01084 }
01085
01086
01087
01088 if (debug == 2) {
01089 cout << "2:I'm colliding over here: ["
01090 << myObj->getName() << "]-" << sa->getFeatureIndex() << " - ["
01091 << otherObj->getName() << "]-" << sb->getFeatureIndex() << endl;
01092 }
01093
01094
01095 return ret_val;
01096 }
01097
01098 bool BoundingSphereLeaf::procChange()
01099 {
01100 if (debug)
01101 cerr << getFeatureObject()->getName() << " index:" << getFeatureIndex()
01102 << " level:" << level << " BSL::procChange" << endl;
01103
01104
01105
01106
01107 setRadiusAndCenterFromFeature();
01108
01109 if (debug==3) {
01110 cerr << "updating leaf: " << this << endl;
01111 switch (feature_type) {
01112 case tetra_ptr:
01113 cerr << "tetra: " << getFeatureIndex() << endl;
01114 break;
01115 case face_ptr:
01116 cerr << "face: " << getFeatureIndex() << endl;
01117 break;
01118 case edge_ptr:
01119 cerr << "edge: " << getFeatureIndex() << endl;
01120 break;
01121 case node_ptr:
01122 cerr << "node: " << getFeatureIndex() << endl;
01123 break;
01124 }
01125 cerr << "radius: " << radius << endl;
01126 cerr << "center: " << center << endl;
01127 }
01128 return true;
01129 }
01130
01131 void BoundingSphereLeaf::insertInUpdateList()
01132 {
01133
01134 if (!enabled) return;
01135
01136
01137
01138 #ifdef OLDUPDATE
01139 sphereLeafSet.AddElement(this);
01140 #else
01141 if (inQueue == false) {
01142
01143 spherePQ.push(this);
01144 inQueue = true;
01145 }
01146 #endif
01147 }
01148
01149 void BoundingSphereLeaf::processUpdate()
01150 {
01151 if (debug==2) cerr << "BoundingSphereLeaf::processUpdate()" << endl;
01152
01153 #ifdef OLDUPDATE
01154
01155 if (debug==3) cerr << " set size: " << sphereLeafSet.NumElements() << endl;
01156
01157 for (int slsIter=0; slsIter<sphereLeafSet.NumElements(); slsIter++)
01158 (sphereLeafSet[slsIter])->propChange();
01159
01160 sphereLeafSet.DeleteAll();
01161 #else
01162
01163
01164 while (!spherePQ.empty()) {
01165
01166 BoundingSphere *top = spherePQ.top();
01167 spherePQ.pop();
01168
01169 top->procChange();
01170 top->inQueue = false;
01171
01172 if (top->parent && !top->parent->inQueue) {
01173 spherePQ.push(top->parent);
01174 top->parent->inQueue = true;
01175 assert(top->parent->level < top->level);
01176 }
01177 }
01178 #endif
01179 }
01180
01181 void BoundingSphereLeaf::setRadiusAndCenterFromFeature()
01182 {
01183 switch (feature_type) {
01184 case tetra_ptr:
01185 this->radius = feature_ptr.tetra->getRadius();
01186 this->center = feature_ptr.tetra->getCenter();
01187 break;
01188 case face_ptr:
01189 this->radius = feature_ptr.face->getRadius();
01190 this->center = feature_ptr.face->getCenter();
01191 break;
01192 case edge_ptr:
01193
01194 this->radius = MAX(getFeatureObject()->getEdgeThresh(),
01195 feature_ptr.edge->getRadius());
01196 this->center = feature_ptr.edge->getCenter();
01197 break;
01198 case node_ptr:
01199 this->radius = feature_ptr.node->getRadius();
01200 this->center = feature_ptr.node->getCenter();
01201 break;
01202 }
01203 }
01204
01205 Object* BoundingSphereLeaf::getFeatureObject()
01206 {
01207 Object *obj = NULL;
01208 switch (feature_type) {
01209 case tetra_ptr:
01210 obj = feature_ptr.tetra->getTetraArray()->getObject();
01211 break;
01212 case face_ptr:
01213 obj = feature_ptr.face->getFaceArray()->getObject();
01214 break;
01215 case edge_ptr:
01216 obj = feature_ptr.edge->getEdgeArray()->getObject();
01217 break;
01218 case node_ptr:
01219 obj = feature_ptr.node->getNodeArray()->getObject();
01220 break;
01221 }
01222 return (obj);
01223 }
01224
01225 int BoundingSphereLeaf::getFeatureIndex()
01226 {
01227 int index = 0;
01228 switch (feature_type) {
01229 case tetra_ptr:
01230 index = feature_ptr.tetra->getIndex();
01231 break;
01232 case face_ptr:
01233 index = feature_ptr.face->getIndex();
01234 break;
01235 case edge_ptr:
01236 index = feature_ptr.edge->getIndex();
01237 break;
01238 case node_ptr:
01239 index = feature_ptr.node->getIndex();
01240 break;
01241 }
01242 return(index);
01243 }