Wm4Delaunay3.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 "Wm4Delaunay3.h"
00019 #include "Wm4DelPolyhedronFace.h"
00020 #include "Wm4Mapper3.h"
00021 #include "Wm4ETManifoldMesh.h"
00022 #include "Wm4Delaunay2.h"
00023 #include "Wm4Query3Filtered.h"
00024 #include "Wm4Query3Int64.h"
00025 #include "Wm4Query3TInteger.h"
00026 #include "Wm4Query3TRational.h"
00027 
00028 // Indexing for the vertices of the triangle opposite a vertex.  The triangle
00029 // opposite vertex j is
00030 //   <gs_aaiIndex[j][0],gs_aaiIndex[j][1],gs_aaiIndex[j][2]>
00031 // and is listed in counterclockwise order when viewed from outside the
00032 // tetrahedron.
00033 static const int gs_aaiIndex[4][3] = { {1,2,3}, {0,3,2}, {0,1,3}, {0,2,1} };
00034 
00035 namespace Wm4
00036 {
00037 //----------------------------------------------------------------------------
00038 template <class Real>
00039 Delaunay3<Real>::Delaunay3 (int iVertexQuantity, Vector3<Real>* akVertex,
00040     Real fEpsilon, bool bOwner, Query::Type eQueryType)
00041     :
00042     Delaunay<Real>(iVertexQuantity,fEpsilon,bOwner,eQueryType),
00043     m_kLineOrigin(Vector3<Real>::ZERO),
00044     m_kLineDirection(Vector3<Real>::ZERO),
00045     m_kPlaneOrigin(Vector3<Real>::ZERO)
00046 {
00047     assert(akVertex);
00048     m_akVertex = akVertex;
00049     m_iUniqueVertexQuantity = 0;
00050     m_akPlaneDirection[0] = Vector3<Real>::ZERO;
00051     m_akPlaneDirection[1] = Vector3<Real>::ZERO;
00052     m_akSVertex = 0;
00053     m_pkQuery = 0;
00054     m_iPathLast = -1;
00055     m_aiPath = 0;
00056     m_iLastFaceV0 = -1;
00057     m_iLastFaceV1 = -1;
00058     m_iLastFaceV2 = -1;
00059     m_iLastFaceOpposite = -1;
00060     m_iLastFaceOppositeIndex = -1;
00061 
00062     Mapper3<Real> kMapper(m_iVertexQuantity,m_akVertex,m_fEpsilon);
00063     if (kMapper.GetDimension() == 0)
00064     {
00065         // The values of m_iDimension, m_aiIndex, and m_aiAdjacent were
00066         // already initialized by the Delaunay base class.
00067         return;
00068     }
00069 
00070     int i;
00071     if (kMapper.GetDimension() == 1)
00072     {
00073         // The set is (nearly) collinear.  The caller is responsible for
00074         // creating a Delaunay1 object.
00075         m_iDimension = 1;
00076         m_kLineOrigin = kMapper.GetOrigin();
00077         m_kLineDirection = kMapper.GetDirection(0);
00078         return;
00079     }
00080 
00081     if (kMapper.GetDimension() == 2)
00082     {
00083         // The set is (nearly) coplanar.  The caller is responsible for
00084         // creating a Delaunay2 object.
00085         m_iDimension = 2;
00086         m_kPlaneOrigin = kMapper.GetOrigin();
00087         m_akPlaneDirection[0] = kMapper.GetDirection(0);
00088         m_akPlaneDirection[1] = kMapper.GetDirection(1);
00089         return;
00090     }
00091 
00092     m_iDimension = 3;
00093 
00094     // Allocate storage for the input vertices and the supertetrahedron
00095     // vertices.
00096     m_akSVertex = WM4_NEW Vector3<Real>[m_iVertexQuantity+4];
00097 
00098     if (eQueryType != Query::QT_RATIONAL && eQueryType != Query::QT_FILTERED)
00099     {
00100         // Transform the vertices to the cube [0,1]^3.
00101         m_kMin = kMapper.GetMin();
00102         m_fScale = ((Real)1.0)/kMapper.GetMaxRange();
00103         for (i = 0; i < m_iVertexQuantity; i++)
00104         {
00105             m_akSVertex[i] = (m_akVertex[i] - m_kMin)*m_fScale;
00106         }
00107 
00108         // Construct the supertetrahedron to contain [0,1]^3.
00109         m_aiSV[0] = m_iVertexQuantity++;
00110         m_aiSV[1] = m_iVertexQuantity++;
00111         m_aiSV[2] = m_iVertexQuantity++;
00112         m_aiSV[3] = m_iVertexQuantity++;
00113         m_akSVertex[m_aiSV[0]] = Vector3<Real>((Real)-1.0,(Real)-1.0,
00114             (Real)-1.0);
00115         m_akSVertex[m_aiSV[1]] = Vector3<Real>((Real)+6.0,(Real)-1.0,
00116             (Real)-1.0);
00117         m_akSVertex[m_aiSV[2]] = Vector3<Real>((Real)-1.0,(Real)+6.0,
00118             (Real)-1.0);
00119         m_akSVertex[m_aiSV[3]] = Vector3<Real>((Real)-1.0,(Real)-1.0,
00120             (Real)+6.0);
00121 
00122         Real fExpand;
00123         if (eQueryType == Query::QT_INT64)
00124         {
00125             // Scale the vertices to the cube [0,2^{10}]^3 to allow use of
00126             // 64-bit integers for tetrahedralization.
00127             fExpand = (Real)(1 << 10);
00128             m_pkQuery = WM4_NEW Query3Int64<Real>(m_iVertexQuantity,
00129                 m_akSVertex);
00130         }
00131         else if (eQueryType == Query::QT_INTEGER)
00132         {
00133             // Scale the vertices to the cube [0,2^{20}]^3 to get more
00134             // precision for TInteger than for 64-bit integers for
00135             // tetrahedralization.
00136             fExpand = (Real)(1 << 20);
00137             m_pkQuery = WM4_NEW Query3TInteger<Real>(m_iVertexQuantity,
00138                 m_akSVertex);
00139         }
00140         else // eQueryType == Query::QT_REAL
00141         {
00142             // No scaling for floating point.
00143             fExpand = (Real)1.0;
00144             m_pkQuery = WM4_NEW Query3<Real>(m_iVertexQuantity,m_akSVertex);
00145         }
00146 
00147         m_fScale *= fExpand;
00148         for (i = 0; i < m_iVertexQuantity; i++)
00149         {
00150             m_akSVertex[i] *= fExpand;
00151         }
00152     }
00153     else
00154     {
00155         // No transformation needed for exact rational arithmetic.
00156         m_kMin = Vector3<Real>::ZERO;
00157         m_fScale = (Real)1.0;
00158         size_t uiSize = m_iVertexQuantity*sizeof(Vector3<Real>);
00159         System::Memcpy(m_akSVertex,uiSize,m_akVertex,uiSize);
00160 
00161         // Construct the supertriangle to contain [min,max].
00162         Vector3<Real> kMin = kMapper.GetMin();
00163         Vector3<Real> kMax = kMapper.GetMax();
00164         Vector3<Real> kDelta = kMax - kMin;
00165         Vector3<Real> kSMin = kMin - kDelta;
00166         Vector3<Real> kSMax = kMax + ((Real)5.0)*kDelta;
00167         m_aiSV[0] = m_iVertexQuantity++;
00168         m_aiSV[1] = m_iVertexQuantity++;
00169         m_aiSV[2] = m_iVertexQuantity++;
00170         m_aiSV[3] = m_iVertexQuantity++;
00171         m_akSVertex[m_aiSV[0]] = kSMin;
00172         m_akSVertex[m_aiSV[1]] = Vector3<Real>(kSMax[0],kSMin[1],kSMin[2]);
00173         m_akSVertex[m_aiSV[2]] = Vector3<Real>(kSMin[0],kSMax[1],kSMin[2]);
00174         m_akSVertex[m_aiSV[3]] = Vector3<Real>(kSMin[0],kSMin[1],kSMax[2]);
00175 
00176         if (eQueryType == Query::QT_RATIONAL)
00177         {
00178             m_pkQuery = WM4_NEW Query3TRational<Real>(m_iVertexQuantity,
00179                 m_akSVertex);
00180         }
00181         else // eQueryType == Query::QT_FILTERED
00182         {
00183             m_pkQuery = WM4_NEW Query3Filtered<Real>(m_iVertexQuantity,
00184                 m_akSVertex,fEpsilon);
00185         }
00186     }
00187 
00188     DelTetrahedron<Real>* pkTetra = WM4_NEW DelTetrahedron<Real>(m_aiSV[0],
00189         m_aiSV[1],m_aiSV[2],m_aiSV[3]);
00190     m_kTetrahedron.insert(pkTetra);
00191 
00192     // Incrementally update the tetrahedralization.  The set of processed
00193     // points is maintained to eliminate duplicates, either in the original
00194     // input points or in the points obtained by snap rounding.
00195     std::set<Vector3<Real> > kProcessed;
00196     for (i = 0; i < m_iVertexQuantity-4; i++)
00197     {
00198         if (kProcessed.find(m_akSVertex[i]) == kProcessed.end())
00199         {
00200             Update(i);
00201             kProcessed.insert(m_akSVertex[i]);
00202         }
00203     }
00204     m_iUniqueVertexQuantity = (int)kProcessed.size();
00205 
00206     // Remove tetrahedra sharing a vertex of the supertetrahedron.
00207     RemoveTetrahedra();
00208 
00209     // Assign integer values to the tetrahedra for use by the caller.
00210     std::map<DelTetrahedron<Real>*,int> kPermute;
00211     typename std::set<DelTetrahedron<Real>*>::iterator pkTIter =
00212         m_kTetrahedron.begin();
00213     for (i = 0; pkTIter != m_kTetrahedron.end(); pkTIter++)
00214     {
00215         pkTetra = *pkTIter;
00216         kPermute[pkTetra] = i++;
00217     }
00218     kPermute[0] = -1;
00219 
00220     // Put Delaunay tetrahedra into an array (vertices and adjacency info).
00221     m_iSimplexQuantity = (int)m_kTetrahedron.size();
00222     if (m_iSimplexQuantity > 0)
00223     {
00224         m_aiIndex = WM4_NEW int[4*m_iSimplexQuantity];
00225         m_aiAdjacent = WM4_NEW int[4*m_iSimplexQuantity];
00226         i = 0;
00227         pkTIter = m_kTetrahedron.begin();
00228         for (; pkTIter != m_kTetrahedron.end(); pkTIter++)
00229         {
00230             pkTetra = *pkTIter;
00231             m_aiIndex[i] = pkTetra->V[0];
00232             m_aiAdjacent[i++] = kPermute[pkTetra->A[0]];
00233             m_aiIndex[i] = pkTetra->V[1];
00234             m_aiAdjacent[i++] = kPermute[pkTetra->A[1]];
00235             m_aiIndex[i] = pkTetra->V[2];
00236             m_aiAdjacent[i++] = kPermute[pkTetra->A[2]];
00237             m_aiIndex[i] = pkTetra->V[3];
00238             m_aiAdjacent[i++] = kPermute[pkTetra->A[3]];
00239         }
00240         assert(i == 4*m_iSimplexQuantity);
00241 
00242         m_iPathLast = -1;
00243         m_aiPath = WM4_NEW int[m_iSimplexQuantity+1];
00244     }
00245 
00246     // Restore the vertex count to the original (discards the vertices of the
00247     // supertetrahedron).
00248     m_iVertexQuantity -= 4;
00249 
00250     pkTIter = m_kTetrahedron.begin();
00251     for (; pkTIter != m_kTetrahedron.end(); ++pkTIter)
00252     {
00253         WM4_DELETE *pkTIter;
00254     }
00255 }
00256 //----------------------------------------------------------------------------
00257 template <class Real>
00258 Delaunay3<Real>::~Delaunay3 ()
00259 {
00260     WM4_DELETE m_pkQuery;
00261     WM4_DELETE[] m_akSVertex;
00262     WM4_DELETE[] m_aiPath;
00263     if (m_bOwner)
00264     {
00265         WM4_DELETE[] m_akVertex;
00266     }
00267 }
00268 //----------------------------------------------------------------------------
00269 template <class Real>
00270 const Vector3<Real>* Delaunay3<Real>::GetVertices () const
00271 {
00272     return m_akVertex;
00273 }
00274 //----------------------------------------------------------------------------
00275 template <class Real>
00276 int Delaunay3<Real>::GetUniqueVertexQuantity () const
00277 {
00278     return m_iUniqueVertexQuantity;
00279 }
00280 //----------------------------------------------------------------------------
00281 template <class Real>
00282 const Vector3<Real>& Delaunay3<Real>::GetLineOrigin () const
00283 {
00284     return m_kLineOrigin;
00285 }
00286 //----------------------------------------------------------------------------
00287 template <class Real>
00288 const Vector3<Real>& Delaunay3<Real>::GetLineDirection () const
00289 {
00290     return m_kLineDirection;
00291 }
00292 //----------------------------------------------------------------------------
00293 template <class Real>
00294 Delaunay1<Real>* Delaunay3<Real>::GetDelaunay1 () const
00295 {
00296     assert(m_iDimension == 1);
00297     if (m_iDimension != 1)
00298     {
00299         return 0;
00300     }
00301 
00302     Real* afProjection = WM4_NEW Real[m_iVertexQuantity];
00303     for (int i = 0; i < m_iVertexQuantity; i++)
00304     {
00305         Vector3<Real> kDiff = m_akVertex[i] - m_kLineOrigin;
00306         afProjection[i] = m_kLineDirection.Dot(kDiff);
00307     }
00308 
00309     return WM4_NEW Delaunay1<Real>(m_iVertexQuantity,afProjection,m_fEpsilon,
00310         true,m_eQueryType);
00311 }
00312 //----------------------------------------------------------------------------
00313 template <class Real>
00314 const Vector3<Real>& Delaunay3<Real>::GetPlaneOrigin () const
00315 {
00316     return m_kPlaneOrigin;
00317 }
00318 //----------------------------------------------------------------------------
00319 template <class Real>
00320 const Vector3<Real>& Delaunay3<Real>::GetPlaneDirection (int i) const
00321 {
00322     assert(0 <= i && i < 2);
00323     return m_akPlaneDirection[i];
00324 }
00325 //----------------------------------------------------------------------------
00326 template <class Real>
00327 Delaunay2<Real>* Delaunay3<Real>::GetDelaunay2 () const
00328 {
00329     assert(m_iDimension == 2);
00330     if (m_iDimension != 2)
00331     {
00332         return 0;
00333     }
00334 
00335     Vector2<Real>* akProjection = WM4_NEW Vector2<Real>[m_iVertexQuantity];
00336     for (int i = 0; i < m_iVertexQuantity; i++)
00337     {
00338         Vector3<Real> kDiff = m_akVertex[i] - m_kPlaneOrigin;
00339         akProjection[i][0] = m_akPlaneDirection[0].Dot(kDiff);
00340         akProjection[i][1] = m_akPlaneDirection[1].Dot(kDiff);
00341     }
00342 
00343     return WM4_NEW Delaunay2<Real>(m_iVertexQuantity,akProjection,m_fEpsilon,
00344         true,m_eQueryType);
00345 }
00346 //----------------------------------------------------------------------------
00347 template <class Real>
00348 bool Delaunay3<Real>::GetHull (int& riTQuantity, int*& raiIndex) const
00349 {
00350     assert(m_iDimension == 3);
00351     if (m_iDimension != 3)
00352     {
00353         return false;
00354     }
00355 
00356     riTQuantity = 0;
00357     raiIndex = 0;
00358 
00359     // Count the number of triangles that are not shared by two tetrahedra.
00360     int i, iAdjQuantity = 4*m_iSimplexQuantity;
00361     for (i = 0; i < iAdjQuantity; i++)
00362     {
00363         if (m_aiAdjacent[i] == -1)
00364         {
00365             riTQuantity++;
00366         }
00367     }
00368     assert(riTQuantity > 0);
00369     if (riTQuantity == 0)
00370     {
00371         return false;
00372     }
00373 
00374     // Enumerate the triangles.
00375     raiIndex = WM4_NEW int[3*riTQuantity];
00376     int* piIndex = raiIndex;
00377     for (i = 0; i < iAdjQuantity; i++)
00378     {
00379         if (m_aiAdjacent[i] == -1)
00380         {
00381             int iTetra = i/4, iFace = i%4;
00382             for (int j = 0; j < 4; j++)
00383             {
00384                 if (j != iFace)
00385                 {
00386                     *piIndex++ = m_aiIndex[4*iTetra+j];
00387                 }
00388             }
00389             if ((iFace % 2) == 0)
00390             {
00391                 int iSave = *(piIndex-1);
00392                 *(piIndex-1) = *(piIndex-2);
00393                 *(piIndex-2) = iSave;
00394             }
00395         }
00396     }
00397 
00398     return true;
00399 }
00400 //----------------------------------------------------------------------------
00401 template <class Real>
00402 int Delaunay3<Real>::GetContainingTetrahedron (const Vector3<Real>& rkP)
00403     const
00404 {
00405     assert(m_iDimension == 3);
00406     if (m_iDimension != 3)
00407     {
00408         return -1;
00409     }
00410 
00411     // convert to scaled coordinates
00412     Vector3<Real> kXFrmP = (rkP - m_kMin)*m_fScale;
00413 
00414     // start at first tetrahedron in mesh
00415     int iIndex = (m_iPathLast >= 0 ? m_aiPath[m_iPathLast] : 0);
00416     m_iPathLast = -1;
00417     m_iLastFaceV0 = -1;
00418     m_iLastFaceV1 = -1;
00419     m_iLastFaceV2 = -1;
00420     m_iLastFaceOpposite = -1;
00421     m_iLastFaceOppositeIndex = -1;
00422 
00423     // use tetrahedron faces as binary separating planes
00424     for (int i = 0; i < m_iSimplexQuantity; i++)
00425     {
00426         m_aiPath[++m_iPathLast] = iIndex;
00427 
00428         int* aiV = &m_aiIndex[4*iIndex];
00429 
00430         // <V1,V2,V3> counterclockwise when viewed outside tetrahedron
00431         if (m_pkQuery->ToPlane(kXFrmP,aiV[1],aiV[2],aiV[3]) > 0)
00432         {
00433             iIndex = m_aiAdjacent[4*iIndex];
00434             if (iIndex == -1)
00435             {
00436                 m_iLastFaceV0 = aiV[1];
00437                 m_iLastFaceV1 = aiV[2];
00438                 m_iLastFaceV2 = aiV[3];
00439                 m_iLastFaceOpposite = aiV[0];
00440                 m_iLastFaceOppositeIndex = 0;
00441                 return -1;
00442             }
00443             continue;
00444         }
00445 
00446         // <V0,V3,V2> counterclockwise when viewed outside tetrahedron
00447         if (m_pkQuery->ToPlane(kXFrmP,aiV[0],aiV[2],aiV[3]) < 0)
00448         {
00449             iIndex = m_aiAdjacent[4*iIndex+1];
00450             if (iIndex == -1)
00451             {
00452                 m_iLastFaceV0 = aiV[0];
00453                 m_iLastFaceV1 = aiV[2];
00454                 m_iLastFaceV2 = aiV[3];
00455                 m_iLastFaceOpposite = aiV[1];
00456                 m_iLastFaceOppositeIndex = 1;
00457                 return -1;
00458             }
00459             continue;
00460         }
00461 
00462         // <V0,V1,V3> counterclockwise when viewed outside tetrahedron
00463         if (m_pkQuery->ToPlane(kXFrmP,aiV[0],aiV[1],aiV[3]) > 0)
00464         {
00465             iIndex = m_aiAdjacent[4*iIndex+2];
00466             if (iIndex == -1)
00467             {
00468                 m_iLastFaceV0 = aiV[0];
00469                 m_iLastFaceV1 = aiV[1];
00470                 m_iLastFaceV2 = aiV[3];
00471                 m_iLastFaceOpposite = aiV[2];
00472                 m_iLastFaceOppositeIndex = 2;
00473                 return -1;
00474             }
00475             continue;
00476         }
00477 
00478         // <V0,V2,V1> counterclockwise when viewed outside tetrahedron
00479         if (m_pkQuery->ToPlane(kXFrmP,aiV[0],aiV[1],aiV[2]) < 0)
00480         {
00481             iIndex = m_aiAdjacent[4*iIndex+3];
00482             if (iIndex == -1)
00483             {
00484                 m_iLastFaceV0 = aiV[0];
00485                 m_iLastFaceV1 = aiV[1];
00486                 m_iLastFaceV2 = aiV[2];
00487                 m_iLastFaceOpposite = aiV[3];
00488                 m_iLastFaceOppositeIndex = 3;
00489                 return -1;
00490             }
00491             continue;
00492         }
00493 
00494         m_iLastFaceV0 = -1;
00495         m_iLastFaceV1 = -1;
00496         m_iLastFaceV2 = -1;
00497         m_iLastFaceOppositeIndex = -1;
00498         return iIndex;
00499     }
00500 
00501     return -1;
00502 }
00503 //----------------------------------------------------------------------------
00504 template <class Real>
00505 int Delaunay3<Real>::GetPathLast () const
00506 {
00507     return m_iPathLast;
00508 }
00509 //----------------------------------------------------------------------------
00510 template <class Real>
00511 const int* Delaunay3<Real>::GetPath () const
00512 {
00513     return m_aiPath;
00514 }
00515 //----------------------------------------------------------------------------
00516 template <class Real>
00517 int Delaunay3<Real>::GetLastFace (int& riV0, int& riV1, int& riV2,
00518     int& riV3) const
00519 {
00520     riV0 = m_iLastFaceV0;
00521     riV1 = m_iLastFaceV1;
00522     riV2 = m_iLastFaceV2;
00523     riV3 = m_iLastFaceOpposite;
00524     return m_iLastFaceOppositeIndex;
00525 }
00526 //----------------------------------------------------------------------------
00527 template <class Real>
00528 bool Delaunay3<Real>::GetVertexSet (int i, Vector3<Real> akV[4]) const
00529 {
00530     assert(m_iDimension == 3);
00531     if (m_iDimension != 3)
00532     {
00533         return false;
00534     }
00535 
00536     if (0 <= i && i < m_iSimplexQuantity)
00537     {
00538         akV[0] = m_akVertex[m_aiIndex[4*i  ]];
00539         akV[1] = m_akVertex[m_aiIndex[4*i+1]];
00540         akV[2] = m_akVertex[m_aiIndex[4*i+2]];
00541         akV[3] = m_akVertex[m_aiIndex[4*i+3]];
00542         return true;
00543     }
00544 
00545     return false;
00546 }
00547 //----------------------------------------------------------------------------
00548 template <class Real>
00549 bool Delaunay3<Real>::GetIndexSet (int i, int aiIndex[4]) const
00550 {
00551     assert(m_iDimension == 3);
00552     if (m_iDimension != 3)
00553     {
00554         return false;
00555     }
00556 
00557     if (0 <= i && i < m_iSimplexQuantity)
00558     {
00559         aiIndex[0] = m_aiIndex[4*i  ];
00560         aiIndex[1] = m_aiIndex[4*i+1];
00561         aiIndex[2] = m_aiIndex[4*i+2];
00562         aiIndex[3] = m_aiIndex[4*i+3];
00563         return true;
00564     }
00565 
00566     return false;
00567 }
00568 //----------------------------------------------------------------------------
00569 template <class Real>
00570 bool Delaunay3<Real>::GetAdjacentSet (int i, int aiAdjacent[4]) const
00571 {
00572     assert(m_iDimension == 3);
00573     if (m_iDimension != 3)
00574     {
00575         return false;
00576     }
00577 
00578     if (0 <= i && i < m_iSimplexQuantity)
00579     {
00580         aiAdjacent[0] = m_aiAdjacent[4*i  ];
00581         aiAdjacent[1] = m_aiAdjacent[4*i+1];
00582         aiAdjacent[2] = m_aiAdjacent[4*i+2];
00583         aiAdjacent[3] = m_aiAdjacent[4*i+3];
00584         return true;
00585     }
00586 
00587     return false;
00588 }
00589 //----------------------------------------------------------------------------
00590 template <class Real>
00591 bool Delaunay3<Real>::GetBarycentricSet (int i, const Vector3<Real>& rkP,
00592     Real afBary[4]) const
00593 {
00594     assert(m_iDimension == 3);
00595     if (m_iDimension != 3)
00596     {
00597         return false;
00598     }
00599 
00600     if (0 <= i && i < m_iSimplexQuantity)
00601     {
00602         Vector3<Real> kV0 = m_akVertex[m_aiIndex[4*i  ]];
00603         Vector3<Real> kV1 = m_akVertex[m_aiIndex[4*i+1]];
00604         Vector3<Real> kV2 = m_akVertex[m_aiIndex[4*i+2]];
00605         Vector3<Real> kV3 = m_akVertex[m_aiIndex[4*i+3]];
00606         rkP.GetBarycentrics(kV0,kV1,kV2,kV3,afBary);
00607         return true;
00608     }
00609 
00610     return false;
00611 }
00612 //----------------------------------------------------------------------------
00613 template <class Real>
00614 void Delaunay3<Real>::Update (int i)
00615 {
00616     // Locate the tetrahedron containing vertex i.
00617     DelTetrahedron<Real>* pkTetra = GetContainingTetrahedron(i);
00618 
00619     // Locate and remove the tetrahedra forming the insertion polyhedron.
00620     std::stack<DelTetrahedron<Real>*> kStack;
00621     ETManifoldMesh kPolyhedron(0,DelPolyhedronFace<Real>::TCreator);
00622     kStack.push(pkTetra);
00623     pkTetra->OnStack = true;
00624     int j, iV0, iV1, iV2;
00625     DelPolyhedronFace<Real>* pkFace;
00626     while (!kStack.empty())
00627     {
00628         pkTetra = kStack.top();
00629         kStack.pop();
00630         pkTetra->OnStack = false;
00631         for (j = 0; j < 4; j++)
00632         {
00633             DelTetrahedron<Real>* pkAdj = pkTetra->A[j];
00634             if (pkAdj)
00635             {
00636                 // Detach tetrahedron and adjacent tetrahedron from each
00637                 // other.
00638                 int iNullIndex = pkTetra->DetachFrom(j,pkAdj);
00639 
00640                 if (pkAdj->IsInsertionComponent(i,pkTetra,m_pkQuery,m_aiSV))
00641                 {
00642                     if (!pkAdj->OnStack)
00643                     {
00644                         // Adjacent triangle inside insertion polyhedron.
00645                         kStack.push(pkAdj);
00646                         pkAdj->OnStack = true;
00647                     }
00648                 }
00649                 else
00650                 {
00651                     // Adjacent tetrahedron outside insertion polyhedron.
00652                     iV0 = pkTetra->V[gs_aaiIndex[j][0]];
00653                     iV1 = pkTetra->V[gs_aaiIndex[j][1]];
00654                     iV2 = pkTetra->V[gs_aaiIndex[j][2]];
00655                     pkFace = (DelPolyhedronFace<Real>*)
00656                         kPolyhedron.InsertTriangle(iV0,iV1,iV2);
00657                     pkFace->NullIndex = iNullIndex;
00658                     pkFace->Tetra = pkAdj;
00659                 }
00660             }
00661             else
00662             {
00663                 // The tetrahedron is in the insertion polyhedron, but the
00664                 // adjacent one does not exist.  This means one of two things:
00665                 // (1) We are at a face of the supertetrahedron, and that
00666                 //     face is part of the insertion polyhedron.
00667                 // (2) We are at a face that was recently shared by the
00668                 //     tetrahedron and the adjacent, but we detached those
00669                 //     tetrahedra from each other.  These faces should be
00670                 //     ignored.
00671 
00672                 iV0 = pkTetra->V[gs_aaiIndex[j][0]];
00673                 if (IsSupervertex(iV0))
00674                 {
00675                     iV1 = pkTetra->V[gs_aaiIndex[j][1]];
00676                     if (IsSupervertex(iV1))
00677                     {
00678                         iV2 = pkTetra->V[gs_aaiIndex[j][2]];
00679                         if (IsSupervertex(iV2))
00680                         {
00681                             pkFace = (DelPolyhedronFace<Real>*)
00682                                 kPolyhedron.InsertTriangle(iV0,iV1,iV2);
00683                             pkFace->NullIndex = -1;
00684                             pkFace->Tetra = 0;
00685                         }
00686                     }
00687                 }
00688             }
00689         }
00690         m_kTetrahedron.erase(pkTetra);
00691         WM4_DELETE pkTetra;
00692     }
00693 
00694     // Insert the new tetrahedra formed by the input point and the faces of
00695     // the insertion polyhedron.
00696     const ETManifoldMesh::TMap& rkTMap = kPolyhedron.GetTriangles();
00697     assert(rkTMap.size() >= 4 && kPolyhedron.IsClosed());
00698     typename ETManifoldMesh::TMapCIterator pkTIter;
00699     for (pkTIter = rkTMap.begin(); pkTIter != rkTMap.end(); pkTIter++)
00700     {
00701         pkFace = (DelPolyhedronFace<Real>*)pkTIter->second;
00702 
00703         // Create and insert the new tetrahedron.
00704         pkTetra = WM4_NEW DelTetrahedron<Real>(i,pkFace->V[0],pkFace->V[1],
00705             pkFace->V[2]);
00706         m_kTetrahedron.insert(pkTetra);
00707 
00708         // Establish the adjacency links across the polyhedron face.
00709         pkTetra->A[0] = pkFace->Tetra;
00710         if (pkFace->Tetra)
00711         {
00712             pkFace->Tetra->A[pkFace->NullIndex] = pkTetra;
00713         }
00714 
00715         // Update the faces's tetrahedron pointer to point to the newly
00716         // created tetrahedron.  This information is used later to establish
00717         // the links between the new tetrahedra.
00718         pkFace->Tetra = pkTetra;
00719     }
00720 
00721     // Establish the adjacency links between the new tetrahedra.
00722     DelPolyhedronFace<Real>* pkAdjFace;
00723     for (pkTIter = rkTMap.begin(); pkTIter != rkTMap.end(); pkTIter++)
00724     {
00725         pkFace = (DelPolyhedronFace<Real>*)pkTIter->second;
00726 
00727         pkAdjFace = (DelPolyhedronFace<Real>*)pkFace->T[0];
00728         pkFace->Tetra->A[3] = pkAdjFace->Tetra;
00729         assert(SharesFace(3,pkFace->Tetra,pkAdjFace->Tetra));
00730 
00731         pkAdjFace = (DelPolyhedronFace<Real>*)pkFace->T[1];
00732         pkFace->Tetra->A[1] = pkAdjFace->Tetra;
00733         assert(SharesFace(1,pkFace->Tetra,pkAdjFace->Tetra));
00734 
00735         pkAdjFace = (DelPolyhedronFace<Real>*)pkFace->T[2];
00736         pkFace->Tetra->A[2] = pkAdjFace->Tetra;
00737         assert(SharesFace(2,pkFace->Tetra,pkAdjFace->Tetra));
00738     }
00739 }
00740 //----------------------------------------------------------------------------
00741 template <class Real>
00742 DelTetrahedron<Real>* Delaunay3<Real>::GetContainingTetrahedron (int i) const
00743 {
00744     // Locate which tetrahedron in the current mesh contains vertex i.  By
00745     // construction, there must be such a tetrahedron (the vertex cannot be
00746     // outside the supertetrahedron).
00747 
00748     DelTetrahedron<Real>* pkTetra = *m_kTetrahedron.begin();
00749     int iTQuantity = (int)m_kTetrahedron.size();
00750     for (int iT = 0; iT < iTQuantity; iT++)
00751     {
00752         int* aiV = pkTetra->V;
00753 
00754         // <V1,V2,V3> counterclockwise when viewed outside tetrahedron
00755         if (m_pkQuery->ToPlane(i,aiV[1],aiV[2],aiV[3]) > 0)
00756         {
00757             pkTetra = pkTetra->A[0];
00758             if (!pkTetra)
00759             {
00760                 break;
00761             }
00762             continue;
00763         }
00764 
00765         // <V0,V3,V2> counterclockwise when viewed outside tetrahedron
00766         if (m_pkQuery->ToPlane(i,aiV[0],aiV[2],aiV[3]) < 0)
00767         {
00768             pkTetra = pkTetra->A[1];
00769             if (!pkTetra)
00770             {
00771                 break;
00772             }
00773             continue;
00774         }
00775 
00776         // <V0,V1,V3> counterclockwise when viewed outside tetrahedron
00777         if (m_pkQuery->ToPlane(i,aiV[0],aiV[1],aiV[3]) > 0)
00778         {
00779             pkTetra = pkTetra->A[2];
00780             if (!pkTetra)
00781             {
00782                 break;
00783             }
00784             continue;
00785         }
00786 
00787         // <V0,V2,V1> counterclockwise when viewed outside tetrahedron
00788         if (m_pkQuery->ToPlane(i,aiV[0],aiV[1],aiV[2]) < 0)
00789         {
00790             pkTetra = pkTetra->A[3];
00791             if (!pkTetra)
00792             {
00793                 break;
00794             }
00795             continue;
00796         }
00797 
00798         return pkTetra;
00799     }
00800 
00801     assert(false);
00802     return 0;
00803 }
00804 //----------------------------------------------------------------------------
00805 template <class Real>
00806 void Delaunay3<Real>::RemoveTetrahedra ()
00807 {
00808     // Identify those triangles sharing a vertex of the supertetrahedron.
00809     std::set<DelTetrahedron<Real>*> kRemoveTetra;
00810     DelTetrahedron<Real>* pkTetra;
00811     typename std::set<DelTetrahedron<Real>*>::iterator pkTIter =
00812         m_kTetrahedron.begin();
00813     for (; pkTIter != m_kTetrahedron.end(); pkTIter++)
00814     {
00815         pkTetra = *pkTIter;
00816         for (int j = 0; j < 4; j++)
00817         {
00818             if (IsSupervertex(pkTetra->V[j]))
00819             {
00820                 kRemoveTetra.insert(pkTetra);
00821                 break;
00822             }
00823         }
00824     }
00825 
00826     // Remove the tetrahedra from the mesh.
00827     pkTIter = kRemoveTetra.begin();
00828     for (; pkTIter != kRemoveTetra.end(); pkTIter++)
00829     {
00830         pkTetra = *pkTIter;
00831         for (int j = 0; j < 4; j++)
00832         {
00833             // Break the links with adjacent tetrahedra.
00834             DelTetrahedron<Real>* pkAdj = pkTetra->A[j];
00835             if (pkAdj)
00836             {
00837                 for (int k = 0; k < 4; k++)
00838                 {
00839                     if (pkAdj->A[k] == pkTetra)
00840                     {
00841                         pkAdj->A[k] = 0;
00842                         break;
00843                     }
00844                 }
00845             }
00846         }
00847         m_kTetrahedron.erase(pkTetra);
00848         WM4_DELETE pkTetra;
00849     }
00850 }
00851 //----------------------------------------------------------------------------
00852 template <class Real>
00853 bool Delaunay3<Real>::IsSupervertex (int i) const
00854 {
00855     for (int j = 0; j < 4; j++)
00856     {
00857         if (i == m_aiSV[j])
00858         {
00859             return true;
00860         }
00861     }
00862     return false;
00863 }
00864 //----------------------------------------------------------------------------
00865 template <class Real>
00866 bool Delaunay3<Real>::SharesFace (int i, DelTetrahedron<Real>* pkFace,
00867     DelTetrahedron<Real>* pkAdj)
00868 {
00869     int aiF[3], iCount = 0, j;
00870     for (j = 0; j < 4; j++)
00871     {
00872         if (j != i)
00873         {
00874             aiF[iCount++] = pkFace->V[j];
00875         }
00876     }
00877 
00878     for (i = 0; i < 4; i++)
00879     {
00880         if (pkAdj->V[i] != aiF[0] &&
00881             pkAdj->V[i] != aiF[1] &&
00882             pkAdj->V[i] != aiF[2])
00883         {
00884             break;
00885         }
00886     }
00887     if (i == 4)
00888     {
00889         return false;
00890     }
00891 
00892     int aiA[3];
00893     for (j = 0, iCount = 0; j < 4; j++)
00894     {
00895         if (j != i)
00896         {
00897             aiA[iCount++] = pkAdj->V[j];
00898         }
00899     }
00900 
00901     if (aiF[0] > aiF[1])
00902     {
00903         j = aiF[0];
00904         aiF[0] = aiF[1];
00905         aiF[1] = j;
00906     }
00907     if (aiF[1] > aiF[2])
00908     {
00909         j = aiF[1];
00910         aiF[1] = aiF[2];
00911         aiF[2] = j;
00912     }
00913     if (aiF[0] > aiF[1])
00914     {
00915         j = aiF[0];
00916         aiF[0] = aiF[1];
00917         aiF[1] = j;
00918     }
00919 
00920     if (aiA[0] > aiA[1])
00921     {
00922         j = aiA[0];
00923         aiA[0] = aiA[1];
00924         aiA[1] = j;
00925     }
00926     if (aiA[1] > aiA[2])
00927     {
00928         j = aiA[1];
00929         aiA[1] = aiA[2];
00930         aiA[2] = j;
00931     }
00932     if (aiA[0] > aiA[1])
00933     {
00934         j = aiA[0];
00935         aiA[0] = aiA[1];
00936         aiA[1] = j;
00937     }
00938 
00939     if (aiA[0] != aiF[0] || aiA[1] != aiF[1] || aiA[2] != aiF[2])
00940     {
00941         return false;
00942     }
00943 
00944     return true;
00945 }
00946 //----------------------------------------------------------------------------
00947 template <class Real>
00948 Delaunay3<Real>::Delaunay3 (const char* acFilename)
00949     :
00950     Delaunay<Real>(0,(Real)0.0,false,Query::QT_REAL)
00951 {
00952     m_akVertex = 0;
00953     m_akSVertex = 0;
00954     m_pkQuery = 0;
00955     m_aiPath = 0;
00956     bool bLoaded = Load(acFilename);
00957     assert(bLoaded);
00958     (void)bLoaded;  // avoid warning in Release build
00959 }
00960 //----------------------------------------------------------------------------
00961 template <class Real>
00962 bool Delaunay3<Real>::Load (const char* acFilename)
00963 {
00964     FILE* pkIFile = System::Fopen(acFilename,"rb");
00965     if (!pkIFile)
00966     {
00967         return false;
00968     }
00969 
00970     Delaunay<Real>::Load(pkIFile);
00971 
00972     WM4_DELETE m_pkQuery;
00973     WM4_DELETE[] m_akSVertex;
00974     WM4_DELETE[] m_aiPath;
00975     if (m_bOwner)
00976     {
00977         WM4_DELETE[] m_akVertex;
00978     }
00979 
00980     m_bOwner = true;
00981     m_akVertex = WM4_NEW Vector3<Real>[m_iVertexQuantity];
00982     m_akSVertex = WM4_NEW Vector3<Real>[m_iVertexQuantity+4];
00983     m_aiPath = WM4_NEW int[m_iSimplexQuantity+1];
00984 
00985     System::Read4le(pkIFile,1,&m_iUniqueVertexQuantity);
00986     System::Read4le(pkIFile,4,m_aiSV);
00987     System::Read4le(pkIFile,1,&m_iPathLast);
00988     System::Read4le(pkIFile,1,&m_iLastFaceV0);
00989     System::Read4le(pkIFile,1,&m_iLastFaceV1);
00990     System::Read4le(pkIFile,1,&m_iLastFaceV2);
00991     System::Read4le(pkIFile,1,&m_iLastFaceOpposite);
00992     System::Read4le(pkIFile,1,&m_iLastFaceOppositeIndex);
00993     System::Read4le(pkIFile,m_iSimplexQuantity+1,m_aiPath);
00994 
00995     size_t uiSize = sizeof(Real);
00996     int iVQ = 3*m_iVertexQuantity, iSVQ = 3*(m_iVertexQuantity + 4);
00997     if (uiSize == 4)
00998     {
00999         System::Read4le(pkIFile,iVQ,m_akVertex);
01000         System::Read4le(pkIFile,iSVQ,m_akSVertex);
01001         System::Read4le(pkIFile,3,(Real*)m_kMin);
01002         System::Read4le(pkIFile,1,&m_fScale);
01003         System::Read4le(pkIFile,3,(Real*)m_kLineOrigin);
01004         System::Read4le(pkIFile,3,(Real*)m_kLineDirection);
01005         System::Read4le(pkIFile,3,(Real*)m_kPlaneOrigin);
01006         System::Read4le(pkIFile,3,(Real*)m_akPlaneDirection[0]);
01007         System::Read4le(pkIFile,3,(Real*)m_akPlaneDirection[1]);
01008     }
01009     else // iSize == 8
01010     {
01011         System::Read8le(pkIFile,iVQ,m_akVertex);
01012         System::Read8le(pkIFile,iSVQ,m_akSVertex);
01013         System::Read8le(pkIFile,3,(Real*)m_kMin);
01014         System::Read8le(pkIFile,1,&m_fScale);
01015         System::Read8le(pkIFile,3,(Real*)m_kLineOrigin);
01016         System::Read8le(pkIFile,3,(Real*)m_kLineDirection);
01017         System::Read8le(pkIFile,3,(Real*)m_kPlaneOrigin);
01018         System::Read8le(pkIFile,3,(Real*)m_akPlaneDirection[0]);
01019         System::Read8le(pkIFile,3,(Real*)m_akPlaneDirection[1]);
01020     }
01021 
01022     System::Fclose(pkIFile);
01023 
01024     switch (m_eQueryType)
01025     {
01026     case Query::QT_INT64:
01027         m_pkQuery = WM4_NEW Query3Int64<Real>(m_iVertexQuantity,m_akSVertex);
01028         break;
01029     case Query::QT_INTEGER:
01030         m_pkQuery = WM4_NEW Query3TInteger<Real>(m_iVertexQuantity,
01031             m_akSVertex);
01032         break;
01033     case Query::QT_RATIONAL:
01034         m_pkQuery = WM4_NEW Query3TRational<Real>(m_iVertexQuantity,
01035             m_akSVertex);
01036         break;
01037     case Query::QT_REAL:
01038         m_pkQuery = WM4_NEW Query3<Real>(m_iVertexQuantity,m_akSVertex);
01039         break;
01040     case Query::QT_FILTERED:
01041         m_pkQuery = WM4_NEW Query3Filtered<Real>(m_iVertexQuantity,
01042             m_akSVertex,m_fEpsilon);
01043         break;
01044     }
01045 
01046     return true;
01047 }
01048 //----------------------------------------------------------------------------
01049 template <class Real>
01050 bool Delaunay3<Real>::Save (const char* acFilename) const
01051 {
01052     FILE* pkOFile = System::Fopen(acFilename,"wb");
01053     if (!pkOFile)
01054     {
01055         return false;
01056     }
01057 
01058     Delaunay<Real>::Save(pkOFile);
01059 
01060     System::Write4le(pkOFile,1,&m_iUniqueVertexQuantity);
01061     System::Write4le(pkOFile,4,m_aiSV);
01062     System::Write4le(pkOFile,1,&m_iPathLast);
01063     System::Write4le(pkOFile,1,&m_iLastFaceV0);
01064     System::Write4le(pkOFile,1,&m_iLastFaceV1);
01065     System::Write4le(pkOFile,1,&m_iLastFaceV2);
01066     System::Write4le(pkOFile,1,&m_iLastFaceOpposite);
01067     System::Write4le(pkOFile,1,&m_iLastFaceOppositeIndex);
01068     System::Write4le(pkOFile,m_iSimplexQuantity+1,m_aiPath);
01069 
01070     size_t uiSize = sizeof(Real);
01071     int iVQ = 3*m_iVertexQuantity, iSVQ = 3*(m_iVertexQuantity + 4);
01072     if (uiSize == 4)
01073     {
01074         System::Write4le(pkOFile,iVQ,m_akVertex);
01075         System::Write4le(pkOFile,iSVQ,m_akSVertex);
01076         System::Write4le(pkOFile,3,(const Real*)m_kMin);
01077         System::Write4le(pkOFile,1,&m_fScale);
01078         System::Write4le(pkOFile,3,(const Real*)m_kLineOrigin);
01079         System::Write4le(pkOFile,3,(const Real*)m_kLineDirection);
01080         System::Write4le(pkOFile,3,(const Real*)m_kPlaneOrigin);
01081         System::Write4le(pkOFile,3,(const Real*)m_akPlaneDirection[0]);
01082         System::Write4le(pkOFile,3,(const Real*)m_akPlaneDirection[1]);
01083     }
01084     else // iSize == 8
01085     {
01086         System::Write8le(pkOFile,iVQ,m_akVertex);
01087         System::Write8le(pkOFile,iSVQ,m_akSVertex);
01088         System::Write8le(pkOFile,3,(const Real*)m_kMin);
01089         System::Write8le(pkOFile,1,&m_fScale);
01090         System::Write8le(pkOFile,3,(const Real*)m_kLineOrigin);
01091         System::Write8le(pkOFile,3,(const Real*)m_kLineDirection);
01092         System::Write8le(pkOFile,3,(const Real*)m_kPlaneOrigin);
01093         System::Write8le(pkOFile,3,(const Real*)m_akPlaneDirection[0]);
01094         System::Write8le(pkOFile,3,(const Real*)m_akPlaneDirection[1]);
01095     }
01096 
01097     System::Fclose(pkOFile);
01098     return true;
01099 }
01100 //----------------------------------------------------------------------------
01101 
01102 //----------------------------------------------------------------------------
01103 // explicit instantiation
01104 //----------------------------------------------------------------------------
01105 template WM4_FOUNDATION_ITEM
01106 class Delaunay3<float>;
01107 
01108 template WM4_FOUNDATION_ITEM
01109 class Delaunay3<double>;
01110 //----------------------------------------------------------------------------
01111 }

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