Triangulation.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) 2005 Werner Mayer <wmayer[at]users.sourceforge.net>     *
00003  *                                                                         *
00004  *   This file is part of the FreeCAD CAx development system.              *
00005  *                                                                         *
00006  *   This library is free software; you can redistribute it and/or         *
00007  *   modify it under the terms of the GNU Library General Public           *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2 of the License, or (at your option) any later version.      *
00010  *                                                                         *
00011  *   This library  is distributed in the hope that it will be useful,      *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00014  *   GNU Library General Public License for more details.                  *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Library General Public     *
00017  *   License along with this library; see the file COPYING.LIB. If not,    *
00018  *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
00019  *   Suite 330, Boston, MA  02111-1307, USA                                *
00020  *                                                                         *
00021  ***************************************************************************/
00022 
00023 
00024 #include "PreCompiled.h"
00025 #ifndef _PreComp_
00026 # include <queue>
00027 #endif
00028 
00029 #include <Base/Console.h>
00030 #include <Base/Exception.h>
00031 #include "Triangulation.h"
00032 #include "Approximation.h"
00033 #include "MeshKernel.h"
00034 
00035 #include <Mod/Mesh/App/WildMagic4/Wm4Delaunay2.h>
00036 
00037 
00038 using namespace MeshCore;
00039 
00040 
00041 AbstractPolygonTriangulator::AbstractPolygonTriangulator()
00042 {
00043     _discard = false;
00044 }
00045 
00046 AbstractPolygonTriangulator::~AbstractPolygonTriangulator()
00047 {
00048 }
00049 
00050 void AbstractPolygonTriangulator::SetPolygon(const std::vector<Base::Vector3f>& raclPoints)
00051 {
00052     this->_points = raclPoints;
00053     if (this->_points.size() > 0) {
00054         if (this->_points.front() == this->_points.back())
00055             this->_points.pop_back();
00056     }
00057 }
00058 
00059 std::vector<Base::Vector3f> AbstractPolygonTriangulator::GetPolygon() const
00060 {
00061     return _points;
00062 }
00063 
00064 float AbstractPolygonTriangulator::GetLength() const
00065 {
00066     float len = 0.0f;
00067     if (_points.size() > 2) {
00068         for (std::vector<Base::Vector3f>::const_iterator it = _points.begin(); it != _points.end();++it) {
00069             std::vector<Base::Vector3f>::const_iterator jt = it + 1;
00070             if (jt == _points.end()) jt = _points.begin();
00071             len += Base::Distance(*it, *jt);
00072         }
00073     }
00074 
00075     return len;
00076 }
00077 
00078 std::vector<Base::Vector3f> AbstractPolygonTriangulator::AddedPoints() const
00079 {
00080     // Apply the inverse transformation to project back to world coordinates
00081     std::vector<Base::Vector3f> added;
00082     added.reserve(_newpoints.size());
00083     for (std::vector<Base::Vector3f>::const_iterator pt = _newpoints.begin(); pt != _newpoints.end(); ++pt)
00084         added.push_back(_inverse * *pt);
00085     return added;
00086 }
00087 
00088 Base::Matrix4D AbstractPolygonTriangulator::GetTransformToFitPlane() const
00089 {
00090     PlaneFit planeFit;
00091     for (std::vector<Base::Vector3f>::const_iterator it = _points.begin(); it!=_points.end(); ++it)
00092         planeFit.AddPoint(*it);
00093 
00094     if (planeFit.Fit() == FLOAT_MAX)
00095         throw Base::Exception("Plane fit failed");
00096 
00097     Base::Vector3f bs = planeFit.GetBase();
00098     Base::Vector3f ex = planeFit.GetDirU();
00099     Base::Vector3f ey = planeFit.GetDirV();
00100     Base::Vector3f ez = planeFit.GetNormal();
00101 
00102     // build the matrix for the inverse transformation
00103     Base::Matrix4D rInverse;
00104     rInverse.setToUnity();
00105     rInverse[0][0] = ex.x; rInverse[0][1] = ey.x; rInverse[0][2] = ez.x; rInverse[0][3] = bs.x;
00106     rInverse[1][0] = ex.y; rInverse[1][1] = ey.y; rInverse[1][2] = ez.y; rInverse[1][3] = bs.y;
00107     rInverse[2][0] = ex.z; rInverse[2][1] = ey.z; rInverse[2][2] = ez.z; rInverse[2][3] = bs.z;
00108 
00109     return rInverse;
00110 }
00111 
00112 std::vector<Base::Vector3f> AbstractPolygonTriangulator::ProjectToFitPlane()
00113 {
00114     std::vector<Base::Vector3f> proj = _points;
00115     _inverse = GetTransformToFitPlane();
00116     Base::Vector3f bs((float)_inverse[0][3], (float)_inverse[1][3], (float)_inverse[2][3]);
00117     Base::Vector3f ex((float)_inverse[0][0], (float)_inverse[1][0], (float)_inverse[2][0]);
00118     Base::Vector3f ey((float)_inverse[0][1], (float)_inverse[1][1], (float)_inverse[2][1]);
00119     for (std::vector<Base::Vector3f>::iterator jt = proj.begin(); jt!=proj.end(); ++jt)
00120         jt->TransformToCoordinateSystem(bs, ex, ey);
00121     return proj;
00122 }
00123 
00124 void AbstractPolygonTriangulator::ProjectOntoSurface(const std::vector<Base::Vector3f>& points)
00125 {
00126     // For a good approximation we should have enough points, i.e. for 9 parameters
00127     // for the fit function we should have at least 50 points.
00128     unsigned int uMinPts = 50;
00129 
00130     PolynomialFit polyFit;
00131     Base::Vector3f bs((float)_inverse[0][3], (float)_inverse[1][3], (float)_inverse[2][3]);
00132     Base::Vector3f ex((float)_inverse[0][0], (float)_inverse[1][0], (float)_inverse[2][0]);
00133     Base::Vector3f ey((float)_inverse[0][1], (float)_inverse[1][1], (float)_inverse[2][1]);
00134 
00135     for (std::vector<Base::Vector3f>::const_iterator it = points.begin(); it != points.end(); ++it) {
00136         Base::Vector3f pt = *it;
00137         pt.TransformToCoordinateSystem(bs, ex, ey);
00138         polyFit.AddPoint(pt);
00139     }
00140 
00141     if (polyFit.CountPoints() >= uMinPts && polyFit.Fit() < FLOAT_MAX) {
00142         for (std::vector<Base::Vector3f>::iterator pt = _newpoints.begin(); pt != _newpoints.end(); ++pt)
00143             pt->z = (float)polyFit.Value(pt->x, pt->y);
00144     }
00145 }
00146 
00147 bool AbstractPolygonTriangulator::TriangulatePolygon()
00148 {
00149     try {
00150         bool ok = Triangulate();
00151         if (ok) Done();
00152         return ok;
00153     }
00154     catch (const Base::Exception& e) {
00155         Base::Console().Log("Triangulation: %s\n", e.what());
00156         return false;
00157     }
00158     catch (const std::exception& e) {
00159         Base::Console().Log("Triangulation: %s\n", e.what());
00160         return false;
00161     }
00162     catch (...) {
00163         return false;
00164     }
00165 }
00166 
00167 std::vector<unsigned long> AbstractPolygonTriangulator::GetInfo() const
00168 {
00169     return _info;
00170 }
00171 
00172 void AbstractPolygonTriangulator::Discard()
00173 {
00174     if (!_discard) {
00175         _discard = true;
00176         _info.pop_back();
00177     }
00178 }
00179 
00180 void AbstractPolygonTriangulator::Done()
00181 {
00182     _info.push_back(_points.size());
00183     _discard = false;
00184 }
00185 
00186 // -------------------------------------------------------------
00187 
00188 EarClippingTriangulator::EarClippingTriangulator()
00189 {
00190 }
00191 
00192 EarClippingTriangulator::~EarClippingTriangulator()
00193 {
00194 }
00195 
00196 bool EarClippingTriangulator::Triangulate()
00197 {
00198     _facets.clear();
00199     _triangles.clear();
00200 
00201     std::vector<Base::Vector3f> pts = ProjectToFitPlane();
00202     std::vector<unsigned long> result;
00203 
00204     //  Invoke the triangulator to triangulate this polygon.
00205     Triangulate::Process(pts,result);
00206 
00207     // print out the results.
00208     unsigned long tcount = result.size()/3;
00209 
00210     bool ok = tcount+2 == _points.size();
00211     if  (tcount > _points.size())
00212         return false; // no valid triangulation
00213 
00214     MeshGeomFacet clFacet;
00215     MeshFacet clTopFacet;
00216     for (unsigned long i=0; i<tcount; i++) {
00217         if (Triangulate::_invert) {
00218             clFacet._aclPoints[0] = _points[result[i*3+0]];
00219             clFacet._aclPoints[2] = _points[result[i*3+1]];
00220             clFacet._aclPoints[1] = _points[result[i*3+2]];
00221             clTopFacet._aulPoints[0] = result[i*3+0];
00222             clTopFacet._aulPoints[2] = result[i*3+1];
00223             clTopFacet._aulPoints[1] = result[i*3+2];
00224         }
00225         else {
00226             clFacet._aclPoints[0] = _points[result[i*3+0]];
00227             clFacet._aclPoints[1] = _points[result[i*3+1]];
00228             clFacet._aclPoints[2] = _points[result[i*3+2]];
00229             clTopFacet._aulPoints[0] = result[i*3+0];
00230             clTopFacet._aulPoints[1] = result[i*3+1];
00231             clTopFacet._aulPoints[2] = result[i*3+2];
00232         }
00233 
00234         _triangles.push_back(clFacet);
00235         _facets.push_back(clTopFacet);
00236     }
00237 
00238     return ok;
00239 }
00240 
00241 float EarClippingTriangulator::Triangulate::Area(const std::vector<Base::Vector3f> &contour)
00242 {
00243     int n = contour.size();
00244 
00245     float A=0.0f;
00246 
00247     for(int p=n-1,q=0; q<n; p=q++) {
00248         A+= contour[p].x*contour[q].y - contour[q].x*contour[p].y;
00249     }
00250     return A*0.5f;
00251 }
00252 
00253 /*
00254   InsideTriangle decides if a point P is Inside of the triangle
00255   defined by A, B, C.
00256 */
00257 bool EarClippingTriangulator::Triangulate::InsideTriangle(float Ax, float Ay, float Bx,
00258                                                           float By, float Cx, float Cy,
00259                                                           float Px, float Py)
00260 {
00261     float ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
00262     float cCROSSap, bCROSScp, aCROSSbp;
00263 
00264     ax = Cx - Bx;  ay = Cy - By;
00265     bx = Ax - Cx;  by = Ay - Cy;
00266     cx = Bx - Ax;  cy = By - Ay;
00267     apx= Px - Ax;  apy= Py - Ay;
00268     bpx= Px - Bx;  bpy= Py - By;
00269     cpx= Px - Cx;  cpy= Py - Cy;
00270 
00271     aCROSSbp = ax*bpy - ay*bpx;
00272     cCROSSap = cx*apy - cy*apx;
00273     bCROSScp = bx*cpy - by*cpx;
00274 
00275     return ((aCROSSbp >= FLOAT_EPS) && (bCROSScp >= FLOAT_EPS) && (cCROSSap >= FLOAT_EPS));
00276 }
00277 
00278 bool EarClippingTriangulator::Triangulate::Snip(const std::vector<Base::Vector3f> &contour,
00279                                                 int u,int v,int w,int n,int *V)
00280 {
00281     int p;
00282     float Ax, Ay, Bx, By, Cx, Cy, Px, Py;
00283 
00284     Ax = contour[V[u]].x;
00285     Ay = contour[V[u]].y;
00286 
00287     Bx = contour[V[v]].x;
00288     By = contour[V[v]].y;
00289 
00290     Cx = contour[V[w]].x;
00291     Cy = contour[V[w]].y;
00292 
00293     if (FLOAT_EPS > (((Bx-Ax)*(Cy-Ay)) - ((By-Ay)*(Cx-Ax)))) return false;
00294 
00295     for (p=0;p<n;p++) {
00296         if( (p == u) || (p == v) || (p == w) ) continue;
00297         Px = contour[V[p]].x;
00298         Py = contour[V[p]].y;
00299         if (InsideTriangle(Ax,Ay,Bx,By,Cx,Cy,Px,Py)) return false;
00300     }
00301 
00302     return true;
00303 }
00304 
00305 bool EarClippingTriangulator::Triangulate::_invert = false;
00306 
00307 bool EarClippingTriangulator::Triangulate::Process(const std::vector<Base::Vector3f> &contour,
00308                                                    std::vector<unsigned long> &result)
00309 {
00310     /* allocate and initialize list of Vertices in polygon */
00311 
00312     int n = contour.size();
00313     if ( n < 3 ) return false;
00314 
00315     int *V = new int[n];
00316 
00317     /* we want a counter-clockwise polygon in V */
00318 
00319     if (0.0f < Area(contour)) {
00320         for (int v=0; v<n; v++) V[v] = v;
00321         _invert = true;
00322     }
00323 //    for(int v=0; v<n; v++) V[v] = (n-1)-v;
00324     else {
00325         for(int v=0; v<n; v++) V[v] = (n-1)-v;
00326         _invert = false;
00327     }
00328 
00329     int nv = n;
00330 
00331     /*  remove nv-2 Vertices, creating 1 triangle every time */
00332     int count = 2*nv;   /* error detection */
00333 
00334     for(int m=0, v=nv-1; nv>2; ) {
00335         /* if we loop, it is probably a non-simple polygon */
00336         if (0 >= (count--)) {
00337             //** Triangulate: ERROR - probable bad polygon!
00338             return false;
00339         }
00340 
00341         /* three consecutive vertices in current polygon, <u,v,w> */
00342         int u = v  ; if (nv <= u) u = 0;     /* previous */
00343         v = u+1; if (nv <= v) v = 0;     /* new v    */
00344         int w = v+1; if (nv <= w) w = 0;     /* next     */
00345 
00346         if (Snip(contour,u,v,w,nv,V)) {
00347             int a,b,c,s,t;
00348 
00349             /* true names of the vertices */
00350             a = V[u]; b = V[v]; c = V[w];
00351 
00352             /* output Triangle */
00353             result.push_back( a );
00354             result.push_back( b );
00355             result.push_back( c );
00356 
00357             m++;
00358 
00359             /* remove v from remaining polygon */
00360             for(s=v,t=v+1;t<nv;s++,t++) V[s] = V[t]; nv--;
00361 
00362             /* resest error detection counter */
00363             count = 2*nv;
00364         }
00365     }
00366 
00367     delete [] V;
00368 
00369     return true;
00370 }
00371 
00372 // -------------------------------------------------------------
00373 
00374 QuasiDelaunayTriangulator::QuasiDelaunayTriangulator()
00375 {
00376 }
00377 
00378 QuasiDelaunayTriangulator::~QuasiDelaunayTriangulator()
00379 {
00380 }
00381 
00382 bool QuasiDelaunayTriangulator::Triangulate()
00383 {
00384     if (EarClippingTriangulator::Triangulate() == false)
00385         return false; // no valid triangulation
00386 
00387     // For each internal edge get the adjacent facets. When doing an edge swap we must update
00388     // this structure.
00389     std::map<std::pair<unsigned long, unsigned long>, std::vector<unsigned long> > aEdge2Face;
00390     for (std::vector<MeshFacet>::iterator pI = _facets.begin(); pI != _facets.end(); pI++) {
00391         for (int i = 0; i < 3; i++) {
00392             unsigned long ulPt0 = std::min<unsigned long>(pI->_aulPoints[i],  pI->_aulPoints[(i+1)%3]);
00393             unsigned long ulPt1 = std::max<unsigned long>(pI->_aulPoints[i],  pI->_aulPoints[(i+1)%3]);
00394             // ignore borderlines of the polygon
00395             if ((ulPt1-ulPt0)%(_points.size()-1) > 1)
00396                 aEdge2Face[std::pair<unsigned long, unsigned long>(ulPt0, ulPt1)].push_back(pI - _facets.begin());
00397         }
00398     }
00399 
00400     // fill up this list with all internal edges and perform swap edges until this list is empty
00401     std::list<std::pair<unsigned long, unsigned long> > aEdgeList;
00402     std::map<std::pair<unsigned long, unsigned long>, std::vector<unsigned long> >::iterator pE;
00403     for (pE = aEdge2Face.begin(); pE != aEdge2Face.end(); ++pE)
00404         aEdgeList.push_back(pE->first);
00405 
00406     // to be sure to avoid an endless loop
00407     unsigned long uMaxIter = 5 * aEdge2Face.size();
00408 
00409     // Perform a swap edge where needed
00410     while (!aEdgeList.empty() && uMaxIter > 0) {
00411         // get the first edge and remove it from the list
00412         std::pair<unsigned long, unsigned long> aEdge = aEdgeList.front();
00413         aEdgeList.pop_front();
00414         uMaxIter--;
00415 
00416         // get the adjacent facets to this edge
00417         pE = aEdge2Face.find( aEdge );
00418 
00419         // this edge has been removed some iterations before
00420         if (pE == aEdge2Face.end())
00421             continue;
00422 
00423         MeshFacet& rF1 = _facets[pE->second[0]];
00424         MeshFacet& rF2 = _facets[pE->second[1]];
00425         unsigned short side1 = rF1.Side(aEdge.first, aEdge.second);
00426 
00427         Base::Vector3f cP1 = _points[rF1._aulPoints[side1]];
00428         Base::Vector3f cP2 = _points[rF1._aulPoints[(side1+1)%3]];
00429         Base::Vector3f cP3 = _points[rF1._aulPoints[(side1+2)%3]];
00430 
00431         unsigned short side2 = rF2.Side(aEdge.first, aEdge.second);
00432         Base::Vector3f cP4 = _points[rF2._aulPoints[(side2+2)%3]];
00433 
00434         MeshGeomFacet cT1(cP1, cP2, cP3); float fMax1 = cT1.MaximumAngle();
00435         MeshGeomFacet cT2(cP2, cP1, cP4); float fMax2 = cT2.MaximumAngle();
00436         MeshGeomFacet cT3(cP4, cP3, cP1); float fMax3 = cT3.MaximumAngle();
00437         MeshGeomFacet cT4(cP3, cP4, cP2); float fMax4 = cT4.MaximumAngle();
00438 
00439         float fMax12 = std::max<float>(fMax1, fMax2);
00440         float fMax34 = std::max<float>(fMax3, fMax4);
00441 
00442         // We must make sure that the two adjacent triangles builds a convex polygon, otherwise 
00443         // the swap edge operation is illegal
00444         Base::Vector3f cU = cP2-cP1;
00445         Base::Vector3f cV = cP4-cP3;
00446         // build a helper plane through cP1 that must separate cP3 and cP4
00447         Base::Vector3f cN1 = (cU % cV) % cU;
00448         if (((cP3-cP1)*cN1)*((cP4-cP1)*cN1) >= 0.0f)
00449             continue; // not convex
00450         // build a helper plane through cP3 that must separate cP1 and cP2
00451         Base::Vector3f cN2 = (cU % cV) % cV;
00452         if (((cP1-cP3)*cN2)*((cP2-cP3)*cN2) >= 0.0f)
00453             continue; // not convex
00454 
00455         // ok, here we should perform a swap edge to minimize the maximum angle
00456         if (fMax12 > fMax34) {
00457             rF1._aulPoints[(side1+1)%3] = rF2._aulPoints[(side2+2)%3];
00458             rF2._aulPoints[(side2+1)%3] = rF1._aulPoints[(side1+2)%3];
00459 
00460             // adjust the edge list
00461             for (int i=0; i<3; i++) {
00462                 std::map<std::pair<unsigned long, unsigned long>, std::vector<unsigned long> >::iterator it;
00463                 // first facet
00464                 unsigned long ulPt0 = std::min<unsigned long>(rF1._aulPoints[i],  rF1._aulPoints[(i+1)%3]);
00465                 unsigned long ulPt1 = std::max<unsigned long>(rF1._aulPoints[i],  rF1._aulPoints[(i+1)%3]);
00466                 it = aEdge2Face.find( std::make_pair(ulPt0, ulPt1) );
00467                 if (it != aEdge2Face.end()) {
00468                     if (it->second[0] == pE->second[1])
00469                         it->second[0] = pE->second[0];
00470                     else if (it->second[1] == pE->second[1])
00471                         it->second[1] = pE->second[0];
00472                     aEdgeList.push_back(it->first);
00473                 }
00474 
00475                 // second facet
00476                 ulPt0 = std::min<unsigned long>(rF2._aulPoints[i],  rF2._aulPoints[(i+1)%3]);
00477                 ulPt1 = std::max<unsigned long>(rF2._aulPoints[i],  rF2._aulPoints[(i+1)%3]);
00478                 it = aEdge2Face.find( std::make_pair(ulPt0, ulPt1) );
00479                 if (it != aEdge2Face.end()) {
00480                     if (it->second[0] == pE->second[0])
00481                         it->second[0] = pE->second[1];
00482                     else if (it->second[1] == pE->second[0])
00483                         it->second[1] = pE->second[1];
00484                     aEdgeList.push_back(it->first);
00485                 }
00486             }
00487 
00488             // Now we must remove the edge and replace it through the new edge
00489             unsigned long ulPt0 = std::min<unsigned long>(rF1._aulPoints[(side1+1)%3], rF2._aulPoints[(side2+1)%3]);
00490             unsigned long ulPt1 = std::max<unsigned long>(rF1._aulPoints[(side1+1)%3], rF2._aulPoints[(side2+1)%3]);
00491             std::pair<unsigned long, unsigned long> aNewEdge = std::make_pair(ulPt0, ulPt1);
00492             aEdge2Face[aNewEdge] = pE->second;
00493             aEdge2Face.erase(pE);
00494         }
00495     }
00496 
00497     return true;
00498 }
00499 
00500 // -------------------------------------------------------------
00501 
00502 namespace MeshCore {
00503 namespace Triangulation {
00504 struct Vertex2d_Less  : public std::binary_function<const Base::Vector3f&, const Base::Vector3f&, bool>
00505 {
00506     bool operator()(const Base::Vector3f& p, const Base::Vector3f& q) const
00507     {
00508         if (fabs(p.x - q.x) < MeshDefinitions::_fMinPointDistanceD1) {
00509         if (fabs(p.y - q.y) < MeshDefinitions::_fMinPointDistanceD1) {
00510         return false; } else return p.y < q.y;
00511         } else return p.x < q.x; return true;
00512     }
00513 };
00514 struct Vertex2d_EqualTo  : public std::binary_function<const Base::Vector3f&, const Base::Vector3f&, bool>
00515 {
00516     bool operator()(const Base::Vector3f& p, const Base::Vector3f& q) const
00517     {
00518         if (fabs(p.x - q.x) < MeshDefinitions::_fMinPointDistanceD1
00519         &&  fabs(p.y - q.y) < MeshDefinitions::_fMinPointDistanceD1)
00520         return true; return false;
00521     }
00522 };
00523 }
00524 }
00525 
00526 DelaunayTriangulator::DelaunayTriangulator()
00527 {
00528 }
00529 
00530 DelaunayTriangulator::~DelaunayTriangulator()
00531 {
00532 }
00533 
00534 bool DelaunayTriangulator::Triangulate()
00535 {
00536     // before starting the triangulation we must make sure that all polygon 
00537     // points are different
00538     std::vector<Base::Vector3f> aPoints = _points;
00539     // sort the points ascending x,y coordinates
00540     std::sort(aPoints.begin(), aPoints.end(), Triangulation::Vertex2d_Less());
00541     // if there are two adjacent points whose distance is less then an epsilon
00542     if (std::adjacent_find(aPoints.begin(), aPoints.end(),
00543         Triangulation::Vertex2d_EqualTo()) < aPoints.end())
00544         return false;
00545 
00546     _facets.clear();
00547     _triangles.clear();
00548 
00549     std::vector<Wm4::Vector2d> akVertex;
00550     akVertex.reserve(_points.size());
00551     for (std::vector<Base::Vector3f>::iterator it = _points.begin(); it != _points.end(); it++) {
00552         akVertex.push_back(Wm4::Vector2d(it->x, it->y));
00553     }
00554 
00555     Wm4::Delaunay2d del(akVertex.size(), &(akVertex[0]), 0.001, false, Wm4::Query::QT_INT64);
00556     int iTQuantity = del.GetSimplexQuantity();
00557     std::vector<int> aiTVertex(3*iTQuantity);
00558     size_t uiSize = 3*iTQuantity*sizeof(int);
00559     Wm4::System::Memcpy(&(aiTVertex[0]),uiSize,del.GetIndices(),uiSize);
00560 
00561     // If H is the number of hull edges and N is the number of vertices,
00562     // then the triangulation must have 2*N-2-H triangles and 3*N-3-H
00563     // edges.
00564     int iEQuantity = 0;
00565     int* aiIndex = 0;
00566     del.GetHull(iEQuantity,aiIndex);
00567     int iUniqueVQuantity = del.GetUniqueVertexQuantity();
00568     int iTVerify = 2*iUniqueVQuantity - 2 - iEQuantity;
00569     (void)iTVerify;  // avoid warning in release build
00570     bool succeeded = (iTVerify == iTQuantity);
00571     int iEVerify = 3*iUniqueVQuantity - 3 - iEQuantity;
00572     (void)iEVerify;  // avoid warning about unused variable
00573     delete[] aiIndex;
00574 
00575     MeshGeomFacet triangle;
00576     MeshFacet facet;
00577     for (int i = 0; i < iTQuantity; i++) {
00578         for (int j=0; j<3; j++) {
00579             facet._aulPoints[j] = aiTVertex[3*i+j];
00580             triangle._aclPoints[j].x = (float)akVertex[aiTVertex[3*i+j]].X();
00581             triangle._aclPoints[j].y = (float)akVertex[aiTVertex[3*i+j]].Y();
00582         }
00583 
00584         _triangles.push_back(triangle);
00585         _facets.push_back(facet);
00586     }
00587 
00588     return succeeded;
00589 }
00590 
00591 // -------------------------------------------------------------
00592 
00593 FlatTriangulator::FlatTriangulator()
00594 {
00595 }
00596 
00597 FlatTriangulator::~FlatTriangulator()
00598 {
00599 }
00600 
00601 bool FlatTriangulator::Triangulate()
00602 {
00603     _newpoints.clear();
00604     // before starting the triangulation we must make sure that all polygon 
00605     // points are different
00606     std::vector<Base::Vector3f> aPoints = ProjectToFitPlane();
00607     std::vector<Base::Vector3f> tmp = aPoints;
00608     // sort the points ascending x,y coordinates
00609     std::sort(tmp.begin(), tmp.end(), Triangulation::Vertex2d_Less());
00610     // if there are two adjacent points whose distance is less then an epsilon
00611     if (std::adjacent_find(tmp.begin(), tmp.end(),
00612         Triangulation::Vertex2d_EqualTo()) < tmp.end() )
00613         return false;
00614 
00615     _facets.clear();
00616     _triangles.clear();
00617 
00618     // Todo: Implement algorithm for constraint delaunay triangulation
00619     QuasiDelaunayTriangulator tria;
00620     tria.SetPolygon(this->GetPolygon());
00621     bool succeeded = tria.TriangulatePolygon();
00622     this->_facets = tria.GetFacets();
00623     this->_triangles = tria.GetTriangles();
00624 
00625     return succeeded;
00626 }
00627 
00628 void FlatTriangulator::ProjectOntoSurface(const std::vector<Base::Vector3f>&)
00629 {
00630 }
00631 
00632 // -------------------------------------------------------------
00633 
00634 ConstraintDelaunayTriangulator::ConstraintDelaunayTriangulator(float area)
00635   : fMaxArea(area)
00636 {
00637 }
00638 
00639 ConstraintDelaunayTriangulator::~ConstraintDelaunayTriangulator()
00640 {
00641 }
00642 
00643 bool ConstraintDelaunayTriangulator::Triangulate()
00644 {
00645     _newpoints.clear();
00646     // before starting the triangulation we must make sure that all polygon 
00647     // points are different
00648     std::vector<Base::Vector3f> aPoints = ProjectToFitPlane();
00649     std::vector<Base::Vector3f> tmp = aPoints;
00650     // sort the points ascending x,y coordinates
00651     std::sort(tmp.begin(), tmp.end(), Triangulation::Vertex2d_Less());
00652     // if there are two adjacent points whose distance is less then an epsilon
00653     if (std::adjacent_find(tmp.begin(), tmp.end(),
00654         Triangulation::Vertex2d_EqualTo()) < tmp.end() )
00655         return false;
00656 
00657     _facets.clear();
00658     _triangles.clear();
00659 
00660     // Todo: Implement algorithm for constraint delaunay triangulation
00661     QuasiDelaunayTriangulator tria;
00662     tria.SetPolygon(this->GetPolygon());
00663     bool succeeded = tria.TriangulatePolygon();
00664     this->_facets = tria.GetFacets();
00665     this->_triangles = tria.GetTriangles();
00666 
00667     return succeeded;
00668 }
00669 
00670 // -------------------------------------------------------------
00671 
00672 Triangulator::Triangulator(const MeshKernel& k) : _kernel(k)
00673 {
00674 }
00675 
00676 Triangulator::~Triangulator()
00677 {
00678 }
00679 
00680 bool Triangulator::Triangulate()
00681 {
00682     return false;
00683 }

Generated on Wed Nov 23 19:00:51 2011 for FreeCAD by  doxygen 1.6.1