X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FGeomAlgoAPI%2FGeomAlgoAPI_WireBuilder.cpp;h=9aab0b6f2b4e5ad40be470ee7da3c7db11112155;hb=06e7f5859095193fc7f498bd89a7d28009794f53;hp=a90d1e95320afd3bb302da0592dde07c4f5e9133;hpb=e14a0493c3a3a7c475cf146e2ec55329d4164681;p=modules%2Fshaper.git diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_WireBuilder.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_WireBuilder.cpp index a90d1e953..9aab0b6f2 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_WireBuilder.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_WireBuilder.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2019 CEA/DEN, EDF R&D +// Copyright (C) 2014-2023 CEA, EDF // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -29,11 +29,71 @@ #include #include #include +#include #include #include #include #include +#include +#include +#include + +class SetOfEdges +{ + class DoubleCompare { + public: + bool operator() (const double d1, const double d2) const { + return d1 + Precision::Confusion() < d2; + } + }; + + typedef std::map, DoubleCompare> ParamMap; + std::map myShapes; + +public: + bool add(const TopoDS_Shape& theEdge) + { + const TopoDS_Edge& anEdge = TopoDS::Edge(theEdge); + if (anEdge.IsNull()) + return true; + + double aFirst, aLast; + Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); + + bool isAdded = true; + std::map::iterator + aFound = myShapes.find(aCurve); + if (aFound == myShapes.end()) + myShapes[aCurve][aFirst].insert(aLast); + else { + ParamMap::iterator aFoundPar = aFound->second.find(aFirst); + if (aFoundPar == aFound->second.end()) + aFound->second[aFirst].insert(aLast); + else if (aFoundPar->second.find(aLast) == aFoundPar->second.end()) + aFoundPar->second.insert(aLast); + else + isAdded = false; + } + return isAdded; + } + + static bool isEqual(const TopoDS_Shape& theShape1, const TopoDS_Shape& theShape2) + { + const TopoDS_Edge& anEdge1 = TopoDS::Edge(theShape1); + const TopoDS_Edge& anEdge2 = TopoDS::Edge(theShape2); + if (anEdge1.IsNull() || anEdge2.IsNull()) + return false; + + double aFirst1, aLast1; + Handle(Geom_Curve) aCurve1 = BRep_Tool::Curve(anEdge1, aFirst1, aLast1); + double aFirst2, aLast2; + Handle(Geom_Curve) aCurve2 = BRep_Tool::Curve(anEdge2, aFirst2, aLast2); + return aCurve1 == aCurve2 && fabs(aFirst1 - aFirst2) < Precision::Confusion() && + fabs(aLast1 - aLast2) < Precision::Confusion(); + } +}; + static GeomShapePtr fromTopoDS(const TopoDS_Shape& theShape) { GeomShapePtr aResultShape(new GeomAPI_Shape()); @@ -45,21 +105,34 @@ GeomAlgoAPI_WireBuilder::GeomAlgoAPI_WireBuilder(const ListOfShape& theShapes, const bool theForceOpenWire) { TopTools_ListOfShape aListOfEdges; + SetOfEdges aProcessedEdges; ListOfShape::const_iterator anIt = theShapes.cbegin(); for (; anIt != theShapes.cend(); ++anIt) { - const TopoDS_Shape& aShape = (*anIt)->impl(); - switch (aShape.ShapeType()) { - case TopAbs_EDGE: { - aListOfEdges.Append(aShape); - break; - } - case TopAbs_WIRE: { - for (TopExp_Explorer anExp(aShape, TopAbs_EDGE); anExp.More(); anExp.Next()) { - aListOfEdges.Append(anExp.Current()); + TopoDS_Shape aShape = (*anIt)->impl(); + switch(aShape.ShapeType()) { + case TopAbs_EDGE: { + aShape.Orientation(TopAbs_FORWARD); + if (aProcessedEdges.add(aShape)) + aListOfEdges.Append(aShape); + break; + } + case TopAbs_WIRE: { + for (TopExp_Explorer anExp(aShape, TopAbs_EDGE); anExp.More(); anExp.Next()) { + TopoDS_Shape anEdge = anExp.Current(); + anEdge.Orientation(TopAbs_FORWARD); + // if the edge was already processed, remove it to keep original order of the current wire + if (!aProcessedEdges.add(anEdge)) { + for (TopTools_ListIteratorOfListOfShape aEIt(aListOfEdges); aEIt.More(); aEIt.Next()) + if (SetOfEdges::isEqual(anEdge, aEIt.Value())) { + aListOfEdges.Remove(aEIt); + break; + } + } + aListOfEdges.Append(anEdge); + } + break; } - break; - } default: break; } @@ -67,7 +140,7 @@ GeomAlgoAPI_WireBuilder::GeomAlgoAPI_WireBuilder(const ListOfShape& theShapes, bool isSplitWire = false; gp_Pnt aSplitPoint; - if (theForceOpenWire) { + if (theForceOpenWire && aListOfEdges.Size() > 1) { // find a vertex to split the wire TopoDS_Vertex V1[2]; TopExp::Vertices(TopoDS::Edge(aListOfEdges.First()), V1[0], V1[1]); @@ -79,7 +152,7 @@ GeomAlgoAPI_WireBuilder::GeomAlgoAPI_WireBuilder(const ListOfShape& theShapes, double Tol2[2] = { BRep_Tool::Tolerance(V2[0]), BRep_Tool::Tolerance(V2[1]) }; for (int i = 0; i < 2 && !isSplitWire; ++i) for (int j = 0; j < 2 && !isSplitWire; ++j) - if (P1[i].Distance(P2[i]) < Max(Tol1[i], Tol2[j])) { + if (P1[i].Distance(P2[j]) < Max(Tol1[i], Tol2[j])) { aSplitPoint = P1[i]; isSplitWire = true; } @@ -168,7 +241,6 @@ bool GeomAlgoAPI_WireBuilder::isSelfIntersected(const GeomShapePtr& theWire) } // Check intersections between edges pair-wise - int aNbEdges = (int)anEdges.size(); std::list::const_iterator anEdgesIt = anEdges.begin(); for (int i = 0; anEdgesIt != anEdges.end(); ++anEdgesIt, i++) { GeomEdgePtr anEdge1(new GeomAPI_Edge(*anEdgesIt));