edgecluster.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) 2010                                                    *
00003  *   Joachim Zettler <Joachim.Zettler@gmx.de>                              *
00004  *                                                                         *
00005  *   This file is part of the FreeCAD CAx development system.              *
00006  *                                                                         *
00007  *   This library is free software; you can redistribute it and/or         *
00008  *   modify it under the terms of the GNU Library General Public           *
00009  *   License as published by the Free Software Foundation; either          *
00010  *   version 2 of the License, or (at your option) any later version.      *
00011  *                                                                         *
00012  *   This library  is distributed in the hope that it will be useful,      *
00013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00015  *   GNU Library General Public License for more details.                  *
00016  *                                                                         *
00017  *   You should have received a copy of the GNU Library General Public     *
00018  *   License along with this library; see the file COPYING.LIB. If not,    *
00019  *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
00020  *   Suite 330, Boston, MA  02111-1307, USA                                *
00021  *                                                                         *
00022  ***************************************************************************/
00023 
00024 
00025 #include "PreCompiled.h"
00026 
00027 #include "edgecluster.h"
00028 #include <TopExp_Explorer.hxx>
00029 #include <TopAbs_ShapeEnum.hxx>
00030 #include <BRep_Tool.hxx>
00031 #include <TopExp.hxx>
00032 #include <TopoDS.hxx>
00033 #include <TopoDS_Shape.hxx>
00034 #include <TopoDS_Vertex.hxx>
00035 #include <TopoDS_Compound.hxx>
00036 #include <BRepAdaptor_Curve.hxx>
00037 #include <GCPnts_QuasiUniformDeflection.hxx>
00038 #include <BRep_Builder.hxx>
00039 
00040 
00041 using namespace Part;
00042 
00043 Edgecluster::Edgecluster(const std::vector<TopoDS_Edge>& unsorted_edges)
00044         :m_unsortededges(unsorted_edges),m_done(false)
00045 {
00046     m_edges.clear();
00047     m_vertices.clear();
00048     m_final_cluster.clear();
00049 }
00050 
00051 Edgecluster::~Edgecluster(void)
00052 {
00053 }
00054 
00055 tEdgeClusterVector Edgecluster::GetClusters()
00056 {
00057     Perform();
00058     return m_final_cluster;
00059 }
00060 
00061 void Edgecluster::Perform()
00062 {
00063     if ( m_unsortededges.empty() )
00064         return;
00065 
00066     //adds all the vertices to a map, and store the associated edges
00067     Standard_Integer nbEdges = 0;
00068     Standard_Integer nbNonEdges = 0;
00069     std::vector<TopoDS_Edge>::iterator aVectorIt;
00070     for (aVectorIt = m_unsortededges.begin();aVectorIt != m_unsortededges.end();aVectorIt++)
00071     {
00072         if (IsValidEdge(*aVectorIt))
00073         {
00074             Perform(*aVectorIt);
00075             nbEdges++;
00076         }
00077         else
00078         {
00079             nbNonEdges++;
00080         }
00081     }
00082 
00083     //now, iterate through the edges to sort and cluster them
00084 
00085     do
00086     {
00087         m_edges.clear();
00088                 //Lets start with a vertice that only has one edge (that means start or end point of the merged edges!)
00089         tMapPntEdge::iterator iter; 
00090                 bool closed = true;
00091                 for(iter=m_vertices.begin();iter!=m_vertices.end();iter++)
00092                 {
00093                         if (iter->second.size()==1)
00094                         {
00095                                 closed = false;
00096                                 break;
00097                         }
00098                 }
00099                 if(closed)iter = m_vertices.begin();
00100         const gp_Pnt& firstPoint = iter->first;
00101         gp_Pnt currentPoint = firstPoint;
00102         Standard_Boolean toContinue;
00103         do
00104         {
00105             toContinue = PerformEdges(currentPoint);
00106         }
00107         while (toContinue == Standard_True);
00108         //Store the current adjacent edges as a cluster
00109         m_final_cluster.push_back(m_edges);
00110         //and continue now with the still existing edges in the m_vertices
00111     }
00112     while (!m_vertices.empty());
00113 
00114     m_done = true;
00115 }
00116 
00117 bool Edgecluster::PerformEdges(gp_Pnt& point)
00118 {
00119     tMapPntEdge::iterator iter = m_vertices.find(point);
00120     if ( iter == m_vertices.end() )
00121         return false;
00122 
00123     tEdgeVector& edges = iter->second;
00124 
00125     tEdgeVector::iterator edgeIt = edges.begin();
00126 
00127     //no more edges. pb
00128     if ( edgeIt == edges.end() )
00129     {
00130         //Delete also the current vertex
00131         m_vertices.erase(iter);
00132 
00133         return false;
00134     }
00135 
00136     TopoDS_Edge theEdge = *edgeIt;
00137 
00138     //we are storing the edge, so remove it from the vertex association
00139     edges.erase(edgeIt);
00140 
00141     //if no more edges, remove the vertex
00142     if ( edges.empty() )
00143         m_vertices.erase(iter);
00144 
00145 
00146     TopoDS_Vertex V1,V2;
00147     TopExp::Vertices(theEdge,V1,V2);
00148     gp_Pnt P1 = BRep_Tool::Pnt(V1);
00149     gp_Pnt P2 = BRep_Tool::Pnt(V2);
00150     if ( theEdge.Orientation() == TopAbs_REVERSED )
00151     {
00152         //switch the points
00153         gp_Pnt tmpP = P1;
00154         P1 = P2;
00155         P2 = tmpP;
00156     }
00157 
00158     gp_Pnt nextPoint;
00159     if ( P2.IsEqual(point,0.2) )
00160     {
00161         //need to reverse the edge
00162 
00163         theEdge.Reverse();
00164         nextPoint = P1;
00165     }
00166     else
00167     {
00168         nextPoint = P2;
00169     }
00170 
00171 
00172     //need to erase the edge from the second point
00173     iter = m_vertices.find(nextPoint);
00174     if ( iter != m_vertices.end() )
00175     {
00176         tEdgeVector& nextEdges = iter->second;
00177         for ( edgeIt = nextEdges.begin() ; edgeIt != nextEdges.end(); ++edgeIt )
00178         {
00179             if ( theEdge.IsSame(*edgeIt) )
00180             {
00181                 nextEdges.erase(edgeIt);
00182                 break;
00183             }
00184         }
00185     }
00186 
00187     //put the edge at the end of the list
00188     m_edges.push_back(theEdge);
00189 
00190     //Update the point for the next do-while loop
00191     point = nextPoint;
00192     return true;
00193 
00194 }
00195 
00196 void Edgecluster::Perform(const TopoDS_Edge& edge)
00197 {
00198     if ( edge.IsNull() )
00199         return;
00200     TopoDS_Vertex V1,V2;
00201     TopExp::Vertices(edge,V1,V2);
00202     gp_Pnt P1 = BRep_Tool::Pnt(V1);
00203     gp_Pnt P2 = BRep_Tool::Pnt(V2);
00204 
00205     tEdgeVector emptyList;
00206 
00207     std::pair<tMapPntEdge::iterator,bool> iter = m_vertices.insert(tMapPntEdgePair(P1,emptyList));
00208     iter.first->second.push_back(edge);
00209     iter = m_vertices.insert(tMapPntEdgePair(P2,emptyList));
00210     iter.first->second.push_back(edge);
00211 }
00212 
00213 #include <BRepAdaptor_Curve.hxx>
00214 
00215 bool Edgecluster::IsValidEdge(const TopoDS_Edge& edge)
00216 {
00217     if ( edge.IsNull() )
00218         return false;
00219     if ( BRep_Tool::Degenerated(edge) )
00220         return false;
00221 
00222     BRepAdaptor_Curve bac(edge);
00223 
00224     Standard_Real fparam = bac.FirstParameter();
00225     Standard_Real lparam = bac.LastParameter();
00226 
00227     gp_Pnt fpoint = bac.Value(fparam);
00228     gp_Pnt lpoint = bac.Value(lparam);
00229 
00230     //do not test the distance first last in case of a full circle edge (fpoint == lastpoint)
00231     //if ( fpoint.IsEqual(lpoint,1e-5 ) )
00232     //      return false;
00233 
00234     gp_Pnt mpoint = bac.Value((fparam+lparam)*0.5);
00235 
00236     Standard_Real dist = mpoint.Distance(lpoint);
00237     if ( dist <= 1e-5 )
00238         return false;
00239     dist = mpoint.Distance(fpoint);
00240     if ( dist <= 1e-5 )
00241         return false;
00242 
00243     return true;
00244 }
00245 

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