00001
00002 #include "edgearray.h"
00003 #include "object.h"
00004 #include "nodearray.h"
00005 #include "edge.h"
00006 #include "node.h"
00007 #include "object.h"
00008 #include "knot.h"
00009 #ifdef _WIN32
00010 #include <glut.h>
00011 #else
00012 #include <GLUT/glut.h>
00013 #include <OpenGL/gl.h>
00014 #endif
00015 #include <stdlib.h>
00016
00017
00018 #include <string>
00019
00020 using namespace std;
00021
00022 const char* EdgeArray::rcsid = "@(#) $Id: edgearray.cpp,v 1.54 2006/05/25 22:23:11 craig Exp $ $Copyright: (c)2001 National Biocomputation Center, Stanford University $";
00023
00024 int EdgeArray::debug = 0;
00025 int default_maxedges = 1000;
00026
00027 EdgeArray::EdgeArray(NodeArray* nodearray_p_in)
00028 : nodearray_p(nodearray_p_in)
00029 {
00030 edges = NULL;
00031 numedges = maxedges = 0;
00032
00033 do_nonlinear = 1;
00034 strcpy(edgefilename, "edge.data");
00035 }
00036
00037 EdgeArray::~EdgeArray()
00038 {
00039 reset();
00040 numedges = maxedges = -1;
00041 }
00042
00043 void EdgeArray::reset(void)
00044 {
00045 if (edges) {
00046
00047 for (int i=0; i<numedges; i++)
00048 delete edges[i];
00049
00050
00051 delete [] edges;
00052 }
00053
00054 numedges = maxedges = 0;
00055 }
00056
00057 void EdgeArray::scaleRestLengths(double scalefactor)
00058 {
00059 for (int i=0; i<numedges; i++)
00060 edges[i]->scaleRestLength(scalefactor);
00061 }
00062
00063 void EdgeArray::computeNewRestLengths()
00064 {
00065 for (int i=0; i<numedges; i++)
00066 edges[i]->computeNewRestLength();
00067 }
00068
00069 int EdgeArray::getIndex(Edge* e)
00070 {
00071
00072 for (int i=0; i<numedges; i++)
00073 if (edges[i] == e)
00074 return(i);
00075
00076
00077 return(-1);
00078 }
00079
00080 void EdgeArray::setEdgeFilename(char *s)
00081 {
00082 strcpy(edgefilename, s);
00083 }
00084
00085 void EdgeArray::allocateEdges(int maxedges_in)
00086 {
00087 numedges=0;
00088 maxedges = maxedges_in;
00089 default_maxedges = maxedges;
00090 edges = new Edge*[maxedges];
00091 if (edges == NULL) {
00092 cerr << "EdgeArray: Could not allocate memory for " << maxedges
00093 << " edges!\n";
00094 }
00095 }
00096
00097 int EdgeArray::addEdge(int i0, int i1, double restLength,
00098 double springConstant, double dampConstant)
00099 {
00100
00101 Node* n0 = nodearray_p->getNode(i0);
00102 Node* n1 = nodearray_p->getNode(i1);
00103
00104
00105 int s = addEdge(n0, n1, restLength, springConstant,
00106 dampConstant);
00107
00108
00109 return(s);
00110 }
00111
00112 int EdgeArray::addEdge(Node* n0, Node* n1, double restLength,
00113 double springConstant,
00114 double dampConstant)
00115 {
00116
00117 if (maxedges == 0) allocateEdges(default_maxedges);
00118
00119
00120 edges[numedges] = new Edge;
00121 edges[numedges]->init(nodearray_p,this, n0,n1,
00122 restLength, springConstant,dampConstant);
00123
00124
00125 if (numedges >= maxedges) {
00126 cerr << "EdgeArray: blew bounds of memory! (" << maxedges << ")\n";
00127 return(numedges);
00128 }
00129 else
00130 return(numedges++);
00131 }
00132
00133
00134
00135 int EdgeArray::getEdgeData() {
00136 FILE *edgefile;
00137 char s[MAXLINE];
00138 int numedges_given;
00139
00140
00141 if ((edgefile = fopen(edgefilename, "r")) == NULL) {
00142 printf("Could not open edge data file\n");
00143 return 0;
00144 }
00145
00146 if (myfgets(s, MAXLINE, edgefile) == NULL) {
00147 printf("No lines in edge data file\n");
00148 return 0;
00149 }
00150 if (sscanf(s, "%d", &numedges_given) != 1) {
00151 printf("Could not read numedges\n");
00152 return 0;
00153 }
00154 printf("%d edges\n", numedges_given);
00155 printf("Edge# Node1# Node2#\n");
00156
00157
00158 allocateEdges((int)(numedges_given * 1.5));
00159
00160
00161 for (int i = 0; i < numedges_given; i++) {
00162 if (myfgets(s, MAXLINE, edgefile) == NULL) {
00163 printf("Not enough edges in data file\n");
00164 return 0;
00165 }
00166
00167
00168 int index = addEdge(0,0,0,0,0);
00169 if (edges[index]->init(nodearray_p, this, s) == 0) {
00170 printf("edges[%d].init failed\n", i);
00171 return 0;
00172 }
00173 if (debug)
00174 printf("%d %d %d\n", edges[i]->getIndex(),
00175 nodearray_p->getIndex(edges[i]->getNodeLink(0)),
00176 nodearray_p->getIndex(edges[i]->getNodeLink(1)));
00177 }
00178 if (fclose(edgefile) == EOF) {
00179 printf("Could not close edge data file\n");
00180 return 0;
00181 }
00182
00183 return 1;
00184 }
00185
00186 void EdgeArray::SaveFrdEdgeData(ostream& os)
00187 {
00188 nodearray_p->CacheIndices();
00189 for (int i=0; i<numedges; i++) {
00190 Edge* ed = getEdge(i);
00191 os << "e";
00192 for (int j=0; j<2; j++) {
00193 Node* n = ed->getNodeLink(j);
00194 os << " " << n->getCachedIndex() + 1;
00195 }
00196 os << endl;
00197 }
00198 }
00199
00200 int EdgeArray::getFRDEdgeData(FILE *meshfile)
00201 {
00202 char s[MAXLINE];
00203 int i, numedges_given;
00204
00205
00206 numedges_given = 0;
00207 while (!feof(meshfile)) {
00208 char s[256];
00209 fgets(s, 256, meshfile);
00210 if (feof(meshfile)) break;
00211 switch (s[0]) {
00212 case 'e' : numedges_given++; break;
00213 case 'f' :
00214 case 'v' :
00215 case '#' :
00216 default :
00217 break;
00218 }
00219 }
00220
00221
00222 fseek(meshfile, 0, SEEK_SET);
00223
00224 printf("%d edges\n", numedges_given);
00225
00226
00227 allocateEdges((int)(numedges_given * 1.5));
00228
00229
00230 for (i = 0; i < numedges_given; i++)
00231 {
00232 do
00233 {
00234 if (myfgets(s, MAXLINE, meshfile) == NULL)
00235 {
00236 printf("Not enough edges in data file\n");
00237 return(0);
00238 }
00239 } while (s[0] != 'e');
00240
00241 {
00242 int i1, i2;
00243 int numread = sscanf(s, "%*c %d %d", &i1, &i2);
00244
00245 if (debug) cerr << "Edge #" << i << ": " << i1 << " "
00246 << i2 << endl;
00247
00248 if (numread != 2)
00249 {
00250 printf("Bad read on edge %d- '%d %d' - IGNORED\n", i, i1,i2);
00251 continue;
00252 }
00253
00254
00255 i1--; i2--;
00256
00257 #ifdef DO_READ_SANITY_CHECKS
00258
00259 int new_index = addEdge(i1,i2);
00260
00261 Edge* new_edge = getEdge(new_index);
00262 int ok = new_edge->SanityCheck(this);
00263
00264
00265 if (!ok)
00266 {
00267
00268 DeleteEdge(new_edge);
00269 }
00270 #else
00271
00272 addEdge(i1,i2);
00273
00274 #endif
00275 }
00276
00277 }
00278
00279
00280 return(1);
00281 }
00282
00283
00284
00285 void EdgeArray::addTorsions(void)
00286 {
00287
00288 for (int i = 0; i < numedges; i++) {
00289 edges[i]->addTorsion();
00290 }
00291 }
00292
00293
00294
00295
00296
00297
00298 void EdgeArray::ComputeForceVectors(int dampingType)
00299 {
00300 int i;
00301
00302 switch (dampingType) {
00303 case FULL:
00304
00305 for (i = 0; i < numedges; i++) {
00306 edges[i]->ComputeSpringForceFullDamp();
00307 }
00308 break;
00309 case REL:
00310
00311 for (i = 0; i < numedges; i++) {
00312 edges[i]->ComputeSpringForceRelDamp();
00313 }
00314 break;
00315 default:
00316
00317 for (i = 0; i < numedges; i++) {
00318 edges[i]->ComputeSpringForce(dampingType);
00319 }
00320 break;
00321 }
00322
00323 }
00324
00325
00326
00327
00328
00329
00330
00331 void EdgeArray::ComputeForceVectorsNonlinear(int dampingType)
00332 {
00333
00334 int i;
00335 for (i = 0; i < numedges; i++) {
00336 edges[i]->ComputeSpringForceNonlinear(dampingType);
00337 }
00338 }
00339
00340
00341
00342
00343 void EdgeArray::KnotIdentify(int testing)
00344 {
00345 extern char knotstring[100];
00346
00347 double zdowker[MAXCROSS];
00348 int zorder[MAXCROSS];
00349 int zdk[MAXCROSS/2];
00350 int zcount = 0;
00351 int i, j;
00352
00353
00354 Edge edummy;
00355 edummy.init(NULL, NULL, getEdge(numedges-1)->getNodeLink(1),
00356 getEdge(0)->getNodeLink(0));
00357
00358
00359 for (i = 0; i < numedges; i++) {
00360
00361 Edge *ea = getEdge(i);
00362 Node *n1 = ea->getNodeLink(0);
00363 Node *n2 = ea->getNodeLink(1);
00364 double x1 = n1->p.x; double y1 = n1->p.y; double z1 = n1->p.z;
00365 double x2 = n2->p.x; double y2 = n2->p.y; double z2 = n2->p.z;
00366
00367 for (j = i+2; j < numedges+1; j++) {
00368
00369 Edge *eb;
00370 if (j == numedges)
00371 eb = &edummy;
00372 else
00373 eb = getEdge(j);
00374 Node *n3 = eb->getNodeLink(0);
00375 Node *n4 = eb->getNodeLink(1);
00376 double x3 = n3->p.x; double y3 = n3->p.y; double z3 = n3->p.z;
00377 double x4 = n4->p.x; double y4 = n4->p.y; double z4 = n4->p.z;
00378
00379
00380
00381 double x2minusx1 = x2 - x1;
00382 double x3minusx1 = x3 - x1;
00383 double x4minusx3 = x4 - x3;
00384 double y2minusy1 = y2 - y1;
00385 double y3minusy1 = y3 - y1;
00386 double y4minusy3 = y4 - y3;
00387 double denom = x2minusx1*y4minusy3 - x4minusx3*y2minusy1;
00388
00389 if (denom == 0.0)
00390 ;
00391 else {
00392 double snum = x3minusx1*y4minusy3 - y3minusy1*x4minusx3;
00393 double tnum = x3minusx1*y2minusy1 - y3minusy1*x2minusx1;
00394 double s = snum/denom;
00395 double t = tnum/denom;
00396 if (s >= 0.0 && s < 1.0 && t >= 0.0 && t < 1.0) {
00397 if (zcount >= MAXCROSS) {
00398
00399 strcpy(knotstring, "too many crossings");
00400 return;
00401 }
00402
00403 zdowker[zcount++] = i + s;
00404 if (zdowker[zcount-1] == 0.0) zdowker[zcount-1] = 0.01;
00405 zdowker[zcount++] = j + t;
00406 if (testing)
00407 printf("z Segment %5.2f crosses ", i+s);
00408
00409 double zs = z1 + s*(z2 - z1);
00410 double zt = z3 + t*(z4 - z3);
00411 if (testing) {
00412 if (zs > zt)
00413 printf("over");
00414 else if (zs < zt)
00415 printf("under");
00416 else
00417 printf("through");
00418 if (t > 0.99) t = 0.99;
00419 printf(" segment %5.2f \n", j+t);
00420 }
00421
00422 if (zs > zt)
00423 zdowker[zcount - 2] = -zdowker[zcount - 2];
00424 else if (zs < zt)
00425 zdowker[zcount - 1] = -zdowker[zcount - 1];
00426 }
00427 }
00428 }
00429 }
00430
00431
00432
00433
00434
00435
00436 for (i = 0; i < zcount; i++) {
00437 double crosssegment = fabs(zdowker[i]);
00438 int crossnumber = 0;
00439 for (j = 0; j < zcount; j++)
00440 if (crosssegment >= fabs(zdowker[j]))
00441 crossnumber++;
00442 if (zdowker[i] > 0.0)
00443 zorder[i] = crossnumber;
00444 else
00445 zorder[i] = -crossnumber;
00446 if (testing)
00447 printf("%d ", zorder[i]);
00448 }
00449 if (testing)
00450 printf("\n");
00451
00452 if (zcount == 0) {
00453 strcpy(knotstring, " unknot");
00454 return;
00455 }
00456
00457
00458
00459 for (i = 0; i < zcount; i = i+2) {
00460 if (abs(zorder[i])%2 == 0 && abs(zorder[i+1])%2 == 1)
00461 zdk[abs(zorder[i+1])/2] = zorder[i];
00462 else if (abs(zorder[i])%2 == 1 && abs(zorder[i+1])%2 == 0)
00463 zdk[abs(zorder[i])/2] = zorder[i+1];
00464 else {
00465 if (testing)
00466 printf("both odd or both even, problem\n");
00467 strcpy(knotstring, "odd/even problem");
00468 return;
00469 }
00470 }
00471
00472
00473 int knots[10][MAXCROSS];
00474 int ret;
00475 Knot k;
00476 char* knotname;
00477
00478 knots[0][0] = zcount/2;
00479 knots[0][1] = 1;
00480 if (testing)
00481 printf("%d %d ", zcount/2, 1);
00482 for (i = 0; i < zcount/2; i++) {
00483 knots[0][i+2] = zdk[i];
00484 if (testing)
00485 printf("%d ", zdk[i]);
00486 }
00487 if (testing)
00488 printf("\n");
00489
00490
00491 ret = k.find_init(knots[0], &knots[0]);
00492 if (testing)
00493 printf("found %d knots\n", ret);
00494 if (ret > 0) {
00495 strcpy(knotstring, "");
00496 for (i = 0 ; i < ret; i++) {
00497 knotname = k.get_knotid(knots[i]);
00498 if (testing)
00499 printf("knot %d: %s : ", i, knotname);
00500 if (i > 0)
00501 strcat(knotstring, "+");
00502 strcat(knotstring, knotname);
00503 if (testing) {
00504 for (j = 0; j < knots[i][0] + 2; j++)
00505 printf("%d ", knots[i][j]);
00506 printf("\n");
00507 }
00508 }
00509 }
00510 else
00511 strcpy(knotstring, " unknot");
00512
00513 }
00514
00515
00516
00517
00518
00519 void EdgeArray::DrawEdges()
00520 {
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551 extern int do_textures;
00552
00553
00554 if (do_textures && getObject()->getType() == Object::edges_only) {
00555 extern int random_flag;
00556 extern int testing_flag;
00557 double EDGETHRESH = getObject()->getEdgeThresh();
00558
00559
00560 if (strstr(getObject()->getName(), "ring")) {
00561 Point3D cam_vec, cam_pos;
00562 cam_pos = getCameraPos();
00563 Point3D perp, perp0, perp1, oldperp, v0, v1, pt, u0, u1;
00564 Edge *e0; Edge *e1;
00565 double widthpct = 0.0;
00566 glColor4f(1.0, 1.0, 1.0, (getObject()->getDiffuseColor())[3]);
00567 glBegin(GL_QUADS);
00568
00569 e1 = getEdge(0);
00570 u1 = e1->UnitDirectionVector();
00571 pt = e1->getNodeLink(0)->p;
00572
00573 cam_vec = pt - cam_pos;
00574 perp1 = u1.Cross(cam_vec);
00575 perp1.Normalize();
00576
00577 e0 = getEdge(numedges-1);
00578 u0 = e0->UnitDirectionVector();
00579 perp0 = u0.Cross(e0->getNodeLink(0)->p - cam_pos);
00580 perp0.Normalize();
00581 perp = perp0 + perp1;
00582 perp.Normalize();
00583 oldperp = perp;
00584
00585 v0 = pt + 0.5*EDGETHRESH*perp;
00586 v1 = pt - 0.5*EDGETHRESH*perp;
00587 glTexCoord2f(widthpct, 0.0);
00588 glVertex3d(v0.x, v0.y, v0.z);
00589 glTexCoord2f(widthpct, 1.0);
00590 glVertex3d(v1.x, v1.y, v1.z);
00591
00592 for (int i = 1; i < numedges; i++) {
00593 perp0 = perp1;
00594 e0 = e1;
00595 u0 = u1;
00596 e1 = getEdge(i);
00597 u1 = e1->UnitDirectionVector();
00598 pt = e1->getNodeLink(0)->p;
00599 perp1 = u1.Cross(cam_vec);
00600 perp1.Normalize();
00601
00602 perp = perp0 + perp1;
00603 perp.Normalize();
00604 v0 = pt + 0.5*EDGETHRESH*perp;
00605 v1 = pt - 0.5*EDGETHRESH*perp;
00606
00607 widthpct += 0.25;
00608
00609 glTexCoord2f(widthpct, 1.0);
00610 glVertex3d(v1.x, v1.y, v1.z);
00611 glTexCoord2f(widthpct, 0.0);
00612 glVertex3d(v0.x, v0.y, v0.z);
00613
00614
00615
00616 glTexCoord2f(widthpct, 0.0);
00617 glVertex3d(v0.x, v0.y, v0.z);
00618 glTexCoord2f(widthpct, 1.0);
00619 glVertex3d(v1.x, v1.y, v1.z);
00620 }
00621
00622 pt = e1->getNodeLink(1)->p;
00623 perp = oldperp;
00624 v0 = pt + 0.5*EDGETHRESH*perp;
00625 v1 = pt - 0.5*EDGETHRESH*perp;
00626 widthpct += 0.25;
00627 glTexCoord2f(widthpct, 1.0);
00628 glVertex3d(v1.x, v1.y, v1.z);
00629 glTexCoord2f(widthpct, 0.0);
00630 glVertex3d(v0.x, v0.y, v0.z);
00631 glEnd();
00632 }
00633
00634 else {
00635 Point3D cam_vec, cam_pos;
00636 cam_pos = getCameraPos();
00637 Point3D perp, oldperp, v0, v1, pt, oldpt, u0, u1;
00638 Edge *e0; Edge *e1;
00639 double widthpct = 0.0;
00640 glColor4f(1.0, 1.0, 1.0, (getObject()->getDiffuseColor())[3]);
00641 glBegin(GL_QUADS);
00642
00643 e1 = getEdge(0);
00644 u1 = e1->UnitDirectionVector();
00645 pt = e1->getNodeLink(0)->p;
00646
00647 cam_vec = pt - cam_pos;
00648 perp = u1.Cross(cam_vec);
00649 perp.Normalize();
00650 v0 = pt + 0.5*EDGETHRESH*perp;
00651 v1 = pt - 0.5*EDGETHRESH*perp;
00652 extern int needle;
00653 if (needle) {
00654
00655 v0 = pt;
00656 v1 = pt;
00657 }
00658 if (!needle)
00659 glTexCoord2f(widthpct, 0.0);
00660 glVertex3d(v0.x, v0.y, v0.z);
00661 if (!needle)
00662 glTexCoord2f(widthpct, 1.0);
00663 glVertex3d(v1.x, v1.y, v1.z);
00664
00665 for (int i = 1; i < numedges; i++) {
00666 e0 = e1;
00667 u0 = u1;
00668 e1 = getEdge(i);
00669 u1 = e1->UnitDirectionVector();
00670
00671 double dot = u0.Dot(u1);
00672 double theta = (acos(dot))*(180.0/PI);
00673 int k = (int)theta/15;
00674 k = MIN(k, 5);
00675 if ((i == 1) && needle)
00676 k = 0;
00677 for (int j = -k; j <= k; j++) {
00678 oldpt = pt;
00679 oldperp = perp;
00680 double param;
00681
00682
00683
00684
00685
00686 param = 0.5 + (0.414*j)/(2*k+1);
00687 widthpct = 0.25*e1->getIndex() + 0.25*j/(2*k+1);
00688 pt = (1.0-param)*(1.0-param)*e0->getNodeLink(0)->p +
00689 2.0*param*(1.0-param)*e1->getNodeLink(0)->p +
00690 param*param*e1->getNodeLink(1)->p;
00691 if ((i == 1) && needle)
00692 pt = e1->getNodeLink(0)->p;
00693 cam_vec = pt - cam_pos;
00694 perp = (pt - oldpt).Cross(cam_vec);
00695 perp.Normalize();
00696 v0 = pt + 0.5*EDGETHRESH*perp;
00697 v1 = pt - 0.5*EDGETHRESH*perp;
00698
00699 dot = perp.Dot(oldperp);
00700 theta = (acos(dot))*(180.0/PI);
00701
00702
00703
00704
00705 if (theta > 135.0) {
00706 v0 = pt - 0.5*EDGETHRESH*perp;
00707 v1 = pt + 0.5*EDGETHRESH*perp;
00708 }
00709
00710 if (i > 1 || !needle)
00711 glTexCoord2f(widthpct, 1.0);
00712 glVertex3d(v1.x, v1.y, v1.z);
00713 if (i > 1 || !needle)
00714 glTexCoord2f(widthpct, 0.0);
00715 glVertex3d(v0.x, v0.y, v0.z);
00716
00717 if (theta > 135.0) {
00718 v0 = pt + 0.5*EDGETHRESH*perp;
00719 v1 = pt - 0.5*EDGETHRESH*perp;
00720 }
00721
00722 if (needle && i == 1)
00723 glColor4f(1.0, 1.0, 1.0, (getObject()->getDiffuseColor())[3]);
00724 glTexCoord2f(widthpct, 0.0);
00725 glVertex3d(v0.x, v0.y, v0.z);
00726 glTexCoord2f(widthpct, 1.0);
00727 glVertex3d(v1.x, v1.y, v1.z);
00728 }
00729 }
00730
00731 pt = e1->getNodeLink(1)->p;
00732 cam_vec = pt - cam_pos;
00733 perp = u1.Cross(cam_vec);
00734 perp.Normalize();
00735 v0 = pt + 0.5*EDGETHRESH*perp;
00736 v1 = pt - 0.5*EDGETHRESH*perp;
00737 widthpct = 0.25*(e1->getIndex() + 1);
00738 glTexCoord2f(widthpct, 1.0);
00739 glVertex3d(v1.x, v1.y, v1.z);
00740 glTexCoord2f(widthpct, 0.0);
00741 glVertex3d(v0.x, v0.y, v0.z);
00742 glEnd();
00743 }
00744 }
00745 else {
00746 int microhack = 0;
00747 if (strstr(getObject()->getName(), "thread"))
00748 microhack = 1;
00749 for (int i = 0; i < numedges; i++) {
00750 glColor3d(1.0, 1.0, 1.0);
00751
00752 if (microhack && (i < RIGIDNEEDLE))
00753 glColor3d(0.5, 0.5, 0.5);
00754 edges[i]->draw();
00755 }
00756 }
00757 }
00758
00759 void EdgeArray::drawover(double scale)
00760 {
00761
00762 for (int i = 0; i < numedges; i++) {
00763 edges[i]->drawover(scale);
00764 }
00765 }
00766
00767 void EdgeArray::drawinitial()
00768 {
00769
00770 for (int i = 0; i < numedges; i++) {
00771
00772 edges[i]->drawInitial();
00773 }
00774 }
00775
00776 void EdgeArray::drawlabels(float offset)
00777 {
00778
00779 for (int i = 0; i < numedges; i++) {
00780
00781 edges[i]->drawlabel(offset);
00782 }
00783 }
00784
00785
00786 void EdgeArray::setSpringConstants(double value, int restLengthScale)
00787 {
00788 for (int i = 0; i < numedges; i++) {
00789 edges[i]->setSpringConstant(value, restLengthScale);
00790 }
00791 }
00792
00793
00794
00795 void EdgeArray::setDampConstants(double value)
00796 {
00797 for (int i = 0; i < numedges; i++) {
00798 edges[i]->setDampConstant(value);
00799 }
00800 }
00801
00802
00803 double EdgeArray::getEnergy(void)
00804 {
00805 int i;
00806 double total = 0.0;
00807 for (i = 0; i < numedges; i++)
00808 total += edges[i]->getEnergy();
00809
00810 return total;
00811 }
00812
00813 void EdgeArray::DeleteEdge(int index)
00814 {
00815 if (debug) cerr << "EdgeArray::DeleteEdge(" << index << ")\n";
00816
00817
00818 if (index < 0) return;
00819
00820
00821 delete edges[index];
00822
00823
00824 for (int i=index; i<numedges-1; i++)
00825 edges[i] = edges[i+1];
00826
00827
00828 numedges--;
00829 }
00830
00831 void EdgeArray::DeleteEdge(Edge* e)
00832 {
00833 if (debug) cerr << "EdgeArray::DeleteEdge(" << e << ")\n";
00834
00835
00836 int index = getIndex(e);
00837
00838
00839 DeleteEdge(index);
00840 }
00841
00842 void EdgeArray::EraseEdge(Edge* e)
00843 {
00844 Edge *tempEdge = e;
00845 Node *node0 = e->getNodeLink(0);
00846
00847 node0->deleteEdgeLink( e );
00848 e->getOtherNode(node0)->deleteEdgeLink( e );
00849 DeleteEdge( tempEdge );
00850 }
00851
00852 void EdgeArray::DeleteFacelessEdges()
00853 {
00854 int open_slot = 0;
00855 for (int i=0; i<numedges; i++) {
00856 if (edges[i]->numFaceLinks() <= 0)
00857 delete edges[i];
00858 else edges[open_slot++] = edges[i];
00859 }
00860 numedges = open_slot;
00861 }
00862
00863 void EdgeArray::DeleteAllEdges()
00864 {
00865
00866 numedges = 0;
00867 }
00868
00869
00870 void EdgeArray::SanityCheck()
00871 {
00872 string s("");
00873
00874
00875 if (numedges < 0) s += "numedges < 0!";
00876 if (numedges > maxedges) s += "numedges > maxedges!";
00877 if (maxedges < 0) s += "maxedges < 0!";
00878 if (!edges) s += "edges is NULL!";
00879 if (!nodearray_p) s += "nodearray_p is NULL!";
00880
00881
00882
00883 if (s.size() > 0)
00884 cerr << "EdgeArray: INSANE: " << s.c_str() << endl;
00885
00886
00887 for (int i=0; i<numedges; i++)
00888 edges[i]->SanityCheck(this);
00889 }
00890
00891 void EdgeArray::Cleanup()
00892 {
00893
00894 for (int i=0; i<numedges; i++) {
00895 Edge* e = getEdge(i);
00896 int s = e->SanityCheck(this);
00897 if (!s) EraseEdge(e);
00898 }
00899 }
00900
00901 int EdgeArray::CompressDuplicateEdges()
00902 {
00903 int num_dup_edges = 0;
00904
00905 for (int i=0; i<getNumEdges(); i++) {
00906 Edge* e = getEdge(i);
00907 Node* n0 = e->getNodeLink(0);
00908 Node* n1 = e->getNodeLink(1);
00909
00910 for (int j=0; j<getNumEdges(); j++) {
00911 Edge* other_e = getEdge(j);
00912
00913
00914 if (other_e->hasNodeLink(n0) && other_e->hasNodeLink(n1)) {
00915
00916
00917
00918
00919 for (int k=0; k<other_e->numFaceLinks(); k++) {
00920 Face* f = other_e->getFaceLink(k);
00921 if (!e->hasFaceLink(f)) e->addFaceLink(f);
00922 }
00923
00924
00925 DeleteEdge(j);
00926
00927
00928 num_dup_edges++;
00929 }
00930 }
00931 }
00932
00933
00934 return(num_dup_edges);
00935 }
00936