Salome HOME
Fix SIGSEGV on model.checkPythonDump() in GUI
[modules/shaper.git] / src / GeomAlgoAPI / GeomAlgoAPI_SketchBuilder.cpp
index 90fbacd0e4ac050bb79fc8b90b002898bf4584fb..0654ee22fdab4039fe1c31b197618b7c72e3e4d2 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+// Copyright (C) 2014-2022  CEA/DEN, EDF R&D
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 //
 // You should have received a copy of the GNU Lesser General Public
 // License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
-// See http://www.salome-platform.org/ or
-// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
 #include <GeomAlgoAPI_SketchBuilder.h>
@@ -166,7 +165,7 @@ bool isFirst(const TopoDS_Shape& theFirst, const TopoDS_Shape& theSecond,
 }
 
 // sorts faces (in theAreas list) to make persistent order: by initial shapes edges
-static void sortFaces(TopTools_ListOfShape& theAreas,
+static void sortAreas(TopTools_ListOfShape& theAreas,
   const std::list<std::shared_ptr<GeomAPI_Shape> >& theInitialShapes)
 {
   // collect indices of all edges to operate them quickly
@@ -214,13 +213,18 @@ void GeomAlgoAPI_SketchBuilder::build(
 
   BRep_Builder aBuilder;
   // Planar face, where the sketch was built
-  Handle(Geom_Surface) aPlane(new Geom_Plane(theOrigin->impl<gp_Pnt>(), theNorm->impl<gp_Dir>()));
+  gp_Ax3 aPlnAxes(theOrigin->impl<gp_Pnt>(), theNorm->impl<gp_Dir>(), theDirX->impl<gp_Dir>());
+  Handle(Geom_Surface) aPlane(new Geom_Plane(aPlnAxes));
   TopoDS_Face aPlnFace;
   aBuilder.MakeFace(aPlnFace, aPlane, Precision::Confusion());
 
   // Use General Fuse algorithm to prepare all subfaces, bounded by given list of edges
   BOPAlgo_Builder* aBB = new BOPAlgo_Builder;
   aBB->AddArgument(aPlnFace);
+  // Set fuzzy value for BOP, because PlaneGCS can solve the set of constraints with
+  // the precision up to 5.e-5 if the sketch contains arcs.
+  static const double THE_FUZZY_TOL = 5.e-5;
+  aBB->SetFuzzyValue(THE_FUZZY_TOL);
 
   setImpl(aBB);
   setBuilderType(OCCT_BOPAlgo_Builder);
@@ -243,7 +247,7 @@ void GeomAlgoAPI_SketchBuilder::build(
 
   // Collect faces
   TopTools_ListOfShape anAreas = aBB->Modified(aPlnFace);
-  sortFaces(anAreas, theEdges); // sort faces by the edges in them
+  sortAreas(anAreas, theEdges); // sort faces by the edges in them
   TopTools_ListIteratorOfListOfShape anIt(anAreas);
   for (; anIt.More(); anIt.Next()) {
     TopoDS_Face aFace = TopoDS::Face(anIt.Value());
@@ -256,10 +260,21 @@ void GeomAlgoAPI_SketchBuilder::build(
     TopoDS_Face aNewFace;
     aBuilder.MakeFace(aNewFace, aPlane, Precision::Confusion());
 
-    // iterate on wires
+    // sort inner wires according to the original edges as well as faces
+    TopTools_ListOfShape aWires;
     TopExp_Explorer aWireExp(aFace, TopAbs_WIRE);
-    for (; aWireExp.More(); aWireExp.Next()) {
-      TopoDS_Wire aWire = TopoDS::Wire(aWireExp.Current());
+    for (; aWireExp.More(); aWireExp.Next())
+      aWires.Append(aWireExp.Current());
+    if (aWires.Size() > 2) {
+      TopoDS_Shape anOuterWire = aWires.First();
+      aWires.RemoveFirst();
+      sortAreas(aWires, theEdges);
+      aWires.Prepend(anOuterWire);
+    }
+
+    // iterate on wires
+    for (TopTools_ListIteratorOfListOfShape aWIt(aWires); aWIt.More(); aWIt.Next()) {
+      TopoDS_Wire aWire = TopoDS::Wire(aWIt.Value());
 
       // to make faces equal on different platforms, we will find
       // a vertex lying on an edge with the lowest index in the list of initial edges
@@ -301,7 +316,7 @@ void GeomAlgoAPI_SketchBuilder::build(
     // store face
     aBuilder.Add(aResult, aNewFace);
     std::shared_ptr<GeomAPI_Shape> aResFace(new GeomAPI_Shape);
-    aResFace->setImpl(new TopoDS_Face(aFace));
+    aResFace->setImpl(new TopoDS_Face(aNewFace));
     myResultFaces.push_back(aResFace);
   }