Degeneration.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) 2005 Imetric 3D GmbH                                    *
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 
00026 #ifndef _PreComp_
00027 # include <algorithm>
00028 # include <map>
00029 #endif
00030 
00031 #include "Degeneration.h"
00032 #include "Definitions.h"
00033 #include "Iterator.h"
00034 #include "Helpers.h"
00035 #include "MeshKernel.h"
00036 #include "Algorithm.h"
00037 #include "Info.h"
00038 #include "Grid.h"
00039 #include "TopoAlgorithm.h"
00040 
00041 #include <Base/Sequencer.h>
00042 
00043 using namespace MeshCore;
00044 
00045 bool MeshEvalInvalids::Evaluate()
00046 {
00047   const MeshFacetArray& rFaces = _rclMesh.GetFacets();
00048   for ( MeshFacetArray::_TConstIterator it = rFaces.begin(); it != rFaces.end(); ++it )
00049   {
00050     if ( !it->IsValid() )
00051       return false;
00052   }
00053 
00054   const MeshPointArray& rPoints = _rclMesh.GetPoints();
00055   for ( MeshPointArray::_TConstIterator jt = rPoints.begin(); jt != rPoints.end(); ++jt )
00056   {
00057     if ( !jt->IsValid() )
00058       return false;
00059   }
00060 
00061   return true;
00062 }
00063 
00064 std::vector<unsigned long> MeshEvalInvalids::GetIndices() const
00065 {
00066   std::vector<unsigned long> aInds;
00067   const MeshFacetArray& rFaces = _rclMesh.GetFacets();
00068   const MeshPointArray& rPoints = _rclMesh.GetPoints();
00069   unsigned long ind=0;
00070   for ( MeshFacetArray::_TConstIterator it = rFaces.begin(); it != rFaces.end(); ++it, ind++ )
00071   {
00072     if ( !it->IsValid() )
00073       aInds.push_back(ind);
00074     else if ( !rPoints[it->_aulPoints[0]].IsValid() )
00075       aInds.push_back(ind);
00076     else if ( !rPoints[it->_aulPoints[1]].IsValid() )
00077       aInds.push_back(ind);
00078     else if ( !rPoints[it->_aulPoints[2]].IsValid() )
00079       aInds.push_back(ind);
00080   }
00081 
00082   return aInds;
00083 }
00084 
00085 bool MeshFixInvalids::Fixup()
00086 {
00087   _rclMesh.RemoveInvalids();
00088   return true;
00089 }
00090 
00091 // ----------------------------------------------------------------------
00092 
00093 namespace MeshCore {
00094 
00095 typedef MeshPointArray::_TConstIterator VertexIterator;
00096 /*
00097  * When building up a mesh then usually the class MeshBuilder is used. This
00098  * class uses internally a std::set<MeshPoint> which uses the '<' operator of
00099  * MeshPoint to sort the points. Thus to be consistent (and avoid using the
00100  * '==' operator of MeshPoint) we use the same operator when comparing the
00101  * points in the function object.
00102  */
00103 struct Vertex_EqualTo  : public std::binary_function<const VertexIterator&,
00104                                                      const VertexIterator&, bool>
00105 {
00106     bool operator()(const VertexIterator& x,
00107                     const VertexIterator& y) const
00108     {
00109         if ( (*x) < (*y) )
00110             return false;
00111         else if ( (*y) < (*x) )
00112             return false;
00113         return true;
00114     }
00115 };
00116 
00117 struct Vertex_Less  : public std::binary_function<const VertexIterator&,
00118                                                   const VertexIterator&, bool>
00119 {
00120     bool operator()(const VertexIterator& x,
00121                     const VertexIterator& y) const
00122     {
00123         return (*x) < (*y);
00124     }
00125 };
00126 
00127 }
00128 
00129 bool MeshEvalDuplicatePoints::Evaluate()
00130 {
00131     // get an const iterator to each vertex and sort them in ascending order by
00132     // their (x,y,z) coordinates
00133     const MeshPointArray& rPoints = _rclMesh.GetPoints();
00134     std::vector<VertexIterator> vertices;
00135     vertices.reserve(rPoints.size());
00136     for (MeshPointArray::_TConstIterator it = rPoints.begin(); it != rPoints.end(); ++it) {
00137         vertices.push_back(it);
00138     }
00139 
00140     // if there are two adjacent vertices which have the same coordinates
00141     std::sort(vertices.begin(), vertices.end(), Vertex_Less());
00142     if (std::adjacent_find(vertices.begin(), vertices.end(), Vertex_EqualTo()) < vertices.end() )
00143         return false;
00144     return true;
00145 }
00146 
00147 std::vector<unsigned long> MeshEvalDuplicatePoints::GetIndices() const
00148 {
00149     //Note: We must neither use map or set to get duplicated indices because
00150     //the sort algorithms deliver different results compared to std::sort of
00151     //a vector.
00152     const MeshPointArray& rPoints = _rclMesh.GetPoints();
00153     std::vector<VertexIterator> vertices;
00154     vertices.reserve(rPoints.size());
00155     for (MeshPointArray::_TConstIterator it = rPoints.begin(); it != rPoints.end(); ++it) {
00156         vertices.push_back(it);
00157     }
00158 
00159     // if there are two adjacent vertices which have the same coordinates
00160     std::vector<unsigned long> aInds;
00161     Vertex_EqualTo pred;
00162     std::sort(vertices.begin(), vertices.end(), Vertex_Less());
00163 
00164     std::vector<VertexIterator>::iterator vt = vertices.begin();
00165     while (vt < vertices.end()) {
00166         // get first item which adjacent element has the same vertex
00167         vt = std::adjacent_find(vt, vertices.end(), pred);
00168         if (vt < vertices.end()) {
00169             vt++;
00170             aInds.push_back(*vt - rPoints.begin());
00171         }
00172     }
00173 
00174     return aInds;
00175 }
00176 
00177 bool MeshFixDuplicatePoints::Fixup()
00178 {
00179     //Note: We must neither use map or set to get duplicated indices because
00180     //the sort algorithms deliver different results compared to std::sort of
00181     //a vector.
00182     const MeshPointArray& rPoints = _rclMesh.GetPoints();
00183     std::vector<VertexIterator> vertices;
00184     vertices.reserve(rPoints.size());
00185     for (MeshPointArray::_TConstIterator it = rPoints.begin(); it != rPoints.end(); ++it) {
00186         vertices.push_back(it);
00187     }
00188 
00189     // get the indices of adjacent vertices which have the same coordinates
00190     std::vector<unsigned long> aInds;
00191     std::sort(vertices.begin(), vertices.end(), Vertex_Less());
00192 
00193     Vertex_EqualTo pred;
00194     std::vector<VertexIterator>::iterator next = vertices.begin();
00195     std::map<unsigned long, unsigned long> mapPointIndex;
00196     std::vector<unsigned long> pointIndices;
00197     while (next < vertices.end()) {
00198         next = std::adjacent_find(next, vertices.end(), pred);
00199         if (next < vertices.end()) {
00200             std::vector<VertexIterator>::iterator first = next;
00201             unsigned long first_index = *first - rPoints.begin();
00202             next++;
00203             while (next < vertices.end() && pred(*first, *next)) {
00204                 unsigned long next_index = *next - rPoints.begin();
00205                 mapPointIndex[next_index] = first_index;
00206                 pointIndices.push_back(next_index);
00207                 next++;
00208             }
00209         }
00210     }
00211 
00212     // now set all facets to the correct index
00213     MeshFacetArray& rFacets = _rclMesh._aclFacetArray;
00214     for (MeshFacetArray::_TIterator it = rFacets.begin(); it != rFacets.end(); ++it) {
00215         for (int i=0; i<3; i++) {
00216             std::map<unsigned long, unsigned long>::iterator pt = mapPointIndex.find(it->_aulPoints[i]);
00217             if (pt != mapPointIndex.end())
00218                 it->_aulPoints[i] = pt->second;
00219         }
00220     }
00221 
00222     // remove invalid indices
00223     _rclMesh.DeletePoints(pointIndices);
00224     _rclMesh.RebuildNeighbours();
00225     
00226     return true;
00227 }
00228 
00229 // ----------------------------------------------------------------------
00230 
00231 namespace MeshCore {
00232 
00233 typedef MeshFacetArray::_TConstIterator FaceIterator;
00234 /*
00235  * The facet with the lowset index is regarded as 'less'.
00236  */
00237 struct MeshFacet_Less  : public std::binary_function<const FaceIterator&, 
00238                                                      const FaceIterator&, bool>
00239 {
00240     bool operator()(const FaceIterator& x, 
00241                     const FaceIterator& y) const
00242     {
00243         unsigned long tmp;
00244         unsigned long x0 = x->_aulPoints[0];
00245         unsigned long x1 = x->_aulPoints[1];
00246         unsigned long x2 = x->_aulPoints[2];
00247         unsigned long y0 = y->_aulPoints[0];
00248         unsigned long y1 = y->_aulPoints[1];
00249         unsigned long y2 = y->_aulPoints[2];
00250 
00251         if (x0 > x1)
00252         { tmp = x0; x0 = x1; x1 = tmp; }
00253         if (x0 > x2)
00254         { tmp = x0; x0 = x2; x2 = tmp; }
00255         if (x1 > x2)
00256         { tmp = x1; x1 = x2; x2 = tmp; }
00257         if (y0 > y1)
00258         { tmp = y0; y0 = y1; y1 = tmp; }
00259         if (y0 > y2)
00260         { tmp = y0; y0 = y2; y2 = tmp; }
00261         if (y1 > y2)
00262         { tmp = y1; y1 = y2; y2 = tmp; }
00263 
00264         if      (x0 < y0)  return true;
00265         else if (x0 > y0)  return false;
00266         else if (x1 < y1)  return true;
00267         else if (x1 > y1)  return false;
00268         else if (x2 < y2)  return true;
00269         else               return false;
00270     }
00271 };
00272 
00273 }
00274 
00275 /*
00276  * Two facets are equal if all its three point indices refer to the same
00277  * location in the point array of the mesh kernel they belong to.
00278  */
00279 struct MeshFacet_EqualTo  : public std::binary_function<const FaceIterator&, 
00280                                                         const FaceIterator&, bool>
00281 {
00282     bool operator()(const FaceIterator& x,
00283                     const FaceIterator& y) const
00284     {
00285         for (int i=0; i<3; i++ ) {
00286             if (x->_aulPoints[0] == y->_aulPoints[i]) {
00287                 if (x->_aulPoints[1] == y->_aulPoints[(i+1)%3] && 
00288                     x->_aulPoints[2] == y->_aulPoints[(i+2)%3])
00289                     return true;
00290                 else if (x->_aulPoints[1] == y->_aulPoints[(i+2)%3] &&
00291                      x->_aulPoints[2] == y->_aulPoints[(i+1)%3])
00292                     return true;
00293             }
00294         }
00295 
00296         return false;
00297     }
00298 };
00299 
00300 bool MeshEvalDuplicateFacets::Evaluate()
00301 {
00302   std::set<FaceIterator, MeshFacet_Less> aFaces;
00303   const MeshFacetArray& rFaces = _rclMesh.GetFacets();
00304   for (MeshFacetArray::_TConstIterator it = rFaces.begin(); it != rFaces.end(); ++it)
00305   {
00306     std::pair<std::set<FaceIterator, MeshFacet_Less>::iterator, bool>
00307         pI = aFaces.insert(it);
00308     if (!pI.second)
00309         return false;
00310   }
00311 
00312   return true;
00313 }
00314 
00315 std::vector<unsigned long> MeshEvalDuplicateFacets::GetIndices() const
00316 {
00317 #if 1
00318     const MeshFacetArray& rFacets = _rclMesh.GetFacets();
00319     std::vector<FaceIterator> faces;
00320     faces.reserve(rFacets.size());
00321     for (MeshFacetArray::_TConstIterator it = rFacets.begin(); it != rFacets.end(); ++it) {
00322         faces.push_back(it);
00323     }
00324 
00325     // if there are two adjacent faces which references the same vertices
00326     std::vector<unsigned long> aInds;
00327     MeshFacet_EqualTo pred;
00328     std::sort(faces.begin(), faces.end(), MeshFacet_Less());
00329 
00330     std::vector<FaceIterator>::iterator ft = faces.begin();
00331     while (ft < faces.end()) {
00332         // get first item which adjacent element has the same face
00333         ft = std::adjacent_find(ft, faces.end(), pred);
00334         if (ft < faces.end()) {
00335             ft++;
00336             aInds.push_back(*ft - rFacets.begin());
00337         }
00338     }
00339 
00340     return aInds;
00341 #else
00342   std::vector<unsigned long> aInds;
00343   const MeshFacetArray& rFaces = _rclMesh.GetFacets();
00344   unsigned long uIndex=0;
00345 
00346   // get all facets
00347   std::set<FaceIterator, MeshFacet_Less > aFaceSet;
00348   for (MeshFacetArray::_TConstIterator it = rFaces.begin(); it != rFaces.end(); ++it, uIndex++)
00349   {
00350     std::pair<std::set<FaceIterator, MeshFacet_Less>::iterator, bool>
00351         pI = aFaceSet.insert(it);
00352     if (!pI.second)
00353       aInds.push_back(uIndex);
00354   }
00355 
00356   return aInds;
00357 #endif
00358 }
00359 
00360 bool MeshFixDuplicateFacets::Fixup()
00361 {
00362     unsigned long uIndex=0;
00363     std::vector<unsigned long> aRemoveFaces;
00364     const MeshFacetArray& rFaces = _rclMesh.GetFacets();
00365 
00366     // get all facets
00367     std::set<FaceIterator, MeshFacet_Less > aFaceSet;
00368     for (MeshFacetArray::_TConstIterator it = rFaces.begin(); it != rFaces.end(); ++it, uIndex++) {
00369         std::pair<std::set<FaceIterator, MeshFacet_Less>::iterator, bool>
00370         pI = aFaceSet.insert(it);
00371         if (!pI.second)
00372             aRemoveFaces.push_back(uIndex);
00373     }
00374 
00375     _rclMesh.DeleteFacets(aRemoveFaces);
00376     _rclMesh.RebuildNeighbours(); // needs to be done here
00377 
00378     return true;
00379 }
00380 
00381 // ----------------------------------------------------------------------
00382 
00383 bool MeshEvalDegeneratedFacets::Evaluate()
00384 {
00385   MeshFacetIterator it(_rclMesh);
00386   for ( it.Init(); it.More(); it.Next() )
00387   {
00388     if ( it->IsDegenerated() )
00389       return false;
00390   }
00391 
00392   return true;
00393 }
00394 
00395 unsigned long MeshEvalDegeneratedFacets::CountEdgeTooSmall (float fMinEdgeLength) const
00396 {
00397   MeshFacetIterator  clFIter(_rclMesh);   
00398   unsigned long k = 0;
00399 
00400   while (clFIter.EndReached() == false)
00401   {
00402     for ( int i = 0; i < 3; i++)
00403     {
00404       if (Base::Distance(clFIter->_aclPoints[i], clFIter->_aclPoints[(i+1)%3]) < fMinEdgeLength)
00405         k++;
00406     }
00407     ++clFIter;
00408   }
00409 
00410   return k;
00411 }
00412 
00413 std::vector<unsigned long> MeshEvalDegeneratedFacets::GetIndices() const
00414 {
00415   std::vector<unsigned long> aInds;
00416   MeshFacetIterator it(_rclMesh);
00417   for ( it.Init(); it.More(); it.Next() )
00418   {
00419     if ( it->IsDegenerated() )
00420       aInds.push_back(it.Position());
00421   }
00422 
00423   return aInds;
00424 }
00425 
00426 bool MeshFixDegeneratedFacets::Fixup()
00427 {
00428   MeshTopoAlgorithm cTopAlg(_rclMesh);
00429 
00430   MeshFacetIterator it(_rclMesh);
00431   for ( it.Init(); it.More(); it.Next() )
00432   {
00433     if ( it->IsDegenerated() )
00434     {
00435       unsigned long uCt = _rclMesh.CountFacets();
00436       unsigned long uId = it.Position();
00437       cTopAlg.RemoveDegeneratedFacet(uId);
00438       if ( uCt != _rclMesh.CountFacets() )
00439       {
00440         // due to a modification of the array the iterator became invalid
00441         it.Set(uId-1);
00442       }
00443     }
00444   }
00445 
00446   return true;
00447 }
00448 
00449 unsigned long MeshFixDegeneratedFacets::RemoveEdgeTooSmall (float fMinEdgeLength, float fMinEdgeAngle)
00450 {
00451     unsigned long ulCtLastLoop, ulCtFacets = _rclMesh.CountFacets();
00452 
00453     MeshFacetArray &rclFAry = _rclMesh._aclFacetArray;
00454     MeshPointArray &rclPAry = _rclMesh._aclPointArray;
00455     MeshFacetArray::_TConstIterator f_beg = rclFAry.begin();
00456 
00457     // repeat until no facet van be removed
00458     do {
00459         MeshRefPointToFacets  clPt2Facets(_rclMesh);
00460 
00461         rclFAry.ResetInvalid();
00462         rclPAry.ResetInvalid();
00463         rclPAry.ResetFlag(MeshPoint::VISIT);
00464 
00465         std::set<std::pair<unsigned long, unsigned long> > aclPtDelList;
00466 
00467         MeshFacetIterator clFIter(_rclMesh), clFN0(_rclMesh), clFN1(_rclMesh), clFN2(_rclMesh);
00468         for (clFIter.Init(); clFIter.More(); clFIter.Next()) {
00469             MeshGeomFacet clSFacet = *clFIter;
00470             Base::Vector3f clP0  = clSFacet._aclPoints[0];
00471             Base::Vector3f clP1  = clSFacet._aclPoints[1];
00472             Base::Vector3f clP2  = clSFacet._aclPoints[2];
00473             Base::Vector3f clE01 = clP1 - clP0;
00474             Base::Vector3f clE12 = clP2 - clP1;
00475             Base::Vector3f clE20 = clP2 - clP0;
00476             MeshFacet clFacet = clFIter.GetIndices();
00477             unsigned long    ulP0 = clFacet._aulPoints[0];
00478             unsigned long    ulP1 = clFacet._aulPoints[1];
00479             unsigned long    ulP2 = clFacet._aulPoints[2];
00480 
00481             if ((Base::Distance(clP0, clP1) < fMinEdgeLength) ||
00482                 (clE20.GetAngle(-clE12) < fMinEdgeAngle)) {
00483                 // delete point P1 on P0
00484                 aclPtDelList.insert(std::make_pair
00485                     (std::min<unsigned long>(ulP1, ulP0), std::max<unsigned long>(ulP1, ulP0)));
00486             }
00487             else if ((Base::Distance(clP1, clP2) < fMinEdgeLength) ||
00488                     (clE01.GetAngle(-clE20) < fMinEdgeAngle)) {
00489                 // delete point P2 on P1
00490                 aclPtDelList.insert(std::make_pair
00491                     (std::min<unsigned long>(ulP2, ulP1), std::max<unsigned long>(ulP2, ulP1)));
00492             }
00493             else if ((Base::Distance(clP2, clP0) < fMinEdgeLength) ||
00494                     (clE12.GetAngle(-clE01) < fMinEdgeAngle)) {
00495                 // delete point P0 on P2
00496                 aclPtDelList.insert(std::make_pair
00497                     (std::min<unsigned long>(ulP0, ulP2), std::max<unsigned long>(ulP0, ulP2)));
00498             }
00499         }
00500 
00501         // remove points, fix indices
00502         for (std::set<std::pair<unsigned long, unsigned long> >::iterator pI = aclPtDelList.begin();
00503             pI != aclPtDelList.end(); pI++) {
00504             // one of the point pairs is already processed
00505             if ((rclPAry[pI->first].IsFlag(MeshPoint::VISIT) == true) ||
00506                 (rclPAry[pI->second].IsFlag(MeshPoint::VISIT) == true))
00507                 continue;
00508 
00509             rclPAry[pI->first].SetFlag(MeshPoint::VISIT);
00510             rclPAry[pI->second].SetFlag(MeshPoint::VISIT);
00511             rclPAry[pI->second].SetInvalid();
00512 
00513             // Redirect all point-indices to the new neighbour point of all facets referencing the
00514             // deleted point
00515             const std::set<unsigned long>& faces = clPt2Facets[pI->second];
00516             for (std::set<unsigned long>::const_iterator pF = faces.begin(); pF != faces.end(); ++pF) {
00517                 const MeshFacet &rclF = f_beg[*pF];
00518 
00519                 for (int i = 0; i < 3; i++) {
00520 //                  if (rclF._aulPoints[i] == pI->second)
00521 //                      rclF._aulPoints[i] = pI->first;
00522                 }
00523 
00524                 // Delete facets with two identical corners
00525                 if ((rclF._aulPoints[0] == rclF._aulPoints[1]) ||
00526                     (rclF._aulPoints[0] == rclF._aulPoints[2]) ||
00527                     (rclF._aulPoints[1] == rclF._aulPoints[2])) {
00528                     rclF.SetInvalid();
00529                 }
00530             }
00531         }
00532 
00533         ulCtLastLoop = _rclMesh.CountFacets();
00534         _rclMesh.RemoveInvalids();
00535     }
00536     while (ulCtLastLoop > _rclMesh.CountFacets());
00537 
00538     _rclMesh.RebuildNeighbours();
00539 
00540     return ulCtFacets - _rclMesh.CountFacets();
00541 }
00542 
00543 // ----------------------------------------------------------------------
00544 
00545 bool MeshEvalDeformedFacets::Evaluate()
00546 {
00547   MeshFacetIterator it(_rclMesh);
00548   for ( it.Init(); it.More(); it.Next() )
00549   {
00550     if ( it->IsDeformed() )
00551       return false;
00552   }
00553 
00554   return true;
00555 }
00556 
00557 std::vector<unsigned long> MeshEvalDeformedFacets::GetIndices() const
00558 {
00559   std::vector<unsigned long> aInds;
00560   MeshFacetIterator it(_rclMesh);
00561   for ( it.Init(); it.More(); it.Next() )
00562   {
00563     if ( it->IsDeformed() )
00564       aInds.push_back(it.Position());
00565   }
00566 
00567   return aInds;
00568 }
00569 
00570 bool MeshFixDeformedFacets::Fixup()
00571 {
00572   Base::Vector3f u,v;
00573   MeshTopoAlgorithm cTopAlg(_rclMesh);
00574 
00575   MeshFacetIterator it(_rclMesh);
00576   for ( it.Init(); it.More(); it.Next() )
00577   {
00578     // possibly deformed but not degenerated
00579     if ( !it->IsDegenerated() )
00580     {
00581       // store the angles to avoid to compute twice
00582       float fCosAngles[3];
00583       bool done=false;
00584 
00585       // first check for angle > 120°: in this case we swap with the opposite edge
00586       for (int i=0; i<3; i++)
00587       {
00588         u = it->_aclPoints[(i+1)%3]-it->_aclPoints[i];
00589         v = it->_aclPoints[(i+2)%3]-it->_aclPoints[i];
00590         u.Normalize();
00591         v.Normalize();
00592 
00593         float fCosAngle = u * v;
00594         fCosAngles[i] = fCosAngle;
00595 
00596         if (fCosAngle < -0.5f) {
00597           const MeshFacet& face = it.GetReference();
00598           unsigned long uNeighbour = face._aulNeighbours[(i+1)%3];
00599           if (uNeighbour!=ULONG_MAX && cTopAlg.ShouldSwapEdge(it.Position(), uNeighbour, fMaxAngle)) {
00600             cTopAlg.SwapEdge(it.Position(), uNeighbour);
00601             done = true;
00602           }
00603           break;
00604         }
00605       }
00606 
00607       // we have swapped already
00608       if (done)
00609         continue;
00610 
00611       // now check for angle < 30°: in this case we swap with one of the edges the corner is part of
00612       for (int j=0; j<3; j++)
00613       {
00614         float fCosAngle = fCosAngles[j];
00615         if (fCosAngle > 0.86f) {
00616           const MeshFacet& face = it.GetReference();
00617 
00618           unsigned long uNeighbour = face._aulNeighbours[j];
00619           if (uNeighbour!=ULONG_MAX && cTopAlg.ShouldSwapEdge(it.Position(), uNeighbour, fMaxAngle)) {
00620             cTopAlg.SwapEdge(it.Position(), uNeighbour);
00621             break;
00622           }
00623           uNeighbour = face._aulNeighbours[(j+2)%3];
00624           if (uNeighbour!=ULONG_MAX && cTopAlg.ShouldSwapEdge(it.Position(), uNeighbour, fMaxAngle)) {
00625             cTopAlg.SwapEdge(it.Position(), uNeighbour);
00626             break;
00627           }
00628         }
00629       }
00630     }
00631   }
00632 
00633   return true;
00634 }
00635 
00636 // ----------------------------------------------------------------------
00637 
00638 bool MeshEvalFoldsOnSurface::Evaluate()
00639 {
00640     this->indices.clear();
00641     MeshRefPointToFacets  clPt2Facets(_rclMesh);
00642     const MeshPointArray& rPntAry = _rclMesh.GetPoints();
00643     MeshFacetArray::_TConstIterator f_beg = _rclMesh.GetFacets().begin();
00644 
00645     MeshGeomFacet rTriangle;
00646     Base::Vector3f tmp;
00647     unsigned long ctPoints = _rclMesh.CountPoints();
00648     for (unsigned long index=0; index < ctPoints; index++) {
00649         std::vector<unsigned long> point;
00650         point.push_back(index);
00651 
00652         // get the local neighbourhood of the point
00653         std::set<unsigned long> nb = clPt2Facets.NeighbourPoints(point,1);
00654         const std::set<unsigned long>& faces = clPt2Facets[index];
00655 
00656         for (std::set<unsigned long>::iterator pt = nb.begin(); pt != nb.end(); ++pt) {
00657             const MeshPoint& mp = rPntAry[*pt];
00658             for (std::set<unsigned long>::const_iterator
00659                 ft = faces.begin(); ft != faces.end(); ++ft) {
00660                     // the point must not be part of the facet we test
00661                     if (f_beg[*ft]._aulPoints[0] == *pt)
00662                         continue;
00663                     if (f_beg[*ft]._aulPoints[1] == *pt)
00664                         continue;
00665                     if (f_beg[*ft]._aulPoints[2] == *pt)
00666                         continue;
00667                     // is the point projectable onto the facet?
00668                     rTriangle = _rclMesh.GetFacet(f_beg[*ft]);
00669                     if (rTriangle.IntersectWithLine(mp,rTriangle.GetNormal(),tmp)) {
00670                         const std::set<unsigned long>& f = clPt2Facets[*pt];
00671                         this->indices.insert(this->indices.end(), f.begin(), f.end());
00672                         break;
00673                     }
00674             }
00675         }
00676     }
00677 
00678     // remove duplicates
00679     std::sort(this->indices.begin(), this->indices.end());
00680     this->indices.erase(std::unique(this->indices.begin(),
00681                         this->indices.end()), this->indices.end());
00682 
00683     return this->indices.empty();
00684 }
00685 
00686 std::vector<unsigned long> MeshEvalFoldsOnSurface::GetIndices() const
00687 {
00688     return this->indices;
00689 }
00690 
00691 bool MeshFixFoldsOnSurface::Fixup()
00692 {
00693     MeshEvalFoldsOnSurface eval(_rclMesh);
00694     if (!eval.Evaluate()) {
00695         std::vector<unsigned long> inds = eval.GetIndices();
00696         _rclMesh.DeleteFacets(inds);
00697     }
00698 
00699     return true;
00700 }
00701 
00702 // ----------------------------------------------------------------------
00703 
00704 bool MeshEvalFoldsOnBoundary::Evaluate()
00705 {
00706     // remove all boundary facets with two open edges and where
00707     // the angle to the neighbour is more than 60 degree
00708     this->indices.clear();
00709     const MeshFacetArray& rFacAry = _rclMesh.GetFacets();
00710     for (MeshFacetArray::_TConstIterator it = rFacAry.begin(); it != rFacAry.end(); ++it) {
00711         if (it->CountOpenEdges() == 2) {
00712             for (int i=0; i<3; i++) {
00713                 if (it->_aulNeighbours[i] != ULONG_MAX) {
00714                     MeshGeomFacet f1 = _rclMesh.GetFacet(*it);
00715                     MeshGeomFacet f2 = _rclMesh.GetFacet(it->_aulNeighbours[i]);
00716                     float cos_angle = f1.GetNormal() * f2.GetNormal();
00717                     if (cos_angle <= 0.5f) // ~ 60 degree
00718                         indices.push_back(it-rFacAry.begin());
00719                 }
00720             }
00721         }
00722     }
00723 
00724     return this->indices.empty();
00725 }
00726 
00727 std::vector<unsigned long> MeshEvalFoldsOnBoundary::GetIndices() const
00728 {
00729     return this->indices;
00730 }
00731 
00732 bool MeshFixFoldsOnBoundary::Fixup()
00733 {
00734     MeshEvalFoldsOnBoundary eval(_rclMesh);
00735     if (!eval.Evaluate()) {
00736         std::vector<unsigned long> inds = eval.GetIndices();
00737         _rclMesh.DeleteFacets(inds);
00738     }
00739 
00740     return true;
00741 }
00742 
00743 // ----------------------------------------------------------------------
00744 
00745 bool MeshEvalFoldOversOnSurface::Evaluate()
00746 {
00747     this->indices.clear();
00748     const MeshCore::MeshFacetArray& facets = _rclMesh.GetFacets();
00749     MeshCore::MeshFacetArray::_TConstIterator f_it,
00750         f_beg = facets.begin(), f_end = facets.end();
00751 
00752     Base::Vector3f n1, n2;
00753     for (f_it = facets.begin(); f_it != f_end; ++f_it) {
00754         for (int i=0; i<3; i++) {
00755             unsigned long index1 = f_it->_aulNeighbours[i];
00756             unsigned long index2 = f_it->_aulNeighbours[(i+1)%3];
00757             if (index1 != ULONG_MAX && index2 != ULONG_MAX) {
00758                 // if the topology is correct but the normals flip from
00759                 // two neighbours we have a fold
00760                 if (f_it->HasSameOrientation(f_beg[index1]) &&
00761                     f_it->HasSameOrientation(f_beg[index2])) {
00762                     n1 = _rclMesh.GetFacet(index1).GetNormal();
00763                     n2 = _rclMesh.GetFacet(index2).GetNormal();
00764                     if (n1 * n2 < -0.5f) { // angle > 120 deg
00765                         this->indices.push_back(f_it-f_beg);
00766                         break;
00767                     }
00768                 }
00769             }
00770         }
00771     }
00772 
00773     return this->indices.empty();
00774 }
00775 
00776 // ----------------------------------------------------------------
00777 
00778 bool MeshEvalBorderFacet::Evaluate()
00779 {
00780     const MeshCore::MeshFacetArray& facets = _rclMesh.GetFacets();
00781     MeshCore::MeshFacetArray::_TConstIterator f_it,
00782         f_beg = facets.begin(), f_end = facets.end();
00783     MeshCore::MeshRefPointToPoints vv_it(_rclMesh);
00784     MeshCore::MeshRefPointToFacets vf_it(_rclMesh);
00785 
00786     for (f_it = facets.begin(); f_it != f_end; ++f_it) {
00787         bool ok = true;
00788         for (int i=0; i<3; i++) {
00789             unsigned long index = f_it->_aulPoints[i];
00790             if (vv_it[index].size() == vf_it[index].size()) {
00791                 ok = false;
00792                 break;
00793             }
00794         }
00795 
00796         if (ok)
00797             _facets.push_back(f_it-f_beg);
00798     }
00799 
00800     return _facets.empty();
00801 }
00802 
00803 // ----------------------------------------------------------------------
00804 
00805 bool MeshEvalRangeFacet::Evaluate()
00806 {
00807   const MeshFacetArray& rFaces = _rclMesh.GetFacets();
00808   unsigned long ulCtFacets = rFaces.size();
00809 
00810   for ( MeshFacetArray::_TConstIterator it = rFaces.begin(); it != rFaces.end(); ++it ) {
00811     for ( int i = 0; i < 3; i++ ) {
00812       if ((it->_aulNeighbours[i] >= ulCtFacets) && (it->_aulNeighbours[i] < ULONG_MAX)) {
00813         return false;
00814       }
00815     }
00816   }
00817 
00818   return true;
00819 }
00820 
00821 std::vector<unsigned long> MeshEvalRangeFacet::GetIndices() const
00822 {
00823   std::vector<unsigned long> aInds;
00824   const MeshFacetArray& rFaces = _rclMesh.GetFacets();
00825   unsigned long ulCtFacets = rFaces.size();
00826 
00827   unsigned long ind=0;
00828   for ( MeshFacetArray::_TConstIterator it = rFaces.begin(); it != rFaces.end(); ++it, ind++ )
00829   {
00830     for ( int i = 0; i < 3; i++ ) {
00831       if ((it->_aulNeighbours[i] >= ulCtFacets) && (it->_aulNeighbours[i] < ULONG_MAX)) {
00832         aInds.push_back(ind);
00833         break;
00834       }
00835     }
00836   }
00837 
00838   return aInds;
00839 }
00840 
00841 bool MeshFixRangeFacet::Fixup()
00842 {
00843   return false;
00844 }
00845 
00846 // ----------------------------------------------------------------------
00847 
00848 bool MeshEvalRangePoint::Evaluate()
00849 {
00850   const MeshFacetArray& rFaces = _rclMesh.GetFacets();
00851   unsigned long ulCtPoints = _rclMesh.CountPoints();
00852 
00853   for ( MeshFacetArray::_TConstIterator it = rFaces.begin(); it != rFaces.end(); ++it ) {
00854     if (std::find_if(it->_aulPoints, it->_aulPoints + 3, std::bind2nd(std::greater_equal<unsigned long>(), ulCtPoints)) < it->_aulPoints + 3)
00855       return false;
00856   }
00857 
00858   return true;
00859 }
00860 
00861 std::vector<unsigned long> MeshEvalRangePoint::GetIndices() const
00862 {
00863   std::vector<unsigned long> aInds;
00864   const MeshFacetArray& rFaces = _rclMesh.GetFacets();
00865   unsigned long ulCtPoints = _rclMesh.CountPoints();
00866 
00867   unsigned long ind=0;
00868   for ( MeshFacetArray::_TConstIterator it = rFaces.begin(); it != rFaces.end(); ++it, ind++ )
00869   {
00870     if (std::find_if(it->_aulPoints, it->_aulPoints + 3, std::bind2nd(std::greater_equal<unsigned long>(), ulCtPoints)) < it->_aulPoints + 3)
00871       aInds.push_back(ind);
00872   }
00873 
00874   return aInds;
00875 }
00876 
00877 bool MeshFixRangePoint::Fixup()
00878 {
00879   return false;
00880 }
00881 
00882 // ----------------------------------------------------------------------
00883 
00884 bool MeshEvalCorruptedFacets::Evaluate()
00885 {
00886   const MeshFacetArray& rFaces = _rclMesh.GetFacets();
00887 
00888   for ( MeshFacetArray::_TConstIterator it = rFaces.begin(); it != rFaces.end(); ++it ) {
00889     // dupicated point indices
00890     if ((it->_aulPoints[0] == it->_aulPoints[1]) || 
00891         (it->_aulPoints[1] == it->_aulPoints[2]) || 
00892         (it->_aulPoints[2] == it->_aulPoints[0]))
00893       return false;
00894   }
00895 
00896   return true;
00897 }
00898 
00899 std::vector<unsigned long> MeshEvalCorruptedFacets::GetIndices() const
00900 {
00901   std::vector<unsigned long> aInds;
00902   const MeshFacetArray& rFaces = _rclMesh.GetFacets();
00903   unsigned long ind=0;
00904 
00905   for ( MeshFacetArray::_TConstIterator it = rFaces.begin(); it != rFaces.end(); ++it, ind++ ) {
00906     if ((it->_aulPoints[0] == it->_aulPoints[1]) || 
00907         (it->_aulPoints[1] == it->_aulPoints[2]) || 
00908         (it->_aulPoints[2] == it->_aulPoints[0]))
00909       aInds.push_back(ind);
00910   }
00911 
00912   return aInds;
00913 }
00914 
00915 bool MeshFixCorruptedFacets::Fixup()
00916 {
00917   MeshTopoAlgorithm cTopAlg(_rclMesh);
00918 
00919   MeshFacetIterator it(_rclMesh);
00920   for ( it.Init(); it.More(); it.Next() )
00921   {
00922     if ( it->Area() <= FLOAT_EPS )
00923     {
00924       unsigned long uId = it.Position();
00925       cTopAlg.RemoveCorruptedFacet(uId);
00926       // due to a modification of the array the iterator became invalid
00927       it.Set(uId-1);
00928     }
00929   }
00930 
00931   return true;
00932 }
00933 

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