Projection.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 <algorithm>
00027 # include <map>
00028 #endif
00029 #ifdef FC_USE_OCC
00030 # include <Bnd_Box.hxx>
00031 # include <BndLib_Add3dCurve.hxx>
00032 # include <BRep_Tool.hxx>
00033 # include <BRepAdaptor_Curve.hxx>
00034 # include <GCPnts_UniformDeflection.hxx>
00035 # include <Geom_Curve.hxx>
00036 # include <Geom_Plane.hxx>
00037 # include <GeomAPI_IntCS.hxx>
00038 # include <gp_Pln.hxx>
00039 # include <TopExp_Explorer.hxx>
00040 # include <TopoDS.hxx>
00041 # include <TopoDS_Edge.hxx>
00042 
00043 #include "Projection.h"
00044 #include "MeshKernel.h"
00045 #include "Iterator.h"
00046 #include "Algorithm.h"
00047 #include "Grid.h"
00048 
00049 #include <Base/Exception.h>
00050 #include <Base/Console.h>
00051 #include <Base/Sequencer.h>
00052 
00053 
00054 using namespace MeshCore;
00055 
00056 
00057 MeshProjection::MeshProjection(const MeshKernel& rMesh) 
00058   : _rcMesh(rMesh)
00059 {
00060 }
00061 
00062 MeshProjection::~MeshProjection()
00063 {
00064 }
00065 
00066 void MeshProjection::splitMeshByShape ( const TopoDS_Shape &aShape, float fMaxDist ) const
00067 {
00068     std::vector<SplitEdge> cSplitEdges;
00069     projectToMesh( aShape, fMaxDist, cSplitEdges );
00070 
00071     std::ofstream str("output.asc", std::ios::out | std::ios::binary);
00072     str.precision(4);
00073     str.setf(std::ios::fixed | std::ios::showpoint);
00074     for (std::vector<SplitEdge>::const_iterator it = cSplitEdges.begin();it!=cSplitEdges.end();++it) {
00075         str << it->cPt.x << " " << it->cPt.y << " " << it->cPt.z << std::endl;
00076     }
00077     str.close();
00078 }
00079 
00080 void MeshProjection::projectToMesh ( const TopoDS_Shape &aShape, float fMaxDist, std::vector<SplitEdge>& rSplitEdges ) const
00081 {
00082     // calculate the average edge length and create a grid
00083     MeshAlgorithm clAlg( _rcMesh );
00084     float fAvgLen = clAlg.GetAverageEdgeLength();
00085     MeshFacetGrid cGrid( _rcMesh, 5.0f*fAvgLen );
00086 
00087     TopExp_Explorer Ex;
00088     TopoDS_Shape Edge;
00089 
00090     int iCnt=0;
00091     for (Ex.Init(aShape, TopAbs_EDGE); Ex.More(); Ex.Next())
00092         iCnt++;
00093 
00094     Base::Sequencer().start( "Project curve on mesh", iCnt );
00095 
00096     for (Ex.Init(aShape, TopAbs_EDGE); Ex.More(); Ex.Next()) {
00097         const TopoDS_Edge& aEdge = TopoDS::Edge(Ex.Current());
00098         projectEdgeToEdge( aEdge, fMaxDist, cGrid, rSplitEdges );
00099         Base::Sequencer().next();
00100     }
00101 
00102     Base::Sequencer().stop();
00103 }
00104 
00105 void MeshProjection::projectEdgeToEdge( const TopoDS_Edge &aEdge, float fMaxDist, const MeshFacetGrid& rGrid,
00106                                          std::vector<SplitEdge>& rSplitEdges ) const
00107 {
00108     std::vector<unsigned long> auFInds;
00109     std::map<std::pair<unsigned long, unsigned long>, std::list<unsigned long> > pEdgeToFace;
00110     const std::vector<MeshFacet>& rclFAry = _rcMesh.GetFacets();
00111 
00112     // search the facets in the local area of the curve
00113     std::vector<Vector3f> acPolyLine;
00114 
00115     BRepAdaptor_Curve clCurve( aEdge );
00116 
00117     Standard_Real fFirst = clCurve.FirstParameter();
00118     Standard_Real fLast  = clCurve.LastParameter();
00119 
00120     GCPnts_UniformDeflection clDefl(clCurve, 0.01f, fFirst, fLast);
00121     if (clDefl.IsDone() == Standard_True) {
00122         Standard_Integer nNbPoints = clDefl.NbPoints();
00123         for (Standard_Integer i = 1; i <= nNbPoints; i++) {
00124             gp_Pnt gpPt = clCurve.Value(clDefl.Parameter(i));
00125             acPolyLine.push_back( Vector3f( (float)gpPt.X(), (float)gpPt.Y(), (float)gpPt.Z() ) );
00126         }
00127     }
00128 
00129     MeshAlgorithm(_rcMesh).SearchFacetsFromPolyline( acPolyLine, fMaxDist, rGrid, auFInds);
00130     // remove duplicated elements
00131     std::sort(auFInds.begin(), auFInds.end());
00132     auFInds.erase(std::unique(auFInds.begin(), auFInds.end()), auFInds.end());
00133 
00134     // facet to edge
00135     for ( std::vector<unsigned long>::iterator pI = auFInds.begin(); pI != auFInds.end(); ++pI ) {
00136         const MeshFacet& rF = rclFAry[*pI];
00137         for (int i = 0; i < 3; i++) {
00138             unsigned long ulPt0 = std::min<unsigned long>(rF._aulPoints[i],  rF._aulPoints[(i+1)%3]);
00139             unsigned long ulPt1 = std::max<unsigned long>(rF._aulPoints[i],  rF._aulPoints[(i+1)%3]);
00140             pEdgeToFace[std::pair<unsigned long, unsigned long>(ulPt0, ulPt1)].push_front(*pI);
00141         }
00142     }
00143 
00144     // sort intersection points by parameter
00145     std::map<Quantity_Parameter, SplitEdge> rParamSplitEdges;
00146 
00147 //  Standard_Real fFirst, fLast;
00148     Handle(Geom_Curve) hCurve = BRep_Tool::Curve( aEdge,fFirst,fLast );
00149 
00150     // bounds of curve
00151 //  Bnd_Box clBB;
00152 //  BndLib_Add3dCurve::Add( BRepAdaptor_Curve(aEdge), 0.0, clBB );
00153 
00154     MeshPointIterator cPI( _rcMesh );
00155     MeshFacetIterator cFI( _rcMesh );
00156 
00157     Base::Sequencer().start( "Project curve on mesh", pEdgeToFace.size() );
00158     std::map<std::pair<unsigned long, unsigned long>, std::list<unsigned long> >::iterator it;
00159     for ( it = pEdgeToFace.begin(); it != pEdgeToFace.end(); ++it ) {
00160         Base::Sequencer().next();
00161 
00162         // edge points
00163         unsigned long uE0 = it->first.first;
00164         cPI.Set( uE0 );
00165         Vector3f cE0 = *cPI;
00166         unsigned long uE1 = it->first.second;
00167         cPI.Set( uE1 );
00168         Vector3f cE1 = *cPI;
00169 
00170         const std::list<unsigned long>& auFaces = it->second;
00171         if ( auFaces.size() > 2 )
00172             continue; // non-manifold edge -> don't handle this
00173 //      if ( clBB.IsOut( gp_Pnt(cE0.x, cE0.y, cE0.z) ) && clBB.IsOut( gp_Pnt(cE1.x, cE1.y, cE1.z) ) )
00174 //          continue;
00175 
00176         Vector3f cEdgeNormal;
00177         for ( std::list<unsigned long>::const_iterator itF = auFaces.begin(); itF != auFaces.end(); ++itF ) {
00178             cFI.Set( *itF );
00179             cEdgeNormal += cFI->GetNormal();
00180         }
00181 
00182         // create a plane from the edge normal and point
00183         Vector3f cPlaneNormal = cEdgeNormal % (cE1 - cE0);
00184         Handle(Geom_Plane) hPlane = new Geom_Plane(gp_Pln(gp_Pnt(cE0.x,cE0.y,cE0.z), 
00185                                     gp_Dir(cPlaneNormal.x,cPlaneNormal.y,cPlaneNormal.z)));
00186 
00187         // get intersection of curve and plane
00188         GeomAPI_IntCS Alg(hCurve,hPlane); 
00189         if ( Alg.IsDone() ) {
00190             Standard_Integer nNbPoints = Alg.NbPoints();
00191             if ( nNbPoints == 1 ) {
00192                 Quantity_Parameter fU, fV, fW;
00193                 Alg.Parameters( 1, fU, fV, fW);
00194 
00195                 gp_Pnt P = Alg.Point(1);
00196                 Vector3f cP0((float)P.X(), (float)P.Y(), (float)P.Z());
00197 
00198                 float l = ( (cP0 - cE0) * (cE1 - cE0) ) / ( (cE1 - cE0) * ( cE1 - cE0) );
00199 
00200                 // lies the point inside the edge?
00201                 if ( l>=0.0f && l<=1.0f ) {
00202                     Vector3f cSplitPoint = (1-l) * cE0 + l * cE1;
00203                     float fDist = Base::Distance( cP0, cSplitPoint );
00204 
00205                     if ( fDist <= fMaxDist ) {
00206                         SplitEdge splitEdge;
00207                         splitEdge.uE0 = uE0;
00208                         splitEdge.uE1 = uE1;
00209                         splitEdge.cPt = cSplitPoint;
00210                         rParamSplitEdges[fW] = splitEdge;
00211                     }
00212                 }
00213             }
00214             // search for the right solution
00215             else if ( nNbPoints > 1 ) {
00216                 int nCntSol=0;
00217                 Vector3f cSplitPoint;
00218                 Quantity_Parameter fSol;
00219                 Vector3f cP0;
00220                 for ( int j=1; j<=nNbPoints; j++ ) {
00221                     Quantity_Parameter fU, fV, fW;
00222                     Alg.Parameters( j, fU, fV, fW);
00223                     gp_Pnt P = Alg.Point(j);
00224                     cP0.Set((float)P.X(), (float)P.Y(), (float)P.Z());
00225 
00226                     float l = ( (cP0 - cE0) * (cE1 - cE0) ) / ( (cE1 - cE0) * ( cE1 - cE0) );
00227 
00228                     // lies the point inside the edge?
00229                     if ( l>=0.0 && l<=1.0 ) {
00230                         cSplitPoint = (1-l) * cE0 + l * cE1;
00231                         float fDist = Base::Distance( cP0, cSplitPoint );
00232   
00233                         if (fDist <= fMaxDist) {
00234                             nCntSol++;
00235                             fSol = fW;
00236                         }
00237                     }
00238                 }
00239 
00240                 // ok, only one sensible solution
00241                 if ( nCntSol == 1 ) {
00242                     SplitEdge splitEdge;
00243                     splitEdge.uE0 = uE0;
00244                     splitEdge.uE1 = uE1;
00245                     splitEdge.cPt = cSplitPoint;
00246                     rParamSplitEdges[fSol] = splitEdge;
00247                 }
00248                 else if ( nCntSol > 1 ) {
00249                     Base::Console().Log("More than one possible intersection points\n");
00250                 }
00251             }
00252         }
00253     }
00254 
00255     // sorted by parameter
00256     for (std::map<Quantity_Parameter, SplitEdge>::iterator itS = 
00257          rParamSplitEdges.begin(); itS != rParamSplitEdges.end(); ++itS) {
00258          rSplitEdges.push_back( itS->second );
00259     }
00260 
00261     Base::Sequencer().stop();
00262 }
00263 
00264 #endif

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