00001
00002 #include "util.h"
00003 #include <assert.h>
00004 #include "face.h"
00005 #include "facearray.h"
00006 #include "object.h"
00007 #include <math.h>
00008
00009 #ifdef _WIN32
00010 #include <glut.h>
00011 #else
00012 #include <GLUT/glut.h>
00013 #include <OpenGL/gl.h>
00014 #endif
00015
00016 #include "intersection.h"
00017 #include "rasterfont.h"
00018 #include "point3d.h"
00019
00020 const char* Face::rcsid = "@(#) $Id: face.cpp,v 1.69 2006/02/01 20:18:01 craig Exp $ $Copyright: (c)2001 National Biocomputation Center, Stanford University $";
00021
00022 int Face::debug = 0;
00023
00024 Face::Face()
00025 {
00026 facearray_p = NULL;
00027 for (int i=0; i<3; i++) {
00028 node[i] = NULL;
00029 edge[i] = NULL;
00030 }
00031
00032 splitNode[0] = splitNode[1] = NULL;
00033 fakeSplitNode[0] = fakeSplitNode[1] = NULL;
00034 splitEdge[0] = splitEdge[1] = NULL;
00035 num_split_edges = 0;
00036
00037 marker = 0;
00038 boundingsphere = NULL;
00039 }
00040
00041 Face::~Face()
00042 {
00043 facearray_p = NULL;
00044 for (int i=0; i<3; i++) {
00045 node[i] = NULL;
00046 edge[i] = NULL;
00047 }
00048 }
00049
00050 void Face::init(NodeArray* nodearray_p, EdgeArray* edgearray_p,
00051 FaceArray* facearray_p_in, int i0, int i1, int i2)
00052 {
00053
00054 facearray_p = facearray_p_in;
00055
00056
00057 node[0] = nodearray_p->getNode(i0);
00058 node[1] = nodearray_p->getNode(i1);
00059 node[2] = nodearray_p->getNode(i2);
00060
00061
00062 init(nodearray_p, edgearray_p, facearray_p, node[0], node[1], node[2]);
00063 }
00064
00065 void Face::init(NodeArray* nodearray_p, EdgeArray* edgearray_p,
00066 FaceArray* facearray_p_in, Node* n0, Node* n1, Node* n2)
00067 {
00068
00069 Edge* e0 = n0->is_adjacent_to(n1);
00070 if (e0 == NULL)
00071 e0 = edgearray_p->getEdge(edgearray_p->addEdge(n0, n1));
00072
00073
00074 Edge* e1 = n1->is_adjacent_to(n2);
00075 if (e1 == NULL)
00076 e1 = edgearray_p->getEdge(edgearray_p->addEdge(n1, n2));
00077
00078
00079 Edge* e2 = n2->is_adjacent_to(n0);
00080 if (e2 == NULL)
00081 e2 = edgearray_p->getEdge(edgearray_p->addEdge(n2, n0));
00082
00083
00084 init(nodearray_p, edgearray_p, facearray_p_in, n0, n1, n2, e0, e1, e2);
00085 }
00086
00087 void Face::init(NodeArray* nodearray_p, EdgeArray* edgearray_p,
00088 FaceArray* facearray_p_in, Node* n0, Node* n1, Node* n2,
00089 Edge* e0, Edge* e1, Edge* e2)
00090 {
00091
00092 facearray_p = facearray_p_in;
00093 node[0] = n0; node[1] = n1; node[2] = n2;
00094 edge[0] = e0; edge[1] = e1; edge[2] = e2;
00095
00096
00097 for (int i=0; i<3; i++) {
00098
00099 node[i]->addFaceLink(this);
00100
00101
00102 edge[i]->addFaceLink(this);
00103 }
00104 }
00105
00106 void Face::replaceNodeLink(Node* old_node, Node* new_node)
00107 {
00108 for (int i=0; i<3; i++)
00109 if (node[i] == old_node) node[i] = new_node;
00110 }
00111
00112 void Face::replaceNodeLink(int which, Node* new_node)
00113 {
00114 node[which] = new_node;
00115 }
00116
00117
00118 Node *Face::getOppositeNode(Edge *e)
00119 {
00120 if(hasEdgeLink(e) == 0){
00121 cerr << "this face and this edge are not related" << endl;
00122 return NULL;
00123 }
00124 for(int i = 0; i < 3; i ++){
00125 Node *tempN = getNodeLink(i);
00126 if(tempN != e->getNodeLink(0) && tempN != e->getNodeLink(1))
00127 return tempN;
00128 }
00129 return NULL;
00130 }
00131
00132
00133
00134 void Face::replaceEdgeLink(Edge* old_edge, Edge* new_edge)
00135 {
00136 for (int i=0; i<3; i++)
00137 if (edge[i] == old_edge) edge[i] = new_edge;
00138 }
00139
00140 int Face::hasNodeLink(Node* n)
00141 {
00142 for (int i=0; i<3; i++)
00143 if (node[i] == n) return(1);
00144 return(0);
00145 }
00146
00147 void Face::unlink()
00148 {int i;
00149
00150 for ( i=0; i<3; i++) {
00151
00152 node[i]->deleteFaceLink(this);
00153
00154
00155 edge[i]->deleteFaceLink(this);
00156 }
00157 for ( i=0; i<tetra.NumElements(); i++) {
00158 tetra[i]->deleteFaceLink(this);
00159 }
00160 }
00161
00162 int Face::hasEdgeLink(Edge* e)
00163 {
00164 for (int i=0; i<3; i++)
00165 if (edge[i] == e) return(1);
00166 return(0);
00167 }
00168
00169 void Face::setNormal(Point3D normal_in)
00170 { normal = normal_in; }
00171
00172 void Face::SaveAsMesh(ostream& os)
00173 {
00174 for (int i=0; i<3; i++)
00175 os << node[i]->getIndex() << " " ;
00176 os << endl;
00177 }
00178
00179 void Face::draw(int do_texture)
00180 {
00181 for (int i=0; i<3; i++)
00182 node[i]->draw(1, 1, do_texture);
00183 }
00184
00185
00186 void Face::drawlabel(float offset)
00187 {
00188 extern RasterFont* font_p;
00189 char s[20]; sprintf(s, "%d", getIndex());
00190 Point3D center = getCenter();
00191
00192 Point3D ll = center + offset*normal;
00193
00194 glBegin(GL_LINES);
00195 glVertex3d(center.x, center.y, center.z);
00196 glVertex3d(ll.x, ll.y, ll.z);
00197 glEnd();
00198
00199 font_p->printString(s, ll.x,ll.y,ll.z);
00200 }
00201
00202 void Face::drawnormal()
00203 {
00204 Point3D p = getCenter();
00205 glVertex3d(p.x, p.y, p.z);
00206 glVertex3d(p.x+normal.x, p.y+normal.y, p.z+normal.z);
00207 }
00208
00209
00210 void Face::drawmarker()
00211 {
00212 if (!marker) return;
00213
00214
00215 glColor3f(1.0, 0.0, 1.0);
00216 glBegin(GL_LINE_LOOP);
00217 for (int i = 0; i < 3; i++)
00218 getNodeLink(i)->drawover(0.05);
00219 glEnd();
00220 }
00221
00222 int Face::getIndex()
00223 { return(facearray_p->getIndex(this)); }
00224
00225
00226
00227
00228
00229 double Face::ZVolume()
00230 {
00231 double Zvol1 = 0, Zvol2 = 0, Zvol3 = 0, Zvolume = 0;
00232 int minzz = getMinZNode();
00233 Point3D n = getNormal();
00234
00235
00236 Point3D a = node[minzz]->p;
00237
00238 Point3D b = node[(minzz+1)%3]->p;
00239 Point3D c = node[(minzz+2)%3]->p;
00240
00241 Point3D bp, cp;
00242 bp.x = b.x; bp.y = b.y; bp.z = a.z;
00243 cp.x = c.x; cp.y = c.y; cp.z = a.z;
00244
00245 Zvol1 = TetraVol(a,b,c,bp);
00246 Zvol2 = TetraVol(a,bp,cp,c);
00247 Zvol3 = a.z * getZShadowArea();
00248
00249 Zvolume = Zvol1 + Zvol2 + Zvol3;
00250 if(n.z < 0)
00251 Zvolume = -Zvolume;
00252
00253 return Zvolume;
00254 }
00255
00256
00257
00258 double Face::TetraVol(Point3D a, Point3D b,
00259 Point3D c, Point3D d)
00260 {
00261 double vol = 0;
00262 vol = -a.z*b.y*c.x + a.y*b.z*c.x + a.z*b.x*c.y - a.x*b.z*c.y -
00263 a.y*b.x*c.z + a.x*b.y*c.z + a.z*b.y*d.x - a.y*b.z*d.x -
00264 a.z*c.y*d.x + b.z*c.y*d.x + a.y*c.z*d.x - b.y*c.z*d.x -
00265 a.z*b.x*d.y + a.x*b.z*d.y + a.z*c.x*d.y - b.z*c.x*d.y -
00266 a.x*c.z*d.y + b.x*c.z*d.y + a.y*b.x*d.z - a.x*b.y*d.z -
00267 a.y*c.x*d.z + b.y*c.x*d.z + a.x*c.y*d.z - b.x*c.y*d.z;
00268 vol = vol/6.0;
00269 return vol;
00270 }
00271
00272 int Face::getMinZNode()
00273 {
00274 Point3D alpha = node[0]->p, beta = node[1]->p,
00275 gamma = node[2]->p;
00276 if(alpha.z <= beta.z)
00277 {
00278 if(alpha.z <= gamma.z) return 0;
00279 else return 2;
00280 }
00281 else if(beta.z <= gamma.z)
00282 {
00283 if(beta.z <= alpha.z) return 1;
00284 else return 0;
00285 }
00286 else if(gamma.z <= alpha.z)
00287 {
00288 if(gamma.z <= beta.z) return 2;
00289 else return 1;
00290 }
00291 printf("/nPb determining MinZNode, returning 0");
00292 return 0;
00293 }
00294
00295
00296 Node *Face::getThirdNode(Node *n0, Node *n1)
00297 {
00298 if ((n0 == node[0] && n1 == node[1]) || (n0 == node[1] && n1 == node[0]))
00299 return node[2];
00300 else if ((n0 == node[0] && n1 == node[2]) || (n0 == node[2] && n1 == node[0]))
00301 return node[1];
00302 else if ((n0 == node[1] && n1 == node[2]) || (n0 == node[2] && n1 == node[1]))
00303 return node[0];
00304 else {
00305 printf("Input nodes are not both in this face\n");
00306 return NULL;
00307 }
00308 }
00309
00310
00311 double Face::PlaneDistanceToPoint(Point3D pt)
00312 {
00313 if (debug) cerr << "PlaneDistanceToPoint(" << pt << ")\n";
00314
00315
00316
00317 double plane_constant = normal.Dot(node[0]->p);
00318
00319
00320 double pt_constant = normal.Dot(pt);
00321
00322
00323 return (pt_constant - plane_constant);
00324 }
00325
00326
00327
00328 Point3D Face::Projection(Point3D pt)
00329 {
00330 double dist = PlaneDistanceToPoint(pt);
00331 Point3D proj = pt - normal*(dist);
00332 return(proj);
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346 }
00347
00348
00349
00350 double Face::FaceDistanceToPoint(Point3D pt, int early_exit, Point3D *nearpt)
00351 {
00352 int i, test[3];
00353 double dist;
00354 Edge *e1, *e2;
00355 Point3D proj, normal;
00356 Node *p[3];
00357
00358 normal = getNormal();
00359 p[0] = getNodeLink(0);
00360 p[1] = getNodeLink(1);
00361 p[2] = getNodeLink(2);
00362
00363 proj = Projection(pt);
00364
00365
00366
00367 for(i = 0; i < 3; i ++)
00368
00369 test[i] = (((p[(i + 1) % 3]->p - p[i]->p).Cross(pt - p[i]->p)).Dot(normal)
00370 >= 0) ? 0 : 1;
00371
00372 assert(!(test[0] == 1 && test[1] == 1 && test[2] == 1));
00373
00374
00375 if(test[0] == 0 && test[1] == 0 && test[2] == 0) {
00376
00377
00378 if (early_exit)
00379 *nearpt = proj;
00380 return(fabs(PlaneDistanceToPoint(pt)));
00381 }
00382
00383 if (early_exit)
00384 return(99999.9);
00385
00386 for(i = 0; i < 3; i ++){
00387
00388 if(test[i] == 1 && test[(i+1) % 3] == 0 && test[(i+2) % 3] == 0){
00389
00390 e1 = p[i]->findEdgeLink(p[(i+1) % 3]);
00391 dist = e1->EdgeDistanceToPoint(proj);
00392
00393 dist = sqrt(dist * dist + (pt - proj).Squared());
00394 return dist;
00395 }
00396 }
00397
00398 for(i = 0; i < 3; i ++){
00399
00400 if(test[i] == 1 && test[(i+1) % 3] == 1 && test[(i+2) % 3] == 0){
00401
00402 e1 = p[i]->findEdgeLink(p[(i+1) % 3]);
00403 e2 = p[(i+1) % 3]->findEdgeLink(p[(i+2) % 3]);
00404 dist = MIN(e1->EdgeDistanceToPoint(proj),e2->EdgeDistanceToPoint(proj));
00405
00406 dist = sqrt(dist * dist + (pt - proj).Squared());
00407 return dist;
00408 }
00409 }
00410
00411
00412 printf("problem in FaceDistanceToPoint\n");
00413 return(99999.9);
00414 }
00415
00416
00417 int Face::IsColliding(Point3D p)
00418 {
00419 if (debug) cerr << "Face::IsColliding(" << p << ")\n";
00420
00421
00422 const double max_dist = 0.1;
00423 double dist = fabs(PlaneDistanceToPoint(p));
00424 if (dist > max_dist) return(0);
00425
00426 if (debug)
00427 cerr << " distance = " << dist << "(max_dist = " << max_dist << ")\n";
00428
00429
00430 Point3D a = node[0]->p;
00431 Point3D b = node[1]->p;
00432 Point3D c = node[2]->p;
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442 Point3D ab = b - a, ap = p - a;
00443 Point3D n1 = ab.Cross(ap);
00444 if (!(n1.IsZero()))
00445 n1.Normalize();
00446 if ((n1 + normal).Squared() < 1.0) return(0);
00447
00448
00449 Point3D bc = c - b, bp = p - b;
00450 Point3D n2 = bc.Cross(bp);
00451 if (!(n2.IsZero()))
00452 n2.Normalize();
00453 if ((n2 + normal).Squared() < 1.0) return(0);
00454
00455
00456 Point3D ca = a - c, cp = p - c;
00457 Point3D n3 = ca.Cross(cp);
00458 if (!(n3.IsZero()))
00459 n3.Normalize();
00460 if ((n3 + normal).Squared() < 1.0) return(0);
00461
00462
00463 if (debug)
00464 cerr << " it passed all tests- is a collision!\n";
00465
00466
00467 return(1);
00468
00469 #ifdef SLOW_WAY_TO_TEST_SIGNS
00470
00471
00472
00473
00474
00475 n1.Normalize(); n2.Normalize(); n3.Normalize();
00476 if ((n1 + normal).Length() < 1.0) return(0);
00477 if ((n2 + normal).Length() < 1.0) return(0);
00478 if ((n3 + normal).Length() < 1.0) return(0);
00479
00480 #elif defined(BAD_WAY_TO_TEST_SIGNS)
00481
00482 cerr << n1.Sign() << " " << n2.Sign() << " " << n3.Sign() << " "
00483 << normal.Sign() << endl;
00484 if (n1.Sign() != normal.Sign()) return(0);
00485 if (n2.Sign() != normal.Sign()) return(0);
00486 if (n3.Sign() != normal.Sign()) return(0);
00487 #endif
00488 }
00489
00490 Node* Face::getClosestNodeInFace(Point3D pt)
00491 {
00492 double dist0 = node[0]->p.SquaredDist(pt);
00493 double dist1 = node[1]->p.SquaredDist(pt);
00494 double dist2 = node[2]->p.SquaredDist(pt);
00495 if (dist0 < dist1) {
00496 if (dist0 < dist2) return(node[0]);
00497 else return(node[2]);
00498 } else {
00499 if (dist1 < dist2) return(node[1]);
00500 else return(node[2]);
00501 }
00502 }
00503
00504
00505
00506 double Face::getArea()
00507 {
00508 Point3D p1 = node[0]->p;
00509 Point3D p2 = node[1]->p;
00510 Point3D p3 = node[2]->p;
00511 Point3D first_part = p2 - p1;
00512 Point3D last_part = p3 - p1;
00513 Point3D cross_part = first_part.Cross(last_part);
00514
00515 return( cross_part.Length()/2.0 );
00516 }
00517
00518
00519
00520 double Face::getShadowArea()
00521 {
00522 Point3D p1 = node[0]->p;
00523 Point3D p2 = node[1]->p;
00524 Point3D p3 = node[2]->p;
00525 p1.y = p2.y = p3.y = 0;
00526 Point3D first_part = p2 - p1;
00527 Point3D last_part = p3 - p1;
00528 Point3D cross_part = first_part.Cross(last_part);
00529
00530 return( cross_part.Length()/2.0 );
00531 }
00532
00533 double Face::getZShadowArea()
00534 {
00535 Point3D p1 = node[0]->p;
00536 Point3D p2 = node[1]->p;
00537 Point3D p3 = node[2]->p;
00538 p1.z = p2.z = p3.z = 0;
00539 Point3D first_part = p2 - p1;
00540 Point3D last_part = p3 - p1;
00541 Point3D cross_part = first_part.Cross(last_part);
00542
00543 return( cross_part.Length()/2.0 );
00544 }
00545
00546 void Face::getAdjacentFaces(Face** f1_p, Face** f2_p, Face** f3_p)
00547 {
00548 if (!f1_p || !f2_p || !f3_p) return;
00549
00550 {
00551 Face* efa = edge[0]->getFaceLink(0);
00552 Face* efb = edge[0]->getFaceLink(1);
00553 if (efa == this) *f1_p = efb;
00554 else *f1_p = efa;
00555 }
00556
00557 {
00558 Face* efa = edge[1]->getFaceLink(0);
00559 Face* efb = edge[1]->getFaceLink(1);
00560 if (efa == this) *f2_p = efb;
00561 else *f2_p = efa;
00562 }
00563
00564 {
00565 Face* efa = edge[2]->getFaceLink(0);
00566 Face* efb = edge[2]->getFaceLink(1);
00567 if (efa == this) *f3_p = efb;
00568 else *f3_p = efa;
00569 }
00570 }
00571
00572
00573 ostream& operator<<(ostream& os, const Face& f_in)
00574 {
00575 Face& f = (Face&)f_in;
00576 if (f.facearray_p)
00577 os << "Face#" << ((Face&)f).getIndex() << ": ";
00578 else os << "Face#UNLINKED: ";
00579 os << "Nodelinks: " ;
00580 { for (int i=0; i<3; i++) os << f.node[i]->getIndex() << " " ; }
00581 os << ", Edgelinks: ";
00582 { for (int i=0; i<3; i++) os << f.edge[i]->getIndex() << " " ; }
00583 os << ", Tetralinks: ";
00584 { for (int i=0; i<f.tetra.NumElements(); i++) os << f.tetra[i]->getIndex() << " " ; }
00585
00586
00587 os << ", adjfaces: ";
00588 for (int i=0;i<3; i++) {
00589 Edge* cur_edge = ((Face)f).getEdgeLink(i);
00590 Face* other_face = cur_edge->getOtherFace((Face*)&f);
00591 if (other_face)
00592 os << other_face->getIndex() << " ";
00593 else os << "NULL ";
00594 }
00595
00596 return(os);
00597 }
00598
00599 int Face::SanityCheck(FaceArray* real_fa_p)
00600 {
00601 char s[1024]; s[0] = '\0';
00602 char tmps[1024]; tmps[0] = '\0';
00603
00604
00605 int my_index = -1;
00606 if (!facearray_p) strcat(s, "facearray is NULL!");
00607 if (facearray_p != real_fa_p) strcat(s, "facearray is BAD!");
00608 else {
00609 my_index = getIndex();
00610 if (my_index < 0) {
00611 sprintf(tmps, "getIndex() = %d\n", my_index);
00612 strcat(s, tmps);
00613 }
00614 }
00615
00616
00617
00618
00619
00620 Object* obj = getFaceArray()->getObject();
00621 if (obj->getBoundingSphereRoot() && !boundingsphere)
00622 strcat(s, "boundingsphere leaf is NULL");
00623
00624 {
00625 for (int i=0; i<3; i++) {
00626 if (!node[i]) {
00627 sprintf(tmps, "nodelink[%d] is NULL", i);
00628 strcat(s, tmps);
00629 }
00630 else if (!node[i]->hasFaceLink(this)) {
00631 sprintf(tmps, "nodelink[%d] doesn't point back to us!", i);
00632 strcat(s, tmps);
00633 }
00634 }
00635 }
00636
00637 {
00638 for (int i=0; i<3; i++) {
00639 if (!edge[i]) {
00640 sprintf(tmps, "edgelink[%d] is NULL!", i);
00641 strcat(s, tmps);
00642 }
00643 else if (!edge[i]->hasFaceLink(this)) {
00644 sprintf(tmps, "edgelink[%d] doesn't point back to us!", i);
00645 strcat(s, tmps);
00646 }
00647 }
00648 }
00649
00650 {
00651 for (int i=0; i<tetra.NumElements(); i++) {
00652 Tetra* t = tetra[i];
00653 if (!t) {
00654 sprintf(tmps, "tetralink[%d] is NULL!", i);
00655 strcat(s, tmps);
00656 }
00657 else {
00658 if (!t->hasFaceLink(this)) {
00659 sprintf(tmps, "tetralink[%d] does not have a link back to us!", i);
00660 strcat(s, tmps);
00661
00662
00663 for (int j=0; j<i; j++) {
00664 if (t == tetra[j]) {
00665 sprintf(tmps, "tetralink[%d] is a duplicate of tetralink[%d]!", i, j);
00666 strcat(s, tmps);
00667 }
00668 }
00669 }
00670 }
00671 }
00672 }
00673
00674
00675 if (strlen(s) > 1) {
00676 cerr << "Face[" << my_index << "]: is INSANE:" << s << endl;
00677 return(0);
00678 }
00679
00680
00681 return(1);
00682 }
00683
00684
00685
00686
00687 void Face::determinePlaneEq(double *a_p, double *b_p, double *c_p, double *d_p)
00688 {
00689 Point3D pt = getNodeLink(0)->p;
00690 Point3D n = getNormal();
00691 *a_p = n.x;
00692 *b_p = n.y;
00693 *c_p = n.z;
00694 *d_p = - ((*a_p) * pt.x + (*b_p) * pt.y + (*c_p) * pt.z);
00695 }
00696
00697
00698
00699 int Face::intersectsEdge(Edge *e_in, Point3D *intersection_p)
00700 {
00701 if (debug)
00702 cerr << "Face::intersectsEdge(" << e_in << ", " << intersection_p
00703 << ")\n";
00704 double a, b, c, d;
00705 int it_crosses;
00706
00707
00708 determinePlaneEq(&a, &b, &c, &d);
00709
00710
00711
00712 it_crosses = e_in->crossesPlane(a, b, c, d, intersection_p);
00713
00714 if (!it_crosses) return 0;
00715
00716 if (debug) cerr << " it crosses plane!\n";
00717
00718
00719 return (IsColliding(*intersection_p));
00720 }
00721
00722
00723
00724 int Face::intersectsFace(Face *f_in, Point3D *intersection_p)
00725 {
00726 if (debug)
00727 cerr << "Face::intersectsFace(" << f_in << ", " << intersection_p
00728 << ")\n";
00729
00730 #if (1)
00731 Edge *e;
00732 {
00733
00734
00735 for (int i = 0; i < 3; i++) {
00736 e = this->getEdgeLink(i);
00737 if (f_in->intersectsEdge(e, intersection_p)) return 1;
00738 }
00739 }
00740
00741 {
00742 for (int i = 0; i < 3; i++) {
00743 e = f_in->getEdgeLink(i);
00744 if (this->intersectsEdge(e, intersection_p)) return 1;
00745 }
00746 }
00747
00748
00749 return 0;
00750 #else
00751
00752 Point3D thisNormal = this->getNormal();
00753 double thisPlaneConst = thisNormal.Dot(this->getNodeLink(0)->p);
00754
00755 double q0d = thisNormal.Dot(f_in->getNodeLink(0)->p) - thisPlaneConst;
00756 double q1d = thisNormal.Dot(f_in->getNodeLink(1)->p) - thisPlaneConst;
00757 double q2d = thisNormal.Dot(f_in->getNodeLink(2)->p) - thisPlaneConst;
00758
00759
00760 if (((q0d > 0) && (q1d > 0) && (q2d > 0)) ||
00761 ((q0d < 0) && (q1d < 0) && (q2d < 0)))
00762 return 0;
00763
00764 Point3D otherNormal = f_in->getNormal();
00765 double otherPlaneConst = otherNormal.Dot(f_in->getNodeLink(0)->p);
00766
00767 double p0d = otherNormal.Dot(this->getNodeLink(0)->p) - otherPlaneConst;
00768 double p1d = otherNormal.Dot(this->getNodeLink(1)->p) - otherPlaneConst;
00769 double p2d = otherNormal.Dot(this->getNodeLink(2)->p) - otherPlaneConst;
00770
00771
00772 if (((p0d > 0) && (p1d > 0) && (p2d > 0)) ||
00773 ((p0d < 0) && (p1d < 0) && (p2d < 0)))
00774 return 0;
00775
00776
00777 if ((q0d >= 0 && q1d < 0) || (q0d < 0 && q1d >= 0)) {
00778
00779 intersection_p->interp(f_in->getNodeLink(0)->p, f_in->getNodeLink(1)->p,
00780 fabs(q0d)/(fabs(q0d)+fabs(q1d)));
00781
00782 if (this->IsColliding(*intersection_p))
00783 return 1;
00784 }
00785 if ((q0d >= 0 && q2d < 0) || (q0d < 0 && q2d >= 0)) {
00786
00787 intersection_p->interp(f_in->getNodeLink(0)->p, f_in->getNodeLink(2)->p,
00788 fabs(q0d)/(fabs(q0d)+fabs(q2d)));
00789
00790 if (this->IsColliding(*intersection_p))
00791 return 1;
00792 }
00793 if ((q1d >= 0 && q2d < 0) || (q1d < 0 && q2d >= 0)) {
00794
00795 intersection_p->interp(f_in->getNodeLink(1)->p, f_in->getNodeLink(2)->p,
00796 fabs(q1d)/(fabs(q1d)+fabs(q2d)));
00797
00798 if (this->IsColliding(*intersection_p))
00799 return 1;
00800 }
00801
00802
00803 if ((p0d >= 0 && p1d < 0) || (p0d < 0 && p1d >= 0)) {
00804
00805 intersection_p->interp(this->getNodeLink(0)->p, this->getNodeLink(1)->p,
00806 fabs(p0d)/(fabs(p0d)+fabs(p1d)));
00807
00808 if (f_in->IsColliding(*intersection_p))
00809 return 1;
00810 }
00811 if ((p0d >= 0 && p2d < 0) || (p0d < 0 && p2d >= 0)) {
00812
00813 intersection_p->interp(this->getNodeLink(0)->p, this->getNodeLink(2)->p,
00814 fabs(p0d)/(fabs(p0d)+fabs(p2d)));
00815
00816 if (f_in->IsColliding(*intersection_p))
00817 return 1;
00818 }
00819 if ((p1d >= 0 && p2d < 0) || (p1d < 0 && p2d >= 0)) {
00820
00821 intersection_p->interp(this->getNodeLink(1)->p, this->getNodeLink(2)->p,
00822 fabs(p1d)/(fabs(p1d)+fabs(p2d)));
00823
00824 if (f_in->IsColliding(*intersection_p))
00825 return 1;
00826 }
00827
00828 return 0;
00829 #endif
00830 }
00831
00832
00833 bool Face::intersectsEdge(Edge *edge)
00834 {
00835 double a, b, c, d;
00836 Point3D intersectionPoint;
00837
00838
00839 determinePlaneEq(&a, &b, &c, &d);
00840
00841
00842
00843 if (edge->crossesPlane(a, b, c, d, &intersectionPoint)) {
00844
00845 return IsColliding(intersectionPoint);
00846 }
00847 else {
00848 return false;
00849 }
00850 }
00851
00852
00853 bool Face::intersectsFace(Face *otherFace)
00854 {
00855
00856 Intersection* intersection = Intersection::Instance();
00857 return intersection->intersects(this, otherFace);
00858 }
00859
00860
00861 bool Face::intersectsBox(Point3D *min, Point3D *max)
00862 {
00863
00864 Intersection* intersection = Intersection::Instance();
00865 return intersection->intersects(this, min, max);
00866 }
00867
00868
00869 int Face::ResolveMyself(Face *f_in)
00870 {
00871 if (debug) cerr << "Face[" << getIndex() << "]:ResolveMyself()\n";
00872
00873
00874
00875
00876
00877 for (int i=0; i<3; i++) {
00878 Node* movee = node[i];
00879 Point3D b = movee->p - f_in->getCenter();
00880 double vd = f_in->getNormal().Dot(b);
00881
00882
00883
00884
00885
00886 if (vd < 0.0) {
00887 movee->setFext(-vd*f_in->getNormal());
00888
00889
00890
00891
00892
00893 }
00894 }
00895
00896
00897 return(1);
00898 }
00899 void Face::addTetraLink(Tetra *t)
00900 {
00901 if (debug)
00902 cout << "\nFace " << getIndex() << " ::addTetraLink(" << t->getIndex() << ")\n";
00903 tetra.Append(t);
00904 }
00905
00906 void Face::deleteTetraLink(Tetra* t)
00907 {
00908 if (debug)
00909 cout << "\nEdge " << getIndex() << " ::deleteTetraLink(" << t->getIndex() << ")\n";
00910
00911 tetra.DeleteItem(t);
00912
00913 }
00914 int Face::stepOffVerts(Point3D intPt)
00915 {
00916 for (int i=0; i<3; i++) {
00917 if (node[i]->p.Dist(intPt) < 0.00001) {
00918
00919 intPt = .01*(node[(i+1)%3]->p - node[(i+0)%3]->p);
00920 return i;
00921 }
00922 }
00923 return -1;
00924 }
00925
00926 int Face::stepOffEdges(Point3D intPt)
00927 {
00928 for (int i=0; i<3; i++) {
00929 if (edge[i]->EdgeDistanceToPoint(intPt) < 0.00001) {
00930
00931 Point3D vect = edge[i]->getNodeLink(1)->p - edge[i]->getNodeLink(0)->p;
00932 intPt = .01*(normal.Cross(vect));
00933 return i;
00934 }
00935 }
00936 return -1;
00937 }
00938 int Face::getCase(int (&v)[9])
00939 {
00940
00941
00942 int num_edges = 0;
00943 {
00944 for (int i=0; i<3; i++) {
00945 if (edge[i]->getSplitNode(0) != NULL)
00946 num_edges++;
00947 }
00948 }
00949
00950 int num_faces = 0;
00951 if (getSplitNode(0) != NULL) {
00952 num_faces++;
00953 }
00954
00955
00956
00957
00958 Node* n[9];
00959 for (int i=0; i<9; i++) {
00960 n[i] = NULL;
00961 v[i] = -1;
00962 }
00963
00964 if (num_edges == 1) {
00965
00966 if (num_faces == 0) {
00967 cerr << "entered and exited thru the same edge " << endl;
00968 return 2;
00969 }
00970 if (num_faces == 1) {
00971
00972 n[0] = getOppositeNode(splitEdge[0]);
00973 int node0Idx = getNodeIndex(n[0]); cerr << "node[0] index: " << node0Idx << endl;
00974 n[1] = getNodeLink((node0Idx+1)%3); cerr << "node[0] index: " << (node0Idx+1)%3 << endl;
00975 n[2] = getNodeLink((node0Idx+2)%3); cerr << "node[0] index: " << (node0Idx+2)%3 << endl;
00976
00977 n[3] = getSplitNode(0);
00978
00979 for (int i=0; i<4; i++) v[i] = n[i]->getIndex();
00980
00981 n[4] = splitEdge[0]->getSplitNode(0);
00982 n[5] = splitEdge[0]->getSplitNode(1);
00983
00984 if (getFaceArray()->getNodeArray()->getNode(v[1])->isConnectedTo(n[5])){
00985 v[4] = n[5]->getIndex();
00986 v[5] = n[4]->getIndex();
00987 }
00988 else {
00989 v[4] = n[4]->getIndex();
00990 v[5] = n[5]->getIndex();
00991 }
00992 return 0;
00993 }
00994 }
00995 if (num_edges == 2) {
00996 if (num_faces == 0) {
00997
00998
00999 n[0] = splitEdge[1]->getNodeLink(0);
01000 n[1] = splitEdge[1]->getNodeLink(1);
01001
01002 for (int i=0; i<2; i++) {
01003 int numsplit = 0;
01004 for (int j=0; j< n[i]->numEdgeLinks(); j++) {
01005 Edge* myedge = n[i]->getEdgeLink(j);
01006 if (myedge->getSplitNode(0) != NULL && hasEdgeLink(myedge)) {
01007 numsplit++;
01008 }
01009 }
01010 if (numsplit > 1) {
01011 v[0] = n[i]->getIndex();
01012 v[1] = n[(i+1)%2]->getIndex();
01013
01014 break;
01015 }
01016 }
01017 n[2] = getOtherNode(n[0],n[1]);
01018 v[2] = n[2]->getIndex();
01019
01020
01021 if ( getEdgeLinkIndex(splitEdge[1]) == (getEdgeLinkIndex(splitEdge[0])+1)%3 ) {
01022 n[3] = splitEdge[0]->getSplitNode(0);
01023 n[4] = splitEdge[0]->getSplitNode(1);
01024
01025 n[5] = splitEdge[1]->getSplitNode(0);
01026 n[6] = splitEdge[1]->getSplitNode(1);
01027 }
01028
01029 else {
01030 n[3] = splitEdge[1]->getSplitNode(0);
01031 n[4] = splitEdge[1]->getSplitNode(1);
01032
01033 n[5] = splitEdge[0]->getSplitNode(0);
01034 n[6] = splitEdge[0]->getSplitNode(1);
01035
01036 int temp = v[1];
01037 v[1] = v[2];
01038 v[2] = temp;
01039 }
01040
01041 if (getFaceArray()->getNodeArray()->getNode(v[2])->isConnectedTo(n[4])){
01042 v[3] = n[4]->getIndex();
01043 v[4] = n[3]->getIndex();
01044 }
01045 else {
01046 v[3] = n[3]->getIndex();
01047 v[4] = n[4]->getIndex();
01048 }
01049
01050 if (getFaceArray()->getNodeArray()->getNode(v[1])->isConnectedTo(n[6])){
01051 v[5] = n[6]->getIndex();
01052 v[6] = n[5]->getIndex();
01053 }
01054 else {
01055 v[5] = n[5]->getIndex();
01056 v[6] = n[6]->getIndex();
01057 }
01058
01059 if (getFakeSplitNode(0) == NULL) {
01060 Point3D mid; mid.interp(n[3]->p,n[5]->p,.5);
01061 n[7] = getFaceArray()->getNodeArray()->getNode(getFaceArray()->getNodeArray()->addNode(mid));
01062 n[8] = getFaceArray()->getNodeArray()->getNode(getFaceArray()->getNodeArray()->addNode(mid));
01063 setFakeSplitNodes(n[7],n[8]);
01064
01065
01066 }
01067 n[7] = getFakeSplitNode(0);
01068 n[8] = getFakeSplitNode(1);
01069
01070 if (getFaceArray()->getNodeArray()->getNode(v[0])->isConnectedTo(n[7])) {
01071 v[7] = n[8]->getIndex();
01072 v[8] = n[7]->getIndex();
01073 }
01074 else {
01075 v[7] = n[7]->getIndex();
01076 v[8] = n[8]->getIndex();
01077 }
01078
01079 return 1;
01080 }
01081 }
01082
01083
01084
01085
01086
01087 return -1;
01088 }
01089 Node* Face::getOtherNode(Node* n0, Node* n1)
01090 {
01091 if (!hasNodeLink(n0) || !hasNodeLink(n1)) return NULL;
01092
01093 for (int i=0; i<3; i++) {
01094 if (node[i] == n0 || node[i] == n1) continue;
01095 return node[i];
01096 }
01097 return NULL;
01098 }
01099 int Face::intersectsPlaneSweptByCuttingEdge(Edge* e_in, Point3D* intersection_p)
01100 {
01101
01102 if (intersectsEdge(e_in,intersection_p)) return 1;
01103
01104
01105 return 0;
01106 }
01107
01108 int Face::vectorCrossesMe(Point3D P1, Point3D P2, Point3D* intPt)
01109 {
01110 double a, b, c, d;
01111 determinePlaneEq(&a, &b, &c, &d);
01112
01113 double alpha, t;
01114
01115 alpha = a * (P1.x - P2.x) + b * (P1.y - P2.y) + c * (P1.z - P2.z);
01116 if(alpha == 0) return 0;
01117
01118 t = -(a * P2.x + b * P2.y + c * P2.z + d) / alpha;
01119 if ((t < 0) || (t > 1)) return 0;
01120
01121 intPt->x = (P1.x - P2.x) * t + P2.x;
01122 intPt->y = (P1.y - P2.y) * t + P2.y;
01123 intPt->z = (P1.z - P2.z) * t + P2.z;
01124
01125 if (intPt->insideTriangle(node[0]->p, node[1]->p, node[2]->p)) return 1;
01126 return 0;
01127
01128 }
01129 void Face::interpolateTextureCoords(Node* n0)
01130 {
01131 double d[3];
01132 double sum_dist = 0;
01133
01134 Point3D nt[3];
01135
01136 n0->setTextureCoords(Point3D(0,0,0));
01137
01138 for (int i=0; i<3; i++) {
01139 d[i] = node[i]->p.Dist(n0->p);
01140 sum_dist += d[i];
01141 nt[i] = node[i]->getTextureCoords();
01142 }
01143
01144 Point3D text_coords;
01145
01146 text_coords.x = (d[0]*nt[0].x + d[1]*nt[1].x + d[2]*nt[2].x)/sum_dist;
01147 text_coords.y = (d[0]*nt[0].y + d[1]*nt[1].y + d[2]*nt[2].y)/sum_dist;
01148 text_coords.z = (d[0]*nt[0].z + d[1]*nt[1].z + d[2]*nt[2].z)/sum_dist;
01149
01150 n0->setTextureCoords(text_coords);
01151
01152 }
01153 int Face::getEdgeLinkIndex(Edge* e)
01154 {
01155 for (int i=0; i<3; i++)
01156 if (edge[i] == e) return(i);
01157 return(-1);
01158 }
01159 Edge* Face::getEdge(int n0, int n1)
01160 {
01161 for (int i=0; i<3; i++){
01162 if ( (edge[i]->getNodeLink(0)->getIndex() == n0 && edge[i]->getNodeLink(1)->getIndex() == n1) ||
01163 (edge[i]->getNodeLink(1)->getIndex() == n0 && edge[i]->getNodeLink(0)->getIndex() == n1) )
01164 return edge[i];
01165 }
01166 return(NULL);
01167 }
01168
01169
01170
01171 Edge* Face::isEdgeAdjacent(Face *f)
01172 {
01173 for(int x=0; x<3; x++)
01174 for(int z=0; z<3; z++) {
01175 if(this->getEdgeLink(x) == f->getEdgeLink(z))
01176 return f->getEdgeLink(z);
01177 }
01178 return NULL;
01179 }
01180
01181
01182 Point3D Face::getSatelite(Face *f, Node *in)
01183 {
01184 Point3D otherp;
01185 Edge *sharededge;
01186 Node *nearnode;
01187
01188 sharededge = this->isEdgeAdjacent(f);
01189 if(sharededge != NULL)
01190 otherp = sharededge->getOtherNode(in)->p;
01191 else
01192 {
01193 nearnode = this->getClosestNodeInFace(f->getCenter(), in);
01194 otherp = nearnode->p;
01195
01196 }
01197
01198 return otherp;
01199 }
01200
01201
01202 Node* Face::getClosestNodeInFace(Point3D pt, Node* notme)
01203 {
01204 double dist0 = node[0]->p.SquaredDist(pt);
01205 double dist1 = node[1]->p.SquaredDist(pt);
01206 double dist2 = node[2]->p.SquaredDist(pt);
01207 double sum;
01208 int who = 0;
01209
01210
01211 sum = dist0+dist1+dist2;
01212 for(int i=0; i<3; i++){
01213 if(node[i] == notme) who = i;
01214 }
01215 if(who==0) dist0 = sum;
01216 if(who==1) dist1 = sum;
01217 if(who==2) dist2 = sum;
01218
01219 if (dist0 < dist1) {
01220 if (dist0 < dist2) return(node[0]);
01221 else return(node[2]);
01222 } else {
01223 if (dist1 < dist2) return(node[1]);
01224 else return(node[2]);
01225 }
01226 }
01227