MeshKernel.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 <stdexcept>
00029 # include <map>
00030 # include <queue>
00031 #endif
00032 
00033 #include <Base/Exception.h>
00034 #include <Base/Sequencer.h>
00035 #include <Base/Stream.h>
00036 #include <Base/Swap.h>
00037 
00038 #include "Algorithm.h"
00039 #include "Approximation.h"
00040 #include "Helpers.h"
00041 #include "MeshKernel.h"
00042 #include "Iterator.h"
00043 #include "Evaluation.h"
00044 #include "Builder.h"
00045 #include "Smoothing.h"
00046 
00047 using namespace MeshCore;
00048 
00049 MeshKernel::MeshKernel (void)
00050 : _bValid(true)
00051 {
00052     _clBoundBox.Flush();
00053 }
00054 
00055 MeshKernel::MeshKernel (const MeshKernel &rclMesh)
00056 {
00057     *this = rclMesh;
00058 }
00059 
00060 MeshKernel& MeshKernel::operator = (const MeshKernel &rclMesh)
00061 {
00062     if (this != &rclMesh) { // must be a different instance
00063         this->_aclPointArray  = rclMesh._aclPointArray;
00064         this->_aclFacetArray  = rclMesh._aclFacetArray;
00065         this->_clBoundBox     = rclMesh._clBoundBox;
00066         this->_bValid         = rclMesh._bValid;
00067     }
00068     return *this;
00069 }
00070 
00071 MeshKernel& MeshKernel::operator = (const std::vector<MeshGeomFacet> &rclFAry)
00072 {
00073     MeshBuilder builder(*this);
00074     builder.Initialize(rclFAry.size());
00075 
00076     for (std::vector<MeshGeomFacet>::const_iterator it = rclFAry.begin(); it != rclFAry.end(); it++)
00077         builder.AddFacet(*it);
00078 
00079     builder.Finish();
00080 
00081     return *this;
00082 }
00083 
00084 void MeshKernel::Assign(const MeshPointArray& rPoints, const MeshFacetArray& rFacets, bool checkNeighbourHood)
00085 {
00086     _aclPointArray = rPoints;
00087     _aclFacetArray = rFacets;
00088     RecalcBoundBox();
00089     if (checkNeighbourHood)
00090         RebuildNeighbours();
00091 }
00092 
00093 void MeshKernel::Adopt(MeshPointArray& rPoints, MeshFacetArray& rFacets, bool checkNeighbourHood)
00094 {
00095     _aclPointArray.swap(rPoints);
00096     _aclFacetArray.swap(rFacets);
00097     RecalcBoundBox();
00098     if (checkNeighbourHood)
00099         RebuildNeighbours();
00100 }
00101 
00102 void MeshKernel::Swap(MeshKernel& mesh)
00103 {
00104     this->_aclPointArray.swap(mesh._aclPointArray);
00105     this->_aclFacetArray.swap(mesh._aclFacetArray);
00106     this->_clBoundBox = mesh._clBoundBox;
00107 }
00108 
00109 MeshKernel& MeshKernel::operator += (const MeshGeomFacet &rclSFacet)
00110 {
00111     this->AddFacet(rclSFacet);
00112     return *this;
00113 }
00114 
00115 void MeshKernel::AddFacet(const MeshGeomFacet &rclSFacet)
00116 {
00117     unsigned long i;
00118     MeshFacet clFacet;
00119 
00120     // set corner points
00121     for (i = 0; i < 3; i++) {
00122         _clBoundBox &= rclSFacet._aclPoints[i];
00123         clFacet._aulPoints[i] = _aclPointArray.GetOrAddIndex(rclSFacet._aclPoints[i]);
00124     }
00125 
00126     // adjust orientation to normal
00127     AdjustNormal(clFacet, rclSFacet.GetNormal());
00128 
00129     unsigned long ulCt = _aclFacetArray.size();
00130 
00131     // set neighbourhood
00132     unsigned long ulP0 = clFacet._aulPoints[0];
00133     unsigned long ulP1 = clFacet._aulPoints[1];
00134     unsigned long ulP2 = clFacet._aulPoints[2];
00135     unsigned long ulCC = 0;
00136     for (TMeshFacetArray::iterator pF = _aclFacetArray.begin(); pF != _aclFacetArray.end(); pF++, ulCC++) {
00137         for (int i=0; i<3;i++) {
00138             unsigned long ulP = pF->_aulPoints[i];
00139             unsigned long ulQ = pF->_aulPoints[(i+1)%3];
00140             if (ulQ == ulP0 && ulP == ulP1) {
00141                 clFacet._aulNeighbours[0] = ulCC;
00142                 pF->_aulNeighbours[i] = ulCt;
00143             }
00144             else if (ulQ == ulP1 && ulP == ulP2) {
00145                 clFacet._aulNeighbours[1] = ulCC;
00146                 pF->_aulNeighbours[i] = ulCt;
00147             }
00148             else if (ulQ == ulP2 && ulP == ulP0) {
00149                 clFacet._aulNeighbours[2] = ulCC;
00150                 pF->_aulNeighbours[i] = ulCt;
00151             }
00152         }
00153     }
00154 
00155     // insert facet into array
00156     _aclFacetArray.push_back(clFacet);
00157 }
00158 
00159 MeshKernel& MeshKernel::operator += (const std::vector<MeshGeomFacet> &rclFAry)
00160 {
00161     this->AddFacets(rclFAry);
00162     return *this;
00163 }
00164 
00165 void MeshKernel::AddFacets(const std::vector<MeshGeomFacet> &rclFAry)
00166 {
00167     // Create a temp. kernel to get the topology of the passed triangles
00168     // and merge them with this kernel. This keeps properties and flags 
00169     // of this mesh.
00170     MeshKernel tmp;
00171     tmp = rclFAry;
00172     Merge(tmp);
00173 }
00174 
00175 unsigned long MeshKernel::AddFacets(const std::vector<MeshFacet> &rclFAry)
00176 {
00177     // Build map of edges of the referencing facets we want to append
00178 #ifdef FC_DEBUG
00179     unsigned long countPoints = CountPoints();
00180 #endif
00181     this->_aclPointArray.ResetInvalid();
00182     unsigned long k = CountFacets();
00183     std::map<std::pair<unsigned long, unsigned long>, std::list<unsigned long> > edgeMap;
00184     for (std::vector<MeshFacet>::const_iterator pF = rclFAry.begin(); pF != rclFAry.end(); pF++, k++) {
00185         // reset INVALID flag for all candidates
00186         pF->ResetFlag(MeshFacet::INVALID);
00187         for (int i=0; i<3; i++) {
00188 #ifdef FC_DEBUG
00189             assert( pF->_aulPoints[i] < countPoints );
00190 #endif
00191             this->_aclPointArray[pF->_aulPoints[i]].SetFlag(MeshPoint::INVALID);
00192             unsigned long ulT0 = pF->_aulPoints[i];
00193             unsigned long ulT1 = pF->_aulPoints[(i+1)%3];
00194             unsigned long ulP0 = std::min<unsigned long>(ulT0, ulT1);
00195             unsigned long ulP1 = std::max<unsigned long>(ulT0, ulT1);
00196             edgeMap[std::make_pair<unsigned long, unsigned long>(ulP0, ulP1)].push_front(k);
00197         }
00198     }
00199 
00200     // Check for the above edges in the current facet array
00201     k=0;
00202     for (MeshFacetArray::_TIterator pF = _aclFacetArray.begin(); pF != _aclFacetArray.end(); pF++, k++) {
00203         // if none of the points references one of the edges ignore the facet
00204         if (!this->_aclPointArray[pF->_aulPoints[0]].IsFlag(MeshPoint::INVALID) &&
00205             !this->_aclPointArray[pF->_aulPoints[1]].IsFlag(MeshPoint::INVALID) &&
00206             !this->_aclPointArray[pF->_aulPoints[2]].IsFlag(MeshPoint::INVALID))
00207             continue;
00208         for (int i=0; i<3; i++) {
00209             unsigned long ulT0 = pF->_aulPoints[i];
00210             unsigned long ulT1 = pF->_aulPoints[(i+1)%3];
00211             unsigned long ulP0 = std::min<unsigned long>(ulT0, ulT1);
00212             unsigned long ulP1 = std::max<unsigned long>(ulT0, ulT1);
00213             std::pair<unsigned long, unsigned long> edge = std::make_pair<unsigned long, unsigned long>(ulP0, ulP1);
00214             std::map<std::pair<unsigned long, unsigned long>, std::list<unsigned long> >::iterator pI = edgeMap.find(edge);
00215             // Does the current facet share the same edge?
00216             if (pI != edgeMap.end()) {
00217                 pI->second.push_front(k);
00218             }
00219         }
00220     }
00221 
00222     this->_aclPointArray.ResetInvalid();
00223 
00224     // Now let's see for which edges we might get manifolds, if so we don't add the corresponding candidates
00225     unsigned long countFacets = CountFacets();
00226     std::map<std::pair<unsigned long, unsigned long>, std::list<unsigned long> >::iterator pE;
00227     for (pE = edgeMap.begin(); pE != edgeMap.end(); ++pE)
00228     {
00229         if (pE->second.size() > 2)
00230         {
00231             for (std::list<unsigned long>::iterator it = pE->second.begin(); it != pE->second.end(); ++it)
00232             {
00233                 if (*it >= countFacets) {
00234                     // this is a candidate
00235                     unsigned long index = *it - countFacets;
00236                     rclFAry[index].SetFlag(MeshFacet::INVALID);
00237                 }
00238             }
00239         }
00240     }
00241 
00242     // Do not insert directly to the data structure because we should get the correct size of new
00243     // facets, otherwise std::vector reallocates too much memory which can't be freed so easily
00244     unsigned long countValid = std::count_if(rclFAry.begin(), rclFAry.end(),
00245         std::bind2nd(MeshIsNotFlag<MeshFacet>(), MeshFacet::INVALID));
00246     _aclFacetArray.reserve( _aclFacetArray.size() + countValid );
00247     // now start inserting the facets to the data structure and set the correct neighbourhood as well
00248     unsigned long startIndex = CountFacets();
00249     for (std::vector<MeshFacet>::const_iterator pF = rclFAry.begin(); pF != rclFAry.end(); pF++) {
00250         if (!pF->IsFlag(MeshFacet::INVALID)) {
00251             _aclFacetArray.push_back(*pF);
00252             pF->SetProperty(startIndex++);
00253         }
00254     }
00255 
00256     // resolve neighbours
00257     for (pE = edgeMap.begin(); pE != edgeMap.end(); pE++)
00258     {
00259         unsigned long ulP0 = pE->first.first;
00260         unsigned long ulP1 = pE->first.second;
00261         if (pE->second.size() == 1)  // border facet
00262         {
00263             unsigned long ulF0 = pE->second.front();
00264             if (ulF0 >= countFacets) {
00265                 ulF0 -= countFacets;
00266                 std::vector<MeshFacet>::const_iterator pF = rclFAry.begin() + ulF0;
00267                 if (!pF->IsFlag(MeshFacet::INVALID))
00268                     ulF0 = pF->_ulProp;
00269                 else
00270                     ulF0 = ULONG_MAX;
00271             }
00272 
00273             if (ulF0 != ULONG_MAX) {
00274                 unsigned short usSide =  _aclFacetArray[ulF0].Side(ulP0, ulP1);
00275                 assert(usSide != USHRT_MAX);
00276                 _aclFacetArray[ulF0]._aulNeighbours[usSide] = ULONG_MAX;
00277             }
00278         }
00279         else if (pE->second.size() == 2)  // normal facet with neighbour
00280         {
00281             // we must check if both facets are part of the mesh now 
00282             unsigned long ulF0 = pE->second.front();
00283             if (ulF0 >= countFacets) {
00284                 ulF0 -= countFacets;
00285                 std::vector<MeshFacet>::const_iterator pF = rclFAry.begin() + ulF0;
00286                 if (!pF->IsFlag(MeshFacet::INVALID))
00287                     ulF0 = pF->_ulProp;
00288                 else
00289                     ulF0 = ULONG_MAX;
00290             }
00291             unsigned long ulF1 = pE->second.back();
00292             if (ulF1 >= countFacets) {
00293                 ulF1 -= countFacets;
00294                 std::vector<MeshFacet>::const_iterator pF = rclFAry.begin() + ulF1;
00295                 if (!pF->IsFlag(MeshFacet::INVALID))
00296                     ulF1 = pF->_ulProp;
00297                 else
00298                     ulF1 = ULONG_MAX;
00299             }
00300             
00301             if (ulF0 != ULONG_MAX) {
00302                 unsigned short usSide = _aclFacetArray[ulF0].Side(ulP0, ulP1);
00303                 assert(usSide != USHRT_MAX);
00304                 _aclFacetArray[ulF0]._aulNeighbours[usSide] = ulF1;
00305             }
00306 
00307             if (ulF1 != ULONG_MAX) {
00308                 unsigned short usSide = _aclFacetArray[ulF1].Side(ulP0, ulP1);
00309                 assert(usSide != USHRT_MAX);
00310                 _aclFacetArray[ulF1]._aulNeighbours[usSide] = ulF0;
00311             }
00312         }
00313     }
00314 
00315     return _aclFacetArray.size();
00316 }
00317 
00318 unsigned long MeshKernel::AddFacets(const std::vector<MeshFacet> &rclFAry, const std::vector<Base::Vector3f>& rclPAry)
00319 {
00320     for (std::vector<Base::Vector3f>::const_iterator it = rclPAry.begin(); it != rclPAry.end(); ++it)
00321         _clBoundBox &= *it;
00322     this->_aclPointArray.insert(this->_aclPointArray.end(), rclPAry.begin(), rclPAry.end());
00323     return this->AddFacets(rclFAry);
00324 }
00325 
00326 void MeshKernel::Merge(const MeshKernel& rKernel)
00327 {
00328     if (this != &rKernel) {
00329         const MeshPointArray& rPoints = rKernel._aclPointArray;
00330         const MeshFacetArray& rFacets  = rKernel._aclFacetArray;
00331         Merge(rPoints, rFacets);
00332     }
00333 }
00334 
00335 void MeshKernel::Merge(const MeshPointArray& rPoints, const MeshFacetArray& rFaces)
00336 {
00337     if (rPoints.empty() || rFaces.empty())
00338         return; // nothing to do
00339     std::vector<unsigned long> increments(rPoints.size());
00340 
00341     unsigned long countFacets = this->_aclFacetArray.size();
00342     // Reserve the additional memory to append the new facets
00343     this->_aclFacetArray.reserve(this->_aclFacetArray.size() + rFaces.size());
00344 
00345     // Copy the new faces immediately to the facet array
00346     MeshFacet face;
00347     for(MeshFacetArray::_TConstIterator it = rFaces.begin(); it != rFaces.end(); ++it) {
00348         face = *it;
00349         for (int i=0; i<3; i++) {
00350             increments[it->_aulPoints[i]]++;
00351         }
00352 
00353         // append to the facet array
00354         this->_aclFacetArray.push_back(face);
00355     }
00356 
00357     unsigned long countNewPoints = std::count_if(increments.begin(), increments.end(),
00358                                    std::bind2nd(std::greater<unsigned long>(), 0));
00359     // Reserve the additional memory to append the new points
00360     unsigned long index = this->_aclPointArray.size();
00361     this->_aclPointArray.reserve(this->_aclPointArray.size() + countNewPoints);
00362     
00363     // Now we can start inserting the points and adjust the point indices of the faces
00364     for (std::vector<unsigned long>::iterator it = increments.begin(); it != increments.end(); ++it) {
00365         if (*it > 0) {
00366             // set the index of the point array
00367             *it = index++;
00368             const MeshPoint& rPt = rPoints[it-increments.begin()];
00369             this->_aclPointArray.push_back(rPt);
00370             _clBoundBox &= rPt;
00371         }
00372     }
00373 
00374     for (MeshFacetArray::_TIterator pF = this->_aclFacetArray.begin()+countFacets;
00375         pF != this->_aclFacetArray.end(); ++pF) {
00376         for (int i=0; i<3; i++) {
00377             pF->_aulPoints[i] = increments[pF->_aulPoints[i]];
00378         }
00379     }
00380 
00381     // Since rFaces could consist of a subset of the actual facet array the
00382     // neighbour indices could be totally wrong so they must be rebuilt from
00383     // scratch. Fortunately, this needs only to be done for the newly inserted
00384     // facets -- not for all
00385     RebuildNeighbours(countFacets);
00386 }
00387 
00388 void MeshKernel::Clear (void)
00389 {
00390     _aclPointArray.clear();
00391     _aclFacetArray.clear();
00392 
00393     // release memory
00394     MeshPointArray().swap(_aclPointArray);
00395     MeshFacetArray().swap(_aclFacetArray);
00396 
00397     _clBoundBox.Flush();
00398 }
00399 
00400 bool MeshKernel::DeleteFacet (const MeshFacetIterator &rclIter)
00401 {
00402     unsigned long i, j, ulNFacet, ulInd;
00403 
00404     if (rclIter._clIter >= _aclFacetArray.end())
00405         return false;
00406 
00407     // index of the facet to delete
00408     ulInd = rclIter._clIter - _aclFacetArray.begin(); 
00409 
00410     // invalidate neighbour indices of the neighbour facet to this facet
00411     for (i = 0; i < 3; i++) {
00412         ulNFacet = rclIter._clIter->_aulNeighbours[i];
00413         if (ulNFacet != ULONG_MAX) {
00414             for (j = 0; j < 3; j++) {
00415                 if (_aclFacetArray[ulNFacet]._aulNeighbours[j] == ulInd) {
00416                     _aclFacetArray[ulNFacet]._aulNeighbours[j] = ULONG_MAX;
00417                     break;
00418                 }
00419             }
00420         }
00421     }
00422 
00423     // erase corner point if needed
00424     for (i = 0; i < 3; i++) {
00425         if ((rclIter._clIter->_aulNeighbours[i] == ULONG_MAX) &&
00426             (rclIter._clIter->_aulNeighbours[(i+1)%3] == ULONG_MAX)) {
00427             // no neighbours, possibly delete point
00428             ErasePoint(rclIter._clIter->_aulPoints[(i+1)%3], ulInd);
00429         }
00430     }
00431 
00432     // remove facet from array
00433     _aclFacetArray.Erase(_aclFacetArray.begin() + rclIter.Position());
00434 
00435     return true;
00436 }
00437 
00438 bool MeshKernel::DeleteFacet (unsigned long ulInd)
00439 {
00440     if (ulInd >= _aclFacetArray.size())
00441         return false;
00442 
00443     MeshFacetIterator clIter(*this);
00444     clIter.Set(ulInd);
00445 
00446     return DeleteFacet(clIter);
00447 }
00448 
00449 void MeshKernel::DeleteFacets (const std::vector<unsigned long> &raulFacets)
00450 {
00451     _aclPointArray.SetProperty(0);
00452 
00453     // number of referencing facets per point
00454     for (MeshFacetArray::_TConstIterator pF = _aclFacetArray.begin(); pF != _aclFacetArray.end(); pF++) {
00455         _aclPointArray[pF->_aulPoints[0]]._ulProp++;
00456         _aclPointArray[pF->_aulPoints[1]]._ulProp++;
00457         _aclPointArray[pF->_aulPoints[2]]._ulProp++;
00458     }
00459 
00460     // invalidate facet and adjust number of point references
00461     _aclFacetArray.ResetInvalid();
00462     for (std::vector<unsigned long>::const_iterator pI = raulFacets.begin(); pI != raulFacets.end(); pI++) {
00463         MeshFacet &rclFacet = _aclFacetArray[*pI];
00464         rclFacet.SetInvalid();
00465         _aclPointArray[rclFacet._aulPoints[0]]._ulProp--;
00466         _aclPointArray[rclFacet._aulPoints[1]]._ulProp--;
00467         _aclPointArray[rclFacet._aulPoints[2]]._ulProp--;
00468     }
00469 
00470     // invalidate all unreferenced points
00471     _aclPointArray.ResetInvalid();
00472     for (MeshPointArray::_TIterator pP = _aclPointArray.begin(); pP != _aclPointArray.end(); pP++) {
00473         if (pP->_ulProp == 0)
00474             pP->SetInvalid();
00475     }
00476 
00477     RemoveInvalids();
00478     RecalcBoundBox();
00479 }
00480 
00481 bool MeshKernel::DeletePoint (unsigned long ulInd)
00482 {
00483     if (ulInd >= _aclPointArray.size())
00484         return false;
00485 
00486     MeshPointIterator clIter(*this);
00487     clIter.Set(ulInd);
00488 
00489     return DeletePoint(clIter);
00490 }
00491 
00492 bool MeshKernel::DeletePoint (const MeshPointIterator &rclIter)
00493 {
00494     MeshFacetIterator pFIter(*this), pFEnd(*this);
00495     std::vector<MeshFacetIterator>  clToDel; 
00496     unsigned long i, ulInd;
00497 
00498     // index of the point to delete
00499     ulInd = rclIter._clIter - _aclPointArray.begin(); 
00500  
00501     pFIter.Begin();
00502     pFEnd.End();
00503 
00504     // check corner points of all facets
00505     while (pFIter < pFEnd) {
00506         for (i = 0; i < 3; i++) {
00507             if (ulInd == pFIter._clIter->_aulPoints[i])
00508                 clToDel.push_back(pFIter);
00509         }
00510         ++pFIter;
00511     }
00512 
00513     // iterators (facets) sort by index
00514     std::sort(clToDel.begin(), clToDel.end());
00515 
00516     // delete each facet separately (from back to front to avoid to
00517     // invalidate the iterators)
00518     for (i = clToDel.size(); i > 0; i--)
00519         DeleteFacet(clToDel[i-1]); 
00520     return true;
00521 }
00522 
00523 void MeshKernel::DeletePoints (const std::vector<unsigned long> &raulPoints)
00524 {
00525     _aclPointArray.ResetInvalid();
00526     for (std::vector<unsigned long>::const_iterator pI = raulPoints.begin(); pI != raulPoints.end(); pI++)
00527         _aclPointArray[*pI].SetInvalid();
00528 
00529     // delete facets if at least one corner point is invalid
00530     _aclPointArray.SetProperty(0);
00531     for (MeshFacetArray::_TIterator pF = _aclFacetArray.begin(); pF != _aclFacetArray.end(); pF++) {
00532         MeshPoint &rclP0 = _aclPointArray[pF->_aulPoints[0]];
00533         MeshPoint &rclP1 = _aclPointArray[pF->_aulPoints[1]];
00534         MeshPoint &rclP2 = _aclPointArray[pF->_aulPoints[2]];
00535 
00536         if ((rclP0.IsValid() == false) || (rclP1.IsValid() == false) || (rclP2.IsValid() == false)) {
00537             pF->SetInvalid();
00538         }
00539         else {
00540             pF->ResetInvalid();
00541             rclP0._ulProp++;
00542             rclP1._ulProp++;
00543             rclP2._ulProp++;
00544         }
00545     }
00546 
00547     // invalidate all unreferenced points to delete them
00548     for (MeshPointArray::_TIterator pP = _aclPointArray.begin(); pP != _aclPointArray.end(); pP++) {
00549         if (pP->_ulProp == 0)
00550             pP->SetInvalid();
00551     }
00552 
00553     RemoveInvalids();
00554     RecalcBoundBox();
00555 }
00556 
00557 void MeshKernel::ErasePoint (unsigned long ulIndex, unsigned long ulFacetIndex, bool bOnlySetInvalid)
00558 {
00559     unsigned long  i;
00560     std::vector<MeshFacet>::iterator pFIter, pFEnd, pFNot;
00561 
00562     pFIter = _aclFacetArray.begin();
00563     pFNot  = _aclFacetArray.begin() + ulFacetIndex;
00564     pFEnd  = _aclFacetArray.end();
00565  
00566     // check all facets
00567     while (pFIter < pFNot) {
00568         for (i = 0; i < 3; i++) {
00569             if (pFIter->_aulPoints[i] == ulIndex)
00570                 return; // point still referenced ==> do not delete
00571         }
00572         pFIter++;
00573     }
00574 
00575     pFIter++;
00576     while (pFIter < pFEnd) {
00577         for (i = 0; i < 3; i++) {
00578             if (pFIter->_aulPoints[i] == ulIndex)
00579                 return; // point still referenced ==> do not delete
00580         }
00581         pFIter++;
00582     }
00583 
00584 
00585     if (bOnlySetInvalid == false) {
00586         // completely remove point
00587         _aclPointArray.erase(_aclPointArray.begin() + ulIndex);
00588 
00589         // correct point indices of the facets
00590         pFIter = _aclFacetArray.begin();
00591         while (pFIter < pFEnd) {
00592             for (i = 0; i < 3; i++) {
00593                 if (pFIter->_aulPoints[i] > ulIndex)
00594                     pFIter->_aulPoints[i]--;
00595             }
00596             pFIter++;
00597         }
00598     }
00599     else // only invalidate
00600         _aclPointArray[ulIndex].SetInvalid();
00601 }
00602 
00603 void MeshKernel::RemoveInvalids ()
00604 {
00605     std::vector<unsigned long> aulDecrements;
00606     std::vector<unsigned long>::iterator pDIter;
00607     unsigned long ulDec, i, k;
00608     MeshPointArray::_TIterator pPIter, pPEnd;
00609     MeshFacetArray::_TIterator pFIter, pFEnd;
00610 
00611     // generate array of decrements
00612     aulDecrements.resize(_aclPointArray.size());
00613     pDIter = aulDecrements.begin();
00614     ulDec  = 0;
00615     pPEnd  = _aclPointArray.end();
00616     for (pPIter = _aclPointArray.begin(); pPIter != pPEnd; pPIter++) {
00617         *pDIter++ = ulDec;
00618         if (pPIter->IsValid() == false)
00619             ulDec++;
00620     }
00621 
00622     // correct point indices of the facets
00623     pFEnd  = _aclFacetArray.end();
00624     for (pFIter = _aclFacetArray.begin(); pFIter != pFEnd; pFIter++) {
00625         if (pFIter->IsValid() == true) {
00626             pFIter->_aulPoints[0] -= aulDecrements[pFIter->_aulPoints[0]];
00627             pFIter->_aulPoints[1] -= aulDecrements[pFIter->_aulPoints[1]];
00628             pFIter->_aulPoints[2] -= aulDecrements[pFIter->_aulPoints[2]];
00629         }
00630     }
00631 
00632     // delete point, number of valid points
00633     unsigned long ulNewPts = std::count_if(_aclPointArray.begin(), _aclPointArray.end(),
00634         std::mem_fun_ref(&MeshPoint::IsValid));
00635     // tmp. point array
00636     MeshPointArray  aclTempPt(ulNewPts);
00637     MeshPointArray::_TIterator pPTemp = aclTempPt.begin();
00638     pPEnd = _aclPointArray.end();
00639     for (pPIter = _aclPointArray.begin(); pPIter != pPEnd; pPIter++) {
00640         if (pPIter->IsValid() == true)
00641             *pPTemp++ = *pPIter;
00642     }
00643 
00644     // free memory
00645     //_aclPointArray = aclTempPt;
00646     //aclTempPt.clear();
00647     _aclPointArray.swap(aclTempPt);
00648     MeshPointArray().swap(aclTempPt);
00649 
00650     // generate array of facet decrements
00651     aulDecrements.resize(_aclFacetArray.size());
00652     pDIter = aulDecrements.begin();
00653     ulDec  = 0;
00654     pFEnd  = _aclFacetArray.end();
00655     for (pFIter = _aclFacetArray.begin(); pFIter != pFEnd; pFIter++, pDIter++) {
00656         *pDIter = ulDec;
00657         if (pFIter->IsValid() == false)
00658             ulDec++;
00659     }
00660 
00661     // correct neighbour indices of the facets
00662     pFEnd = _aclFacetArray.end();
00663     for (pFIter = _aclFacetArray.begin(); pFIter != pFEnd; pFIter++) {
00664         if (pFIter->IsValid() == true) {
00665             for (i = 0; i < 3; i++) {
00666                 k = pFIter->_aulNeighbours[i];
00667                 if (k != ULONG_MAX) {
00668                     if (_aclFacetArray[k].IsValid() == true)
00669                         pFIter->_aulNeighbours[i] -= aulDecrements[k];
00670                     else
00671                         pFIter->_aulNeighbours[i] = ULONG_MAX;
00672                 }
00673             }
00674         }
00675     }
00676 
00677     // delete facets, number of valid facets
00678     unsigned long ulDelFacets = std::count_if(_aclFacetArray.begin(), _aclFacetArray.end(),
00679         std::mem_fun_ref(&MeshFacet::IsValid));
00680     MeshFacetArray aclFArray(ulDelFacets);
00681     MeshFacetArray::_TIterator pFTemp = aclFArray.begin();  
00682     pFEnd  = _aclFacetArray.end();
00683     for (pFIter = _aclFacetArray.begin(); pFIter != pFEnd; pFIter++) {
00684         if (pFIter->IsValid() == true)
00685             *pFTemp++ = *pFIter;
00686     }
00687 
00688     // free memory
00689     //_aclFacetArray = aclFArray;
00690     _aclFacetArray.swap(aclFArray);
00691 }
00692 
00693 void MeshKernel::CutFacets(const MeshFacetGrid& rclGrid, const Base::ViewProjMethod* pclProj, 
00694                            const Base::Polygon2D& rclPoly, bool bCutInner, std::vector<MeshGeomFacet> &raclFacets) 
00695 {
00696     std::vector<unsigned long> aulFacets;
00697 
00698     MeshAlgorithm(*this).CheckFacets(rclGrid, pclProj, rclPoly, bCutInner, aulFacets );
00699 
00700     for (std::vector<unsigned long>::iterator i = aulFacets.begin(); i != aulFacets.end(); i++)
00701         raclFacets.push_back(GetFacet(*i));
00702 
00703     DeleteFacets(aulFacets);
00704 }
00705 
00706 void MeshKernel::CutFacets(const MeshFacetGrid& rclGrid, const Base::ViewProjMethod* pclProj,
00707                            const Base::Polygon2D& rclPoly, bool bInner, std::vector<unsigned long> &raclCutted)
00708 {
00709     MeshAlgorithm(*this).CheckFacets(rclGrid, pclProj, rclPoly, bInner, raclCutted);
00710     DeleteFacets(raclCutted);
00711 }
00712 
00713 std::vector<unsigned long> MeshKernel::GetFacetPoints(const std::vector<unsigned long>& facets) const
00714 {
00715     std::vector<unsigned long> points;
00716     for (std::vector<unsigned long>::const_iterator it = facets.begin(); it != facets.end(); ++it) {
00717         unsigned long p0, p1, p2;
00718         GetFacetPoints(*it, p0, p1, p2);
00719         points.push_back(p0);
00720         points.push_back(p1);
00721         points.push_back(p2);
00722   }
00723 
00724     std::sort(points.begin(), points.end());
00725     points.erase(std::unique(points.begin(), points.end()), points.end());
00726     return points;
00727 }
00728 
00729 std::vector<unsigned long> MeshKernel::HasFacets (const MeshPointIterator &rclIter) const
00730 {
00731     unsigned long i, ulPtInd = rclIter.Position();
00732     std::vector<MeshFacet>::const_iterator  pFIter = _aclFacetArray.begin();
00733     std::vector<MeshFacet>::const_iterator  pFBegin = _aclFacetArray.begin();
00734     std::vector<MeshFacet>::const_iterator  pFEnd = _aclFacetArray.end();
00735     std::vector<unsigned long> aulBelongs;
00736 
00737       while (pFIter < pFEnd) {
00738         for (i = 0; i < 3; i++) {
00739             if (pFIter->_aulPoints[i] == ulPtInd) {
00740                 aulBelongs.push_back(pFIter - pFBegin);
00741                 break;
00742             }
00743         }
00744         pFIter++;
00745     }
00746 
00747     return aulBelongs;
00748 }
00749 
00750 MeshFacetArray MeshKernel::GetFacets(const std::vector<unsigned long>& indices) const
00751 {
00752     MeshFacetArray ary;
00753     ary.reserve(indices.size());
00754     for (std::vector<unsigned long>::const_iterator it = indices.begin(); it != indices.end(); ++it)
00755         ary.push_back(this->_aclFacetArray[*it]);
00756     return ary;
00757 }
00758 
00759 void MeshKernel::Write (std::ostream &rclOut) const 
00760 {
00761     if (!rclOut || rclOut.bad())
00762         return;
00763 
00764     Base::OutputStream str(rclOut);
00765 
00766     // Write a header with a "magic number" and a version
00767     str << (uint32_t)0xA0B0C0D0;
00768     str << (uint32_t)0x010000;
00769 
00770     char szInfo[257]; // needs an additional byte for zero-termination
00771     strcpy(szInfo, "MESH-MESH-MESH-MESH-MESH-MESH-MESH-MESH-MESH-MESH-MESH-MESH-MESH-MESH-MESH-MESH-"
00772                    "MESH-MESH-MESH-MESH-MESH-MESH-MESH-MESH-MESH-MESH-MESH-MESH-MESH-MESH-MESH-MESH-"
00773                    "MESH-MESH-MESH-MESH-MESH-MESH-MESH-MESH-MESH-MESH-MESH-MESH-MESH-MESH-MESH-MESH-"
00774                    "MESH-MESH-MESH-\n");
00775     rclOut.write(szInfo, 256);
00776 
00777     // write the number of points and facets
00778     str << (uint32_t)CountPoints() << (uint32_t)CountFacets();
00779 
00780     // write the data
00781     for (MeshPointArray::_TConstIterator it = _aclPointArray.begin(); it != _aclPointArray.end(); ++it) {
00782         str << it->x << it->y << it->z;
00783     }
00784 
00785     for (MeshFacetArray::_TConstIterator it = _aclFacetArray.begin(); it != _aclFacetArray.end(); ++it) {
00786         str << (uint32_t)it->_aulPoints[0] 
00787             << (uint32_t)it->_aulPoints[1] 
00788             << (uint32_t)it->_aulPoints[2];
00789         str << (uint32_t)it->_aulNeighbours[0] 
00790             << (uint32_t)it->_aulNeighbours[1] 
00791             << (uint32_t)it->_aulNeighbours[2];
00792     }
00793 
00794     str << _clBoundBox.MinX << _clBoundBox.MaxX;
00795     str << _clBoundBox.MinY << _clBoundBox.MaxY;
00796     str << _clBoundBox.MinZ << _clBoundBox.MaxZ;
00797 }
00798 
00799 void MeshKernel::Read (std::istream &rclIn)
00800 {
00801     if (!rclIn || rclIn.bad())
00802         return;
00803 
00804     // get header
00805     Base::InputStream str(rclIn);
00806 
00807     // Read the header with a "magic number" and a version
00808     uint32_t magic, version, swap_magic, swap_version;
00809     str >> magic >> version;
00810     swap_magic = magic; Base::SwapEndian(swap_magic);
00811     swap_version = version; Base::SwapEndian(swap_version);
00812 
00813     // is it the new or old format?
00814     bool new_format = false;
00815     if (magic == 0xA0B0C0D0 && version == 0x010000) {
00816         new_format = true;
00817     }
00818     else if (swap_magic == 0xA0B0C0D0 && swap_version == 0x010000) {
00819         new_format = true;
00820         str.setByteOrder(Base::Stream::BigEndian);
00821     }
00822 
00823     if (new_format) {
00824         char szInfo[256];
00825         rclIn.read(szInfo, 256);
00826 
00827         // read the number of points and facets
00828         uint32_t uCtPts=0, uCtFts=0;
00829         str >> uCtPts >> uCtFts;
00830 
00831         try {
00832             // read the data
00833             MeshPointArray pointArray;
00834             pointArray.resize(uCtPts);
00835             for (MeshPointArray::_TIterator it = pointArray.begin(); it != pointArray.end(); ++it) {
00836                 str >> it->x >> it->y >> it->z;
00837             }
00838           
00839             MeshFacetArray facetArray;
00840             facetArray.resize(uCtFts);
00841 
00842             uint32_t v1, v2, v3;
00843             for (MeshFacetArray::_TIterator it = facetArray.begin(); it != facetArray.end(); ++it) {
00844                 str >> v1 >> v2 >> v3;
00845                 it->_aulPoints[0] = v1;
00846                 it->_aulPoints[1] = v2;
00847                 it->_aulPoints[2] = v3;
00848 
00849                 str >> v1 >> v2 >> v3;
00850                 it->_aulNeighbours[0] = v1;
00851                 it->_aulNeighbours[1] = v2;
00852                 it->_aulNeighbours[2] = v3;
00853             }
00854 
00855             str >> _clBoundBox.MinX >> _clBoundBox.MaxX;
00856             str >> _clBoundBox.MinY >> _clBoundBox.MaxY;
00857             str >> _clBoundBox.MinZ >> _clBoundBox.MaxZ;
00858 
00859             // If we reach this block no exception occurred and we can safely assign the mesh
00860             _aclPointArray.swap(pointArray);
00861             _aclFacetArray.swap(facetArray);
00862         }
00863         catch (std::exception&) {
00864             // Special handling of std::length_error
00865             throw Base::Exception("Reading from stream failed");
00866         }
00867     }
00868     else {
00869         // The old format
00870         unsigned long uCtPts=magic, uCtFts=version;
00871 
00872         // the stored mesh kernel might be empty
00873         if ( uCtPts > 0 ) {
00874           _aclPointArray.resize(uCtPts);
00875           rclIn.read((char*)&(_aclPointArray[0]), uCtPts*sizeof(MeshPoint));
00876         }
00877         if ( uCtFts > 0 ) {
00878           _aclFacetArray.resize(uCtFts);
00879           rclIn.read((char*)&(_aclFacetArray[0]), uCtFts*sizeof(MeshFacet));
00880         }
00881         rclIn.read((char*)&_clBoundBox, sizeof(Base::BoundBox3f));
00882     }
00883 }
00884 
00885 void MeshKernel::operator *= (const Base::Matrix4D &rclMat)
00886 {
00887     this->Transform(rclMat);
00888 }
00889 
00890 void MeshKernel::Transform (const Base::Matrix4D &rclMat)
00891 {
00892     MeshPointArray::_TIterator  clPIter = _aclPointArray.begin(), clPEIter = _aclPointArray.end();
00893     Base::Matrix4D clMatrix(rclMat);
00894 
00895     _clBoundBox.Flush();
00896     while (clPIter < clPEIter) {
00897         *clPIter *= clMatrix;
00898         _clBoundBox &= *clPIter;
00899         clPIter++;
00900     }
00901 }
00902 
00903 void MeshKernel::Smooth(int iterations, float stepsize)
00904 {
00905     LaplaceSmoothing(*this).Smooth(iterations);
00906 }
00907 
00908 void MeshKernel::RecalcBoundBox (void)
00909 {
00910     _clBoundBox.Flush();
00911     for (MeshPointArray::_TConstIterator pI = _aclPointArray.begin(); pI != _aclPointArray.end(); pI++)
00912         _clBoundBox &= *pI;
00913 }
00914 
00915 std::vector<Base::Vector3f> MeshKernel::CalcVertexNormals() const
00916 {
00917     std::vector<Base::Vector3f> normals;
00918 
00919     normals.resize(CountPoints());
00920 
00921     unsigned long p1,p2,p3;
00922     unsigned int ct = CountFacets();
00923     for (unsigned int pFIter = 0;pFIter < ct; pFIter++) {
00924         GetFacetPoints(pFIter,p1,p2,p3);
00925         Base::Vector3f Norm = (GetPoint(p2)-GetPoint(p1)) % (GetPoint(p3)-GetPoint(p1));
00926 
00927         normals[p1] += Norm;
00928         normals[p2] += Norm;
00929         normals[p3] += Norm;
00930     }
00931 
00932     return normals;
00933 }
00934 
00935 // Evaluation
00936 float MeshKernel::GetSurface() const
00937 {
00938     float fSurface = 0.0;
00939     MeshFacetIterator cIter(*this);
00940     for (cIter.Init(); cIter.More(); cIter.Next())
00941         fSurface += cIter->Area();
00942 
00943     return fSurface;
00944 }
00945 
00946 float MeshKernel::GetSurface( const std::vector<unsigned long>& aSegment ) const
00947 {
00948     float fSurface = 0.0;
00949     MeshFacetIterator cIter(*this);
00950 
00951     for (std::vector<unsigned long>::const_iterator it = aSegment.begin(); it != aSegment.end(); ++it) {
00952         cIter.Set(*it);
00953         fSurface += cIter->Area();
00954     }
00955 
00956     return fSurface;
00957 }
00958 
00959 float MeshKernel::GetVolume() const
00960 {
00961     MeshEvalSolid cSolid(*this);
00962     if ( !cSolid.Evaluate() )
00963         return 0.0f; // no solid
00964 
00965     float fVolume = 0.0;
00966     MeshFacetIterator cIter(*this);
00967     Base::Vector3f p1,p2,p3;
00968     for (cIter.Init(); cIter.More(); cIter.Next()) {
00969         const MeshGeomFacet& rclF = *cIter;
00970         p1 = rclF._aclPoints[0];
00971         p2 = rclF._aclPoints[1];
00972         p3 = rclF._aclPoints[2];
00973 
00974         fVolume += (-p3.x*p2.y*p1.z + p2.x*p3.y*p1.z + p3.x*p1.y*p2.z - p1.x*p3.y*p2.z - p2.x*p1.y*p3.z + p1.x*p2.y*p3.z);
00975     }
00976 
00977     fVolume /= 6.0;
00978     fVolume = (float)fabs(fVolume);
00979 
00980     return fVolume;
00981 }
00982 
00983 bool MeshKernel::HasOpenEdges() const
00984 {
00985     MeshEvalSolid eval(*this);
00986     return !eval.Evaluate();
00987 }
00988 
00989 bool MeshKernel::HasNonManifolds() const
00990 {
00991     MeshEvalTopology eval(*this);
00992     return !eval.Evaluate();
00993 }
00994 
00995 bool MeshKernel::HasSelfIntersections() const
00996 {
00997     MeshEvalSelfIntersection eval(*this);
00998     return !eval.Evaluate();
00999 }
01000 
01001 // Iterators
01002 MeshFacetIterator MeshKernel::FacetIterator() const
01003 {
01004     MeshFacetIterator it(*this);
01005     it.Begin(); return it;
01006 }
01007 
01008 MeshPointIterator MeshKernel::PointIterator() const
01009 {
01010     MeshPointIterator it(*this);
01011     it.Begin(); return it;
01012 }
01013 
01014 void MeshKernel::GetEdges (std::vector<MeshGeomEdge>& edges) const
01015 {
01016     std::set<MeshBuilder::Edge> tmp;
01017 
01018     for (MeshFacetArray::_TConstIterator it = _aclFacetArray.begin(); it != _aclFacetArray.end(); it++) {
01019         for (int i = 0; i < 3; i++) {
01020             tmp.insert(MeshBuilder::Edge(it->_aulPoints[i], it->_aulPoints[(i+1)%3], it->_aulNeighbours[i]));
01021         }
01022     }
01023 
01024     edges.reserve(tmp.size());
01025     for (std::set<MeshBuilder::Edge>::iterator it2 = tmp.begin(); it2 != tmp.end(); it2++) {
01026         MeshGeomEdge edge;
01027         edge._aclPoints[0] = this->_aclPointArray[it2->pt1];
01028         edge._aclPoints[1] = this->_aclPointArray[it2->pt2];
01029         edge._bBorder = it2->facetIdx == ULONG_MAX;
01030 
01031         edges.push_back(edge);
01032     }
01033 }
01034 
01035 unsigned long MeshKernel::CountEdges (void) const
01036 {
01037     unsigned long openEdges = 0, closedEdges = 0;
01038 
01039     for (MeshFacetArray::_TConstIterator it = _aclFacetArray.begin(); it != _aclFacetArray.end(); it++) {
01040         for (int i = 0; i < 3; i++) {
01041             if (it->_aulNeighbours[i] == ULONG_MAX)
01042                 openEdges++;
01043             else
01044                 closedEdges++;
01045         }
01046     }
01047 
01048     return (openEdges + (closedEdges / 2));
01049 }
01050 

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