Salome HOME
Issue #1664 In the Sketcher, add the function Split a segment - correction for arc...
[modules/shaper.git] / src / GeomAlgoAPI / GeomAlgoAPI_SketchBuilder.cpp
index 9713fda503f839eb42b77fa19d9725fcdd31d295..880273df25fe4665fa09d37cd3649dfca5df5be9 100644 (file)
 #include <BRepTopAdaptor_FClass2d.hxx>
 #include <Geom_Plane.hxx>
 #include <Precision.hxx>
+#include <TopExp.hxx>
 #include <TopExp_Explorer.hxx>
 #include <TopoDS.hxx>
 #include <TopoDS_Edge.hxx>
 #include <TopTools_ListIteratorOfListOfShape.hxx>
 
+#include <list>
+#include <cmath>
+
+
+static TopoDS_Vertex findStartVertex(const TopoDS_Shape& theShape)
+{
+  static const double aTol = Precision::PConfusion();
+
+  TopExp_Explorer anExp(theShape, TopAbs_VERTEX);
+  TopoDS_Vertex aStart = TopoDS::Vertex(anExp.Current());
+  gp_Pnt aStartPnt(BRep_Tool::Pnt(aStart));
+  TopoDS_Vertex aCurrent;
+  gp_Pnt aCurrentPnt;
+
+  for (anExp.Next(); anExp.More(); anExp.Next()) {
+    aCurrent = TopoDS::Vertex(anExp.Current());
+    aCurrentPnt = BRep_Tool::Pnt(aCurrent);
+    if ((aCurrentPnt.X() > aStartPnt.X() + aTol) ||
+        (aCurrentPnt.X() > aStartPnt.X() - aTol && aCurrentPnt.Y() > aStartPnt.Y() + aTol) ||
+        (aCurrentPnt.X() > aStartPnt.X() - aTol && aCurrentPnt.Y() > aStartPnt.Y() - aTol &&
+            aCurrentPnt.Z() > aStartPnt.Z() + aTol)) {
+      aStart = aCurrent;
+      aStartPnt = aCurrentPnt;
+    }
+  }
+  return aStart;
+}
 
 void GeomAlgoAPI_SketchBuilder::createFaces(
     const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
@@ -61,24 +89,54 @@ void GeomAlgoAPI_SketchBuilder::createFaces(
     if (aFClass.PerformInfinitePoint() == TopAbs_IN)
       continue;
 
-    // remove internal edges from faces
-    TopExp_Explorer anExp(aFace, TopAbs_EDGE);
-    for (; anExp.More(); anExp.Next())
-      if (anExp.Current().Orientation() == TopAbs_INTERNAL)
-        break;
-    if (anExp.More()) {
-      TopoDS_Face aNewFace;
-      aBuilder.MakeFace(aNewFace, aPlane, Precision::Confusion());
-      TopoDS_Wire aWire;
-      aBuilder.MakeWire(aWire);
-      for (anExp.ReInit(); anExp.More(); anExp.Next())
-        if (anExp.Current().Orientation() != TopAbs_INTERNAL)
-          aBuilder.Add(aWire, anExp.Current());
-      aBuilder.Add(aNewFace, aWire);
-      aFace = aNewFace;
+    // rebuild face
+    TopoDS_Face aNewFace;
+    aBuilder.MakeFace(aNewFace, aPlane, Precision::Confusion());
+
+    // iterate on wires
+    TopExp_Explorer aWireExp(aFace, TopAbs_WIRE);
+    for (; aWireExp.More(); aWireExp.Next()) {
+      TopoDS_Wire aWire = TopoDS::Wire(aWireExp.Current());
+
+      // to make faces equal on different platforms, we will find
+      // a vertex with greater coordinates and start wire from it
+      TopoDS_Vertex aStartVertex = findStartVertex(aWire);
+
+      TopoDS_Wire aNewWire;
+      aBuilder.MakeWire(aNewWire);
+      std::list<TopoDS_Edge> aSkippedEdges;
+      bool aStartFound = false;
+
+      // remove internal edges from faces and make wire start from found vertex
+      TopExp_Explorer anExp(aWire, TopAbs_EDGE);
+      for (; anExp.More(); anExp.Next()) {
+        if (anExp.Current().Orientation() == TopAbs_INTERNAL)
+          continue;
+        if (!aStartFound) {
+          const TopoDS_Edge& anEdge = TopoDS::Edge(anExp.Current());
+          TopoDS_Vertex aV1, aV2;
+          TopExp::Vertices(anEdge, aV1, aV2, Standard_True);
+          if (aV1.IsSame(aStartVertex) == Standard_True)
+            aStartFound = true;
+          else
+            aSkippedEdges.push_back(anEdge);
+        }
+        if (aStartFound)
+          aBuilder.Add(aNewWire, anExp.Current());
+      }
+      // add skipped edges to the end of wire
+      std::list<TopoDS_Edge>::const_iterator aSkIt = aSkippedEdges.begin();
+      for (; aSkIt != aSkippedEdges.end(); ++aSkIt)
+        aBuilder.Add(aNewWire, *aSkIt);
+
+      // check the wire is empty
+      anExp.Init(aNewWire, TopAbs_EDGE);
+      if (anExp.More())
+        aBuilder.Add(aNewFace, aNewWire);
     }
 
-    // Store face
+    // store face
+    aFace = aNewFace;
     std::shared_ptr<GeomAPI_Shape> aResFace(new GeomAPI_Shape);
     aResFace->setImpl(new TopoDS_Face(aFace));
     theResultFaces.push_back(aResFace);