Wm4Delaunay2.cpp

Go to the documentation of this file.
00001 // Wild Magic Source Code
00002 // David Eberly
00003 // http://www.geometrictools.com
00004 // Copyright (c) 1998-2007
00005 //
00006 // This library is free software; you can redistribute it and/or modify it
00007 // under the terms of the GNU Lesser General Public License as published by
00008 // the Free Software Foundation; either version 2.1 of the License, or (at
00009 // your option) any later version.  The license is available for reading at
00010 // either of the locations:
00011 //     http://www.gnu.org/copyleft/lgpl.html
00012 //     http://www.geometrictools.com/License/WildMagicLicense.pdf
00013 // The license applies to versions 0 through 4 of Wild Magic.
00014 //
00015 // Version: 4.0.0 (2006/06/28)
00016 
00017 #include "Wm4FoundationPCH.h"
00018 #include "Wm4Delaunay2.h"
00019 #include "Wm4DelPolygonEdge.h"
00020 #include "Wm4Mapper2.h"
00021 #include "Wm4VEManifoldMesh.h"
00022 #include "Wm4Query2Filtered.h"
00023 #include "Wm4Query2Int64.h"
00024 #include "Wm4Query2TInteger.h"
00025 #include "Wm4Query2TRational.h"
00026 
00027 namespace Wm4
00028 {
00029 //----------------------------------------------------------------------------
00030 template <class Real>
00031 Delaunay2<Real>::Delaunay2 (int iVertexQuantity, Vector2<Real>* akVertex,
00032     Real fEpsilon, bool bOwner, Query::Type eQueryType)
00033     :
00034     Delaunay<Real>(iVertexQuantity,fEpsilon,bOwner,eQueryType),
00035     m_kLineOrigin(Vector2<Real>::ZERO),
00036     m_kLineDirection(Vector2<Real>::ZERO)
00037 {
00038     assert(akVertex);
00039     m_akVertex = akVertex;
00040     m_iUniqueVertexQuantity = 0;
00041     m_akSVertex = 0;
00042     m_pkQuery = 0;
00043     m_iPathLast = -1;
00044     m_aiPath = 0;
00045     m_iLastEdgeV0 = -1;
00046     m_iLastEdgeV1 = -1;
00047     m_iLastEdgeOpposite = -1;
00048     m_iLastEdgeOppositeIndex = -1;
00049 
00050     Mapper2<Real> kMapper(m_iVertexQuantity,m_akVertex,m_fEpsilon);
00051     if (kMapper.GetDimension() == 0)
00052     {
00053         // The values of m_iDimension, m_aiIndex, and m_aiAdjacent were
00054         // already initialized by the Delaunay base class.
00055         return;
00056     }
00057 
00058     if (kMapper.GetDimension() == 1)
00059     {
00060         // The set is (nearly) collinear.  The caller is responsible for
00061         // creating a Delaunay1 object.
00062         m_iDimension = 1;
00063         m_kLineOrigin = kMapper.GetOrigin();
00064         m_kLineDirection = kMapper.GetDirection(0);
00065         return;
00066     }
00067 
00068     m_iDimension = 2;
00069 
00070     // Allocate storage for the input vertices and the supertriangle
00071     // vertices.
00072     m_akSVertex = WM4_NEW Vector2<Real>[m_iVertexQuantity+3];
00073     int i;
00074 
00075     if (eQueryType != Query::QT_RATIONAL && eQueryType != Query::QT_FILTERED)
00076     {
00077         // Transform the vertices to the square [0,1]^2.
00078         m_kMin = kMapper.GetMin();
00079         m_fScale = ((Real)1.0)/kMapper.GetMaxRange();
00080         for (i = 0; i < m_iVertexQuantity; i++)
00081         {
00082             m_akSVertex[i] = (m_akVertex[i] - m_kMin)*m_fScale;
00083         }
00084 
00085         // Construct the supertriangle to contain [0,1]^2.
00086         m_aiSV[0] = m_iVertexQuantity++;
00087         m_aiSV[1] = m_iVertexQuantity++;
00088         m_aiSV[2] = m_iVertexQuantity++;
00089         m_akSVertex[m_aiSV[0]] = Vector2<Real>((Real)-1.0,(Real)-1.0);
00090         m_akSVertex[m_aiSV[1]] = Vector2<Real>((Real)+4.0,(Real)-1.0);
00091         m_akSVertex[m_aiSV[2]] = Vector2<Real>((Real)-1.0,(Real)+4.0);
00092 
00093         Real fExpand;
00094         if (eQueryType == Query::QT_INT64)
00095         {
00096             // Scale the vertices to the square [0,2^{16}]^2 to allow use of
00097             // 64-bit integers for triangulation.
00098             fExpand = (Real)(1 << 16);
00099             m_pkQuery = WM4_NEW Query2Int64<Real>(m_iVertexQuantity,
00100                 m_akSVertex);
00101         }
00102         else if (eQueryType == Query::QT_INTEGER)
00103         {
00104             // Scale the vertices to the square [0,2^{20}]^2 to get more
00105             // precision for TInteger than for 64-bit integers for
00106             // triangulation.
00107             fExpand = (Real)(1 << 20);
00108             m_pkQuery = WM4_NEW Query2TInteger<Real>(m_iVertexQuantity,
00109                 m_akSVertex);
00110         }
00111         else // eQueryType == Query::QT_REAL
00112         {
00113             // No scaling for floating point.
00114             fExpand = (Real)1.0;
00115             m_pkQuery = WM4_NEW Query2<Real>(m_iVertexQuantity,m_akSVertex);
00116         }
00117 
00118         m_fScale *= fExpand;
00119         for (i = 0; i < m_iVertexQuantity; i++)
00120         {
00121             m_akSVertex[i] *= fExpand;
00122         }
00123     }
00124     else
00125     {
00126         // No transformation needed for exact rational arithmetic.
00127         m_kMin = Vector2<Real>::ZERO;
00128         m_fScale = (Real)1.0;
00129         size_t uiSize = m_iVertexQuantity*sizeof(Vector2<Real>);
00130         System::Memcpy(m_akSVertex,uiSize,m_akVertex,uiSize);
00131 
00132         // Construct the supertriangle to contain [min,max].
00133         Vector2<Real> kMin = kMapper.GetMin();
00134         Vector2<Real> kMax = kMapper.GetMax();
00135         Vector2<Real> kDelta = kMax - kMin;
00136         Vector2<Real> kSMin = kMin - kDelta;
00137         Vector2<Real> kSMax = kMax + kDelta*((Real)3.0);
00138         m_aiSV[0] = m_iVertexQuantity++;
00139         m_aiSV[1] = m_iVertexQuantity++;
00140         m_aiSV[2] = m_iVertexQuantity++;
00141         m_akSVertex[m_aiSV[0]] = kSMin;
00142         m_akSVertex[m_aiSV[1]] = Vector2<Real>(kSMax[0],kSMin[1]);
00143         m_akSVertex[m_aiSV[2]] = Vector2<Real>(kSMin[0],kSMax[1]);
00144 
00145         if (eQueryType == Query::QT_RATIONAL)
00146         {
00147             m_pkQuery = WM4_NEW Query2TRational<Real>(m_iVertexQuantity,
00148                 m_akSVertex);
00149         }
00150         else // eQueryType == Query::QT_FILTERED
00151         {
00152             m_pkQuery = WM4_NEW Query2Filtered<Real>(m_iVertexQuantity,
00153                 m_akSVertex,m_fEpsilon);
00154         }
00155     }
00156 
00157     DelTriangle<Real>* pkTri = WM4_NEW DelTriangle<Real>(m_aiSV[0],m_aiSV[1],
00158         m_aiSV[2]);
00159     m_kTriangle.insert(pkTri);
00160 
00161     // Incrementally update the triangulation.  The set of processed points
00162     // is maintained to eliminate duplicates, either in the original input
00163     // points or in the points obtained by snap rounding.
00164     std::set<Vector2<Real> > kProcessed;
00165     for (i = 0; i < m_iVertexQuantity-3; i++)
00166     {
00167         if (kProcessed.find(m_akSVertex[i]) == kProcessed.end())
00168         {
00169             Update(i);
00170             kProcessed.insert(m_akSVertex[i]);
00171         }
00172     }
00173     m_iUniqueVertexQuantity = (int)kProcessed.size();
00174 
00175     // Remove triangles sharing a vertex of the supertriangle.
00176     RemoveTriangles();
00177 
00178     // Assign integer values to the triangles for use by the caller.
00179     std::map<DelTriangle<Real>*,int> kPermute;
00180     typename std::set<DelTriangle<Real>*>::iterator pkTIter =
00181         m_kTriangle.begin();
00182     for (i = 0; pkTIter != m_kTriangle.end(); pkTIter++)
00183     {
00184         pkTri = *pkTIter;
00185         kPermute[pkTri] = i++;
00186     }
00187     kPermute[0] = -1;
00188 
00189     // Put Delaunay triangles into an array (vertices and adjacency info).
00190     m_iSimplexQuantity = (int)m_kTriangle.size();
00191     if (m_iSimplexQuantity > 0)
00192     {
00193         m_aiIndex = WM4_NEW int[3*m_iSimplexQuantity];
00194         m_aiAdjacent = WM4_NEW int[3*m_iSimplexQuantity];
00195         i = 0;
00196         pkTIter = m_kTriangle.begin();
00197         for (; pkTIter != m_kTriangle.end(); pkTIter++)
00198         {
00199             pkTri = *pkTIter;
00200             m_aiIndex[i] = pkTri->V[0];
00201             m_aiAdjacent[i++] = kPermute[pkTri->A[0]];
00202             m_aiIndex[i] = pkTri->V[1];
00203             m_aiAdjacent[i++] = kPermute[pkTri->A[1]];
00204             m_aiIndex[i] = pkTri->V[2];
00205             m_aiAdjacent[i++] = kPermute[pkTri->A[2]];
00206         }
00207         assert(i == 3*m_iSimplexQuantity);
00208 
00209         m_iPathLast = -1;
00210         m_aiPath = WM4_NEW int[m_iSimplexQuantity+1];
00211     }
00212 
00213     // Restore the vertex count to the original (discards the vertices of the
00214     // supertriangle).
00215     m_iVertexQuantity -= 3;
00216 
00217     pkTIter = m_kTriangle.begin();
00218     for (; pkTIter != m_kTriangle.end(); ++pkTIter)
00219     {
00220         WM4_DELETE *pkTIter;
00221     }
00222 }
00223 //----------------------------------------------------------------------------
00224 template <class Real>
00225 Delaunay2<Real>::~Delaunay2 ()
00226 {
00227     WM4_DELETE m_pkQuery;
00228     WM4_DELETE[] m_akSVertex;
00229     WM4_DELETE[] m_aiPath;
00230     if (m_bOwner)
00231     {
00232         WM4_DELETE[] m_akVertex;
00233     }
00234 }
00235 //----------------------------------------------------------------------------
00236 template <class Real>
00237 const Vector2<Real>* Delaunay2<Real>::GetVertices () const
00238 {
00239     return m_akVertex;
00240 }
00241 //----------------------------------------------------------------------------
00242 template <class Real>
00243 int Delaunay2<Real>::GetUniqueVertexQuantity () const
00244 {
00245     return m_iUniqueVertexQuantity;
00246 }
00247 //----------------------------------------------------------------------------
00248 template <class Real>
00249 const Vector2<Real>& Delaunay2<Real>::GetLineOrigin () const
00250 {
00251     return m_kLineOrigin;
00252 }
00253 //----------------------------------------------------------------------------
00254 template <class Real>
00255 const Vector2<Real>& Delaunay2<Real>::GetLineDirection () const
00256 {
00257     return m_kLineDirection;
00258 }
00259 //----------------------------------------------------------------------------
00260 template <class Real>
00261 Delaunay1<Real>* Delaunay2<Real>::GetDelaunay1 () const
00262 {
00263     assert(m_iDimension == 1);
00264     if (m_iDimension != 1)
00265     {
00266         return 0;
00267     }
00268 
00269     Real* afProjection = WM4_NEW Real[m_iVertexQuantity];
00270     for (int i = 0; i < m_iVertexQuantity; i++)
00271     {
00272         Vector2<Real> kDiff = m_akVertex[i] - m_kLineOrigin;
00273         afProjection[i] = m_kLineDirection.Dot(kDiff);
00274     }
00275 
00276     return WM4_NEW Delaunay1<Real>(m_iVertexQuantity,afProjection,m_fEpsilon,
00277         true,m_eQueryType);
00278 }
00279 //----------------------------------------------------------------------------
00280 template <class Real>
00281 bool Delaunay2<Real>::GetHull (int& riEQuantity, int*& raiIndex)
00282 {
00283     assert(m_iDimension == 2);
00284     if (m_iDimension != 2)
00285     {
00286         return false;
00287     }
00288 
00289     riEQuantity = 0;
00290     raiIndex = 0;
00291 
00292     // Count the number of edges that are not shared by two triangles.
00293     int i, iAdjQuantity = 3*m_iSimplexQuantity;
00294     for (i = 0; i < iAdjQuantity; i++)
00295     {
00296         if (m_aiAdjacent[i] == -1)
00297         {
00298             riEQuantity++;
00299         }
00300     }
00301     assert(riEQuantity > 0);
00302     if (riEQuantity == 0)
00303     {
00304         return false;
00305     }
00306 
00307     // Enumerate the edges.
00308     raiIndex = WM4_NEW int[2*riEQuantity];
00309     int* piIndex = raiIndex;
00310     for (i = 0; i < iAdjQuantity; i++)
00311     {
00312         if (m_aiAdjacent[i] == -1)
00313         {
00314             int iTri = i/3, j = i%3;
00315             *piIndex++ = m_aiIndex[3*iTri+j];
00316             *piIndex++ = m_aiIndex[3*iTri+((j+1)%3)];
00317         }
00318     }
00319 
00320     return true;
00321 }
00322 //----------------------------------------------------------------------------
00323 template <class Real>
00324 int Delaunay2<Real>::GetContainingTriangle (const Vector2<Real>& rkP) const
00325 {
00326     assert(m_iDimension == 2);
00327     if (m_iDimension != 2)
00328     {
00329         return -1;
00330     }
00331 
00332     // convert to scaled coordinates
00333     Vector2<Real> kXFrmP = (rkP - m_kMin)*m_fScale;
00334 
00335     // start at first triangle in mesh
00336     int iIndex = (m_iPathLast >= 0 ? m_aiPath[m_iPathLast] : 0);
00337     m_iPathLast = -1;
00338     m_iLastEdgeV0 = -1;
00339     m_iLastEdgeV1 = -1;
00340     m_iLastEdgeOpposite = -1;
00341     m_iLastEdgeOppositeIndex = -1;
00342 
00343     // use triangle edges as binary separating lines
00344     for (int i = 0; i < m_iSimplexQuantity; i++)
00345     {
00346         m_aiPath[++m_iPathLast] = iIndex;
00347 
00348         int* aiV = &m_aiIndex[3*iIndex];
00349 
00350         if (m_pkQuery->ToLine(kXFrmP,aiV[0],aiV[1]) > 0)
00351         {
00352             iIndex = m_aiAdjacent[3*iIndex];
00353             if (iIndex == -1)
00354             {
00355                 m_iLastEdgeV0 = aiV[0];
00356                 m_iLastEdgeV1 = aiV[1];
00357                 m_iLastEdgeOpposite = aiV[2];
00358                 m_iLastEdgeOppositeIndex = 2;
00359                 return -1;
00360             }
00361             continue;
00362         }
00363 
00364         if (m_pkQuery->ToLine(kXFrmP,aiV[1],aiV[2]) > 0)
00365         {
00366             iIndex = m_aiAdjacent[3*iIndex+1];
00367             if (iIndex == -1)
00368             {
00369                 m_iLastEdgeV0 = aiV[1];
00370                 m_iLastEdgeV1 = aiV[2];
00371                 m_iLastEdgeOpposite = aiV[0];
00372                 m_iLastEdgeOppositeIndex = 0;
00373                 return -1;
00374             }
00375             continue;
00376         }
00377 
00378         if (m_pkQuery->ToLine(kXFrmP,aiV[2],aiV[0]) > 0)
00379         {
00380             iIndex = m_aiAdjacent[3*iIndex+2];
00381             if (iIndex == -1)
00382             {
00383                 m_iLastEdgeV0 = aiV[2];
00384                 m_iLastEdgeV1 = aiV[0];
00385                 m_iLastEdgeOpposite = aiV[1];
00386                 m_iLastEdgeOppositeIndex = 1;
00387                 return -1;
00388             }
00389             continue;
00390         }
00391 
00392         m_iLastEdgeV0 = -1;
00393         m_iLastEdgeV1 = -1;
00394         m_iLastEdgeOpposite = -1;
00395         m_iLastEdgeOppositeIndex = -1;
00396         return iIndex;
00397     }
00398 
00399     return -1;
00400 }
00401 //----------------------------------------------------------------------------
00402 template <class Real>
00403 int Delaunay2<Real>::GetPathLast () const
00404 {
00405     return m_iPathLast;
00406 }
00407 //----------------------------------------------------------------------------
00408 template <class Real>
00409 const int* Delaunay2<Real>::GetPath () const
00410 {
00411     return m_aiPath;
00412 }
00413 //----------------------------------------------------------------------------
00414 template <class Real>
00415 int Delaunay2<Real>::GetLastEdge (int& riV0, int& riV1, int& riV2) const
00416 {
00417     riV0 = m_iLastEdgeV0;
00418     riV1 = m_iLastEdgeV1;
00419     riV2 = m_iLastEdgeOpposite;
00420     return m_iLastEdgeOppositeIndex;
00421 }
00422 //----------------------------------------------------------------------------
00423 template <class Real>
00424 bool Delaunay2<Real>::GetVertexSet (int i, Vector2<Real> akV[3]) const
00425 {
00426     assert(m_iDimension == 2);
00427     if (m_iDimension != 2)
00428     {
00429         return false;
00430     }
00431 
00432     if (0 <= i && i < m_iSimplexQuantity)
00433     {
00434         akV[0] = m_akVertex[m_aiIndex[3*i  ]];
00435         akV[1] = m_akVertex[m_aiIndex[3*i+1]];
00436         akV[2] = m_akVertex[m_aiIndex[3*i+2]];
00437         return true;
00438     }
00439 
00440     return false;
00441 }
00442 //----------------------------------------------------------------------------
00443 template <class Real>
00444 bool Delaunay2<Real>::GetIndexSet (int i, int aiIndex[3]) const
00445 {
00446     assert(m_iDimension == 2);
00447     if (m_iDimension != 2)
00448     {
00449         return false;
00450     }
00451 
00452     if (0 <= i && i < m_iSimplexQuantity)
00453     {
00454         aiIndex[0] = m_aiIndex[3*i  ];
00455         aiIndex[1] = m_aiIndex[3*i+1];
00456         aiIndex[2] = m_aiIndex[3*i+2];
00457         return true;
00458     }
00459 
00460     return false;
00461 }
00462 //----------------------------------------------------------------------------
00463 template <class Real>
00464 bool Delaunay2<Real>::GetAdjacentSet (int i, int aiAdjacent[3]) const
00465 {
00466     assert(m_iDimension == 2);
00467     if (m_iDimension != 2)
00468     {
00469         return false;
00470     }
00471 
00472     if (0 <= i && i < m_iSimplexQuantity)
00473     {
00474         aiAdjacent[0] = m_aiAdjacent[3*i  ];
00475         aiAdjacent[1] = m_aiAdjacent[3*i+1];
00476         aiAdjacent[2] = m_aiAdjacent[3*i+2];
00477         return true;
00478     }
00479 
00480     return false;
00481 }
00482 //----------------------------------------------------------------------------
00483 template <class Real>
00484 bool Delaunay2<Real>::GetBarycentricSet (int i, const Vector2<Real>& rkP,
00485     Real afBary[3]) const
00486 {
00487     assert(m_iDimension == 2);
00488     if (m_iDimension != 2)
00489     {
00490         return false;
00491     }
00492 
00493     if (0 <= i && i < m_iSimplexQuantity)
00494     {
00495         Vector2<Real> kV0 = m_akVertex[m_aiIndex[3*i  ]];
00496         Vector2<Real> kV1 = m_akVertex[m_aiIndex[3*i+1]];
00497         Vector2<Real> kV2 = m_akVertex[m_aiIndex[3*i+2]];
00498         rkP.GetBarycentrics(kV0,kV1,kV2,afBary);
00499         return true;
00500     }
00501 
00502     return false;
00503 }
00504 //----------------------------------------------------------------------------
00505 template <class Real>
00506 void Delaunay2<Real>::Update (int i)
00507 {
00508     // Locate the triangle containing vertex i.
00509     DelTriangle<Real>* pkTri = GetContainingTriangle(i);
00510 
00511     // Locate and remove the triangles forming the insertion polygon.
00512     std::stack<DelTriangle<Real>*> kStack;
00513     VEManifoldMesh kPolygon(0,DelPolygonEdge<Real>::ECreator);
00514     kStack.push(pkTri);
00515     pkTri->OnStack = true;
00516     int j, iV0, iV1;
00517     DelPolygonEdge<Real>* pkEdge;
00518     while (!kStack.empty())
00519     {
00520         pkTri = kStack.top();
00521         kStack.pop();
00522         pkTri->OnStack = false;
00523         for (j = 0; j < 3; j++)
00524         {
00525             DelTriangle<Real>* pkAdj = pkTri->A[j];
00526             if (pkAdj)
00527             {
00528                 // Detach triangle and adjacent triangle from each other.
00529                 int iNullIndex = pkTri->DetachFrom(j,pkAdj);
00530 
00531                 if (pkAdj->IsInsertionComponent(i,pkTri,m_pkQuery,m_aiSV))
00532                 {
00533                     if (!pkAdj->OnStack)
00534                     {
00535                         // Adjacent triangle inside insertion polygon.
00536                         kStack.push(pkAdj);
00537                         pkAdj->OnStack = true;
00538                     }
00539                 }
00540                 else
00541                 {
00542                     // Adjacent triangle outside insertion polygon.
00543                     iV0 = pkTri->V[j];
00544                     iV1 = pkTri->V[(j+1)%3];
00545                     pkEdge = (DelPolygonEdge<Real>*)kPolygon.InsertEdge(iV0,
00546                         iV1);
00547                     pkEdge->NullIndex = iNullIndex;
00548                     pkEdge->Tri = pkAdj;
00549                 }
00550             }
00551             else
00552             {
00553                 // The triangle is in the insertion polygon, but the adjacent
00554                 // one does not exist.  This means one of two things:
00555                 // (1) We are at an edge of the supertriangle, and that edge
00556                 //     is part of the insertion polygon.
00557                 // (2) We are at an edge that was recently shared by the
00558                 //     triangle and the adjacent, but we detached those
00559                 //     triangles from each other.  These edges should be
00560                 //     ignored.
00561                 iV0 = pkTri->V[j];
00562                 if (IsSupervertex(iV0))
00563                 {
00564                     iV1 = pkTri->V[(j+1)%3];
00565                     if (IsSupervertex(iV1))
00566                     {
00567                         pkEdge = (DelPolygonEdge<Real>*)kPolygon.InsertEdge(
00568                             iV0,iV1);
00569                         pkEdge->NullIndex = -1;
00570                         pkEdge->Tri = 0;
00571                     }
00572                 }
00573             }
00574         }
00575         m_kTriangle.erase(pkTri);
00576         WM4_DELETE pkTri;
00577     }
00578 
00579     // Insert the new triangles formed by the input point and the edges of
00580     // the insertion polygon.
00581     const VEManifoldMesh::EMap& rkEMap = kPolygon.GetEdges();
00582     assert(rkEMap.size() >= 3 && kPolygon.IsClosed());
00583     typename VEManifoldMesh::EMapCIterator pkEIter;
00584     for (pkEIter = rkEMap.begin(); pkEIter != rkEMap.end(); pkEIter++)
00585     {
00586         pkEdge = (DelPolygonEdge<Real>*)pkEIter->second;
00587 
00588         // Create and insert the new triangle.
00589         pkTri = WM4_NEW DelTriangle<Real>(i,pkEdge->V[0],pkEdge->V[1]);
00590         m_kTriangle.insert(pkTri);
00591 
00592         // Establish the adjacency links across the polygon edge.
00593         pkTri->A[1] = pkEdge->Tri;
00594         if (pkEdge->Tri)
00595         {
00596             pkEdge->Tri->A[pkEdge->NullIndex] = pkTri;
00597         }
00598 
00599         // Update the edge's triangle pointer to point to the newly created
00600         // triangle.  This information is used later to establish the links
00601         // between the new triangles.
00602         pkEdge->Tri = pkTri;
00603     }
00604 
00605     // Establish the adjacency links between the new triangles.
00606     DelPolygonEdge<Real>* pkAdjEdge;
00607     for (pkEIter = rkEMap.begin(); pkEIter != rkEMap.end(); pkEIter++)
00608     {
00609         pkEdge = (DelPolygonEdge<Real>*)pkEIter->second;
00610         pkAdjEdge = (DelPolygonEdge<Real>*)pkEdge->E[0];
00611         pkEdge->Tri->A[0] = pkAdjEdge->Tri;
00612         pkAdjEdge = (DelPolygonEdge<Real>*)pkEdge->E[1];
00613         pkEdge->Tri->A[2] = pkAdjEdge->Tri;
00614     }
00615 }
00616 //----------------------------------------------------------------------------
00617 template <class Real>
00618 DelTriangle<Real>* Delaunay2<Real>::GetContainingTriangle (int i) const
00619 {
00620     // Locate which triangle in the current mesh contains vertex i.  By
00621     // construction, there must be such a triangle (the vertex cannot be
00622     // outside the supertriangle).
00623 
00624     DelTriangle<Real>* pkTri = *m_kTriangle.begin();
00625     int iTQuantity = (int)m_kTriangle.size();
00626     for (int iT = 0; iT < iTQuantity; iT++)
00627     {
00628         int* aiV = pkTri->V;
00629 
00630         if (m_pkQuery->ToLine(i,aiV[0],aiV[1]) > 0)
00631         {
00632             pkTri = pkTri->A[0];
00633             if (!pkTri)
00634             {
00635                 break;
00636             }
00637             continue;
00638         }
00639 
00640         if (m_pkQuery->ToLine(i,aiV[1],aiV[2]) > 0)
00641         {
00642             pkTri = pkTri->A[1];
00643             if (!pkTri)
00644             {
00645                 break;
00646             }
00647             continue;
00648         }
00649 
00650         if (m_pkQuery->ToLine(i,aiV[2],aiV[0]) > 0)
00651         {
00652             pkTri = pkTri->A[2];
00653             if (!pkTri)
00654             {
00655                 break;
00656             }
00657             continue;
00658         }
00659 
00660         return pkTri;
00661     }
00662 
00663     assert(false);
00664     return 0;
00665 }
00666 //----------------------------------------------------------------------------
00667 template <class Real>
00668 void Delaunay2<Real>::RemoveTriangles ()
00669 {
00670     // Identify those triangles sharing a vertex of the supertriangle.
00671     std::set<DelTriangle<Real>*> kRemoveTri;
00672     DelTriangle<Real>* pkTri;
00673     typename std::set<DelTriangle<Real>*>::iterator pkTIter =
00674         m_kTriangle.begin();
00675     for (; pkTIter != m_kTriangle.end(); pkTIter++)
00676     {
00677         pkTri = *pkTIter;
00678         for (int j = 0; j < 3; j++)
00679         {
00680             if (IsSupervertex(pkTri->V[j]))
00681             {
00682                 kRemoveTri.insert(pkTri);
00683                 break;
00684             }
00685         }
00686     }
00687 
00688     // Remove the triangles from the mesh.
00689     pkTIter = kRemoveTri.begin();
00690     for (; pkTIter != kRemoveTri.end(); pkTIter++)
00691     {
00692         pkTri = *pkTIter;
00693         for (int j = 0; j < 3; j++)
00694         {
00695             // Break the links with adjacent triangles.
00696             DelTriangle<Real>* pkAdj = pkTri->A[j];
00697             if (pkAdj)
00698             {
00699                 for (int k = 0; k < 3; k++)
00700                 {
00701                     if (pkAdj->A[k] == pkTri)
00702                     {
00703                         pkAdj->A[k] = 0;
00704                         break;
00705                     }
00706                 }
00707             }
00708         }
00709         m_kTriangle.erase(pkTri);
00710         WM4_DELETE pkTri;
00711     }
00712 }
00713 //----------------------------------------------------------------------------
00714 template <class Real>
00715 bool Delaunay2<Real>::IsSupervertex (int i) const
00716 {
00717     for (int j = 0; j < 3; j++)
00718     {
00719         if (i == m_aiSV[j])
00720         {
00721             return true;
00722         }
00723     }
00724     return false;
00725 }
00726 //----------------------------------------------------------------------------
00727 template <class Real>
00728 Delaunay2<Real>::Delaunay2 (const char* acFilename)
00729     :
00730     Delaunay<Real>(0,(Real)0.0,false,Query::QT_REAL)
00731 {
00732     m_akVertex = 0;
00733     m_akSVertex = 0;
00734     m_pkQuery = 0;
00735     m_aiPath = 0;
00736     bool bLoaded = Load(acFilename);
00737     assert(bLoaded);
00738     (void)bLoaded;  // avoid warning in Release build
00739 }
00740 //----------------------------------------------------------------------------
00741 template <class Real>
00742 bool Delaunay2<Real>::Load (const char* acFilename)
00743 {
00744     FILE* pkIFile = System::Fopen(acFilename,"rb");
00745     if (!pkIFile)
00746     {
00747         return false;
00748     }
00749 
00750     Delaunay<Real>::Load(pkIFile);
00751 
00752     WM4_DELETE m_pkQuery;
00753     WM4_DELETE[] m_akSVertex;
00754     WM4_DELETE[] m_aiPath;
00755     if (m_bOwner)
00756     {
00757         WM4_DELETE[] m_akVertex;
00758     }
00759 
00760     m_bOwner = true;
00761     m_akVertex = WM4_NEW Vector2<Real>[m_iVertexQuantity];
00762     m_akSVertex = WM4_NEW Vector2<Real>[m_iVertexQuantity+3];
00763     m_aiPath = WM4_NEW int[m_iSimplexQuantity+1];
00764 
00765     System::Read4le(pkIFile,1,&m_iUniqueVertexQuantity);
00766     System::Read4le(pkIFile,3,m_aiSV);
00767     System::Read4le(pkIFile,1,&m_iPathLast);
00768     System::Read4le(pkIFile,1,&m_iLastEdgeV0);
00769     System::Read4le(pkIFile,1,&m_iLastEdgeV1);
00770     System::Read4le(pkIFile,1,&m_iLastEdgeOpposite);
00771     System::Read4le(pkIFile,1,&m_iLastEdgeOppositeIndex);
00772     System::Read4le(pkIFile,m_iSimplexQuantity+1,m_aiPath);
00773 
00774     size_t uiSize = sizeof(Real);
00775     int iVQ = 2*m_iVertexQuantity, iSVQ = 2*(m_iVertexQuantity + 3);
00776     if (uiSize == 4)
00777     {
00778         System::Read4le(pkIFile,iVQ,m_akVertex);
00779         System::Read4le(pkIFile,iSVQ,m_akSVertex);
00780         System::Read4le(pkIFile,2,(Real*)m_kMin);
00781         System::Read4le(pkIFile,1,&m_fScale);
00782         System::Read4le(pkIFile,2,(Real*)m_kLineOrigin);
00783         System::Read4le(pkIFile,2,(Real*)m_kLineDirection);
00784     }
00785     else // iSize == 8
00786     {
00787         System::Read8le(pkIFile,iVQ,m_akVertex);
00788         System::Read8le(pkIFile,iSVQ,m_akSVertex);
00789         System::Read8le(pkIFile,2,(Real*)m_kMin);
00790         System::Read8le(pkIFile,1,&m_fScale);
00791         System::Read8le(pkIFile,2,(Real*)m_kLineOrigin);
00792         System::Read8le(pkIFile,2,(Real*)m_kLineDirection);
00793     }
00794 
00795     System::Fclose(pkIFile);
00796 
00797     switch (m_eQueryType)
00798     {
00799     case Query::QT_INT64:
00800         m_pkQuery = WM4_NEW Query2Int64<Real>(m_iVertexQuantity,m_akSVertex);
00801         break;
00802     case Query::QT_INTEGER:
00803         m_pkQuery = WM4_NEW Query2TInteger<Real>(m_iVertexQuantity,
00804             m_akSVertex);
00805         break;
00806     case Query::QT_RATIONAL:
00807         m_pkQuery = WM4_NEW Query2TRational<Real>(m_iVertexQuantity,
00808             m_akSVertex);
00809         break;
00810     case Query::QT_REAL:
00811         m_pkQuery = WM4_NEW Query2<Real>(m_iVertexQuantity,m_akSVertex);
00812         break;
00813     case Query::QT_FILTERED:
00814         m_pkQuery = WM4_NEW Query2Filtered<Real>(m_iVertexQuantity,
00815             m_akSVertex,m_fEpsilon);
00816         break;
00817     }
00818 
00819     return true;
00820 }
00821 //----------------------------------------------------------------------------
00822 template <class Real>
00823 bool Delaunay2<Real>::Save (const char* acFilename) const
00824 {
00825     FILE* pkOFile = System::Fopen(acFilename,"wb");
00826     if (!pkOFile)
00827     {
00828         return false;
00829     }
00830 
00831     Delaunay<Real>::Save(pkOFile);
00832 
00833     System::Write4le(pkOFile,1,&m_iUniqueVertexQuantity);
00834     System::Write4le(pkOFile,3,m_aiSV);
00835     System::Write4le(pkOFile,1,&m_iPathLast);
00836     System::Write4le(pkOFile,1,&m_iLastEdgeV0);
00837     System::Write4le(pkOFile,1,&m_iLastEdgeV1);
00838     System::Write4le(pkOFile,1,&m_iLastEdgeOpposite);
00839     System::Write4le(pkOFile,1,&m_iLastEdgeOppositeIndex);
00840     System::Write4le(pkOFile,m_iSimplexQuantity+1,m_aiPath);
00841 
00842     size_t uiSize = sizeof(Real);
00843     int iVQ = 2*m_iVertexQuantity, iSVQ = 2*(m_iVertexQuantity + 3);
00844     if (uiSize == 4)
00845     {
00846         System::Write4le(pkOFile,iVQ,m_akVertex);
00847         System::Write4le(pkOFile,iSVQ,m_akSVertex);
00848         System::Write4le(pkOFile,2,(const Real*)m_kMin);
00849         System::Write4le(pkOFile,1,&m_fScale);
00850         System::Write4le(pkOFile,2,(const Real*)m_kLineOrigin);
00851         System::Write4le(pkOFile,2,(const Real*)m_kLineDirection);
00852     }
00853     else // iSize == 8
00854     {
00855         System::Write8le(pkOFile,iVQ,m_akVertex);
00856         System::Write8le(pkOFile,iSVQ,m_akSVertex);
00857         System::Write8le(pkOFile,2,(const Real*)m_kMin);
00858         System::Write8le(pkOFile,1,&m_fScale);
00859         System::Write8le(pkOFile,2,(const Real*)m_kLineOrigin);
00860         System::Write8le(pkOFile,2,(const Real*)m_kLineDirection);
00861     }
00862 
00863     System::Fclose(pkOFile);
00864     return true;
00865 }
00866 //----------------------------------------------------------------------------
00867 
00868 //----------------------------------------------------------------------------
00869 // explicit instantiation
00870 //----------------------------------------------------------------------------
00871 template WM4_FOUNDATION_ITEM
00872 class Delaunay2<float>;
00873 
00874 template WM4_FOUNDATION_ITEM
00875 class Delaunay2<double>;
00876 //----------------------------------------------------------------------------
00877 }

Generated on Wed Nov 23 19:01:03 2011 for FreeCAD by  doxygen 1.6.1