00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <stack>
00029 #include <fstream>
00030 #include "triangulation.hpp"
00031
00032 #define ALTERNATE_INCIRCLE
00033 #define DEBUG_FIND
00034
00035 #define STEP_WRITE
00036 #define STANDALONE
00037
00038 #ifdef STANDALONE
00039 template<class FLT>
00040 inline FLT sqr(const FLT &x) { return x * x; }
00041 #else
00042
00043
00044
00045
00046 #endif
00047
00048 #include <cstdlib>
00049
00050 int myrand(const int width) {
00051 return (int)(static_cast<double>(width)*rand()/(RAND_MAX+1.0));
00052 }
00053
00054 #include <map>
00055 #include <set>
00056
00057
00058
00059
00061 inline double SDet(const Vertex & V1, const Vertex & V2, const Vertex & V3) {
00062 return (V2[0]-V1[0]) * (V3[1]-V1[1]) - (V2[1]-V1[1]) * (V3[0]-V1[0]);
00063 }
00064
00065
00066
00067
00068
00069
00070 inline bool checkInter(const Vertex &P1, const Vertex &P2, const Vertex &Q1, const Vertex &Q2) {
00071
00072 ASSERT(!(P1 == P2 || P1 == Q1 || P1 == Q2 || P2 == Q1 || P2 == Q2 || Q1 == Q2));
00073 return (SDet(P1,P2,Q1)*SDet(P1,P2,Q2) < 0) && (SDet(Q1,Q2,P1)*SDet(Q1,Q2,P2) < 0);
00074 }
00075
00076 inline double Angle(const Vertex &V1, const Vertex &V2, const Vertex &V3) {
00077 const double distance = sqrt(sqr(V3[0]-V1[0])+sqr(V3[1]-V1[1]));
00078 return (((V2[0]-V1[0])*(V3[0]-V1[0]))+((V2[1]-V1[1])*(V3[1]-V1[1])))/distance;
00079 }
00080
00081
00082
00083
00084
00085 void Triangulation::setBox(const PointNumType xmin, const PointNumType ymin,
00086 const PointNumType xmax, const PointNumType ymax) {
00087 __triangles.clear();
00088 __corners[0] = Vertex(xmin,ymax,0);
00089 __corners[1] = Vertex(xmin,ymin,0);
00090 __corners[2] = Vertex(xmax,ymin,0);
00091 __corners[3] = Vertex(xmax,ymax,0);
00092 __triangles.push_back(ConnectedTriangle(&__corners[0],&__corners[2],&__corners[3]));
00093 __triangles.push_back(ConnectedTriangle(&__corners[0],&__corners[1],&__corners[2]));
00094 __triangles.front().neigh(2) = (&__triangles.back());
00095 __triangles.back().neigh(1) = (&__triangles.front());
00096
00097 #ifdef STEP_WRITE
00098 { ASSERT(__checkAll()); std::ofstream o("init.mesh"); export_mesh(o); }
00099 #endif
00100 }
00101
00102 #ifndef ALTERNATE_INCIRCLE
00103 bool Triangulation::isInCircle(const Vertex & position, const Triangle & tri) const {
00104 double x1,x2,x3,y1,y2,y3;
00105 double a,b,c,d,e,f;
00106 double centre_cercle_x,centre_cercle_y;
00107 double rayon_cercle,distance;
00108 double tolerance = 1.e-13;
00109 x1=tri[0][0];
00110 x2=tri[1][0];
00111 x3=tri[2][0];
00112 y1=tri[0][1];
00113 y2=tri[1][1];
00114 y3=tri[2][1];
00115
00116 a=x2-x3;
00117 b=y2-y3;
00118 c=((y2+y3)*(y2-y3)+(x2+x3)*(x2-x3))/2.;
00119 d=x2-x1;
00120 e=y2-y1;
00121 f=((y2+y1)*(y2-y1)+(x2+x1)*(x2-x1))/2.;
00122
00123 centre_cercle_y = (d*c-a*f)/(b*d-a*e);
00124 centre_cercle_x = (c*e-f*b)/(a*e-b*d);
00125
00126 distance = sqr(centre_cercle_x-position[0]) + sqr(centre_cercle_y-position[1]);
00127 rayon_cercle = sqr(centre_cercle_x-x1) + sqr(centre_cercle_y-y1);
00128 return (distance<=(rayon_cercle+tolerance));
00129 }
00130
00131 #else
00132
00133 bool Triangulation::__isInCircle(const Vertex & position, const Triangle & tri) const {
00134 const double eps = 1e-13;
00135
00136
00137 const double
00138 BxmAx=tri(1)[0]-tri(0)[0],
00139 CxmAx=tri(2)[0]-tri(0)[0],
00140 DxmAx=position[0]-tri(0)[0];
00141 const double
00142 BymAy=tri(1)[1]-tri(0)[1],
00143 CymAy=tri(2)[1]-tri(0)[1],
00144 DymAy=position[1]-tri(0)[1];
00145 const double
00146 BA2=BxmAx*(tri(1)[0]+tri(0)[0])+BymAy*(tri(1)[1]+tri(0)[1]),
00147 CA2=CxmAx*(tri(2)[0]+tri(0)[0])+CymAy*(tri(2)[1]+tri(0)[1]),
00148 DA2=DxmAx*(position[0]+tri(0)[0])+DymAy*(position[1]+tri(0)[1]);
00149 const double r=
00150 (BxmAx*CymAy-CxmAx*BymAy)*DA2+(CxmAx*DymAy-DxmAx*CymAy)*BA2+(DxmAx*BymAy-BxmAx*DymAy)*CA2;
00151
00152 return (r<eps);
00153 }
00154
00155 #endif
00156
00157 void Triangulation::__permutation(TriangleIndex num_tri1, const unsigned k1) {
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178 const TriangleIndex num_tri2 = num_tri1->neigh(k1);
00179 ASSERT(num_tri2 != NULL);
00180 const unsigned k2 = num_tri2->localizeNeigh(num_tri1);
00181
00182 const PointIndex
00183 S1=num_tri1->base()[k1],
00184 S2=num_tri1->base()[(k1+1)%3],
00185 S4=num_tri1->base()[(k1+2)%3];
00186
00187 const unsigned tag01 = num_tri1->tag;
00188 const unsigned tag02 = num_tri2->tag;
00189
00190
00191
00192 ASSERT((tag01 & HSide[k1]) == 0);
00193 ASSERT((tag02 & HSide[k2]) == 0);
00194 num_tri1->tag = ((tag01&HSide[(k1+2)%3])?HSide[2]:0)|((tag02&HSide[(k2+1)%3])?HSide[0]:0);
00195 num_tri2->tag = ((tag01&HSide[(k1+1)%3])?HSide[1]:0)|((tag02&HSide[(k2+2)%3])?HSide[0]:0);
00196
00197 const TriangleIndex
00198 V1=num_tri1->neigh((k1+1)%3),
00199 V2=num_tri1->neigh((k1+2)%3);
00200
00201 PointIndex S3;
00202 TriangleIndex V3,V4;
00203
00204
00205 for(unsigned k=0;k<3;++k)
00206 if(num_tri2->neigh(k) == num_tri1) {
00207 S3=num_tri2->base()[k];
00208 V3=num_tri2->neigh((k+1)%3);
00209 V4=num_tri2->neigh((k+2)%3);
00210 break;
00211 }
00212
00213 for(unsigned k=0;k<3;++k) {
00214 if(V1 != NULL)
00215 if(V1->neigh(k) == num_tri1)
00216 V1->neigh(k) = num_tri2;
00217 if(V3 != NULL)
00218 if(V3->neigh(k) == num_tri2)
00219 V3->neigh(k) = num_tri1;
00220 }
00221
00222 num_tri1->setVertices(S1,S2,S3);
00223 num_tri2->setVertices(S1,S3,S4);
00224 num_tri1->setNeighs(V3,num_tri2,V2);
00225 num_tri2->setNeighs(V4,V1,num_tri1);
00226 }
00227
00228
00229 void Triangulation::__elimination_tri(TriangleIndex num_tri) {
00230
00231 for(unsigned k=0;k<3;++k) {
00232 TriangleIndex neigh = num_tri->neigh(k);
00233 if(neigh != NULL) {
00234 for(unsigned k2=0;k2<3;++k2)
00235 if(neigh->neigh(k2) == num_tri) {
00236 neigh->neigh(k2) = NULL;
00237 break;
00238 }
00239 }
00240 num_tri->neigh(k) = NULL;
00241 }
00242
00243 __deleteTriangle(num_tri);
00244 }
00245
00246
00247
00248 TriangleIndex Triangulation::__find_P_in_elt(const Vertex & P) {
00249
00250 #ifdef DEBUG_FIND
00251
00252 for(Triangles::iterator i = __triangles.begin();true;++i) {
00253 ASSERT(i != __triangles.end());
00254 const Vertex & P1 = (*i)(0);
00255 const Vertex & P2 = (*i)(1);
00256 const Vertex & P3 = (*i)(2);
00257 ASSERT(SDet(P1,P2,P3)>=0);
00258
00259
00260
00261
00262
00263 if ( (SDet(P1,P2,P)>=-1e-15) && (SDet(P2,P3,P)>=-1e-15) && (SDet(P3,P1,P)>=-1e-15) ) {
00264 return &*i;
00265 }
00266 }
00267
00268 #else
00269
00270
00271
00272
00273 for(TriangleIndex i = &*__triangles.begin();;) {
00274 ASSERT(i != NULL);
00275
00276 const Vertex & P2 = (*i)(1);
00277 const Vertex & P3 = (*i)(2);
00278
00279 if(SDet(P2,P3,P)<0) {
00280 i=i->neigh(0);
00281 } else {
00282 const Vertex & P1 = (*i)(0);
00283 if(SDet(P3,P1,P)<0) {
00284 i=i->neigh(1);
00285 } else {
00286 if(SDet(P1,P2,P)<0) {
00287 i=i->neigh(2);
00288 } else {
00289
00290 return i;
00291 }
00292 }
00293 }
00294 }
00295
00296 #endif
00297 }
00298
00299
00300 void Triangulation::__insertPoint(Vertex * newPoint, const TriangleIndex & curTriangle) {
00301
00302 __newTriangle(ConnectedTriangle(&__corners[0],&__corners[0],&__corners[0]));
00303 const Triangles::iterator first = --__triangles.end();
00304
00305 Vertex * last = curTriangle->base()[1];
00306 for(unsigned i=0;i<3;++i) {
00307 if (__scanNeigh(curTriangle, i, newPoint, last) ) {
00308
00309 TriangleIndex tmpNeigh = curTriangle->neigh(i);
00310 __newTriangle(ConnectedTriangle(last,curTriangle->base()[(i+2)%3],newPoint,NULL,NULL,tmpNeigh));
00311 if (tmpNeigh != NULL)
00312 tmpNeigh->neigh(tmpNeigh->localizeNeigh(curTriangle)) = &__triangles.back();
00313 last = curTriangle->base()[(i+2)%3];
00314 }
00315 }
00316 __deleteTriangle(curTriangle);
00317
00318 Triangles::iterator
00319 LTi = first,
00320 LTf = __triangles.end(),
00321 LTaux;
00322 ++LTi;
00323
00324 LTi->neigh(1) = &*(--LTf);
00325 LTf->neigh(0) = &*LTi;
00326
00327 LTaux = LTi;
00328 ++LTaux;
00329
00330 while(LTi != LTf) {
00331 LTi->neigh(0) = &*LTaux;
00332 LTaux->neigh(1) = &*LTi;
00333 ++LTi; ++LTaux;
00334 }
00335 __triangles.erase(first);
00336 }
00337
00338 bool Triangulation::__scanNeigh(const TriangleIndex & start,
00339 const unsigned in,
00340 Vertex * newPoint,
00341 Vertex * &last) {
00342
00343
00344 const TriangleIndex curNeigh = start->neigh(in);
00345
00346 if (curNeigh != NULL && __isInCircle(*newPoint,*curNeigh)) {
00347 const unsigned k = curNeigh->localizeNeigh(&*start);
00348
00349 if (__scanNeigh(curNeigh, (k+1)%3, newPoint, last) ) {
00350
00351 TriangleIndex tmpNeigh = curNeigh->neigh((k+1)%3);
00352 __newTriangle(ConnectedTriangle(last,curNeigh->base()[k],newPoint,NULL,NULL,tmpNeigh));
00353 if (tmpNeigh != NULL)
00354 tmpNeigh->neigh(tmpNeigh->localizeNeigh(curNeigh)) = &__triangles.back();
00355 last = curNeigh->base()[k];
00356 }
00357
00358
00359 if (__scanNeigh(curNeigh, (k+2)%3, newPoint, last)) {
00360
00361 TriangleIndex tmpNeigh = curNeigh->neigh((k+2)%3);
00362 __newTriangle(ConnectedTriangle(last,curNeigh->base()[(k+1)%3],newPoint,NULL,NULL,tmpNeigh));
00363 if (tmpNeigh != NULL)
00364 tmpNeigh->neigh(tmpNeigh->localizeNeigh(curNeigh)) = &__triangles.back();
00365 last = curNeigh->base()[(k+1)%3];
00366 }
00367 __deleteTriangle(curNeigh);
00368 return false;
00369 }
00370 return true;
00371 }
00372
00373 void Triangulation::__resetTags() {
00374 for(Triangles::iterator i = __triangles.begin(); i != __triangles.end(); ++i)
00375 i->tag = 0;
00376 }
00377
00378
00379 bool Triangulation::__checkLine(const CurveVertex &L, const bool closed) {
00380 ASSERT(L.size() > 1);
00381 ASSERT(closed);
00382 ASSERT(!closed || L.front() == L.back());
00383
00384 typedef TinyVector<2,PointIndex> Edge;
00385 typedef std::map<Edge,TinyVector<2,TriangleIndex> > EdgeMapping;
00386
00387 typedef std::set<Edge> BorderEdges;
00388 BorderEdges borderEdges;
00389 PointIndex lastPoint = L.front();
00390
00391 for(CurveVertex::const_iterator i=L.begin(); ++i != L.end();) {
00392 Edge edge;
00393 edge[0]=lastPoint;
00394 edge[1]=*i;
00395 if(edge[0] > edge[1]) std::swap(edge[0],edge[1]);
00396 borderEdges.insert(edge);
00397 lastPoint = *i;
00398 }
00399
00400 EdgeMapping edgeMapping;
00401 do {
00402 edgeMapping.clear();
00403 for(Triangles::iterator tr = __triangles.begin();tr !=__triangles.end(); ++tr) {
00404 for(unsigned j=0; j<3; ++j) {
00405 PointIndex p1 = tr->base()[(j+1)%3];
00406 PointIndex p2 = tr->base()[(j+2)%3];
00407 if(p1 > p2) std::swap(p1,p2);
00408 Edge edge;
00409 edge[0]=p1;
00410 edge[1]=p2;
00411 const TriangleIndex tr2 = tr->neigh(j);
00412
00413 if ((tr2 != NULL) && !(tr->tag & HSide[j]) && edgeMapping.find(edge) == edgeMapping.end()) {
00414 Edge edgetemp;
00415 edgetemp[0]=p1;
00416 edgetemp[1]=p2;
00417 TinyVector<2,TriangleIndex> trtemp;
00418 trtemp[0]=&*tr;
00419 trtemp[1]=tr2;
00420 edgeMapping.insert(EdgeMapping::value_type(edgetemp,trtemp));
00421 }
00422 }
00423 }
00424
00425 for(BorderEdges::const_iterator i = borderEdges.begin(); i != borderEdges.end();) {
00426 EdgeMapping::iterator foundi = edgeMapping.find(*i);
00427 if (foundi != edgeMapping.end()) {
00428
00429 TriangleIndex tr0 = foundi->second[0];
00430 TriangleIndex tr1 = foundi->second[1];
00431 ASSERT(tr0 != NULL && tr1 != NULL);
00432 tr0->tag |= HSide[tr0->localizeNeigh(tr1)];
00433 tr1->tag |= HSide[tr1->localizeNeigh(tr0)];
00434 edgeMapping.erase(foundi);
00435 BorderEdges::const_iterator i_to_rm = i++;
00436 borderEdges.erase(i_to_rm);
00437 } else ++i;
00438 }
00439
00440 if (!borderEdges.empty()) {
00441 bool done = false;
00442 while (!done) {
00443 EdgeMapping::iterator e = edgeMapping.begin();
00444 for(unsigned n = myrand(edgeMapping.size());n>0;--n) ++e;
00445 const PointIndex P1 = e->first[0];
00446 const PointIndex P2 = e->first[1];
00447 TriangleIndex tr0 = e->second[0];
00448 TriangleIndex tr1 = e->second[1];
00449 ASSERT(tr0 != NULL && tr1 != NULL);
00450 const unsigned l0 = tr0->localizeNeigh(tr1);
00451 const unsigned l1 = tr1->localizeNeigh(tr0);
00452 const PointIndex Q1 = tr0->base()[l0];
00453 const PointIndex Q2 = tr1->base()[l1];
00454 if (checkInter(*P1,*P2,*Q1,*Q2)) {
00455
00456 done = true;
00457 __permutation(tr0,tr0->localizeNeigh(tr1));
00458 }
00459 }
00460 }
00461 } while (!borderEdges.empty());
00462
00463 return false;
00464 }
00465
00466 bool Triangulation::__colorize(const Points & points) {
00467
00468 std::stack<TriangleIndex> Stack;
00469
00470
00471
00472 Stack.push(__find_P_in_elt(__corners[0]));
00473
00474 while(!Stack.empty()) {
00475 TriangleIndex itr = Stack.top(); Stack.pop();
00476 if (!(itr->tag & HMask)) {
00477 itr->tag |= 1;
00478
00479 for(unsigned j=0;j<3;j++) {
00480 TriangleIndex ktr = itr->neigh(j);
00481 if (ktr != NULL &&
00482 !(itr->tag & HSide[j]) &&
00483 !(ktr->tag & HMask)
00484 ) {
00485 Stack.push(ktr);
00486 }
00487 }
00488 }
00489 }
00490
00491 Triangles::iterator llf = __triangles.begin();
00492 const Triangles::iterator lle = __triangles.end();
00493 while(llf != lle && !((llf->tag & HUMask) &&
00494 !(llf->tag & HMask) &&
00495 (llf->neigh(0)->tag & HMask ||
00496 llf->neigh(1)->tag & HMask ||
00497 llf->neigh(2)->tag & HMask))) {
00498 ++llf;
00499 }
00500
00501 if (llf == lle) {
00502 #ifndef STEP_DETAILS
00503 ffout(4) << "Bad Domain\n";
00504 #endif
00505 return false;
00506 }
00507
00508
00509
00510 Stack.push(&*llf);
00511
00512 while(!Stack.empty()) {
00513 TriangleIndex itr = Stack.top();
00514 Stack.pop();
00515 if (!(itr->tag & HMask)) {
00516 itr->tag |= 2;
00517
00518 for(unsigned j=0;j<3;j++) {
00519 TriangleIndex ktr = itr->neigh(j);
00520 if (ktr != NULL &&
00521 !(itr->tag & HSide[j]) &&
00522 !(ktr->tag & HMask)) {
00523 Stack.push(ktr);
00524 }
00525 }
00526 }
00527 }
00528 return true;
00529 }
00530
00531 TriangleIndex Triangulation::__findVertex(const Vertex * const p) {
00532 for(Triangles::iterator i = __triangles.begin(); i != __triangles.end(); ++i) {
00533 for(unsigned j=0;j<3;++j)
00534 if (i->base()[j] == p)
00535 return &*i;
00536 }
00537 ASSERT(false);
00538 return NULL;
00539 }
00540
00541 bool Triangulation::triangulize(Points & points,
00542 const CurveVertex & envVertex,
00543 const std::vector<CurveVertex> & holes,
00544 const std::vector<CurveVertex> & curves) {
00545
00546 ASSERT(points.size() > 0);
00547 __points = &points;
00548 const Vertex & firstPoint = points[0];
00549
00550 PointNumType
00551 xmin=firstPoint[0],xmax=firstPoint[0],
00552 ymin=firstPoint[1],ymax=firstPoint[1];
00553
00554 for(unsigned i=0;i<points.size();++i) {
00555 const PointNumType x = points[i][0];
00556 const PointNumType y = points[i][1];
00557 xmin = std::min(xmin,x);
00558 xmax = std::max(xmax,x);
00559 ymin = std::min(ymin,y);
00560 ymax = std::max(ymax,y);
00561 }
00562
00563 PointNumType
00564 dx=(xmax-xmin)/10,
00565 dy=(ymax-ymin)/10;
00566
00567 setBox(xmin-2.*dx,ymin-dy,xmax+2.*dx,ymax+dy);
00568 #ifdef STEP_DETAILS
00569 ffout(4) << "Box : (" << xmin-dx << " , " << ymin-dy << " ) , ( " << xmax+dx << " , " << ymax+dy << " )" << "\n";
00570 #endif
00571
00572 #ifdef STEP_DETAILS
00573
00574 #endif
00575 for(unsigned i=0;i<points.size();++i) {
00576 ASSERT(__checkAll());
00577 __findInsert(points[i]);
00578 }
00579 #ifdef STEP_DETAILS
00580
00581 #endif
00582
00583 #ifdef STEP_WRITE
00584 { ASSERT(__checkAll()); std::ofstream o("insert.mesh"); export_mesh(o); }
00585 #endif
00586
00587
00588 __resetTags();
00589
00590 #ifdef STEP_DETAILS
00591 ffout(4) << "Check Enveloppe" << "\n";
00592 for(unsigned i=1;checkLine(envVertex,true);)
00593
00594 {
00595 ffout(4) << "\tPasse " << ++i << "\n";
00596 ASSERT(checkAll()); std::ofstream o("passe.mesh"); export_mesh(o);
00597 }
00598 #else
00599 while(__checkLine(envVertex,true));
00600 #endif
00601
00602
00603
00604
00605
00606
00607
00608 for(std::vector<CurveVertex>::const_iterator lf = holes.begin(); lf != holes.end(); ++lf)
00609 while(__checkLine(*lf,true));
00610
00611
00612 #ifdef STEP_DETAILS
00613 ffout(4) << "Check Courbe(s)" << "\n";
00614 for(std::vector<CurveVertex>::const_iterator lf = curves.begin(); lf != curves.end(); ++lf)
00615 for(unsigned i=1;checkLine(*lf,false);)
00616 ffout(4) << "\tPasse " << ++i << "\n";
00617 #else
00618 for(std::vector<CurveVertex>::const_iterator lf = curves.begin(); lf != curves.end(); ++lf)
00619 while(__checkLine(*lf,false));
00620 #endif
00621
00622 #ifdef STEP_WRITE
00623 { ASSERT(__checkAll()); std::ofstream o("check.mesh"); export_mesh(o); }
00624 #endif
00625
00626 #ifdef STEP_DETAILS
00627 ffout(4) << "Colorize" << "\n";
00628 #endif
00629 __colorize(points);
00630
00631 #ifdef STEP_WRITE
00632 { ASSERT(__checkAll()); std::ofstream o("color.mesh"); export_mesh(o); }
00633 #endif
00634
00635 unsigned count_tri = 0;
00636 const Triangles::iterator e = __triangles.end();
00637 for(Triangles::iterator ff,f = __triangles.begin(); f != e;) {
00638 ff = f++;
00639 if ((ff->tag & HMask) != 2) {
00640 __elimination_tri(&*ff);
00641 ++count_tri;
00642 }
00643 }
00644 #ifdef STEP_DETAILS
00645 ffout(4) << count_tri << " Triangles Deleted " << __triangles.size() << " triangles left" << "\n";
00646 #endif
00647
00648 #ifdef STEP_WRITE
00649 { ASSERT(__checkAll()); std::ofstream o("final.mesh"); export_mesh(o); }
00650 #endif
00651
00652 return true;
00653 }
00654
00655 void Triangulation::export_mesh(std::ostream &o) const {
00656 const Points & points = *__points;
00657
00658 o << "MeshVersionFormatted 1\n"
00659 "Dimension\n"
00660 "\t2\n"
00661 "Vertices\n"
00662 "\t" << points.size()+4
00663 << "\n";
00664
00665 for(unsigned i=0;i<4;++i)
00666 o << __corners[i][0] << " " << __corners[i][1] << " 1\n";
00667 for(Points::const_iterator i = points.begin(); i != points.end(); ++i) {
00668 o << i->x() << " " << i->y() << " 1\n";
00669 }
00670
00671 class BestRef {
00672 private:
00673 public:
00674 const Vertex *points, *__corners;
00675 public:
00676
00677
00678
00679 unsigned operator()(const Vertex & p) {
00680 const unsigned n = &p-__corners;
00681 if (n < 4)
00682 return n+1;
00683 else
00684 return &p-points+5;
00685 }
00686 } ref;
00687 ref.points = &points[0];
00688 ref.__corners = __corners;
00689
00690 o << "Triangles\n\t" << __triangles.size() << "\n";
00691 for(Triangles::const_iterator i = __triangles.begin(); i != __triangles.end(); ++i) {
00692 o << " " << ref((*i)(0))
00693 << " " << ref((*i)(1))
00694 << " " << ref((*i)(2)) << " " << (i->tag & HMask) << "\n";
00695 }
00696 }
00697
00698
00699 bool Triangulation::__checkAll() {
00700 bool ok = true;
00701
00702 unsigned jj = 0;
00703 for(Triangles::iterator i = __triangles.begin(); i != __triangles.end(); ++i,++jj) {
00704
00705 const double S = SDet((*i)(0),(*i)(1),(*i)(2));
00706 const bool check_point =
00707 ((i->base())[0] != (i->base())[1]) &&
00708 ((i->base())[0] != (i->base())[2]) &&
00709 ((i->base())[1] != (i->base())[2]);
00710
00711 if (!check_point) {
00712 ffout(4) << "Warning : Triangle " << jj << " Plat : " << "\n";
00713 ok = false;
00714 }
00715 ASSERT(check_point);
00716 if (S <= 0) {
00717 ffout(4) << "< triangle " << jj << " " << " : " << S << "\n";
00718 ok = false;
00719 }
00720
00721
00722 for(unsigned j=0;j<3;j++) {
00723 const TriangleIndex k = i->neigh(j);
00724 if (k != NULL) {
00725 const unsigned l = k->localizeNeigh(&*i);
00726 if (!(k->base()[(l+2)%3] == i->base()[(j+1)%3] &&
00727 k->base()[(l+1)%3] == i->base()[(j+2)%3])) {
00728 ffout(4) << "Bad edge " << j << " for triangle : " << "\n";
00729 ok = false;
00730 }
00731 }
00732 }
00733 }
00734 return ok;
00735 }
00736