Builder.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 #endif
00029 
00030 #include <Base/Sequencer.h>
00031 #include <Base/Exception.h>
00032 
00033 #include "Builder.h"
00034 #include "MeshKernel.h"
00035 
00036 using namespace MeshCore;
00037 
00038 
00039 MeshBuilder::MeshBuilder (MeshKernel& kernel) : _meshKernel(kernel), _seq(0)
00040 {
00041     _fSaveTolerance = MeshDefinitions::_fMinPointDistanceD1;
00042 }
00043 
00044 MeshBuilder::~MeshBuilder (void)
00045 {
00046     MeshDefinitions::_fMinPointDistanceD1 = _fSaveTolerance;
00047     delete this->_seq;
00048 }
00049 
00050 void MeshBuilder::SetTolerance(float fTol)
00051 {
00052     MeshDefinitions::_fMinPointDistanceD1 = fTol;
00053 }
00054 
00055 void MeshBuilder::Initialize (unsigned long ctFacets, bool deletion)
00056 {
00057     if (deletion)
00058     {
00059         // Clear the mesh structure and free all memory
00060         _meshKernel.Clear();
00061     
00062         // Allocate new memory that is needed later on. If AddFacet() gets called exactly ctFacets times there is no wastage of memory
00063         // otherwise the vector reallocates ~50% of its future memory usage.
00064         // Note: A feature of the std::vector implementation is that it can hold more memory (capacity) than it actually needs (size).
00065         //       This usually happens if its elements are added without specifying its final size. Later on it's a bit tricky to free the wasted 
00066         //       memory. So we're strived to avoid the wastage of memory.
00067         _meshKernel._aclFacetArray.reserve(ctFacets);
00068 
00069         // Usually the number of vertices is the half of the number of facets. So we reserve this memory with 10% surcharge
00070         // To save memory we hold an array with iterators that point to the right vertex (insertion order) in the set, instead of
00071         // holding the vertex array twice.
00072         unsigned long ctPoints = ctFacets / 2;
00073         _pointsIterator.reserve((unsigned long)(float(ctPoints)*1.10f));
00074         _ptIdx = 0;
00075     }
00076     else
00077     {
00078         for (MeshPointArray::_TConstIterator it1 = _meshKernel._aclPointArray.begin(); it1 != _meshKernel._aclPointArray.end(); it1++)
00079         {
00080             MeshPointIterator pit = _points.insert(*it1);                       
00081             _pointsIterator.push_back(pit);
00082         }
00083         _ptIdx = _points.size();
00084 
00085         // As we have a copy of our vertices in the set we must clear them from our array now  But we can keep its
00086         // memory as we reuse it later on anyway.
00087         _meshKernel._aclPointArray.clear();
00088         // additional memory
00089         unsigned long newCtFacets = _meshKernel._aclFacetArray.size()+ctFacets;
00090         _meshKernel._aclFacetArray.reserve(newCtFacets);
00091         unsigned long ctPoints = newCtFacets / 2;
00092         _pointsIterator.reserve((unsigned long)(float(ctPoints)*1.10f));
00093     }
00094 
00095     this->_seq = new Base::SequencerLauncher("create mesh structure...", ctFacets * 2);
00096 }
00097 
00098 void MeshBuilder::AddFacet (const MeshGeomFacet& facet, bool takeFlag, bool takeProperty)
00099 {
00100     unsigned char flag = 0;
00101     unsigned long prop = 0;
00102     if (takeFlag)
00103         flag = facet._ucFlag;
00104     if (takeProperty)
00105         prop = facet._ulProp;
00106 
00107     AddFacet(facet._aclPoints[0], facet._aclPoints[1], facet._aclPoints[2], facet.GetNormal(), flag, prop);
00108 }
00109 
00110 void MeshBuilder::AddFacet (const Base::Vector3f& pt1, const Base::Vector3f& pt2, const Base::Vector3f& pt3, const Base::Vector3f& normal, unsigned char flag, unsigned long prop)
00111 {
00112     Base::Vector3f facetPoints[4] = { pt1, pt2, pt3, normal };
00113     AddFacet(facetPoints, flag, prop);
00114 }
00115 
00116 void MeshBuilder::AddFacet (Base::Vector3f* facetPoints, unsigned char flag, unsigned long prop)
00117 {
00118     this->_seq->next(true); // allow to cancel
00119 
00120     // adjust circulation direction
00121     if ((((facetPoints[1] - facetPoints[0]) % (facetPoints[2] - facetPoints[0])) * facetPoints[3]) < 0.0f)
00122     {
00123         std::swap(facetPoints[1], facetPoints[2]);
00124     }
00125 
00126     MeshFacet mf;
00127     mf._ucFlag = flag;
00128     mf._ulProp = prop;
00129 
00130     int i = 0;
00131     for (i = 0; i < 3; i++)
00132     {
00133         MeshPoint pt(facetPoints[i]);                   
00134         std::set<MeshPoint>::iterator p = _points.find(pt);
00135         if (p == _points.end())
00136         {
00137             mf._aulPoints[i] = _ptIdx;
00138             pt._ulProp = _ptIdx++;
00139             // keep an iterator to the right vertex
00140             MeshPointIterator it = _points.insert(pt);                  
00141             _pointsIterator.push_back(it);
00142         }
00143         else
00144             mf._aulPoints[i] = p->_ulProp;
00145     }
00146 
00147     // check for degenerated facet (one edge has length 0)
00148     if ((mf._aulPoints[0] == mf._aulPoints[1]) || (mf._aulPoints[0] == mf._aulPoints[2]) || (mf._aulPoints[1] == mf._aulPoints[2]))
00149         return;
00150 
00151     _meshKernel._aclFacetArray.push_back(mf);
00152 }
00153 
00154 void MeshBuilder::SetNeighbourhood ()
00155 {
00156     std::set<Edge> edges;
00157     int facetIdx = 0;
00158 
00159     for (MeshFacetArray::_TIterator it = _meshKernel._aclFacetArray.begin(); it != _meshKernel._aclFacetArray.end(); it++)
00160     {
00161         this->_seq->next(true); // allow to cancel
00162         MeshFacet& mf = *it;
00163 
00164         for (int i = 0; i < 3; i++)
00165         {
00166             Edge edge(mf._aulPoints[i], mf._aulPoints[(i+1)%3], facetIdx);
00167             std::set<Edge>::iterator e = edges.find(edge);
00168             if (e != edges.end())
00169             { // edge exists, set neighbourhood
00170                 MeshFacet& mf1 = _meshKernel._aclFacetArray[e->facetIdx];
00171                 if (mf1._aulPoints[0] == edge.pt1)
00172                 {
00173                     if (mf1._aulPoints[1] == edge.pt2)
00174                         mf1._aulNeighbours[0] = facetIdx;
00175                     else
00176                         mf1._aulNeighbours[2] = facetIdx;
00177                 }
00178                 else if (mf1._aulPoints[0] == edge.pt2)
00179                 {
00180                     if (mf1._aulPoints[1] == edge.pt1)
00181                         mf1._aulNeighbours[0] = facetIdx;
00182                     else
00183                         mf1._aulNeighbours[2] = facetIdx;
00184                 }
00185                 else
00186                     mf1._aulNeighbours[1] = facetIdx;
00187 
00188                 mf._aulNeighbours[i] = e->facetIdx;
00189             }
00190             else
00191             {  // new edge
00192                 edges.insert(edge);
00193             }
00194         }
00195 
00196         facetIdx++;
00197     }
00198 }
00199 
00200 void MeshBuilder::RemoveUnreferencedPoints()
00201 {
00202     _meshKernel._aclPointArray.SetFlag(MeshPoint::INVALID);
00203     for ( MeshFacetArray::_TConstIterator it = _meshKernel._aclFacetArray.begin(); it != _meshKernel._aclFacetArray.end(); ++it )
00204     {
00205         for ( int i=0; i<3; i++ )
00206             _meshKernel._aclPointArray[it->_aulPoints[i]].ResetInvalid();
00207     }
00208 
00209     unsigned long uValidPts = std::count_if(_meshKernel._aclPointArray.begin(), _meshKernel._aclPointArray.end(), std::mem_fun_ref(&MeshPoint::IsValid));
00210     if ( uValidPts < _meshKernel.CountPoints() )
00211         _meshKernel.RemoveInvalids();
00212 }
00213 
00214 void MeshBuilder::Finish (bool freeMemory)
00215 {
00216     // now we can resize the vertex array to the exact size and copy the vertices with their correct positions in the array
00217     unsigned long i=0;
00218     _meshKernel._aclPointArray.resize(_pointsIterator.size());
00219     for ( std::vector<MeshPointIterator>::iterator it = _pointsIterator.begin(); it != _pointsIterator.end(); ++it)
00220         _meshKernel._aclPointArray[i++] = *(it->first);
00221 
00222     // free all memory of the internal structures
00223     // Note: this scope is needed to free memory immediately
00224     { std::vector<MeshPointIterator>().swap(_pointsIterator); }
00225     _points.clear();
00226 
00227     SetNeighbourhood();
00228     RemoveUnreferencedPoints();
00229 
00230     // if AddFacet() has been called more often (or even less) as specified in Initialize() we have a wastage of memory
00231     if ( freeMemory )
00232     {
00233         unsigned long cap = _meshKernel._aclFacetArray.capacity();
00234         unsigned long siz = _meshKernel._aclFacetArray.size();
00235         // wastage of more than 5%
00236         if ( cap > siz+siz/20 )
00237         {
00238             try {
00239                 unsigned long i=0;
00240                 MeshFacetArray faces(siz);
00241                 for ( MeshFacetArray::_TIterator it = _meshKernel._aclFacetArray.begin(); it != _meshKernel._aclFacetArray.end(); ++it )
00242                     faces[i++]=*it;
00243                 _meshKernel._aclFacetArray.swap(faces);
00244             } catch ( const Base::MemoryException&) {
00245                 // sorry, we cannot reduce the memory
00246             }
00247         }
00248     }
00249 
00250     _meshKernel.RecalcBoundBox();
00251 }

Generated on Wed Nov 23 18:59:59 2011 for FreeCAD by  doxygen 1.6.1