Files Classes Functions Hierarchy
00001 00002 #include <iomanip> 00003 #include <vector> 00004 #include <sstream> 00005 using namespace std; 00006 00007 #include <d3fan.h> 00008 #include <d3fan2.h> 00009 #include <d3tess.h> 00010 #include <message.h> 00011 #include <print.h> 00012 #include <simplexD2linked.h> 00013 #include <simplexface.h> 00014 #include <trianglespace.h> 00015 00016 00017 00018 void d3tess::splitmidpoint1D(uintc s, uintc p1) 00019 { 00020 assert(s<vi.size()); 00021 assert(p1<pt.size()); 00022 00023 simplexD2linked & S(vi[s]); 00024 00025 assert(S.piInverseHas(p1)==true); 00026 00027 uintc j = S.piInverse(p1); 00028 00029 uintc a = S.pi[(j+1)%3]; 00030 uintc b = S.pi[(j+2)%3]; 00031 00032 uintc n = pt.size(); 00033 pt.push_back( (pt[a]+pt[b])*0.5 ); 00034 00035 split1D(s,p1,n); 00036 } 00037 00038 void d3tess::removenullsimplexes() 00039 { 00040 // Remove any null simplexes at the end of the 00041 // tessellation so the last simplex is non null 00042 // or there is no tessellation. 00043 if (vi[vi.size()-1].isnull()) 00044 { 00045 for ( ; vi[vi.size()-1].isnull() && (vi.size()>1) ; ) 00046 vi.pop_back(); 00047 } 00048 00049 // Swap null simplexes with non null simplexes 00050 // and delete them. 00051 for (uint i=1; i<vi.size(); ++i) 00052 { 00053 if (vi[i].isnull()==false) 00054 continue; 00055 00056 simplexswap(i,vi.size()-1); 00057 for ( ; vi[vi.size()-1].isnull() && (vi.size()>1) ; ) 00058 vi.pop_back(); 00059 } 00060 00061 debugcheck(); 00062 } 00063 00064 void d3tess::simplexswap(uintc s0, uintc s1) 00065 { 00066 assert(s0<vi.size()); 00067 assert(s1<vi.size()); 00068 00069 if (s0==s1) 00070 return; 00071 00072 uint a[3]; 00073 uint b[3]; 00074 00075 // Copy the neighbor links of both simplexes. 00076 uint i; 00077 00078 simplexD2linked & A(vi[s0]); 00079 for (i=0; i<3; ++i) 00080 a[i] = A.ni[i]; 00081 00082 simplexD2linked & B(vi[s1]); 00083 for (i=0; i<3; ++i) 00084 b[i] = B.ni[i]; 00085 00086 // Change the links in the actual mesh. 00087 for (i=0; i<3; ++i) 00088 { 00089 if (a[i]==0) 00090 continue; 00091 00092 simplexD2linked & x(vi[a[i]]); 00093 if (x.niInverseHas(s1)==false) 00094 x.changelink(s0,s1); 00095 else 00096 { 00097 // The case where the neighbor has both simplexes 00098 // on its boundary. 00099 uint c = x.niInverse(s1); 00100 x.ni[ x.niInverse(s0) ] = s1; 00101 x.ni[ c ] = s0; 00102 } 00103 } 00104 00105 for (i=0; i<3; ++i) 00106 { 00107 if (b[i]==0) 00108 continue; 00109 simplexD2linked & x(vi[b[i]]); 00110 if (x.niInverseHas(s0)==false) 00111 x.changelink(s1,s0); 00112 } 00113 00114 // Swap the simplexes s0 and s1 in memory 00115 uint c; 00116 for (i=0; i<3; ++i) 00117 { 00118 c = A.pi[i]; 00119 A.pi[i] = B.pi[i]; 00120 B.pi[i] = c; 00121 00122 c = A.ni[i]; 00123 A.ni[i] = B.ni[i]; 00124 B.ni[i] = c; 00125 } 00126 } 00127 00128 00129 00130 void d3tess::splitwithline 00131 ( 00132 uintc s, 00133 uintc p0, 00134 uintc w0, 00135 uintc p1, 00136 uintc w1 00137 ) 00138 { 00139 uintc n0 = vi.size(); 00140 assert(s<n0); 00141 00142 // Neighboring triangle opposite p0 00143 uintc neib = vi[s].nifrom(p0); 00144 00145 // If the first splitting point has no neighbor on the given 00146 // boundary then handle this case. 00147 if (neib==0) 00148 { 00149 split1D(s,p0,w0); 00150 if ( vi[s].piInverseHas(p1) ) 00151 split1D(n0,w0,w1); 00152 else 00153 split1D(s,w0,w1); 00154 00155 return; 00156 } 00157 00158 // The first split will create 4 new triangles and delete two. 00159 00160 split1D(s,p0,w0); 00161 00162 // The second triangle to be split contains the point p0 but 00163 // does not contain the point p1 as one of its points. 00164 00165 uint k[4]; 00166 k[0] = s; 00167 k[1] = neib; 00168 k[2] = n0; 00169 k[3] = n0+1; 00170 00171 simplexD2linked *t; 00172 uint ki; 00173 for ( uint i=0; i<4; ++i ) 00174 { 00175 ki=k[i]; 00176 t = & vi[ki]; 00177 if ( t->piInverseHas(p1) == true ) 00178 continue; 00179 if ( t->piInverseHas(p0) == false ) 00180 continue; 00181 00182 split1D(ki,w0,w1); 00183 00184 return; 00185 } 00186 00187 assert(false); // The case should have been handled. 00188 } 00189 00190 00191 00192 00193 void d3tess::splitonboundarynoneighbor 00194 ( 00195 uintc s, 00196 uintc j, 00197 uintc w 00198 ) 00199 { 00200 // Two triangles produced from split. 00201 00202 assert(w<pt.size()); 00203 assert(w!=0); 00204 assert(s<vi.size()); 00205 00206 // Extract info from mesh. 00207 00208 uint p[4]; 00209 uint n[2]; 00210 00211 simplexD2linked & x(vi[s]); 00212 00213 p[0] = x.pi[(j+1)%3]; 00214 p[1] = x.pi[(j+2)%3]; 00215 p[2] = x.pi[j]; 00216 p[3] = w; 00217 00218 assert(x.ni[j]==0); 00219 00220 n[0] = x.ni[(j+1)%3]; 00221 n[1] = x.ni[(j+2)%3]; 00222 00223 // Check the mesh before changing it. 00224 debugcheck(); 00225 00226 // Indexes to new triangles. 00227 uint k[2]; 00228 k[0] = s; 00229 k[1] = vi.size(); 00230 00231 x = simplexD2linked(p[1],p[2],p[3],k[1],0,n[0]); 00232 vi.push_back( simplexD2linked(p[3],p[2],p[0],n[1],0,k[0]) ); 00233 00234 if (n[1]!=0) 00235 vi[n[1]].changelink(s,k[1]); 00236 00237 if (n[0]!=0) 00238 vi[n[0]].changelink(s,k[0]); 00239 00240 debugcheck(); 00241 } 00242 00243 void d3tess::split1D( uintc s, uintc p0, uintc w0 ) 00244 { 00245 assert(s<vi.size()); 00246 00247 uintc j = vi[s].piInverse(p0); 00248 00249 if (vi[s].ni[j]==0) 00250 { 00251 splitonboundarynoneighbor(s,j,w0); 00252 return; 00253 } 00254 00255 // General Splitting on Boundary, 00256 // four triangles produced. 00257 00258 assert(w0<pt.size()); 00259 assert(w0!=0); 00260 00261 // Extract info from mesh. 00262 00263 uint p[5]; 00264 uint n[4]; 00265 00266 simplexD2linked & x(vi[s]); 00267 uint b = x.ni[j]; 00268 assert(b!=0); 00269 simplexD2linked & y(vi[b]); 00270 00271 assert( isconnected(s,b) ); 00272 00273 uintc j2 = y.niInverse(s); 00274 00275 p[0] = x.pi[(j+1)%3]; 00276 p[1] = y.pi[j2]; 00277 p[2] = x.pi[(j+2)%3]; 00278 p[3] = x.pi[j]; 00279 p[4] = w0; 00280 00281 n[0] = x.ni[(j+1)%3]; 00282 n[1] = x.ni[(j+2)%3]; 00283 n[2] = y.ni[(j2+1)%3]; 00284 n[3] = y.ni[(j2+2)%3]; 00285 00286 // Check the mesh before changing it. 00287 debugcheck(); 00288 00289 // Indexes to new triangles. 00290 uint k[4]; 00291 k[0] = s; 00292 k[1] = b; 00293 k[2] = vi.size(); 00294 k[3] = k[2]+1; 00295 00296 x = simplexD2linked(p[4],p[2],p[3],n[0],k[1],k[3]); 00297 y = simplexD2linked(p[4],p[3],p[0],n[1],k[2],k[0]); 00298 vi.push_back( simplexD2linked(p[4],p[0],p[1],n[2],k[3],k[1]) ); 00299 vi.push_back( simplexD2linked(p[4],p[1],p[2],n[3],k[0],k[2]) ); 00300 00301 if (n[0]!=0) 00302 vi[n[0]].changelink(s,k[0]); 00303 00304 if (n[1]!=0) 00305 vi[n[1]].changelink(s,k[1]); 00306 00307 if (n[2]!=0) 00308 vi[n[2]].changelink(b,k[2]); 00309 00310 if (n[3]!=0) 00311 vi[n[3]].changelink(b,k[3]); 00312 00313 debugcheck(); 00314 } 00315 00316 bool const d3tess::simplexdelete(uintc s) 00317 { 00318 if (s>=vi.size()) 00319 return false; 00320 00321 simplexD2linked & t(vi[s]); 00322 00323 // If already deleted return true. 00324 if (t.isnull()) 00325 return true; 00326 00327 uint nb; 00328 00329 // Visit each neighbor and unlink. 00330 for (int i=0; i<3; ++i) 00331 { 00332 nb = t.ni[i]; 00333 if (nb!=0) 00334 vi[nb].changelink(s,0); 00335 } 00336 00337 t.setnull(); 00338 00339 return true; 00340 } 00341 00342 00343 00344 d3tess::~d3tess() 00345 { 00346 delete minimizer; 00347 minimizer=0; 00348 } 00349 00350 d3tess::d3tess( uintc arrayMax ) 00351 : 00352 fan(*this), 00353 minimizer( new d3minoperator(*this) ), 00354 debugenable(true) 00355 // enablesplit(true), 00356 // enablefan(true) 00357 { 00358 pt.reserve(arrayMax); 00359 vi.reserve(arrayMax); 00360 00361 reset(); 00362 } 00363 00364 void d3tess::initialize() 00365 { 00366 assert(pt.size()>3); 00367 assert(vi.size()==1); 00368 00369 pt3c & p0(pt[1]); 00370 pt3c & p1(pt[2]); 00371 pt3c & p2(pt[3]); 00372 00373 halfspaceD2< pt3, double > h(p1,p0); 00374 if (h.isInside(p2)==false) 00375 vi.push_back( simplexD2linked(1,2,3, 0,0,0) ); 00376 else 00377 vi.push_back( simplexD2linked(3,2,1, 0,0,0) ); 00378 } 00379 00380 void d3tess::reset() 00381 { 00382 pt.clear(); 00383 vi.clear(); 00384 00385 pt.push_back( pt3(0.0,0.0,0.0) ); 00386 vi.push_back( simplexD2linked() ); 00387 00388 cp=1; 00389 } 00390 00391 void d3tess::minimizerSet( d3minoperator* m) 00392 { 00393 assert(m!=0); 00394 00395 delete minimizer; 00396 minimizer = m; 00397 } 00398 00399 bool const d3tess::surfaceviewable(uintc k) const 00400 { 00401 simplexD2linked const & x(vi[cp]); 00402 halfspaceD2< pt3, double > h(pt[x.pi[vs.v[1]]],pt[x.pi[vs.v[0]]]); 00403 return h.isInside(pt[k]); 00404 } 00405 00406 00407 00408 00409 bool const d3tess::isconnected(uintc a, uintc b) const 00410 { 00411 #ifndef NDEBUG 00412 uintc sz(vi.size()); 00413 assert(a<sz); 00414 assert(b<sz); 00415 #endif 00416 00417 //simplexD2linked const & A(vi[a]); 00418 //simplexD2linked const & B(vi[b]); 00419 00420 if (vi[a].niInverseHas(b)==false) 00421 return false; 00422 00423 if (vi[b].niInverseHas(a)==false) 00424 return false; 00425 00426 /* 00427 bool res; 00428 00429 A.niInverse(res,b); 00430 if (res==false) 00431 return false; 00432 00433 B.niInverse(res,a); 00434 if (res==false) 00435 return false; 00436 */ 00437 00438 return true; 00439 } 00440 00441 00442 00443 bool const d3tess::isconvex(uintc a, uintc b) const 00444 { 00445 #ifndef NDEBUG 00446 uintc sz(vi.size()); 00447 assert(a<sz); 00448 assert(b<sz); 00449 #endif 00450 00451 simplexD2linked const & A(vi[a]); 00452 simplexD2linked const & B(vi[b]); 00453 00454 bool res; 00455 00456 uint ai = A.niInverse(res,b); 00457 if (res==false) 00458 return false; 00459 00460 uint bi = B.niInverse(res,a); 00461 if (res==false) 00462 return false; 00463 00464 pt3 const & P0(pt[A.pi[ai]]); 00465 pt3 const & P1(pt[A.pi[(ai+1)%3]]); 00466 pt3 const & P2(pt[A.pi[(ai+2)%3]]); 00467 00468 //cout << SHOW(P0) << " " << SHOW(P1) << " " << SHOW(P2) << endl; 00469 00470 halfspaceD2< pt3, double > h1(P0,P1); 00471 halfspaceD2< pt3, double > h2(P2,P0); 00472 00473 pt3 const & P3(pt[B.pi[bi]]); 00474 00475 if (h1.isInside(P3)==false) 00476 return false; 00477 00478 if (h2.isInside(P3)==false) 00479 return false; 00480 00481 return true; 00482 } 00483 00484 00485 bool const d3tess::moveleft() 00486 { 00487 vs.clockwise(); 00488 00489 if (movedown()==false) 00490 { 00491 vs.anticlockwise(); 00492 return false; 00493 } 00494 00495 return true; 00496 } 00497 00498 bool const d3tess::moveright() 00499 { 00500 vs.anticlockwise(); 00501 00502 if (movedown()==false) 00503 { 00504 vs.clockwise(); 00505 return false; 00506 } 00507 00508 return true; 00509 } 00510 00511 bool const d3tess::movedown() 00512 { 00513 simplexD2linked const & x(vi[cp]); 00514 00515 uint cp2 = x.ni[ vs.v[2] ]; 00516 if (cp2==0) 00517 return false; 00518 00519 simplexD2linked const & y(vi[cp2]); 00520 00521 uint yi = y.niInverse(cp); 00522 cp = cp2; 00523 vs.set(yi); 00524 00525 return true; 00526 } 00527 00528 bool const d3tess::boundaryorient() 00529 { 00530 simplexD2linked const & x(vi[cp]); 00531 00532 for (uint i=0; i<3; ++i) 00533 if(x.ni[0]==0) 00534 { 00535 vs.set(i); 00536 return true; 00537 } 00538 00539 return false; 00540 } 00541 00542 simplexface const d3tess::cpsimplexfaceget() const 00543 { 00544 assert(vs.validstate()); 00545 return simplexface(cp,vs.v[2]); 00546 } 00547 00548 void d3tess::cpsimplexfaceset( simplexface const & sf) 00549 { 00550 cp = sf.id; 00551 vs.set(sf.face); 00552 } 00553 00554 double const d3tess::cpbasemeasure() const 00555 { 00556 simplexD2linked const & x(vi[cp]); 00557 00558 pt3 p0( pt[x.pi[vs.v[0]]]); 00559 pt3 p1( pt[x.pi[vs.v[1]]]); 00560 p0 -= p1; 00561 00562 return p0.distance(); 00563 } 00564 00565 00566 00567 00568 void d3tess::split2D( uintc w ) 00569 { 00570 assert(w<pt.size()); 00571 assert(w!=0); 00572 00573 // Extract info from mesh. 00574 00575 uint p[4]; 00576 uint n[3]; 00577 00578 //cout << SHOW(pt[w]) << " "; 00579 //cout << cpsimplex() << endl; 00580 00581 simplexD2linked & x(vi[cp]); 00582 for (uint i=0; i<3; ++i) 00583 { 00584 p[i] = x.pi[i]; 00585 n[i] = x.ni[i]; 00586 } 00587 p[3] = w; 00588 00589 debugcheck(); 00590 00591 // Indexes to new triangles. 00592 uint k[3]; 00593 k[0] = cp; 00594 k[1] = vi.size(); 00595 k[2] = k[1]+1; 00596 00597 x = simplexD2linked(p[3],p[1],p[2],n[0],k[1],k[2]); 00598 vi.push_back( simplexD2linked(p[3],p[2],p[0],n[1],k[2],k[0]) ); 00599 vi.push_back( simplexD2linked(p[3],p[0],p[1],n[2],k[0],k[1]) ); 00600 00601 if (n[1]!=0) 00602 vi[n[1]].changelink(cp,k[1]); 00603 00604 if (n[2]!=0) 00605 vi[n[2]].changelink(cp,k[2]); 00606 00607 debugcheck(); 00608 00609 for (uint i=0; i<3; ++i) 00610 { 00611 if (n[i]==0) 00612 continue; 00613 00614 assert(isconnected(n[i],k[i])); 00615 } 00616 00617 for (uint i=0; i<3; ++i) 00618 { 00619 if (n[i]==0) 00620 continue; 00621 00622 minimizer->eval(n[i],k[i]); 00623 } 00624 00625 debugcheck(); 00626 } 00627 00628 00629 00630 00631 void d3tess::addpoint(uintc k) 00632 { 00633 00634 bool found = searchminimizetowardspoint(k); 00635 if (found) 00636 { 00637 00638 //cout << "*1: " << SHOW(enablesplit) << endl; 00639 // if (enablesplit==false) 00640 // return; 00641 00642 //cout << "*2" << endl; 00643 split2D(k); 00644 00645 return; 00646 } 00647 00648 00649 //cout << "*3: " << SHOW(enablefan) << endl; 00650 // if (enablefan==false); 00651 // return; 00652 00653 //cout << "*4" << endl; 00654 00655 fan.eval(k); 00656 } 00657 00658 bool const d3tess::searchminimizetowardspoint( uintc p ) 00659 { 00660 // Statistics only. 00661 movecounter = 0; 00662 00663 bool notfound = false; 00664 bool isinside = false; 00665 uint viewableface; 00666 for ( ; !notfound; ) 00667 notfound = move_terminated(isinside,viewableface,p); 00668 00669 if (isinside==false) 00670 { 00671 if (vs.v[2]!=viewableface) 00672 vs.anticlockwise(); 00673 else 00674 return isinside; 00675 00676 if (vs.v[2]!=viewableface) 00677 vs.anticlockwise(); 00678 else 00679 return isinside; 00680 00681 if (vs.v[2]!=viewableface) 00682 assert(false); 00683 } 00684 00685 return isinside; 00686 } 00687 00688 00689 bool const d3tess::move_terminated 00690 ( 00691 bool & insidetriangle, 00692 uint & viewableface, 00693 uintc p 00694 ) 00695 { 00696 //For measuring statistics only. 00697 ++movecounter; 00698 00699 simplexD2linked & x(vi[cp]); 00700 00701 assert(p<pt.size()); 00702 point3<double> const & target(pt[p]); 00703 00704 trianglespace<pt3,double> t 00705 ( 00706 pt[ x.pi[0] ], 00707 pt[ x.pi[1] ], 00708 pt[ x.pi[2] ] 00709 ); 00710 00711 // Is the point inside the triangle? 00712 if (!t.isInside(target)) 00713 { 00714 insidetriangle=true; 00715 00716 return true; 00717 } 00718 00719 for ( uint i=0; i<3; ++i ) 00720 { 00721 // Is the target viewable? 00722 if (t.hi[i].isInside(target)) 00723 { 00724 if(x.ni[i]==0) 00725 { 00726 viewableface=i; 00727 return true; 00728 } 00729 00730 // Move 00731 cp = x.ni[i]; 00732 00733 return false; 00734 } 00735 } 00736 00737 assert(false); 00738 00739 return false; 00740 } 00741 00742 bool const d3tess::valid(uintc k) const 00743 { 00744 if (k>=vi.size()) 00745 return false; 00746 00747 if (vi[k].isnull()) 00748 return true; 00749 00750 // Look at each neighbor for links. 00751 for (uint i=0, nb; i<3; ++i) 00752 { 00753 nb = vi[k].ni[i]; 00754 if (nb==0) 00755 continue; 00756 00757 bool res; 00758 00759 // Each point bordering neighbor must also be one 00760 // of the neighbors own points. 00761 for (uint w=0; w<3; ++w) 00762 { 00763 if (w==i) 00764 continue; 00765 00766 vi[nb].piInverse( res, vi[k].pi[w] ); 00767 if (res==false) 00768 return false; 00769 } 00770 00771 // The neighbor must have a pointer back to k. 00772 00773 if (vi[nb].niInverseHas(k)==false) 00774 return false; 00775 00776 /* 00777 vi[nb].niInverse( res, k ); 00778 if (res==false) 00779 return false; 00780 */ 00781 } 00782 00783 return true; 00784 } 00785 00786 istream & d3tess::serializeInverse(istream & is) 00787 { 00788 pt.clear(); 00789 vi.clear(); 00790 cp=1; 00791 00792 pt3 p; 00793 00794 uint sz; 00795 is >> sz; 00796 00797 uint k; 00798 00799 for (uint i=0; i<sz; ++i) 00800 { 00801 is >> k; 00802 is >> p; 00803 00804 pt.push_back(p); 00805 } 00806 00807 simplexD2linked t; 00808 00809 is >> sz; 00810 for (uint i=0; i<sz; ++i) 00811 { 00812 is >> k; 00813 is >> t; 00814 00815 vi.push_back(t); 00816 } 00817 00818 return is; 00819 } 00820 00821 istream & operator >> (istream & is, d3tess & x) 00822 { 00823 return x.serializeInverse(is); 00824 } 00825 00826 void d3tess::print(string & s) const 00827 { 00828 s=""; 00829 uintc ptsz = pt.size(); 00830 { stringstream ss; ss << ptsz; s+=(ss.str()+'\n'); } 00831 00832 for (uint i=0; i<ptsz; ++i) 00833 { 00834 if (i<10) 00835 s += " "; 00836 if (i<100) 00837 s += " "; 00838 { stringstream ss; ss << i; s+=ss.str(); } 00839 s += (" " + (string)(pt[i]) + '\n'); 00840 } 00841 00842 uintc visz = vi.size(); 00843 { stringstream ss; ss << visz; s+=(ss.str()+'\n'); } 00844 for (uint i=0; i<visz; ++i) 00845 { 00846 if (i<10) 00847 s += " "; 00848 if (i<100) 00849 s += " "; 00850 { stringstream ss; ss << i; s+=ss.str(); } 00851 s += (" " + (string)(vi[i]) + '\n'); 00852 } 00853 } 00854 00855 ostream & d3tess::print(ostream & os) const 00856 { 00857 uintc ptsz = pt.size(); 00858 os << ptsz << endl; 00859 00860 for (uint i=0; i<ptsz; ++i) 00861 { 00862 os << setw(2) << i; 00863 os << " " << pt[i] << endl; 00864 } 00865 00866 uintc visz = vi.size(); 00867 os << visz << endl; 00868 for (uint i=0; i<visz; ++i) 00869 { 00870 os << setw(2) << i; 00871 os << " " << vi[i] << endl; 00872 } 00873 00874 return os; 00875 } 00876 00877 ostream & operator << (ostream& os, d3tess const & x) 00878 { 00879 return x.print(os); 00880 } 00881 00882 00883 void d3tess::surfaceright() 00884 { 00885 assert( vi[cp].ni[ vs.v[2] ]==0 ); 00886 00887 if( vi[cp].ni[ vs.v[0] ]==0 ) 00888 { 00889 vs.anticlockwise(); 00890 return; 00891 } 00892 00893 for ( ; moveright(); ); 00894 00895 vs.anticlockwise(); 00896 } 00897 00898 void d3tess::surfaceleft() 00899 { 00900 assert( vi[cp].ni[ vs.v[2] ]==0 ); 00901 00902 if( vi[cp].ni[ vs.v[1] ]==0 ) 00903 { 00904 vs.clockwise(); 00905 return; 00906 } 00907 00908 for ( ; moveleft(); ); 00909 00910 vs.clockwise(); 00911 } 00912 00913 00914 00915 00916 bool const d3tess::debugcheck() const 00917 { 00918 00919 if (debugenable==false) 00920 return true; 00921 00922 // This function checks for correct links and 00923 // duplicate traingles. 00924 // 00925 // Another test that could be added is to check the 00926 // triangles winding. ie line(pi[0],pi[1]) to creat a halfplane h 00927 // left and including the line. h sees p[2]. Include degenerate case 00928 // where all the points lie on the same line. 00929 00930 #ifndef NDEBUG 00931 00932 //cout << "DEBUG ON" << endl; 00933 00934 bool res(true); 00935 uintc visz = vi.size(); 00936 00937 // Are the triangles unique. 00938 for (uint i=1; i<visz; ++i ) 00939 { 00940 if ( vi[i].isnull() ) 00941 continue; 00942 00943 for (uint k=i+1; k<visz; ++k) 00944 { 00945 if (vi[i]==vi[k]) 00946 { 00947 res=false; 00948 00949 messageglobal() << "\n"; 00950 messageglobal() << "error: triangles with the same points.\n"; 00951 messageglobal() << " check " << i << " " << k << "\n"; 00952 messageglobal() << "vi[i]=" << vi[i] << "\n"; 00953 messageglobal() << "vk[i]=" << vi[k] << "\n"; 00954 messageglobal() << "\n"; 00955 messageglobal() << *this; 00956 } 00957 } 00958 } 00959 assert(res==true); 00960 00961 for (uint i=1; i<visz; ++i) 00962 { 00963 if ( vi[i].isnull() ) 00964 continue; 00965 00966 if(valid(i)==false) 00967 { 00968 res=false; 00969 messageglobal() << "error: "; 00970 //messageglobal() << setw(2) << i; 00971 messageglobal() << " " << vi[i] << "\n"; 00972 messageglobal() << "Printing out tess." << "\n"; 00973 messageglobal() << *this << "\n"; 00974 } 00975 } 00976 00977 assert(res==true); 00978 00979 return res; 00980 00981 #else 00982 return true; 00983 #endif 00984 00985 } 00986 00987 00988 bool const d3tess::flip() 00989 { 00990 simplexD2linked & x(vi[cp]); 00991 uint b = x.ni[vs.v[2]]; 00992 00993 return flip(cp,b); 00994 } 00995 00996 bool const d3tess::flip(uintc a, uintc b) 00997 { 00998 //cout << a << " " << b << " " << isconvex(a,b) << " | "; 00999 if (isconvex(a,b)==false) 01000 return false; 01001 01002 simplexD2linked const & A(vi[a]); 01003 simplexD2linked const & B(vi[b]); 01004 01005 // Have vs base bordering triangle b. 01006 uint ai = A.niInverse(b); 01007 cp=a; 01008 vs.set(ai); 01009 01010 // Extract point and neighbor information 01011 // from the mesh. 01012 01013 uint p[4]; 01014 01015 for (uint i=0; i<3; ++i) 01016 p[i] = A.pi[ vs.v[i] ]; 01017 p[3] = B.pi[B.niInverse(a)]; 01018 01019 uint n[4]; 01020 n[0] = A.ni[ vs.v[0] ]; 01021 n[1] = A.ni[ vs.v[1] ]; 01022 n[2] = B.ni[ B.piInverse(p[0]) ]; 01023 n[3] = B.ni[ B.piInverse(p[1]) ]; 01024 01025 //for (uint i=0; i<4; ++i) 01026 // cout << "p[" << i << "]=" << p[i] << " "; 01027 //cout << endl; 01028 01029 //for (uint i=0; i<4; ++i) 01030 // cout << "n[" << i << "]=" << n[i] << " "; 01031 //cout << endl; 01032 01033 // Overwrite the previous triangles with new ones. 01034 01035 uint k[2]; 01036 k[0] = a; 01037 k[1] = b; 01038 01039 vi[k[0]] = simplexD2linked(p[3],p[2],p[0],n[1],n[3],k[1]); 01040 vi[k[1]] = simplexD2linked(p[2],p[3],p[1],n[2],n[0],k[0]); 01041 01042 // Relink neighbors to new triangles. 01043 // Test if the neighbor exists before resetting. 01044 if (n[3]!=0) 01045 vi[n[3]].changelink(b,a); 01046 if (n[0]!=0) 01047 vi[n[0]].changelink(a,b); 01048 01049 // Have vs base bordering b. 01050 ai = A.niInverse(b); 01051 cp=a; 01052 vs.set(ai); 01053 01054 debugcheck(); 01055 01056 return true; 01057 } 01058 01059 01060 01061 void d3tess::viadd 01062 ( 01063 uintc v0, uintc v1, uintc v2, 01064 uintc n0, uintc n1, uintc n2 01065 ) 01066 { 01067 vi.push_back( simplexD2linked(v0,v1,v2,n0,n1,n2) ); 01068 } 01069 01070 01071 void d3tess::cppreserve(uint & cp0, virtualtriangle & vs0) const 01072 { 01073 cp0 = cp; 01074 vs0 = vs; 01075 } 01076 01077 void d3tess::cppreserveInverse 01078 ( 01079 uint const & cp0, 01080 virtualtriangle const & vs0 01081 ) 01082 { 01083 cp = cp0; 01084 vs = vs0; 01085 } 01086 01087 01088 d3tesspreserve::d3tesspreserve( d3tess & _tess) 01089 : tess(_tess) 01090 { 01091 tess.cppreserve(cp0,vs0); 01092 } 01093 01094 d3tesspreserve::~d3tesspreserve() 01095 { 01096 tess.cppreserveInverse(cp0,vs0); 01097 } 01098 01099 01100 01101 01102 01103 01104
1.5.8