Wm4TriangulateEC.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.5 (2006/10/23)
00016 
00017 #include "Wm4FoundationPCH.h"
00018 #include "Wm4TriangulateEC.h"
00019 #include "Wm4Query2Filtered.h"
00020 #include "Wm4Query2Int64.h"
00021 #include "Wm4Query2TInteger.h"
00022 #include "Wm4Query2TRational.h"
00023 
00024 namespace Wm4
00025 {
00026 //----------------------------------------------------------------------------
00027 template <class Real>
00028 TriangulateEC<Real>::TriangulateEC (const Positions& rkPositions,
00029     Query::Type eQueryType, Real fEpsilon, Indices& rkTriangles)
00030 {
00031     // No extra elements are needed for triangulating a simple polygon.
00032     InitializePositions(rkPositions,eQueryType,fEpsilon,0);
00033 
00034     // Triangulate the unindexed polygon.
00035     int iVQuantity = (int)rkPositions.size();
00036     const int* aiIndex = 0;
00037     InitializeVertices(iVQuantity,aiIndex,rkTriangles);
00038     DoEarClipping(iVQuantity,aiIndex,rkTriangles);
00039 }
00040 //----------------------------------------------------------------------------
00041 template <class Real>
00042 TriangulateEC<Real>::TriangulateEC (const Positions& rkPositions,
00043     Query::Type eQueryType, Real fEpsilon, const Indices& rkPolygon,
00044     Indices& rkTriangles)
00045 {
00046     // No extra elements are needed for triangulating a simple polygon.
00047     InitializePositions(rkPositions,eQueryType,fEpsilon,0);
00048 
00049     // Triangulate the indexed polygon.
00050     int iVQuantity = (int)rkPolygon.size();
00051     const int* aiIndex = &rkPolygon[0];
00052     InitializeVertices(iVQuantity,aiIndex,rkTriangles);
00053     DoEarClipping(iVQuantity,aiIndex,rkTriangles);
00054 }
00055 //----------------------------------------------------------------------------
00056 template <class Real>
00057 TriangulateEC<Real>::TriangulateEC (const Positions& rkPositions,
00058     Query::Type eQueryType, Real fEpsilon, const Indices& rkOuter,
00059     const Indices& rkInner, Indices& rkTriangles)
00060 {
00061     // Two extra elements are needed to duplicate the endpoints of the edge
00062     // introduced to combine outer and inner polygons.
00063     InitializePositions(rkPositions,eQueryType,fEpsilon,2);
00064 
00065     // Combine the outer polygon and the inner polygon into a simple polygon
00066     // by inserting two edges connecting mutually visible vertices, one from
00067     // the outer polygon and one from the inner polygon.
00068     int iNextElement = (int)rkPositions.size();  // next available element
00069     IndexMap kMap;
00070     Indices kCombined;
00071     CombinePolygons(eQueryType,fEpsilon,iNextElement,rkOuter,rkInner,kMap,
00072         kCombined);
00073 
00074     // The combined polygon is now in the format of a simple polygon, albeit
00075     // one with coincident edges.
00076     int iVQuantity = (int)kCombined.size();
00077     const int* aiIndex = &kCombined[0];
00078     InitializeVertices(iVQuantity,aiIndex,rkTriangles);
00079     DoEarClipping(iVQuantity,aiIndex,rkTriangles);
00080 
00081     // Map the duplicate indices back to the original indices.
00082     RemapIndices(kMap,rkTriangles);
00083 }
00084 //----------------------------------------------------------------------------
00085 template <class Real>
00086 TriangulateEC<Real>::TriangulateEC (const Positions& rkPositions,
00087     Query::Type eQueryType, Real fEpsilon, const Indices& rkOuter,
00088     const IndicesArray& rkInners, Indices& rkTriangles)
00089 {
00090     // Two extra elements per inner polygon are needed to duplicate the
00091     // endpoints of the edges introduced to combine outer and inner polygons.
00092     int iNumInners = (int)rkInners.size();
00093     int iExtraElements = 2*iNumInners;
00094     InitializePositions(rkPositions,eQueryType,fEpsilon,iExtraElements);
00095 
00096     // Combine the outer polygon and the inner polygons into a simple polygon
00097     // by inserting two edges per inner polygon connecting mutually visible
00098     // vertices.
00099     int iNextElement = (int)rkPositions.size();
00100     Indices kCombined;
00101     IndexMap kMap;
00102     ProcessOuterAndInners(eQueryType,fEpsilon,rkOuter,rkInners,iNextElement,
00103         kMap,kCombined);
00104 
00105     // The combined polygon is now in the format of a simple polygon, albeit
00106     // with coincident edges.
00107     int iVQuantity = (int)kCombined.size();
00108     const int* aiIndex = &kCombined[0];
00109     InitializeVertices(iVQuantity,aiIndex,rkTriangles);
00110     DoEarClipping(iVQuantity,aiIndex,rkTriangles);
00111 
00112     // Map the duplicate indices back to the original indices.
00113     RemapIndices(kMap,rkTriangles);
00114 }
00115 //----------------------------------------------------------------------------
00116 template <class Real>
00117 TriangulateEC<Real>::TriangulateEC (const Positions& rkPositions,
00118     Query::Type eQueryType, Real fEpsilon, const Tree* pkTree,
00119     Indices& rkTriangles)
00120 {
00121     // Two extra elements per inner polygon are needed to duplicate the
00122     // endpoints of the edges introduced to combine outer and inner polygons.
00123     int iExtraElements = GetExtraElements(pkTree);
00124     InitializePositions(rkPositions,eQueryType,fEpsilon,iExtraElements);
00125 
00126     int iNextElement = (int)rkPositions.size();
00127     IndexMap kMap;
00128 
00129     std::queue<const Tree*> kQueue;
00130     kQueue.push(pkTree);
00131     while (kQueue.size() > 0)
00132     {
00133         const Tree* pkOuterNode = kQueue.front();
00134         kQueue.pop();
00135 
00136         int iNumChildren = (int)pkOuterNode->Child.size();
00137         int iVQuantity;
00138         const int* aiIndex;
00139 
00140         if (iNumChildren == 0)
00141         {
00142             // The outer polygon is a simple polygon (no nested inner
00143             // polygons).  Triangulate the simple polygon.
00144             iVQuantity = (int)pkOuterNode->Polygon.size();
00145             aiIndex = &pkOuterNode->Polygon[0];
00146             InitializeVertices(iVQuantity,aiIndex,rkTriangles);
00147             DoEarClipping(iVQuantity,aiIndex,rkTriangles);
00148         }
00149         else
00150         {
00151             // Place the next level of outer polygon nodes on the queue for
00152             // triangulation.
00153             std::vector<std::vector<int>*> kInners(iNumChildren);
00154             for (int i = 0; i < iNumChildren; i++)
00155             {
00156                 const Tree* pkInnerNode = pkOuterNode->Child[i];
00157                 kInners[i] = (std::vector<int>*)&pkInnerNode->Polygon;
00158                 int iNumGrandChildren = (int)pkInnerNode->Child.size();
00159                 for (int j = 0; j < iNumGrandChildren; j++)
00160                 {
00161                     kQueue.push(pkInnerNode->Child[j]);
00162                 }
00163             }
00164 
00165             // Combine the outer polygon and the inner polygons into a
00166             // simple polygon by inserting two edges per inner polygon
00167             // connecting mutually visible vertices.
00168             std::vector<int> kCombined;
00169             ProcessOuterAndInners(eQueryType,fEpsilon,pkOuterNode->Polygon,
00170                 kInners,iNextElement,kMap,kCombined);
00171 
00172             // The combined polygon is now in the format of a simple polygon,
00173             // albeit with coincident edges.
00174             iVQuantity = (int)kCombined.size();
00175             aiIndex = &kCombined[0];
00176             InitializeVertices(iVQuantity,aiIndex,rkTriangles);
00177             DoEarClipping(iVQuantity,aiIndex,rkTriangles);
00178         }
00179     }
00180 
00181     // Map the duplicate indices back to the original indices.
00182     RemapIndices(kMap,rkTriangles);
00183 }
00184 //----------------------------------------------------------------------------
00185 template <class Real>
00186 TriangulateEC<Real>::~TriangulateEC ()
00187 {
00188     WM4_DELETE m_pkQuery;
00189 }
00190 //----------------------------------------------------------------------------
00191 template <class Real>
00192 void TriangulateEC<Real>::InitializePositions (const Positions& rkPositions,
00193     Query::Type eQueryType, Real fEpsilon, int iExtraElements)
00194 {
00195     int iPQuantity = (int)rkPositions.size();
00196     assert(iPQuantity >= 3);
00197     int iPEQuantity = iPQuantity + iExtraElements;
00198     m_kSPositions.resize(iPEQuantity);
00199 
00200     if (eQueryType == Query::QT_FILTERED)
00201     {
00202         assert((Real)0.0 <= fEpsilon && fEpsilon <= (Real)1.0);
00203     }
00204 
00205     Vector2<Real> kMin, kMax, kRange;
00206     Real fScale, fRMax;
00207     int i;
00208 
00209     switch (eQueryType)
00210     {
00211     case Query::QT_INT64:
00212         // Transform the vertices to the square [0,2^{20}]^2.
00213         Vector2<Real>::ComputeExtremes(iPQuantity,&rkPositions[0],kMin,kMax);
00214         kRange = kMax - kMin;
00215         fRMax = (kRange[0] >= kRange[1] ? kRange[0] : kRange[1]);
00216         fScale = ((Real)(1 << 20))/fRMax;
00217         for (i = 0; i < iPQuantity; i++)
00218         {
00219             m_kSPositions[i] = (rkPositions[i] - kMin)*fScale;
00220         }
00221         m_pkQuery = WM4_NEW Query2Int64<Real>(iPEQuantity,&m_kSPositions[0]);
00222         return;
00223 
00224     case Query::QT_INTEGER:
00225         // Transform the vertices to the square [0,2^{24}]^2.
00226         Vector2<Real>::ComputeExtremes(iPQuantity,&rkPositions[0],kMin,kMax);
00227         kRange = kMax - kMin;
00228         fRMax = (kRange[0] >= kRange[1] ? kRange[0] : kRange[1]);
00229         fScale = ((Real)(1 << 24))/fRMax;
00230         for (i = 0; i < iPQuantity; i++)
00231         {
00232             m_kSPositions[i] = (rkPositions[i] - kMin)*fScale;
00233         }
00234         m_pkQuery = WM4_NEW Query2TInteger<Real>(iPEQuantity,
00235             &m_kSPositions[0]);
00236         return;
00237 
00238     case Query::QT_REAL:
00239         // Transform the vertices to the square [0,1]^2.
00240         Vector2<Real>::ComputeExtremes(iPQuantity,&rkPositions[0],kMin,kMax);
00241         kRange = kMax - kMin;
00242         fRMax = (kRange[0] >= kRange[1] ? kRange[0] : kRange[1]);
00243         fScale = ((Real)1.0)/fRMax;
00244         for (i = 0; i < iPQuantity; i++)
00245         {
00246             m_kSPositions[i] = (rkPositions[i] - kMin)*fScale;
00247         }
00248         m_pkQuery = WM4_NEW Query2<Real>(iPEQuantity,&m_kSPositions[0]);
00249         return;
00250 
00251     case Query::QT_RATIONAL:
00252         // No transformation of the input data.  Make a copy that can be
00253         // expanded when triangulating polygons with holes.
00254         for (i = 0; i < iPQuantity; i++)
00255         {
00256             m_kSPositions[i] = rkPositions[i];
00257         }
00258         m_pkQuery = WM4_NEW Query2TRational<Real>(iPEQuantity,
00259             &m_kSPositions[0]);
00260         return;
00261 
00262     case Query::QT_FILTERED:
00263         // No transformation of the input data.  Make a copy that can be
00264         // expanded when triangulating polygons with holes.
00265         for (i = 0; i < iPQuantity; i++)
00266         {
00267             m_kSPositions[i] = rkPositions[i];
00268         }
00269         m_pkQuery = WM4_NEW Query2Filtered<Real>(iPEQuantity,
00270             &m_kSPositions[0],fEpsilon);
00271         return;
00272     }
00273 
00274     assert(false);
00275 }
00276 //----------------------------------------------------------------------------
00277 template <class Real>
00278 void TriangulateEC<Real>::InitializeVertices (int iVQuantity,
00279     const int* aiIndex, std::vector<int>& rkTriangle)
00280 {
00281     m_kVertex.clear();
00282     m_kVertex.resize(iVQuantity);
00283     m_iCFirst = -1;
00284     m_iCLast = -1;
00285     m_iRFirst = -1;
00286     m_iRLast = -1;
00287     m_iEFirst = -1;
00288     m_iELast = -1;
00289 
00290     // Create a circular list of the polygon vertices for dynamic removal of
00291     // vertices.
00292     int iVQm1 = iVQuantity - 1;
00293     int i;
00294     for (i = 0; i <= iVQm1; i++)
00295     {
00296         Vertex& rkV = V(i);
00297         rkV.Index = (aiIndex ? aiIndex[i] : i);
00298         rkV.VPrev = (i > 0 ? i-1 : iVQm1);
00299         rkV.VNext = (i < iVQm1 ? i+1 : 0);
00300     }
00301 
00302     // Create a circular list of the polygon vertices for dynamic removal of
00303     // vertices.  Keep track of two linear sublists, one for the convex
00304     // vertices and one for the reflex vertices.  This is an O(N) process
00305     // where N is the number of polygon vertices.
00306     for (i = 0; i <= iVQm1; i++)
00307     {
00308         if (IsConvex(i))
00309         {
00310             InsertAfterC(i);
00311         }
00312         else
00313         {
00314             InsertAfterR(i);
00315         }
00316     }
00317 }
00318 //----------------------------------------------------------------------------
00319 template <class Real>
00320 void TriangulateEC<Real>::DoEarClipping (int iVQuantity, const int* aiIndex,
00321     std::vector<int>& rkTriangle)
00322 {
00323     // If the polygon is convex, just create a triangle fan.
00324     int i;
00325     if (m_iRFirst == -1)
00326     {
00327         int iVQm1 = iVQuantity - 1;
00328         if (aiIndex)
00329         {
00330             for (i = 1; i < iVQm1; i++)
00331             {
00332                 rkTriangle.push_back(aiIndex[0]);
00333                 rkTriangle.push_back(aiIndex[i]);
00334                 rkTriangle.push_back(aiIndex[i+1]);
00335             }
00336         }
00337         else
00338         {
00339             for (i = 1; i < iVQm1; i++)
00340             {
00341                 rkTriangle.push_back(0);
00342                 rkTriangle.push_back(i);
00343                 rkTriangle.push_back(i+1);
00344             }
00345         }
00346         return;
00347     }
00348 
00349     // Identify the ears and build a circular list of them.  Let V0, V1, and
00350     // V2 be consecutive vertices forming a triangle T.  The vertex V1 is an
00351     // ear if no other vertices of the polygon lie inside T.  Although it is
00352     // enough to show that V1 is not an ear by finding at least one other
00353     // vertex inside T, it is sufficient to search only the reflex vertices.
00354     // This is an O(C*R) process, where C is the number of convex vertices and
00355     // R is the number of reflex vertices with N = C+R.  The order is O(N^2),
00356     // for example when C = R = N/2.
00357     for (i = m_iCFirst; i != -1; i = V(i).SNext)
00358     {
00359         if (IsEar(i))
00360         {
00361             InsertEndE(i);
00362         }
00363     }
00364     V(m_iEFirst).EPrev = m_iELast;
00365     V(m_iELast).ENext = m_iEFirst;
00366 
00367     // Remove the ears, one at a time.
00368     while (true)
00369     {
00370         // Add the triangle with the ear to the output list of triangles.
00371         int iVPrev = V(m_iEFirst).VPrev;
00372         int iVNext = V(m_iEFirst).VNext;
00373         rkTriangle.push_back(V(iVPrev).Index);
00374         rkTriangle.push_back(V(m_iEFirst).Index);
00375         rkTriangle.push_back(V(iVNext).Index);
00376 
00377         // Remove the vertex corresponding to the ear.
00378         RemoveV(m_iEFirst);
00379         if (--iVQuantity == 3)
00380         {
00381             // Only one triangle remains, just remove the ear and copy it.
00382             m_iEFirst = RemoveE(m_iEFirst);
00383             iVPrev = V(m_iEFirst).VPrev;
00384             iVNext = V(m_iEFirst).VNext;
00385             rkTriangle.push_back(V(iVPrev).Index);
00386             rkTriangle.push_back(V(m_iEFirst).Index);
00387             rkTriangle.push_back(V(iVNext).Index);
00388             break;
00389         }
00390 
00391         // Removal of the ear can cause an adjacent vertex to become an ear
00392         // or to stop being an ear.
00393         Vertex& rkVPrev = V(iVPrev);
00394         if (rkVPrev.IsEar)
00395         {
00396             if (!IsEar(iVPrev))
00397             {
00398                 RemoveE(iVPrev);
00399             }
00400         }
00401         else
00402         {
00403             bool bWasReflex = !rkVPrev.IsConvex;
00404             if (IsConvex(iVPrev))
00405             {
00406                 if (bWasReflex)
00407                 {
00408                     RemoveR(iVPrev);
00409                 }
00410 
00411                 if (IsEar(iVPrev))
00412                 {
00413                     InsertBeforeE(iVPrev);
00414                 }
00415             }
00416         }
00417 
00418         Vertex& rkVNext = V(iVNext);
00419         if (rkVNext.IsEar)
00420         {
00421             if (!IsEar(iVNext))
00422             {
00423                 RemoveE(iVNext);
00424             }
00425         }
00426         else
00427         {
00428             bool bWasReflex = !rkVNext.IsConvex;
00429             if (IsConvex(iVNext))
00430             {
00431                 if (bWasReflex)
00432                 {
00433                     RemoveR(iVNext);
00434                 }
00435 
00436                 if (IsEar(iVNext))
00437                 {
00438                     InsertAfterE(iVNext);
00439                 }
00440             }
00441         }
00442 
00443         // Remove the ear.
00444         m_iEFirst = RemoveE(m_iEFirst);
00445     }
00446 }
00447 //----------------------------------------------------------------------------
00448 template <class Real>
00449 int TriangulateEC<Real>::TriangleQuery (const Vector2<Real>& rkPoint,
00450     Query::Type eQueryType, Real fEpsilon, const Vector2<Real> akSTriangle[3])
00451     const
00452 {
00453     switch (eQueryType)
00454     {
00455     case Query::QT_INT64:
00456         return Query2Int64<Real>(3,akSTriangle).ToTriangle(rkPoint,0,1,2);
00457 
00458     case Query::QT_INTEGER:
00459         return Query2TInteger<Real>(3,akSTriangle).ToTriangle(rkPoint,0,1,2);
00460 
00461     case Query::QT_REAL:
00462         return Query2<Real>(3,akSTriangle).ToTriangle(rkPoint,0,1,2);
00463 
00464     case Query::QT_RATIONAL:
00465         return Query2TRational<Real>(3,akSTriangle).ToTriangle(rkPoint,0,1,2);
00466 
00467     case Query::QT_FILTERED:
00468         return Query2Filtered<Real>(3,akSTriangle,fEpsilon).ToTriangle(
00469             rkPoint,0,1,2);
00470     }
00471 
00472     assert(false);
00473     return 1;
00474 }
00475 //----------------------------------------------------------------------------
00476 template <class Real>
00477 void TriangulateEC<Real>::CombinePolygons (Query::Type eQueryType,
00478     Real fEpsilon, int iNextElement, const Indices& rkOuter,
00479     const Indices& rkInner, IndexMap& rkMap, Indices& rkCombined)
00480 {
00481     int iOQuantity = (int)rkOuter.size();
00482     int iIQuantity = (int)rkInner.size();
00483 
00484     // Locate the inner-polygon vertex of maximum x-value, call this vertex M.
00485     Real fXMax = m_kSPositions[rkInner[0]][0];
00486     int iXMaxIndex = 0;
00487     int i;
00488     for (i = 1; i < iIQuantity; i++)
00489     {
00490         Real fX = m_kSPositions[rkInner[i]][0];
00491         if (fX > fXMax)
00492         {
00493             fXMax = fX;
00494             iXMaxIndex = i;
00495         }
00496     }
00497     Vector2<Real> kM = m_kSPositions[rkInner[iXMaxIndex]];
00498 
00499     // Find the edge whose intersection Intr with the ray M+t*(1,0) minimizes
00500     // the ray parameter t >= 0.
00501     Vector2<Real> kIntr(Math<Real>::MAX_REAL,kM[1]);
00502     int iV0Min = -1, iV1Min = -1, iEndMin = -1;
00503     int i0, i1;
00504     for (i0 = iOQuantity-1, i1 = 0; i1 < iOQuantity; i0 = i1++)
00505     {
00506         // Only consider edges for which the first vertex is below (or on)
00507         // the ray and the second vertex is above (or on) the ray.
00508         Vector2<Real> kDiff0 = m_kSPositions[rkOuter[i0]] - kM;
00509         if (kDiff0[1] > (Real)0.0)
00510         {
00511             continue;
00512         }
00513         Vector2<Real> kDiff1 = m_kSPositions[rkOuter[i1]] - kM;
00514         if (kDiff1[1] < (Real)0.0)
00515         {
00516             continue;
00517         }
00518 
00519         // At this time, diff0.y <= 0 and diff1.y >= 0.
00520         Real fS, fT;
00521         int iCurrentEndMin = -1;
00522         if (kDiff0[1] < (Real)0.0)
00523         {
00524             if (kDiff1[1] > (Real)0.0)
00525             {
00526                 // The intersection of the edge and ray occurs at an interior
00527                 // edge point.
00528                 fS = kDiff0[1]/(kDiff0[1] - kDiff1[1]);
00529                 fT = kDiff0[0] + fS*(kDiff1[0] - kDiff0[0]);
00530             }
00531             else  // diff1.y == 0
00532             {
00533                 // The vertex Outer[i1] is the intersection of the edge and
00534                 // the ray.
00535                 fT = kDiff1[0];
00536                 iCurrentEndMin = i1;
00537             }
00538         }
00539         else  // diff0.y == 0
00540         {
00541             if (kDiff1[1] > (Real)0.0)
00542             {
00543                 // The vertex Outer[i0] is the intersection of the edge and
00544                 // the ray;
00545                 fT = kDiff0[0];
00546                 iCurrentEndMin = i0;
00547             }
00548             else  // diff1.y == 0
00549             {
00550                 if (kDiff0[0] < kDiff1[0])
00551                 {
00552                     fT = kDiff0[0];
00553                     iCurrentEndMin = i0;
00554                 }
00555                 else
00556                 {
00557                     fT = kDiff1[0];
00558                     iCurrentEndMin = i1;
00559                 }
00560             }
00561         }
00562 
00563         if ((Real)0.0 <= fT && fT < kIntr[0])
00564         {
00565             kIntr[0] = fT;
00566             iV0Min = i0;
00567             iV1Min = i1;
00568             if (iCurrentEndMin == -1)
00569             {
00570                 // The current closest point is an edge-interior point.
00571                 iEndMin = -1;
00572             }
00573             else
00574             {
00575                 // The current closest point is a vertex.
00576                 iEndMin = iCurrentEndMin;
00577             }
00578         }
00579     }
00580 
00581     int iMaxCosIndex;
00582     if (iEndMin == -1)
00583     {
00584         // Select one of Outer[v0min] and Outer[v1min] that has an x-value
00585         // larger than M.x, call this vertex P.  The triangle <M,I,P> must
00586         // contain an outer-polygon vertex that is visible to M, which is
00587         // possibly P itself.
00588         Vector2<Real> akSTriangle[3];  // <P,M,I> or <P,I,M>
00589         int iPIndex;
00590         if (m_kSPositions[rkOuter[iV0Min]][0] >
00591             m_kSPositions[rkOuter[iV1Min]][0])
00592         {
00593             akSTriangle[0] = m_kSPositions[rkOuter[iV0Min]];
00594             akSTriangle[1] = kIntr;
00595             akSTriangle[2] = kM;
00596             iPIndex = iV0Min;
00597         }
00598         else
00599         {
00600             akSTriangle[0] = m_kSPositions[rkOuter[iV1Min]];
00601             akSTriangle[1] = kM;
00602             akSTriangle[2] = kIntr;
00603             iPIndex = iV1Min;
00604         }
00605 
00606         // If any outer-polygon vertices other than P are inside the triangle
00607         // <M,I,P>, then at least one of these vertices must be a reflex
00608         // vertex.  It is sufficient to locate the reflex vertex R (if any)
00609         // in <M,I,P> that minimizes the angle between R-M and (1,0).  The
00610         // data member m_pkQuery is used for the reflex query.
00611         Vector2<Real> kDiff = akSTriangle[0] - kM;
00612         Real fMaxSqrLen = kDiff.SquaredLength();
00613         Real fMaxCos = kDiff[0]*kDiff[0]/fMaxSqrLen;
00614         iMaxCosIndex = iPIndex;
00615         for (i = 0; i < iOQuantity; i++)
00616         {
00617             if (i == iPIndex)
00618             {
00619                 continue;
00620             }
00621 
00622             int iCurr = rkOuter[i];
00623             int iPrev = rkOuter[(i+iOQuantity-1) % iOQuantity];
00624             int iNext = rkOuter[(i+1) % iOQuantity];
00625             if (m_pkQuery->ToLine(iCurr,iPrev,iNext) <= 0
00626             &&  TriangleQuery(m_kSPositions[iCurr],eQueryType,fEpsilon,
00627                     akSTriangle) <= 0)
00628             {
00629                 // The vertex is reflex and inside the <M,I,P> triangle.
00630                 kDiff = m_kSPositions[iCurr] - kM;
00631                 Real fSqrLen = kDiff.SquaredLength();
00632                 Real fCos = kDiff[0]*kDiff[0]/fSqrLen;
00633                 if (fCos > fMaxCos)
00634                 {
00635                     // The reflex vertex forms a smaller angle with the
00636                     // positive x-axis, so it becomes the new visible
00637                     // candidate.
00638                     fMaxSqrLen = fSqrLen;
00639                     fMaxCos = fCos;
00640                     iMaxCosIndex = i;
00641                 }
00642                 else if (fCos == fMaxCos && fSqrLen < fMaxSqrLen)
00643                 {
00644                     // The reflex vertex has angle equal to the current
00645                     // minimum but the length is smaller, so it becomes the
00646                     // new visible candidate.
00647                     fMaxSqrLen = fSqrLen;
00648                     iMaxCosIndex = i;
00649                 }
00650             }
00651         }
00652     }
00653     else
00654     {
00655         iMaxCosIndex = iEndMin;
00656     }
00657 
00658     // The visible vertices are Position[Inner[iXMaxIndex]] and
00659     // Position[Outer[iMaxCosIndex]].  Two coincident edges with these
00660     // endpoints are inserted to connect the outer and inner polygons into a
00661     // simple polygon.  Each of the two Position[] values must be duplicated,
00662     // because the original might be convex (or reflex) and the duplicate is
00663     // reflex (or convex).  The ear-clipping algorithm needs to distinguish
00664     // between them.
00665     rkCombined.resize(iOQuantity+iIQuantity+2);
00666     int iCIndex = 0;
00667     for (i = 0; i <= iMaxCosIndex; i++, iCIndex++)
00668     {
00669         rkCombined[iCIndex] = rkOuter[i];
00670     }
00671 
00672     for (i = 0; i < iIQuantity; i++, iCIndex++)
00673     {
00674         int j = (iXMaxIndex + i) % iIQuantity;
00675         rkCombined[iCIndex] = rkInner[j];
00676     }
00677 
00678     int iInnerIndex = rkInner[iXMaxIndex];
00679     m_kSPositions[iNextElement] = m_kSPositions[iInnerIndex];
00680     rkCombined[iCIndex] = iNextElement;
00681     IndexMap::iterator pkIter = rkMap.find(iInnerIndex);
00682     if (pkIter != rkMap.end())
00683     {
00684         iInnerIndex = pkIter->second;
00685     }
00686     rkMap[iNextElement] = iInnerIndex;
00687     iCIndex++;
00688     iNextElement++;
00689 
00690     int iOuterIndex = rkOuter[iMaxCosIndex];
00691     m_kSPositions[iNextElement] = m_kSPositions[iOuterIndex];
00692     rkCombined[iCIndex] = iNextElement;
00693     pkIter = rkMap.find(iOuterIndex);
00694     if (pkIter != rkMap.end())
00695     {
00696         iOuterIndex = pkIter->second;
00697     }
00698     rkMap[iNextElement] = iOuterIndex;
00699     iCIndex++;
00700     iNextElement++;
00701 
00702     for (i = iMaxCosIndex+1; i < iOQuantity; i++, iCIndex++)
00703     {
00704         rkCombined[iCIndex] = rkOuter[i];
00705     }
00706 }
00707 //----------------------------------------------------------------------------
00708 template <class Real>
00709 void TriangulateEC<Real>::ProcessOuterAndInners (Query::Type eQueryType,
00710     Real fEpsilon, const Indices& rkOuter, const IndicesArray& rkInners,
00711     int& riNextElement, IndexMap& rkMap, Indices& rkCombined)
00712 {
00713     // Sort the inner polygons based on maximum x-values.
00714     int iNumInners = (int)rkInners.size();
00715     std::vector<std::pair<Real,int> > kPairs(iNumInners);
00716     int i;
00717     for (i = 0; i < iNumInners; i++)
00718     {
00719         const Indices& rkInner = *rkInners[i];
00720         int iVQuantity = (int)rkInner.size();
00721         Real fXMax = m_kSPositions[rkInner[0]][0];
00722         for (int j = 1; j < iVQuantity; j++)
00723         {
00724             Real fX = m_kSPositions[rkInner[j]][0];
00725             if (fX > fXMax)
00726             {
00727                 fXMax = fX;
00728             }
00729         }
00730         kPairs[i].first = fXMax;
00731         kPairs[i].second = i;
00732     }
00733     std::sort(kPairs.begin(),kPairs.end());
00734 
00735     // Merge the inner polygons with the outer polygon.
00736     Indices kCurrentOuter = rkOuter;
00737     for (i = iNumInners-1; i >= 0; i--)
00738     {
00739         const Indices& rkInner = *rkInners[kPairs[i].second];
00740         Indices kCurrentCombined;
00741         CombinePolygons(eQueryType,fEpsilon,riNextElement,kCurrentOuter,
00742             rkInner,rkMap,kCurrentCombined);
00743         kCurrentOuter = kCurrentCombined;
00744         riNextElement += 2;
00745     }
00746 
00747     for (i = 0; i < (int)kCurrentOuter.size(); i++)
00748     {
00749         rkCombined.push_back(kCurrentOuter[i]);
00750     }
00751 }
00752 //----------------------------------------------------------------------------
00753 template <class Real>
00754 void TriangulateEC<Real>::RemapIndices (const IndexMap& rkMap,
00755     Indices& rkTriangles) const
00756 {
00757     // The triangulation includes indices to the duplicated outer and inner
00758     // vertices.  These indices must be mapped back to the original ones.
00759     for (int i = 0; i < (int)rkTriangles.size(); i++)
00760     {
00761         IndexMap::const_iterator pkIter = rkMap.find(rkTriangles[i]);
00762         if (pkIter != rkMap.end())
00763         {
00764             rkTriangles[i] = pkIter->second;
00765         }
00766     }
00767 }
00768 //----------------------------------------------------------------------------
00769 
00770 //----------------------------------------------------------------------------
00771 // Vertex list handling
00772 //----------------------------------------------------------------------------
00773 template <class Real>
00774 typename TriangulateEC<Real>::Vertex& TriangulateEC<Real>::V (int i)
00775 {
00776     return m_kVertex[i];
00777 }
00778 //----------------------------------------------------------------------------
00779 template <class Real>
00780 bool TriangulateEC<Real>::IsConvex (int i)
00781 {
00782     Vertex& rkV = V(i);
00783     int iCurr = rkV.Index;
00784     int iPrev = V(rkV.VPrev).Index;
00785     int iNext = V(rkV.VNext).Index;
00786     rkV.IsConvex = (m_pkQuery->ToLine(iCurr,iPrev,iNext) > 0);
00787     return rkV.IsConvex;
00788 }
00789 //----------------------------------------------------------------------------
00790 template <class Real>
00791 bool TriangulateEC<Real>::IsEar (int i)
00792 {
00793     Vertex& rkV = V(i);
00794 
00795     if (m_iRFirst == -1)
00796     {
00797         // The remaining polygon is convex.
00798         rkV.IsEar = true;
00799         return true;
00800     }
00801 
00802     // Search the reflex vertices and test if any are in the triangle
00803     // <V[prev],V[curr],V[next]>.
00804     int iPrev = V(rkV.VPrev).Index;
00805     int iCurr = rkV.Index;
00806     int iNext = V(rkV.VNext).Index;
00807     rkV.IsEar = true;
00808     for (int j = m_iRFirst; j != -1; j = V(j).SNext)
00809     {
00810         // Check if the test vertex is already one of the triangle vertices.
00811         if (j == rkV.VPrev || j == i || j == rkV.VNext)
00812         {
00813             continue;
00814         }
00815 
00816         // V[j] has been ruled out as one of the original vertices of the
00817         // triangle <V[prev],V[curr],V[next]>.  When triangulating polygons
00818         // with holes, V[j] might be a duplicated vertex, in which case it
00819         // does not affect the earness of V[curr].
00820         int iTest = V(j).Index;
00821         if (m_kSPositions[iTest] == m_kSPositions[iPrev]
00822         ||  m_kSPositions[iTest] == m_kSPositions[iCurr]
00823         ||  m_kSPositions[iTest] == m_kSPositions[iNext])
00824         {
00825             continue;
00826         }
00827 
00828         // Test if the vertex is inside or on the triangle.  When it is, it
00829         // causes V[curr] not to be an ear.
00830         if (m_pkQuery->ToTriangle(iTest,iPrev,iCurr,iNext) <= 0)
00831         {
00832             rkV.IsEar = false;
00833             break;
00834         }
00835     }
00836 
00837     return rkV.IsEar;
00838 }
00839 //----------------------------------------------------------------------------
00840 template <class Real>
00841 void TriangulateEC<Real>::InsertAfterC (int i)
00842 {
00843     if (m_iCFirst == -1)
00844     {
00845         // add first convex vertex
00846         m_iCFirst = i;
00847     }
00848     else
00849     {
00850         V(m_iCLast).SNext = i;
00851         V(i).SPrev = m_iCLast;
00852     }
00853     m_iCLast = i;
00854 }
00855 //----------------------------------------------------------------------------
00856 template <class Real>
00857 void TriangulateEC<Real>::InsertAfterR (int i)
00858 {
00859     if (m_iRFirst == -1)
00860     {
00861         // add first reflex vertex
00862         m_iRFirst = i;
00863     }
00864     else
00865     {
00866         V(m_iRLast).SNext = i;
00867         V(i).SPrev = m_iRLast;
00868     }
00869     m_iRLast = i;
00870 }
00871 //----------------------------------------------------------------------------
00872 template <class Real>
00873 void TriangulateEC<Real>::InsertEndE (int i)
00874 {
00875     if (m_iEFirst == -1)
00876     {
00877         // add first ear
00878         m_iEFirst = i;
00879         m_iELast = i;
00880     }
00881     V(m_iELast).ENext = i;
00882     V(i).EPrev = m_iELast;
00883     m_iELast = i;
00884 }
00885 //----------------------------------------------------------------------------
00886 template <class Real>
00887 void TriangulateEC<Real>::InsertAfterE (int i)
00888 {
00889     Vertex& rkVFirst = V(m_iEFirst);
00890     int iCurrENext = rkVFirst.ENext;
00891     Vertex& rkV = V(i);
00892     rkV.EPrev = m_iEFirst;
00893     rkV.ENext = iCurrENext;
00894     rkVFirst.ENext = i;
00895     V(iCurrENext).EPrev = i;
00896 }
00897 //----------------------------------------------------------------------------
00898 template <class Real>
00899 void TriangulateEC<Real>::InsertBeforeE (int i)
00900 {
00901     Vertex& rkVFirst = V(m_iEFirst);
00902     int iCurrEPrev = rkVFirst.EPrev;
00903     Vertex& rkV = V(i);
00904     rkV.EPrev = iCurrEPrev;
00905     rkV.ENext = m_iEFirst;
00906     rkVFirst.EPrev = i;
00907     V(iCurrEPrev).ENext = i;
00908 }
00909 //----------------------------------------------------------------------------
00910 template <class Real>
00911 void TriangulateEC<Real>::RemoveV (int i)
00912 {
00913     int iCurrVPrev = V(i).VPrev;
00914     int iCurrVNext = V(i).VNext;
00915     V(iCurrVPrev).VNext = iCurrVNext;
00916     V(iCurrVNext).VPrev = iCurrVPrev;
00917 }
00918 //----------------------------------------------------------------------------
00919 template <class Real>
00920 int TriangulateEC<Real>::RemoveE (int i)
00921 {
00922     int iCurrEPrev = V(i).EPrev;
00923     int iCurrENext = V(i).ENext;
00924     V(iCurrEPrev).ENext = iCurrENext;
00925     V(iCurrENext).EPrev = iCurrEPrev;
00926     return iCurrENext;
00927 }
00928 //----------------------------------------------------------------------------
00929 template <class Real>
00930 void TriangulateEC<Real>::RemoveR (int i)
00931 {
00932     assert(m_iRFirst != -1 && m_iRLast != -1);
00933 
00934     if (i == m_iRFirst)
00935     {
00936         m_iRFirst = V(i).SNext;
00937         if (m_iRFirst != -1)
00938         {
00939             V(m_iRFirst).SPrev = -1;
00940         }
00941         V(i).SNext = -1;
00942     }
00943     else if (i == m_iRLast)
00944     {
00945         m_iRLast = V(i).SPrev;
00946         if (m_iRLast != -1)
00947         {
00948             V(m_iRLast).SNext = -1;
00949         }
00950         V(i).SPrev = -1;
00951     }
00952     else
00953     {
00954         int iCurrSPrev = V(i).SPrev;
00955         int iCurrSNext = V(i).SNext;
00956         V(iCurrSPrev).SNext = iCurrSNext;
00957         V(iCurrSNext).SPrev = iCurrSPrev;
00958         V(i).SNext = -1;
00959         V(i).SPrev = -1;
00960     }
00961 }
00962 //----------------------------------------------------------------------------
00963 
00964 //----------------------------------------------------------------------------
00965 // Tree support.
00966 //----------------------------------------------------------------------------
00967 template <class Real>
00968 void TriangulateEC<Real>::Delete (Tree*& rpkRoot)
00969 {
00970     if (rpkRoot)
00971     {
00972         std::queue<Tree*> kQueue;
00973         kQueue.push(rpkRoot);
00974 
00975         while (kQueue.size() > 0)
00976         {
00977             Tree* pkTree = kQueue.front();
00978             kQueue.pop();
00979             for (int i = 0; i < (int)pkTree->Child.size(); i++)
00980             {
00981                kQueue.push(pkTree->Child[i]);
00982             }
00983             WM4_DELETE pkTree;
00984         }
00985 
00986         rpkRoot = 0;
00987     }
00988 }
00989 //----------------------------------------------------------------------------
00990 template <class Real>
00991 int TriangulateEC<Real>::GetExtraElements (const Tree* pkTree)
00992 {
00993     int iExtraElements = 0;
00994 
00995     std::queue<const Tree*> kQueue;
00996     kQueue.push(pkTree);
00997     while (kQueue.size() > 0)
00998     {
00999         const Tree* pkRoot = kQueue.front();
01000         kQueue.pop();
01001         int iNumChildren = (int)pkRoot->Child.size();
01002         iExtraElements += 2*iNumChildren;
01003 
01004         for (int i = 0; i < iNumChildren; i++)
01005         {
01006             const Tree* pkChild = pkRoot->Child[i];
01007             int iNumGrandChildren = (int)pkChild->Child.size();
01008             for (int j = 0; j < iNumGrandChildren; j++)
01009             {
01010                 kQueue.push(pkChild->Child[j]);
01011             }
01012         }
01013     }
01014 
01015     return iExtraElements;
01016 }
01017 //----------------------------------------------------------------------------
01018 
01019 //----------------------------------------------------------------------------
01020 // explicit instantiation
01021 //----------------------------------------------------------------------------
01022 template WM4_FOUNDATION_ITEM
01023 class TriangulateEC<float>;
01024 
01025 template WM4_FOUNDATION_ITEM
01026 class TriangulateEC<double>;
01027 //----------------------------------------------------------------------------
01028 }

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