00001
00002 #include "edge.h"
00003 #include "node.h"
00004 #include "face.h"
00005 #include "object.h"
00006 #include "point3d.h"
00007 #include "nodearray.h"
00008 #include "edgearray.h"
00009 #include "rasterfont.h"
00010 #include <stdio.h>
00011 #include <math.h>
00012
00013 #ifdef _WIN32
00014 #include <windows.h>
00015 #endif
00016
00017 #ifdef __APPLE__
00018 #include <OpenGL/gl.h>
00019 #else
00020 #include <GL/gl.h>
00021 #endif // __APPLE__
00022
00023 const char* Edge::rcsid = "@(#) $Id: edge.cpp,v 1.59 2006/01/06 19:28:11 craig Exp $ $Copyright: (c)2001 National Biocomputation Center, Stanford University $";
00024
00025
00026 int Edge::debug = 0;
00027
00028 Edge::Edge()
00029 {
00030 node[0] = node[1] = NULL;
00031 splitNode[0] = splitNode[1] = NULL;
00032 marker = -1.0;
00033 boundingsphere = NULL;
00034 }
00035
00036 Edge::~Edge()
00037 {
00038 node[0] = node[1] = NULL;
00039 }
00040
00041
00042 int Edge::init(NodeArray* nodearray_p, EdgeArray* edgearray_p_in,
00043 char *initString)
00044 {
00045 int n1, n2, index;
00046 double restLength_given, springConstant_given, dampConstant_given;
00047
00048
00049 if (sscanf(initString, "%d %d %d %lf %lf %lf", &index, &n1, &n2,
00050 &restLength_given, &springConstant_given, &dampConstant_given) !=6){
00051 printf("Wrong number of arguments in edge data line\n");
00052 return 0;
00053 }
00054
00055
00056 int s = init(nodearray_p, edgearray_p_in, n1, n2, restLength_given,
00057 springConstant_given, dampConstant_given);
00058 return(s);
00059 }
00060
00061
00062 int Edge::init(NodeArray* nodearray_p, EdgeArray* edgearray_p_in,
00063 int i0, int i1, double restLength_in,
00064 double springConstant_in, double dampConstant_in)
00065 {
00066
00067 int numnodes = nodearray_p->getNumNodes();
00068 if ((i0 < 0) || (i1 < 0) || (i0 > numnodes) || (i1 > numnodes)) {
00069 printf("Node numbers in edge data line are out of bounds\n");
00070 return(0);
00071 }
00072 else if (i0 == i1) {
00073 printf("Edge can't connect a node to itself\n");
00074 return(0);
00075 }
00076
00077
00078 Node* n0 = nodearray_p->getNode(i0);
00079 Node* n1 = nodearray_p->getNode(i1);
00080
00081
00082 int s = init(nodearray_p, edgearray_p, n0, n1, restLength_in,
00083 springConstant_in, dampConstant_in);
00084
00085
00086 return(s);
00087 }
00088
00089
00090 int Edge::init(NodeArray* nodearray_p, EdgeArray* edgearray_p_in,
00091 Node* n0, Node* n1, double restLength_in,
00092 double springConstant_in, double dampConstant_in)
00093 {
00094
00095 edgearray_p = edgearray_p_in;
00096 node[0] = n0;
00097 node[1] = n1;
00098
00099
00100 node[0]->addEdgeLink(this);
00101 node[1]->addEdgeLink(this);
00102
00103
00104 switch( (int) restLength_in ) {
00105 case -1: restLength = this->getLength(); break;
00106 case -2: restLength = this->getLength() * 0.95; break;
00107 case -3: restLength = this->getLength() * 1.07; break;
00108 default: restLength = restLength_in; break;
00109 }
00110
00111 springConstant = springConstant_in;
00112 dampConstant = dampConstant_in;
00113
00114 return (1);
00115 }
00116
00117
00118
00119
00120
00121
00122 void Edge::addFaceLink(Face *f)
00123 {
00124 if (debug)
00125 cout << "\nEdge " << getIndex() << " ::addFaceLink(" << f->getIndex() << ")\n";
00126 face.Append(f);
00127
00128 #ifdef TORSION
00129
00130 if (face.NumElements()) {
00131
00132
00133 face[0]->computenormal();
00134 face[1]->computenormal();
00135 init_angle = getAngle();
00136 }
00137 #endif
00138 }
00139
00140 void Edge::addTetraLink(Tetra *t)
00141 {
00142 if (debug)
00143 cerr << "\nEdge " << getIndex() << " ::addTetraLink(" << t->getIndex() << ")\n";
00144 tetra.Append(t);
00145 }
00146
00147 void Edge::deleteFaceLink(Face* f)
00148 {
00149 if (debug)
00150 cout << "\nEdge " << getIndex() << " ::deleteFaceLink(" << f->getIndex() << ")\n";
00151
00152 face.DeleteItem(f);
00153 if (debug)
00154 cout << "ended up with " << face.NumElements() << " face left\n";
00155 }
00156
00157 void Edge::deleteTetraLink(Tetra *t)
00158 {
00159 if (debug)
00160 cout << "\nEdge " << getIndex() << " ::deleteTetraLink(" << t->getIndex() << ")\n";
00161
00162 tetra.DeleteItem(t);
00163 if (debug)
00164 cout << "ended up with " << tetra.NumElements() << " tetra left\n";
00165 }
00166
00167 void Edge::replaceNodeLink(Node* old_node, Node* new_node)
00168 {
00169 for (int i=0; i<2; i++) {
00170 if (node[i] == old_node) node[i] = new_node;
00171 }
00172 }
00173
00174 int Edge::getIndex()
00175 { return(edgearray_p->getIndex(this)); }
00176
00177
00178
00179
00180 double Edge::getAngle(void)
00181 {
00182 Point3D norm1, norm2, vec;
00183 double dot, theta, dot2, retangle;
00184 if (face.NumElements()!= 2) {
00185 printf("called getAngle with face.NumElements() != 2, bad \n");
00186 return (-1);
00187 }
00188
00189 norm1 = face[0]->getNormal();
00190 norm2 = face[1]->getNormal();
00191 dot = norm1.Dot(norm2);
00192 theta = (acos(dot))*(180.0/PI);
00193
00194
00195
00196 Node *n = face[1]->getThirdNode(node[0], node[1]);
00197
00198
00199 vec = n->p - node[0]->p;
00200 dot2 = norm1.Dot(vec);
00201 if (dot2 < 0.0)
00202 retangle = 180.0 + theta;
00203 else
00204 retangle = 180.0 - theta;
00205
00206 if (debug)
00207 printf("edge %d normal angle %f face angle %f \n",
00208 getIndex(), theta, retangle);
00209 return (retangle);
00210 }
00211
00212
00213 void Edge::ComputeSpringForceFullDamp(void)
00214 {
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224 Point3D diff = node[1]->p - node[0]->p;
00225
00226
00227 double normSquared = diff.Squared();
00228
00229
00230 if (normSquared > 0.0) {
00231 Point3D vdiff = node[1]->v - node[0]->v;
00232 double velocityDotSpring = vdiff.Dot(diff);
00233
00234 double springLength = sqrt(normSquared);
00235 double deltaPosition = springLength - restLength;
00236
00237 double totalDampMagnitude =
00238 (dampConstant * velocityDotSpring / normSquared);
00239
00240 force = -((springConstant * deltaPosition / springLength) + totalDampMagnitude) * diff;
00241 }
00242 else {
00243 force = Point3D(0.0, 0.0, 0.0);
00244 }
00245 }
00246
00247
00248 void Edge::ComputeSpringForceRelDamp(void)
00249 {
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259 Point3D diff = node[1]->p - node[0]->p;
00260
00261
00262 double normSquared = diff.Squared();
00263 double springLength = sqrt(normSquared);
00264 double deltaPosition = springLength - restLength;
00265
00266
00267
00268
00269
00270
00271 Point3D vdiff = node[1]->v - node[0]->v;
00272
00273 force = -(springConstant * deltaPosition / springLength) * diff - dampConstant * vdiff;
00274 }
00275
00276
00277
00278
00279
00280
00281
00282 void Edge::ComputeSpringForce(int dampingType)
00283 {
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293 Point3D diff = node[1]->p - node[0]->p;
00294
00295
00296 double normSquared = diff.Squared();
00297 double springLength = sqrt(normSquared);
00298 double deltaPosition = springLength - restLength;
00299
00300
00301
00302 switch (dampingType) {
00303 case ABS:
00304 case NONE:
00305 force = -(springConstant * deltaPosition / springLength) * diff;
00306 break;
00307
00308 case FULL:
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318 if (normSquared > 0.0) {
00319 Point3D vdiff = node[1]->v - node[0]->v;
00320 double velocityDotSpring = vdiff.Dot(diff);
00321
00322 force = -(springConstant * deltaPosition / springLength +
00323 dampConstant * velocityDotSpring / normSquared) * diff;
00324
00325 }
00326 break;
00327
00328 case REL:
00329
00330
00331
00332
00333
00334 Point3D vdiff = node[1]->v - node[0]->v;
00335 force = -(springConstant * deltaPosition / springLength) * diff;
00336 force -= dampConstant*vdiff;
00337 break;
00338
00339
00340 }
00341
00342 }
00343
00344 void Edge::ComputeSpringForceNonlinear(int dampingType)
00345 {
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355 Point3D diff = node[1]->p - node[0]->p;
00356
00357
00358 double normSquared = diff.Squared();
00359 double springLength = sqrt(normSquared);
00360 double deltaPosition = springLength - restLength;
00361
00362 if (normSquared <= 0.0) {
00363
00364 force.x = force.y = force.z = 0.0;
00365 return;
00366 }
00367
00368 double nonlinear_factor = 1.0;
00369 {
00370 double ratio = springLength/restLength;
00371 if (ratio < 1.0 && ratio != 0.0)
00372
00373 ratio = 1/ratio;
00374 if (ratio < 2)
00375 ;
00376 else if (ratio < 4)
00377 nonlinear_factor = 1.2;
00378 else if (ratio < 8)
00379 nonlinear_factor = 1.4;
00380 else if (ratio >= 8)
00381 nonlinear_factor = 1.6;
00382 }
00383
00384
00385
00386
00387 switch (dampingType) {
00388
00389 case FULL:
00390 {
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400 Point3D vdiff = node[1]->v - node[0]->v;
00401
00402 double velocityDotSpring = vdiff.Dot(diff);
00403
00404 double totalDampMagnitude = (dampConstant * velocityDotSpring / normSquared);
00405
00406
00407 force = -(nonlinear_factor * springConstant * deltaPosition / springLength + totalDampMagnitude) * diff;
00408 }
00409 break;
00410
00411 case REL:
00412 {
00413
00414
00415
00416
00417
00418 Point3D vdiff = node[1]->v - node[0]->v;
00419 force = -(nonlinear_factor * springConstant * deltaPosition / springLength) * diff;
00420 force -= dampConstant*vdiff;
00421 }
00422 break;
00423
00424 case ABS:
00425 case NONE:
00426 default:
00427 {
00428
00429 force = -(nonlinear_factor * springConstant * deltaPosition / springLength) * diff;
00430 }
00431 break;
00432
00433 }
00434
00435 }
00436
00437
00438
00439 void Edge::addTorsion(void)
00440 {
00441 if (face.NumElements() == 2) {
00442
00443 face[0]->computenormal();
00444 face[1]->computenormal();
00445
00446 double anglediff = getAngle() - init_angle;
00447 Point3D force1 = (anglediff*TORSION_FORCE)*(face[0]->getNormal());
00448 Point3D force2 = (anglediff*TORSION_FORCE)*(face[1]->getNormal());
00449 Node *n1 = face[0]->getThirdNode(node[0], node[1]);
00450 Node *n2 = face[1]->getThirdNode(node[0], node[1]);
00451 n1->addForce(force1);
00452 n2->addForce(force2);
00453 }
00454 }
00455
00456
00457
00458
00459
00460 double Edge::getEnergy(void)
00461 {
00462 double length = getLength();
00463 double displacement = fabs(length - restLength);
00464 double energy = 0.5*springConstant*displacement*displacement;
00465 return (energy);
00466 }
00467
00468
00469 Point3D Edge::UnitDirectionVector(void)
00470 {
00471 Point3D vect = getNodeLink(1)->p - getNodeLink(0)->p;
00472 vect.Normalize();
00473 return vect;
00474 }
00475
00476
00477
00478 double Edge::EdgeDistanceToPoint(Point3D pt, double *near1)
00479 {
00480 Point3D dirVect;
00481 Node *n0, *n1;
00482 double t;
00483 double dummy;
00484 if (near1 == NULL)
00485 near1 = &dummy;
00486 *near1 = 0.0;
00487
00488 n0 = getNodeLink(0);
00489 n1 = getNodeLink(1);
00490 dirVect = UnitDirectionVector();
00491
00492
00493
00494 t = dirVect.Dot(pt - n0->p);
00495
00496 if( t <= 0 ) {
00497
00498 return( (pt - n0->p).Length() );
00499 }
00500 double length = getLength();
00501 if( t >= length ) {
00502 *near1 = 1.0;
00503 return( (pt - n1->p).Length() );
00504 }
00505
00506 if (length != 0.0)
00507 *near1 = t/length;
00508 return((pt - n0->p - t*dirVect).Length());
00509 }
00510
00511
00512
00513 double Edge::EdgeDistanceToEdge(Edge* e2, double *near1, double *near2)
00514 {
00515 Edge *e1 = this;
00516 double dummy1;
00517 double dummy2;
00518 if (near1 == NULL) {
00519 near1 = &dummy1;
00520 near2 = &dummy2;
00521 }
00522
00523
00524
00525
00526
00527 Point3D p1 = e1->getNodeLink(0)->p;
00528 Point3D p2 = e2->getNodeLink(0)->p;
00529 Point3D v1 = e1->UnitDirectionVector();
00530 Point3D v2 = e2->UnitDirectionVector();
00531 Point3D p2minusp1 = p2 - p1;
00532 Point3D v1crossv2 = v1.Cross(v2);
00533 double denom = v1crossv2.Squared();
00534
00535 if (denom != 0.0) {
00536 double t = (p2minusp1.Determinant(v2, v1crossv2))/denom;
00537 double s = (p2minusp1.Determinant(v1, v1crossv2))/denom;
00538 if (t > 0 && s > 0 && t < e1->getLength() && s < e2->getLength()) {
00539
00540 *near1 = t/(e1->getLength());
00541 *near2 = s/(e2->getLength());
00542 return (((p1 + v1*t) - (p2 + v2*s)).Length());
00543 }
00544 }
00545
00546 double nearA, nearB, nearC, nearD;
00547 double d1 = e1->EdgeDistanceToPoint(p2, &nearA);
00548 double d2 = e1->EdgeDistanceToPoint(e2->getNodeLink(1)->p, &nearB);
00549 double d3 = e2->EdgeDistanceToPoint(p1, &nearC);
00550 double d4 = e2->EdgeDistanceToPoint(e1->getNodeLink(1)->p, &nearD);
00551
00552 double min12 = MIN(d1, d2);
00553 double min34 = MIN(d3, d4);
00554 double min = MIN(min12, min34);
00555
00556 if (d1 == min) {
00557 *near1 = nearA;
00558 *near2 = 0.0;
00559 }
00560 else if (d2 == min) {
00561 *near1 = nearB;
00562 *near2 = 1.0;
00563 }
00564 else if (d3 == min) {
00565 *near1 = 0.0;
00566 *near2 = nearC;
00567 }
00568 else if (d4 == min) {
00569 *near1 = 1.0;
00570 *near2 = nearD;
00571 }
00572 else
00573 printf("Um, problem in EdgeDistanceToEdge\n");
00574
00575 return (min);
00576 }
00577
00578
00579
00580
00581
00582 double Edge::EdgeDistanceToFaceNoIntersect(Face* f, double *near1,
00583 Point3D *nearpt)
00584 {
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594 Point3D nearpt1, nearpt2;
00595 double nearA1, nearA2, nearB1, nearB2, nearC1, nearC2;
00596 Edge *fe0 = f->getEdgeLink(0);
00597 Edge *fe1 = f->getEdgeLink(1);
00598 Edge *fe2 = f->getEdgeLink(2);
00599
00600 double d1 = f->FaceDistanceToPoint(getNodeLink(0)->p, 1, &nearpt1);
00601 double d2 = f->FaceDistanceToPoint(getNodeLink(1)->p, 1, &nearpt2);
00602 double d3 = EdgeDistanceToEdge(fe0, &nearA1, &nearA2);
00603 double d4 = EdgeDistanceToEdge(fe1, &nearB1, &nearB2);
00604 double d5 = EdgeDistanceToEdge(fe2, &nearC1, &nearC2);
00605
00606 double min12 = MIN(d1, d2);
00607 double min34 = MIN(d3, d4);
00608 double min1234 = MIN(min12, min34);
00609 double min = MIN(min1234, d5);
00610
00611
00612 if (d1 == min) {
00613 *near1 = 0.0;
00614 *nearpt = nearpt1;
00615 }
00616 else if (d2 == min) {
00617 *near1 = 1.0;
00618 *nearpt = nearpt2;
00619 }
00620 else if (d3 == min) {
00621 *near1 = nearA1;
00622 *nearpt = fe0->getNodeLink(0)->p + nearA2*
00623 (fe0->getNodeLink(1)->p - fe0->getNodeLink(0)->p);
00624 }
00625 else if (d4 == min) {
00626 *near1 = nearB1;
00627 *nearpt = fe1->getNodeLink(0)->p + nearB2*
00628 (fe1->getNodeLink(1)->p - fe1->getNodeLink(0)->p);
00629 }
00630 else if (d5 == min) {
00631 *near1 = nearC1;
00632 *nearpt = fe2->getNodeLink(0)->p + nearC2*
00633 (fe2->getNodeLink(1)->p - fe2->getNodeLink(0)->p);
00634 }
00635 else
00636 printf("Um, problem in EdgeDistanceToFaceNoIntersect\n");
00637
00638 return (min);
00639 }
00640
00641 void Edge::draw()
00642 {
00643 Node* n1 = getNodeLink(0);
00644 Node* n2 = getNodeLink(1);
00645
00646
00647
00648 if (marker >= 0.0) {
00649
00650 glColor3d(1.0, 0.0, 0.0);
00651 glPointSize(5.0);
00652 Point3D pt = n1->p + marker*(n2->p - n1->p);
00653 glBegin(GL_POINTS);
00654 glVertex3d(pt.x, pt.y, pt.z);
00655 glEnd();
00656
00657 glColor3d(0.0, 1.0, 0.0);
00658 }
00659
00660 glLineWidth(2.0);
00661 glBegin(GL_LINES);
00662 n1->draw(0, 0, 0);
00663 n2->draw(0, 0, 0);
00664 glEnd();
00665 glLineWidth(1.0);
00666 }
00667
00668 void Edge::drawover(double scale)
00669 {
00670
00671 switch (face.NumElements()) {
00672 case 0: glColor3d(1.0, 1.0, 0.0); break;
00673 case 1: glColor3d(0.0, 1.0, 0.0); break;
00674 case 2: glColor3d(0.0, 0.0, 0.0); break;
00675 }
00676
00677 Node* n1 = getNodeLink(0);
00678 Node* n2 = getNodeLink(1);
00679 glBegin(GL_LINES);
00680 n1->drawover(scale);
00681 n2->drawover(scale);
00682 glEnd();
00683 }
00684
00685 void Edge::drawInitial()
00686 {
00687 Node* n1 = getNodeLink(0);
00688 Node* n2 = getNodeLink(1);
00689 glColor3f(0.5, 0.5, 0.5);
00690 glBegin(GL_LINES);
00691 n1->drawinitial();
00692 n2->drawinitial();
00693 glEnd();
00694 }
00695
00696
00697 void Edge::drawlabel(float offset)
00698 {
00699 extern RasterFont* font_p;
00700 char s[20]; sprintf(s, "%d", getIndex());
00701 Node* n1 = getNodeLink(0);
00702 Node* n2 = getNodeLink(1);
00703 Point3D center = (n1->p + n2->p)/2.0;
00704
00705 Point3D avg_normal = (n1->getNormal() + n2->getNormal())/2.0;
00706 Point3D ll = center + offset*avg_normal;
00707
00708 glBegin(GL_LINES);
00709 glVertex3d(center.x, center.y, center.z);
00710 glVertex3d(ll.x, ll.y, ll.z);
00711 glEnd();
00712
00713 font_p->printString(s, ll.x,ll.y,ll.z);
00714 }
00715
00716
00717
00718 int Edge::crossesPlane(double a, double b, double c, double d,
00719 Point3D *intersection_p)
00720 {
00721 Point3D P1 = getNodeLink(0)->p;
00722 Point3D P2 = getNodeLink(1)->p;
00723 double alpha, t;
00724
00725 alpha = a * (P1.x - P2.x) + b * (P1.y - P2.y) + c * (P1.z - P2.z);
00726 if(alpha == 0) return 0;
00727
00728 t = -(a * P2.x + b * P2.y + c * P2.z + d) / alpha;
00729 if ((t < 0) || (t > 1)) return 0;
00730
00731 if (intersection_p) {
00732 intersection_p->x = (P1.x - P2.x) * t + P2.x;
00733 intersection_p->y = (P1.y - P2.y) * t + P2.y;
00734 intersection_p->z = (P1.z - P2.z) * t + P2.z;
00735 }
00736
00737 return 1;
00738 }
00739 int Edge::crossesPlane(Point3D p1, Point3D p2, Point3D p3, Point3D *intPt)
00740 {
00741 int intersects = 0;
00742 double a,b,c,d;
00743 a = p1.y*(p2.z-p3.z) + p2.y*(p3.z - p1.z) + p3.y*(p1.z - p2.z);
00744 b = p1.z*(p2.x-p3.x) + p2.z*(p3.x - p1.x) + p3.z*(p1.x - p2.x);
00745 c = p1.x*(p2.y-p3.y) + p2.x*(p3.y - p1.y) + p3.x*(p1.y - p2.y);
00746 d = -(p1.x*(p2.y*p3.z - p2.z*p3.y) +
00747 p2.x*(p3.y*p1.z - p3.z*p1.y) +
00748 p3.x*(p1.y*p2.z - p1.z*p2.y));
00749 intersects = crossesPlane(a,b,c,d,intPt);
00750 return intersects;
00751 }
00752
00753 int Edge::SanityCheck(EdgeArray* real_ea_p)
00754 {
00755 char s[1024]; s[0] = '\0';
00756 char tmps[1024]; tmps[0] = '\0';
00757
00758
00759 int my_index = -1;
00760 if (!edgearray_p) strcat(s,"edgearray_p is NULL!");
00761 if (edgearray_p != real_ea_p) strcat(s,"edgearray_p is incorrect!");
00762 else {
00763 my_index = getIndex();
00764 if (my_index < 0) { sprintf(tmps, "getIndex() = %d\n", my_index); strcat(s, tmps); }
00765 }
00766
00767
00768 if (restLength <= 0) strcat(s, "restLength <= 0!");
00769 if (springConstant <= 0) strcat(s, "springConstant <= 0!");
00770 if (dampConstant <= 0) strcat(s, "dampConstant <= 0!");
00771 if (face.NumElements() < 0) strcat(s, "face.NumElements() < 0!");
00772 if (face.NumElements() == 0) strcat(s, "face.NumElements() = 0!");
00773
00774 {
00775 for (int i=0; i<2; i++) {
00776 Node* n = getNodeLink(i);
00777 if (!n) {
00778 sprintf(tmps, "nodelink[%d] is NULL!", i);
00779 strcat(s,tmps);
00780 }
00781 else if (!n->hasEdgeLink(this)) {
00782 sprintf(tmps, "nodelink[%d] (%d) does not have a link back to us!", i, n->getIndex() );
00783 strcat(s, tmps);
00784 }
00785 }
00786
00787
00788 if (node[0] == node[1])
00789 strcat(s,"nodelinks point to the same node!\n");
00790 }
00791
00792 {
00793 for (int i=0; i<face.NumElements(); i++) {
00794 Face* f = getFaceLink(i);
00795 if (!f) {
00796 sprintf(tmps, "facelink[%d] is NULL!", i);
00797 strcat(s, tmps);
00798 }
00799 else {
00800 if (!f->hasEdgeLink(this)) {
00801 sprintf(tmps, "facelink[%d] (%d) does not have a link back to us!", i, f->getIndex() );
00802 strcat(s, tmps);
00803 }
00804
00805
00806 for (int j=0; j<i; j++) {
00807 if (f == getFaceLink(j)) {
00808 sprintf(tmps, "facelink[%d] is a duplicate of facelink[%d]!", i, j);
00809 strcat(s, tmps);
00810 }
00811 }
00812 }
00813 }
00814 }
00815
00816
00817 if (strlen(s) > 1) {
00818 cerr << "Edge[" << my_index << "] is INSANE: " << s << endl;
00819 return(0);
00820 }
00821
00822
00823 return(1);
00824 }
00825
00826 ostream& operator<<(ostream& os, const Edge& e_in)
00827 {
00828 Edge& e = (Edge&)e_in;
00829
00830 if (e.edgearray_p)
00831 os << "Edge#" << ((Edge&)e).getIndex() << ": ";
00832 else os << "Edge#UNLINKED: ";
00833
00834
00835 os << ", nodelinks:"
00836 << e.node[0]->getIndex() << " "
00837 << e.node[1]->getIndex();
00838
00839 os << ", facelinks:";
00840 int i;
00841 for ( i=0; i<e.face.NumElements(); i++)
00842 os << e.face[i]->getIndex() << " ";
00843
00844
00845 os << ", tetralinks:";
00846 for ( i=0; i<e.tetra.NumElements(); i++)
00847 os << e.tetra[i]->getIndex() << " ";
00848
00849 return(os);
00850 }
00851 Face* Edge::getOtherFace(Face* f)
00852 {
00853 if (face.NumElements() > 2) {
00854 cout << "can't use this function with this mesh" << endl;
00855 return NULL;
00856 }
00857
00858 if (face.NumElements() == 1) {
00859 if (face[0] == f) return (NULL);
00860 }
00861
00862 if (face[0] == f)
00863 return(face[1]);
00864
00865 else if (face[1] == f)
00866 return(face[0]);
00867
00868 else return(NULL);
00869 }
00870 int Edge::stepOffVerts(Point3D intPt)
00871 {
00872 for (int i=0; i<2; i++) {
00873 if (node[i]->p.Dist(intPt) < 0.00001) {
00874
00875 intPt = .01*(node[(i+1)%3]->p - node[(i+0)%3]->p);
00876 return i;
00877 }
00878 }
00879 return -1;
00880 }
00881 int Edge::intersectsPlaneSweptByCuttingEdge(Edge* e_in, Point3D* intersection_p)
00882 { return 0;}
00883
00884 int Edge::intersectsPlaneSweptFromEntryPt(Point3D entPt, Edge* cuttingEdge,Point3D *intPt)
00885 {
00886
00887 Point3D p2(cuttingEdge->getNodeLink(0)->p.x,
00888 cuttingEdge->getNodeLink(0)->p.y,
00889 cuttingEdge->getNodeLink(0)->p.z);
00890 Point3D p3(cuttingEdge->getNodeLink(1)->p.x,
00891 cuttingEdge->getNodeLink(1)->p.y,
00892 cuttingEdge->getNodeLink(1)->p.z);
00893
00894 int intersects = 0;
00895 intersects =crossesPlane(entPt, p2, p3, intPt);
00896
00897 if (intersects) {
00898 intersects = intPt->insideTriangle(entPt, p2, p3);
00899
00900 }
00901 return intersects;
00902 }
00903
00904
00905 void Edge::ResolveMyself(Edge* other_edge)
00906 {
00907
00908 double myradius = getRadius();
00909 double otherradius = other_edge->getRadius();
00910 double totalradius = otherradius + myradius;
00911
00912
00913 for (int i=0; i<2; i++) {
00914 Node* mynode = getNodeLink(i);
00915
00916 for (int j=0; j<2; j++) {
00917 Node* othernode = other_edge->getNodeLink(j);
00918
00919
00920 double d = mynode->p.Dist(othernode->p);
00921
00922
00923 if (d < totalradius)
00924 mynode->p += (mynode->p - othernode->p) * (totalradius-d);
00925 }
00926 }
00927 }
00928