00001
00002 #include "face.h"
00003 #include "facearray.h"
00004 #include "object.h"
00005 #include "objectarray.h"
00006 #include <stdio.h>
00007 #include <stdlib.h>
00008 #ifdef _WIN32
00009 #include <glut.h>
00010 #else
00011 #include <GLUT/glut.h>
00012 #include <OpenGL/gl.h>
00013 #endif
00014
00015 #include <string>
00016
00017 using namespace std;
00018
00019 const char* FaceArray::rcsid = "@(#) $Id: facearray.cpp,v 1.72 2006/05/25 22:23:47 craig Exp $ $Copyright: (c)2001 National Biocomputation Center, Stanford University $";
00020 int FaceArray::debug = 0;
00021
00022 FaceArray::FaceArray(NodeArray* nodearray_p_in, EdgeArray* edgearray_p_in)
00023 : nodearray_p(nodearray_p_in), edgearray_p(edgearray_p_in)
00024 {
00025 faces = NULL;
00026 numfaces = maxfaces = 0;
00027 }
00028
00029 FaceArray::~FaceArray()
00030 {
00031
00032 reset();
00033
00034
00035 numfaces = maxfaces = -1;
00036 }
00037
00038 void FaceArray::reset(void)
00039 {
00040 if (faces) {
00041
00042 for (int i=0; i<numfaces; i++)
00043 delete faces[i];
00044
00045
00046 delete [] faces;
00047 }
00048
00049
00050 numfaces = maxfaces = 0;
00051 }
00052
00053
00054 Face* FaceArray::getFace(Edge *e, Node *n)
00055 {
00056
00057 if( (n == e->getNodeLink(0)) || (n == e->getNodeLink(1))) {
00058 cerr << "The node cannot be one of the edge link!!" << endl;
00059 return NULL;
00060 }
00061
00062 for(int i = 0; i < e->numFaceLinks(); i ++){
00063 Face *curFace = e->getFaceLink(i);
00064 for(int j = 0; j < 3; j ++)
00065 if(n == curFace->getNodeLink(j))
00066 return curFace;
00067 }
00068
00069 cerr << "The node is not 'adjacent' to the edge!" << endl;
00070 return NULL;
00071 }
00072
00073 int FaceArray::getIndex(Face* f)
00074 {
00075
00076 for (int i=0; i<numfaces; i++)
00077 if (faces[i] == f)
00078 return(i);
00079
00080
00081 return(-1);
00082 }
00083
00084 void FaceArray::allocateFaces(int maxfaces_in)
00085 {
00086 maxfaces = maxfaces_in;
00087 faces = new Face*[maxfaces];
00088 numfaces=0;
00089 if (!faces) printf("Could not allocate space for %d faces\n", maxfaces);
00090 }
00091
00092 int FaceArray::addFace()
00093 {
00094 faces[numfaces] = new Face;
00095 if (numfaces >= maxfaces) {
00096 cerr << "FaceArray::addFace()- blew bounds of array (" << maxfaces
00097 << ")!\n";
00098 return(numfaces);
00099 }
00100
00101
00102 return(numfaces++);
00103 }
00104
00105
00106 int FaceArray::addFace(int i1, int i2, int i3)
00107 {
00108 int index = addFace();
00109 faces[index]->init(nodearray_p, edgearray_p, this, i1,i2,i3);
00110 return(index);
00111 }
00112
00113
00114
00115
00116 int FaceArray::getMeshFaceData(FILE *meshfile)
00117 {
00118 char s[MAXLINE];
00119 int numfaces_given, numedges_given;
00120
00121
00122 if (myfgets(s, MAXLINE, meshfile) == NULL) {
00123 printf("No lines in face data file\n");
00124 return(0);
00125 }
00126 if (sscanf(s, "%d", &numfaces_given) != 1) {
00127 printf("Could not read numfaces\n");
00128 return(0);
00129 }
00130 printf("%d faces\n", numfaces_given);
00131
00132
00133 allocateFaces(numfaces_given * 2);
00134
00135
00136 numedges_given = 3 * numfaces_given;
00137 printf("%d maxedges\n", numedges_given);
00138 edgearray_p->allocateEdges(numedges_given);
00139
00140
00141 for (int i=0; i<numfaces_given; i++) {
00142 if (myfgets(s, MAXLINE, meshfile) == NULL) {
00143 printf("Not enough faces in data file\n");
00144 return(0);
00145 }
00146
00147 {
00148 int i1, i2, i3;
00149 int numread = sscanf(s, "%d %d %d", &i1, &i2, &i3);
00150
00151 if (numread != 3) {
00152 printf("Bad read on face %d- '%d %d %d' - IGNORED\n", i, i1,i2,i3);
00153 continue;
00154 }
00155
00156 #ifdef DO_READ_SANITY_CHECKS
00157
00158 int new_index = addFace(i1,i2,i3);
00159
00160
00161 Face* new_face = getFace(new_index);
00162 int ok = new_face->SanityCheck(this);
00163
00164
00165 if (!ok) {
00166 new_face->unlink();
00167 DeleteFace(new_face);
00168 }
00169 #else
00170
00171 addFace(i1,i2,i3);
00172 #endif
00173 }
00174
00175 }
00176
00177
00178 return(1);
00179 }
00180
00181
00182
00183 int FaceArray::getSMFFaceData(FILE *meshfile)
00184 {
00185 char s[MAXLINE];
00186 int i, numfaces_given, numedges_given;
00187
00188
00189 numfaces_given = 0;
00190 while (!feof(meshfile)) {
00191 char s[256];
00192 fgets(s, 256, meshfile);
00193 if (feof(meshfile)) break;
00194 switch (s[0]) {
00195 case 'f' : numfaces_given++; break;
00196 case 'e' :
00197 case 'v' :
00198 case '#' :
00199 default :
00200 break;
00201 }
00202 }
00203
00204
00205 fseek(meshfile, 0, SEEK_SET);
00206
00207 printf("%d faces\n", numfaces_given);
00208
00209
00210 allocateFaces((int)(numfaces_given * 1.5));
00211
00212
00213 if(edgearray_p->getNumEdges()==0)
00214 {
00215 numedges_given = 3 * numfaces_given;
00216 printf("%d maxedges\n", numedges_given);
00217 edgearray_p->allocateEdges(numedges_given);
00218 }
00219
00220
00221 for (i = 0; i < numfaces_given; i++) {
00222 do {
00223 if (myfgets(s, MAXLINE, meshfile) == NULL) {
00224 printf("Not enough faces in data file\n");
00225 return(0);
00226 }
00227 } while (s[0] != 'f');
00228
00229 {
00230 int i1, i2, i3;
00231 int numread = sscanf(s, "%*c %d %d %d", &i1, &i2, &i3);
00232
00233 if (debug) cerr << "Face #" << i << ": " << i1 << " "
00234 << i2 << " " << i3 << endl;
00235
00236 if (numread != 3) {
00237 printf("Bad read on face %d- '%d %d %d' - IGNORED\n", i, i1,i2,i3);
00238 continue;
00239 }
00240
00241
00242 i1--; i2--; i3--;
00243
00244 #ifdef DO_READ_SANITY_CHECKS
00245
00246 int new_index = addFace(i1,i2,i3);
00247
00248
00249 Face* new_face = getFace(new_index);
00250 int ok = new_face->SanityCheck(this);
00251
00252
00253 if (!ok) {
00254 new_face->unlink();
00255 DeleteFace(new_face);
00256 }
00257 #else
00258
00259 addFace(i1,i2,i3);
00260 #endif
00261 }
00262
00263 }
00264
00265
00266 return(1);
00267 }
00268
00269 int FaceArray::getOBJFaceData(FILE *meshfile)
00270 {
00271 char s[MAXLINE];
00272 int i, numfaces_given, numedges_given;
00273
00274
00275 numfaces_given = 0;
00276 while (!feof(meshfile)) {
00277 char s[256];
00278 fgets(s, 256, meshfile);
00279 if (feof(meshfile)) break;
00280 switch (s[0]) {
00281 case 'f' : numfaces_given++; break;
00282 case 'g' :
00283 case 'v' :
00284 case '#' :
00285 default :
00286 break;
00287 }
00288 }
00289
00290
00291 fseek(meshfile, 0, SEEK_SET);
00292
00293 printf("%d faces\n", numfaces_given);
00294
00295
00296
00297 allocateFaces((int)(numfaces_given * 2.5));
00298
00299
00300 if(edgearray_p->getNumEdges()==0)
00301 {
00302 numedges_given = 6 * numfaces_given;
00303 printf("%d maxedges\n", numedges_given);
00304 edgearray_p->allocateEdges(numedges_given);
00305 }
00306
00307
00308 for (i = 0; i < numfaces_given; i++) {
00309 do {
00310 if (myfgets(s, MAXLINE, meshfile) == NULL) {
00311 printf("Not enough faces in data file\n");
00312 return(0);
00313 }
00314 } while (s[0] != 'f');
00315
00316 {
00317 int i1, i2, i3, i4;
00318 char arg1[20], arg2[20], arg3[20], arg4[20];
00319
00320 int numread = sscanf(s, "%*s %s %s %s %s", arg1, arg2, arg3, arg4);
00321 i1 = atoi(arg1); i2 = atoi(arg2); i3 = atoi(arg3); i4 = atoi(arg4);
00322
00323 if (debug) {
00324 cerr << "Face #" << i << ": " << i1 << " "
00325 << i2 << " " << i3 << endl;
00326 if (numread > 3)
00327 cerr << "Face #" << i << ": " << i2 << " "
00328 << i3 << " " << i4 << endl;
00329 }
00330
00331
00332 i1--; i2--; i3--; i4--;
00333
00334
00335 addFace(i1,i2,i3);
00336 if (numread > 3) addFace(i1,i3,i4);
00337 }
00338
00339 }
00340
00341
00342 return(1);
00343 }
00344
00345 void FaceArray::SaveMeshFaceData(ostream& os)
00346 {
00347 os << numfaces << endl;
00348 for (int i=0; i<numfaces; i++)
00349 faces[i]->SaveAsMesh(os);
00350 }
00351
00352 void FaceArray::SaveSMFFaceData(ostream& os)
00353 {
00354 nodearray_p->CacheIndices();
00355 for (int i=0; i<numfaces; i++) {
00356 Face* f = getFace(i);
00357 os << "f";
00358 for (int j=0; j<3; j++) {
00359 Node* n = f->getNodeLink(j);
00360 os << " " << n->getCachedIndex() + 1;
00361 }
00362 os << endl;
00363 }
00364 }
00365
00366 void FaceArray::SaveVRMLFaceData(ostream& os)
00367 {
00368 nodearray_p->CacheIndices();
00369 for (int i=0; i<numfaces; i++) {
00370 Face* f = getFace(i);
00371 for (int j=0; j<3; j++) {
00372 Node* n = f->getNodeLink(j);
00373 os << " " << n->getCachedIndex() << ", ";
00374 }
00375 os << "-1,\n";
00376 }
00377 }
00378
00379 void FaceArray::SaveSTLFaceData(ostream& os)
00380 {
00381 for (int i=0; i<numfaces; i++) {
00382 Face* f = getFace(i);
00383
00384
00385 Point3D normal = f->getNormal();
00386 os << "FACET NORMAL " << normal << "\n";
00387
00388
00389 os << "OUTER LOOP\n";
00390 for (int j=0; j<3; j++) {
00391 Node* n = f->getNodeLink(j);
00392 os << "VERTEX " << n->p.x << " " << n->p.y << " " << n->p.z << "\n";
00393 }
00394 os << "ENDLOOP\n";
00395 os << "ENDFACET\n";
00396 }
00397 }
00398
00399
00400 void FaceArray::DrawFaces(int do_texture)
00401 {
00402
00403
00404
00405
00406
00407 GLint rendermode;
00408 glGetIntegerv(GL_RENDER_MODE, &rendermode);
00409 if (debug) cerr << "DrawFaces(): rendermode = " << rendermode << endl;
00410
00411 if (rendermode == GL_RENDER) {
00412 {
00413 glBegin(GL_TRIANGLES);
00414 for (int i = 0; i < numfaces; i++)
00415 faces[i]->draw(do_texture);
00416 glEnd();
00417 }
00418 }
00419 else {
00420 for (int i = 0; i < numfaces; i++) {
00421
00422 glPushName(i / 65535);
00423 glPushName(i % 65535);
00424 glBegin(GL_TRIANGLES);
00425
00426
00427 faces[i]->draw(0);
00428
00429
00430 glEnd();
00431 glPopName();
00432 glPopName();
00433 }
00434 }
00435 }
00436
00437 void FaceArray::drawlabels(float offset)
00438 {
00439 for (int i=0; i<numfaces; i++)
00440 faces[i]->drawlabel(offset);
00441 }
00442
00443 void FaceArray::drawmarkers()
00444 {
00445 for (int i=0; i<numfaces; i++)
00446 faces[i]->drawmarker();
00447 }
00448
00449 void FaceArray::drawnormals()
00450 {
00451 glBegin(GL_LINES);
00452 glColor3f(1.0, 0.5, 1.0);
00453 for (int i=0; i<numfaces; i++)
00454 faces[i]->drawnormal();
00455 glEnd();
00456 }
00457
00458
00459 void FaceArray::computeNormals(void)
00460 {
00461 for (int i = 0; i < numfaces; i++)
00462 faces[i]->computenormal();
00463 }
00464
00465 void FaceArray::computeIsobarys(void)
00466 {
00467 for (int i = 0; i < numfaces; i++)
00468 faces[i]->computeisobary();
00469 }
00470
00471 void FaceArray::DeleteFace(int index)
00472 {
00473 if (debug) cerr << "FaceArray::DeleteFace(" << index << ")\n";
00474
00475
00476 if (index < 0) return;
00477
00478
00479 delete faces[index];
00480
00481
00482 for (int i=index; i<numfaces-1; i++)
00483 faces[i] = faces[i+1];
00484
00485
00486 numfaces--;
00487 }
00488
00489 void FaceArray::DeleteFace(Face* f)
00490 {
00491 if (debug) cerr << "FaceArray::DeleteFace(" << f << ")\n";
00492
00493
00494 int index = getIndex(f);
00495
00496
00497 DeleteFace(index);
00498 }
00499
00500 void FaceArray::EraseFace(Face * f)
00501 {
00502 Face *tempFace;
00503
00504 tempFace = f;
00505 f->unlink();
00506 DeleteFace( tempFace );
00507 }
00508
00509 void FaceArray::EraseFacesOfColor(int color)
00510 {
00511 if (debug) cerr << "EraseFacesOfColor()\n";
00512
00513 int open_slot = 0;
00514 for (int i = 0; i < numfaces; i++) {
00515 Face* face = getFace(i);
00516
00517
00518 Node* n = face->getNodeLink(0);
00519 if (n->getPartId() == color) {
00520 face->unlink();
00521 }
00522 else {
00523 *faces[open_slot] = *faces[i];
00524 open_slot++;
00525 }
00526 }
00527
00528
00529 numfaces = open_slot;
00530 }
00531
00532 void FaceArray::DeleteAllFaces()
00533 {
00534 if (debug) cerr << "DeleteAllFaces()\n";
00535
00536
00537 numfaces = 0;
00538 }
00539
00540 void FaceArray::WriteDXF(ostream& os)
00541 {
00542 for (int i=0; i<numfaces; i++) {
00543 Face* face = getFace(i);
00544 os << "0\n3DFACE\n";
00545 Node* node1 = face->getNodeLink(0);
00546 Node* node2 = face->getNodeLink(1);
00547 Node* node3 = face->getNodeLink(2);
00548 os << "10\n" << node1->p.x << "\n20\n" << node1->p.y << "\n30\n"
00549 << node1->p.z << endl;
00550 os << "11\n" << node2->p.x << "\n21\n" << node2->p.y << "\n31\n"
00551 << node2->p.z << endl;
00552 os << "12\n" << node3->p.x << "\n22\n" << node3->p.y << "\n32\n"
00553 << node3->p.z << endl;
00554 os << "13\n" << node3->p.x << "\n23\n" << node3->p.y << "\n33\n"
00555 << node3->p.z << endl;
00556 }
00557 }
00558
00559 double FaceArray::getSurfaceArea()
00560 {
00561 if (debug) cerr << "FaceArray::getSurfaceArea()\n";
00562
00563
00564 double area_sum = 0.0;
00565 for (int i=0; i<numfaces; i++) {
00566 Face* face = getFace(i);
00567 area_sum += face->getArea();
00568 }
00569
00570
00571 return(area_sum);
00572 }
00573
00574 double FaceArray::getVolume()
00575 {
00576 if (debug) cerr << "FaceArray::getVolume()\n";
00577
00578
00579 Point3D min, max;
00580 nodearray_p->getBoundingBox(&min, &max);
00581
00582
00583 double volume_sum = 0.0;
00584 for (int i=0; i<numfaces; i++) {
00585 Face* face = getFace(i);
00586 Point3D n = face->getNormal();
00587 Point3D center = face->getCenter();
00588
00589 double height = center.y - min.y;
00590 double volume = height * face->getShadowArea();
00591
00592
00593 if (n.y < 0)
00594 volume = -volume;
00595
00596
00597 volume_sum += volume;
00598 }
00599
00600
00601 return(volume_sum);
00602 }
00603
00604 double FaceArray::getExactZVolume(int Num_Face_Surface)
00605 {
00606 if (debug) cerr << "FaceArray::getExactZVolume()\n";
00607
00608
00609
00610
00611
00612
00613 double volume_sum = 0.0;
00614 for (int i=0; i<Num_Face_Surface; i++)
00615 volume_sum += getFace(i)->ZVolume();
00616 return volume_sum;
00617 }
00618
00619
00620
00621
00622
00623 Node* FaceArray::subdivideFace(Face *initial_p, Point3D S, Face* *t1_p,
00624 Face* *t2_p, Face* *t3_p)
00625 {
00626 cerr << "FaceArray::subdivideFace(" << initial_p << ", " << S << ", "
00627 << t1_p << "," << t2_p << "," << t3_p << "," << ")\n";
00628
00629
00630 cerr << "initial_p is face # " << initial_p->getIndex() << endl;
00631 int index_S = nodearray_p->addNode(S);
00632 Node* node_S = nodearray_p->getNode(index_S);
00633 cerr << " Created new node S of index " << index_S <<": "<< *node_S << endl;
00634
00635
00636 Node* ret_ptr = subdivideFace(initial_p, node_S, t1_p, t2_p, t3_p);
00637
00638
00639 if (ret_ptr == NULL) nodearray_p->DeleteNode(node_S);
00640
00641
00642 return(ret_ptr);
00643 }
00644
00645
00646
00647
00648
00649
00650 Node* FaceArray::subdivideFace(Face *initial_p, Node* node_S, Face* *t1_p,
00651 Face* *t2_p, Face* *t3_p)
00652 {
00653 cerr << "FaceArray::subdivideFace(" << initial_p << ", " << node_S << ", "
00654 << t1_p << "," << t2_p << "," << t3_p << "," << ")\n";
00655 cerr << "SUBDIVIDING FACE: " << *initial_p << endl;
00656
00657 const double precision = 0.001;
00658 double dist, dot;
00659 Point3D center = initial_p->getCenter();
00660 Node *p[3];
00661 p[0] = initial_p->getNodeLink(0);
00662 p[1] = initial_p->getNodeLink(1);
00663 p[2] = initial_p->getNodeLink(2);
00664
00665 Point3D p_S[3];
00666 Point3D p_p[3];
00667 Point3D p_center[3];
00668 Point3D cross1, cross2;
00669 Face *t1, *t2, *t3;
00670
00671 for (int i = 0; i < 3; i++){
00672 p_S[i] = node_S->p - p[i]->p;
00673
00674
00675 if (p_S[i].Length() < precision) {
00676 cerr << "too close to vertex (length = " << p_S[i].Length()
00677 << "<" << precision << "\n";
00678 return(NULL);
00679 }
00680
00681 p_p[i] = p[(i + 1) % 3]->p - p[i]->p;
00682 p_center[i] = center - p[i]->p;
00683 cross1 = p_S[i].Cross(p_p[i]);
00684 cross2 = p_center[i].Cross(p_p[i]);
00685 dot = cross1.Dot(cross2);
00686
00687 if (dot < -precision) {
00688 cerr << "dot < 0 (=" << dot << ")\n";
00689 return(NULL);
00690 }
00691
00692 dist = cross1.Length() / p_p[i].Length();
00693
00694
00695 if(dist <= precision) {
00696 cerr << " split into 2 faces\n";
00697
00698
00699
00700 getObject()->getObjectArray()->ResetCollisions();
00701 getObject()->DestroySphereTree();
00702
00703
00704
00705 initial_p->unlink();
00706
00707
00708 DeleteFace(initial_p);
00709
00710
00711 int new_index1 = addFace(); int new_index2 = addFace();
00712 t1 = getFace(new_index1); t2 = getFace(new_index2);
00713
00714
00715 t1->init(nodearray_p, edgearray_p, this, node_S, p[(i+1) % 3],
00716 p[(i+2)%3]);
00717 t2->init(nodearray_p, edgearray_p, this, node_S, p[(i+2) % 3],p[i]);
00718 cerr << "split_node = " << *node_S << endl;
00719 cerr << "subtri t1: " << *t1 << endl;
00720 cerr << "subtri t2: " << *t2 << endl;
00721
00722
00723 t1->computenormal();
00724 t2->computenormal();
00725
00726
00727 if (t1_p) *t1_p = t1;
00728 if (t2_p) *t2_p = t2;
00729 if (t3_p) *t3_p = NULL;
00730
00731 getObject()->CreateSphereTree();
00732 return(node_S);
00733 }
00734 }
00735
00736
00737 cerr << " split into 3 faces\n";
00738
00739
00740
00741 getObject()->getObjectArray()->ResetCollisions();
00742 getObject()->DestroySphereTree();
00743
00744
00745 int new_index1 = addFace();
00746 int new_index2 = addFace();
00747 int new_index3 = addFace();
00748 t1 = getFace(new_index1);
00749 t2 = getFace(new_index2);
00750 t3 = getFace(new_index3);
00751
00752
00753
00754 initial_p->unlink();
00755
00756
00757 DeleteFace(initial_p);
00758
00759
00760 t1->init(nodearray_p, edgearray_p, this, node_S, p[1], p[2]);
00761 t2->init(nodearray_p, edgearray_p, this, node_S, p[2], p[0]);
00762 t3->init(nodearray_p, edgearray_p, this, node_S, p[0], p[1]);
00763
00764
00765 t1->computenormal();
00766 t2->computenormal();
00767 t3->computenormal();
00768
00769 cerr << "split_node = " << *node_S << endl;
00770 cerr << "subtri t1: " << *t1 << endl;
00771 cerr << "subtri t2: " << *t2 << endl;
00772 cerr << "subtri t3: " << *t3 << endl;
00773
00774 if (t1_p) *t1_p = t1;
00775 if (t2_p) *t2_p = t2;
00776 if (t3_p) *t3_p = t3;
00777
00778 getObject()->CreateSphereTree();
00779 return(node_S);
00780 }
00781
00782
00783
00784
00785 Face* FaceArray::unSubdivideFace(Node *n_in)
00786 {
00787 printf("unsubdividing ...\n");
00788
00789
00790 (getObject()->getObjectArray())->ResetCollisions();
00791 getObject()->DestroySphereTree();
00792 int i;
00793 int n_facedegree = n_in->numFaceLinks();
00794 int n_edgedegree = n_in->numEdgeLinks();
00795 Face* f[3];
00796 Edge* e[3];
00797 Node* n[3];
00798
00799 if (n_facedegree < 2 || n_facedegree > 3 || n_edgedegree != 3) {
00800 printf("node not created by subdivideFace, or resubdivided fd %d ed %d\n",
00801 n_facedegree, n_edgedegree);
00802
00803
00804 cerr << "more node info: " << *n_in << endl;
00805 return(NULL);
00806 }
00807
00808 for (i = 0; i < n_facedegree; i++) {
00809 f[i] = n_in->getFaceLink(i);
00810 cerr << "old face " << *f[i] << endl;
00811 }
00812 for (i = 0; i < n_edgedegree; i++) {
00813 e[i] = n_in->getEdgeLink(i);
00814 n[i] = e[i]->getOtherNode(n_in);
00815 }
00816
00817 for (i = 0; i < n_facedegree; i++) {
00818 f[i]->unlink();
00819 DeleteFace(f[i]);
00820 }
00821
00822 for (i = 0; i < n_edgedegree; i++) {
00823 n[i]->deleteEdgeLink(e[i]);
00824 n_in->deleteEdgeLink(e[i]);
00825 edgearray_p->DeleteEdge(e[i]);
00826 }
00827
00828 nodearray_p->DeleteNode(n_in);
00829
00830 i = addFace();
00831 Face* f_out = getFace(i);
00832 f_out->init(nodearray_p, edgearray_p, this, n[0], n[1], n[2]);
00833 f_out->computenormal();
00834 cerr << "new face " << *f_out << endl;
00835 getObject()->CreateSphereTree();
00836 return(f_out);
00837 }
00838
00839 void FaceArray::SanityCheck(NodeArray* real_na_p, EdgeArray* real_ea_p)
00840 {
00841 string s;
00842
00843 if (!nodearray_p) s += "nodearray is NULL!";
00844 if (nodearray_p != real_na_p) s += "nodearray is BAD!";
00845 if (!edgearray_p) s += "edgearray is NULL!";
00846 if (edgearray_p != real_ea_p) s += "edgearray is BAD!";
00847 if (numfaces < 0) s += "numfaces < 0!";
00848 if (numfaces > maxfaces) s += "numfaces > maxfaces!";
00849 if (maxfaces < 0) s += "maxfaces < 0!";
00850
00851 if (s.size() > 1)
00852 cerr << "FaceArray is INSANE: " << s.c_str() << endl;
00853
00854
00855 for (int i=0; i<numfaces; i++)
00856 faces[i]->SanityCheck(this);
00857 }
00858
00859
00860 void FaceArray::Cleanup()
00861 {
00862
00863 for (int i=0; i<numfaces; i++) {
00864 Face* f = faces[i];
00865 if (!f->SanityCheck(this)) {
00866 f->unlink();
00867 DeleteFace(i);
00868
00869 i--;
00870 }
00871 }
00872 }
00873
00874 double FaceArray::DistanceToNearestFace(Point3D p)
00875 {
00876 double min_dist = 1e20;
00877 for (int i=0; i<numfaces; i++) {
00878 Face* f = getFace(i);
00879
00880
00881
00882
00883
00884
00885
00886 Point3D face_center = f->getCenter();
00887 double cur_dist = p.Dist(face_center);
00888
00889 if (cur_dist < min_dist)
00890 min_dist = cur_dist;
00891 }
00892
00893 return(min_dist);
00894 }
00895
00896
00897
00898 Face* FaceArray::ClosestFaceToPoint(Point3D pt)
00899 {
00900 int numF = getNumFaces();
00901 Face* current = getFace(0);
00902 Face* closest = current;
00903 double minDist = current->FaceDistanceToPoint(pt);
00904 for (int i = 1; i < numF; i ++){
00905 current = getFace(i);
00906 double currDist = current->FaceDistanceToPoint(pt);
00907 if( minDist > currDist ){
00908 minDist = currDist;
00909 closest = current;
00910 }
00911 }
00912
00913 return(closest);
00914 }
00915
00916
00917
00918
00919
00920 void FaceArray::ReorderFacesBasedOnViewingMatrix(double* model, double* proj,
00921 GLint* view)
00922 {
00923
00924 double* depths = new double[getNumFaces()];
00925 double min = 1e20, max = -1e20;
00926
00927 {
00928 for (int i=0; i<getNumFaces(); i++) {
00929
00930 Face* f = getFace(i);
00931 Point3D center = f->getCenter();
00932
00933
00934 double projx, projy, depth;
00935 gluProject(center.x,center.y,center.z, model,proj,view,
00936 &projx,&projy,&depth);
00937
00938
00939 depths[i] = depth;
00940 if (depth > max) max = depth;
00941 if (depth < min) min = depth;
00942 }
00943 }
00944
00945
00946 if (debug) cerr << "Max = " << max << ", " << "Min = " << min << endl;
00947
00948 {
00949
00950 for (int i=0; i<getNumFaces(); i++) {
00951 for (int j=i+1; j<getNumFaces(); j++) {
00952
00953
00954 if (depths[i] < depths[j]) {
00955 Face* tmp = faces[i];
00956 faces[i] = faces[j];
00957 faces[j] = tmp;
00958
00959 double d_tmp = depths[i];
00960 depths[i] = depths[j];
00961 depths[j] = d_tmp;
00962 }
00963 }
00964 }
00965 }
00966
00967
00968 delete [] depths;
00969 }
00970
00971
00972
00973 void FaceArray::GeometryReplicate(GeometryReplicator* gr)
00974 {
00975 if (debug) cerr << "FaceArray::GeometryReplicate(" << gr << ")\n";
00976
00977
00978 const int buf_size = 1490;
00979 char buffer[buf_size];
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993 int numNodesInBuffer = 0;
00994 int faceEntry[3];
00995 u_long* netFaceEntry = (u_long*)faceEntry;
00996
00997 int nodeEntrySize = sizeof(int) + 3*sizeof(int);
00998
00999 u_long netvalue;
01000
01001 int s = sprintf(buffer, "%c%c", GR_CODE, GR_FACE);
01002 netvalue = htonl(numNodesInBuffer);
01003 memcpy(&buffer[s],&netvalue,sizeof(int));
01004 s += sizeof(int);
01005
01006 for (int i=0; i<getNumFaces(); i++)
01007 {
01008 if (s + nodeEntrySize < buf_size)
01009 {
01010 Face* face = getFace(i);
01011 Node* i0 = face->getNodeLink(0);
01012 Node* i1 = face->getNodeLink(1);
01013 Node* i2 = face->getNodeLink(2);
01014
01015 faceEntry[0] = i0->getIndex();
01016 faceEntry[1] = i1->getIndex();
01017 faceEntry[2] = i2->getIndex();
01018
01019 netFaceEntry[0] = htonl(netFaceEntry[0]);
01020 netFaceEntry[1] = htonl(netFaceEntry[1]);
01021 netFaceEntry[2] = htonl(netFaceEntry[2]);
01022
01023
01024
01025 netvalue = htonl(i);
01026
01027 memcpy(&buffer[s],&netvalue,sizeof(int));
01028 s += sizeof(int);
01029
01030 memcpy(&buffer[s],netFaceEntry,3*sizeof(int));
01031 s += 3*sizeof(int);
01032
01033 numNodesInBuffer++;
01034
01035 }
01036
01037 if ((s + nodeEntrySize >= buf_size) || (i == getNumFaces() - 1) )
01038 {
01039
01040 netvalue = htonl(numNodesInBuffer);
01041 memcpy(&buffer[2],&netvalue,sizeof(int));
01042 gr->SendMessage(buffer, s);
01043
01044
01045 s = sprintf(buffer, "%c%c", GR_CODE, GR_FACE);
01046 numNodesInBuffer = 0;
01047 netvalue = htonl(numNodesInBuffer);
01048 memcpy(&buffer[2],&netvalue,sizeof(int));
01049 s += sizeof(int);
01050 }
01051 }
01052
01053
01054 }
01055
01056 ostream& operator<<(ostream& os, const FaceArray& fa)
01057 {
01058 os << fa.numfaces << endl;
01059 for (int i=0; i<fa.numfaces; i++) {
01060 const FaceArray* fa_p = &fa;
01061 Face* cur_face = ((FaceArray*)fa_p)->getFace(i);
01062 os << (*cur_face) << endl;
01063 }
01064 return(os);
01065 }