Salome HOME
Merge remote-tracking branch 'remotes/origin/master' into CEA_2019
[modules/shaper.git] / src / SketchAPI / SketchAPI_Sketch.cpp
index 7476380df64883cc5312f9ef257df8d527045890..e1aabba8adf3eac43c6e913336d0c696425389bc 100644 (file)
 #include "SketchAPI_Rotation.h"
 #include "SketchAPI_Translation.h"
 //--------------------------------------------------------------------------------------
+#include <GeomAPI_Curve.h>
 #include <GeomAPI_Dir2d.h>
+#include <GeomAPI_PlanarEdges.h>
+#include <GeomAPI_ShapeExplorer.h>
 #include <GeomAPI_XY.h>
+#include <GeomAlgoAPI_SketchBuilder.h>
 #include <cmath>
 //--------------------------------------------------------------------------------------
 SketchAPI_Sketch::SketchAPI_Sketch(
@@ -130,8 +134,7 @@ void SketchAPI_Sketch::setPlane(const std::shared_ptr<GeomAPI_Ax3> & thePlane)
 void SketchAPI_Sketch::setPlane(const ModelHighAPI_Selection & thePlane,
                                 bool theRemoveExternalDependency)
 {
-  std::shared_ptr<SketchPlugin_Sketch> aSketch =
-      std::dynamic_pointer_cast<SketchPlugin_Sketch>(feature());
+  FeaturePtr aSketch = feature();
 
   DocumentPtr aDoc = aSketch->document();
   bool useVisible = false;
@@ -223,6 +226,78 @@ SketchPtr addSketch(const std::shared_ptr<ModelAPI_Document> & thePart,
 }
 
 
+//--------------------------------------------------------------------------------------
+std::list< std::shared_ptr<SketchAPI_Point> > SketchAPI_Sketch::getFreePoints()
+{
+  std::list< std::shared_ptr<SketchAPI_Point> > aFreePoints;
+  std::list<ResultPtr> aPoints = SketcherPrs_Tools::getFreePoints(compositeFeature());
+  for (std::list<ResultPtr>::iterator anIt = aPoints.begin(); anIt != aPoints.end(); ++anIt) {
+    FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
+    PointPtr aPoint(new SketchAPI_Point(aFeature));
+    aFreePoints.push_back(aPoint);
+  }
+  return aFreePoints;
+}
+
+//--------------------------------------------------------------------------------------
+static GeomCurvePtr untrimmedCurve(GeomShapePtr theShape)
+{
+  GeomCurvePtr aCurve(new GeomAPI_Curve(theShape));
+  if (aCurve->isTrimmed())
+    aCurve = aCurve->basisCurve();
+  return aCurve;
+}
+
+void SketchAPI_Sketch::changeFacesOrder(
+    const std::list<std::list<ModelHighAPI_Selection> >& theFaces)
+{
+  // collect faces of the sketch
+  ResultConstructionPtr aSketchResult =
+      std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(feature()->lastResult());
+  if (!aSketchResult) {
+    // sketch is nested to a boolean operation, thus, it has no result yet.
+    feature()->execute();
+    aSketchResult =
+        std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(feature()->lastResult());
+  }
+  std::list<GeomFacePtr> aFaces;
+  int aFacesNum = aSketchResult->facesNum();
+  for (int i = 0; i < aFacesNum; ++i)
+    aFaces.push_back(aSketchResult->face(i));
+  // find new faces order according to the given lists of edges
+  std::list<GeomFacePtr> aNewFacesOrder;
+  std::list<std::list<ModelHighAPI_Selection> >::const_iterator anIt = theFaces.begin();
+  for (; anIt != theFaces.end(); ++anIt) {
+    // find the appropriate face
+    std::list<GeomFacePtr>::iterator aFIt = aFaces.begin();
+    for (; aFIt != aFaces.end(); ++aFIt) {
+      std::list<ModelHighAPI_Selection>::const_iterator aEdgeIt = anIt->begin();
+      GeomAPI_ShapeExplorer aFExp(*aFIt, GeomAPI_Shape::EDGE);
+      for (; aEdgeIt != anIt->end() && aFExp.more(); ++aEdgeIt, aFExp.next()) {
+        ResultPtr aCurRes = aEdgeIt->resultSubShapePair().first;
+        if (!aCurRes)
+          break;
+        GeomCurvePtr aCurve1 = untrimmedCurve(aCurRes->shape());
+        GeomCurvePtr aCurve2 = untrimmedCurve(aFExp.current());
+        if (!aCurve1->isEqual(aCurve2))
+          break;
+      }
+
+      if (aEdgeIt == anIt->end() && !aFExp.more()) {
+        // face is found
+        aNewFacesOrder.push_back(*aFIt);
+        aFaces.erase(aFIt);
+        break;
+      }
+    }
+  }
+  // place the rest faces at the end of new faces list
+  if (!aFaces.empty())
+    aNewFacesOrder.insert(aNewFacesOrder.end(), aFaces.begin(), aFaces.end());
+  // update the result of the sketch with the new order of faces
+  aSketchResult->setFacesOrder(aNewFacesOrder);
+}
+
 //--------------------------------------------------------------------------------------
 std::shared_ptr<SketchAPI_Point> SketchAPI_Sketch::addPoint(
     double theX, double theY)
@@ -448,22 +523,33 @@ std::shared_ptr<SketchAPI_MacroArc> SketchAPI_Sketch::addArc(
 std::shared_ptr<SketchAPI_MacroArc> SketchAPI_Sketch::addArc(
                                                 const ModelHighAPI_RefAttr& theTangentPoint,
                                                 double theEndX, double theEndY,
-                                                bool theInversed)
+                                                bool theInversed,
+                                                bool theTransversal)
 {
   std::shared_ptr<ModelAPI_Feature> aFeature =
     compositeFeature()->addFeature(SketchPlugin_MacroArc::ID());
-  return MacroArcPtr(new SketchAPI_MacroArc(
-    aFeature, theTangentPoint, theEndX, theEndY, theInversed));
+  MacroArcPtr aMacroArc(new SketchAPI_MacroArc(aFeature));
+  if (theTransversal)
+    aMacroArc->setByTransversal(theTangentPoint, theEndX, theEndY, theInversed);
+  else
+    aMacroArc->setByTangent(theTangentPoint, theEndX, theEndY, theInversed);
+  return aMacroArc;
 }
 
 std::shared_ptr<SketchAPI_MacroArc> SketchAPI_Sketch::addArc(
                                               const ModelHighAPI_RefAttr& theTangentPoint,
                                               const std::shared_ptr<GeomAPI_Pnt2d>& theEnd,
-                                              bool theInversed)
+                                              bool theInversed,
+                                              bool theTransversal)
 {
   std::shared_ptr<ModelAPI_Feature> aFeature =
     compositeFeature()->addFeature(SketchPlugin_MacroArc::ID());
-  return MacroArcPtr(new SketchAPI_MacroArc(aFeature, theTangentPoint, theEnd, theInversed));
+  MacroArcPtr aMacroArc(new SketchAPI_MacroArc(aFeature));
+  if (theTransversal)
+    aMacroArc->setByTransversal(theTangentPoint, theEnd, theInversed);
+  else
+    aMacroArc->setByTangent(theTangentPoint, theEnd, theInversed);
+  return aMacroArc;
 }
 
 std::shared_ptr<SketchAPI_Arc> SketchAPI_Sketch::addArc(const ModelHighAPI_Selection & theExternal)
@@ -996,6 +1082,99 @@ std::shared_ptr<GeomAPI_Pnt2d> SketchAPI_Sketch::to2D(const std::shared_ptr<Geom
 
 //--------------------------------------------------------------------------------------
 
+static bool isDifferent(GeomFacePtr theFace1, GeomFacePtr theFace2)
+{
+  // collect edges of the first face
+  std::list<GeomShapePtr> anEdges1;
+  for (GeomAPI_ShapeExplorer anExp(theFace1, GeomAPI_Shape::EDGE); anExp.more(); anExp.next())
+    anEdges1.push_back(anExp.current());
+  // compare edges of faces
+  for (GeomAPI_ShapeExplorer anExp(theFace2, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
+    GeomShapePtr aCurrent = anExp.current();
+    bool isFound = false;
+    std::list<GeomShapePtr>::iterator anIt1 = anEdges1.begin();
+    for (; anIt1 != anEdges1.end(); ++anIt1)
+      if (aCurrent->isSameGeometry(*anIt1)) {
+        isFound = true;
+        anEdges1.erase(anIt1);
+        break;
+      }
+    if (!isFound)
+      return true;
+  }
+  return !anEdges1.empty();
+}
+
+static bool isCustomFacesOrder(CompositeFeaturePtr theSketch)
+{
+  ResultConstructionPtr aSketchResult =
+      std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(theSketch->lastResult());
+  if (!aSketchResult)
+    return false;
+
+  std::shared_ptr<GeomAPI_PlanarEdges> aWires =
+      std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aSketchResult->shape());
+  if (!aWires)
+    return false;
+
+  // collect faces constructed by SketchBuilder algorithm
+  GeomAlgoAPI_SketchBuilder aSketchBuilder(aWires->origin(), aWires->dirX(),
+                                           aWires->norm(), aWires);
+  const ListOfShape& aFaces = aSketchBuilder.faces();
+
+  // compare faces stored in sketch with faces generated by SketchBuilder
+  int aNbSketchFaces = aSketchResult->facesNum();
+  int aFaceIndex = 0;
+  for (ListOfShape::const_iterator aFIt = aFaces.begin();
+       aFIt != aFaces.end() && aFaceIndex < aNbSketchFaces;
+       ++aFIt, ++aFaceIndex) {
+    GeomFacePtr aSketchFace = aSketchResult->face(aFaceIndex);
+    GeomFacePtr aCurFace = (*aFIt)->face();
+    if (isDifferent(aSketchFace, aCurFace))
+      return true;
+  }
+  return false;
+}
+
+static void edgesOfSketchFaces(CompositeFeaturePtr theSketch,
+                               std::list<std::list<ResultPtr> >& theEdges)
+{
+  ResultConstructionPtr aSketchResult =
+      std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(theSketch->lastResult());
+  if (!aSketchResult)
+    return;
+
+  // collect curves of the sketch
+  std::map<GeomCurvePtr, ResultPtr, GeomAPI_Curve::Comparator> aCurves;
+  int aSubNum = theSketch->numberOfSubs();
+  for (int a = 0; a < aSubNum; ++a) {
+    FeaturePtr aSub = theSketch->subFeature(a);
+    const std::list<ResultPtr>& aResults = aSub->results();
+    std::list<ResultPtr>::const_iterator aRes = aResults.cbegin();
+    for (; aRes != aResults.cend(); aRes++) {
+      GeomShapePtr aCurShape = (*aRes)->shape();
+      if (aCurShape && aCurShape->isEdge())
+        aCurves[untrimmedCurve(aCurShape)] = *aRes;
+    }
+  }
+
+  // convert each face to the list of results of its edges
+  int aFacesNum = aSketchResult->facesNum();
+  for (int a = 0; a < aFacesNum; ++a) {
+    theEdges.push_back(std::list<ResultPtr>());
+    std::list<ResultPtr>& aCurEdges = theEdges.back();
+
+    GeomFacePtr aFace = aSketchResult->face(a);
+    for (GeomAPI_ShapeExplorer anExp(aFace, GeomAPI_Shape::EDGE);
+         anExp.more(); anExp.next()) {
+      GeomCurvePtr aCurrent = untrimmedCurve(anExp.current());
+      aCurEdges.push_back(aCurves[aCurrent]);
+    }
+  }
+}
+
+//--------------------------------------------------------------------------------------
+
 void SketchAPI_Sketch::dump(ModelHighAPI_Dumper& theDumper) const
 {
   FeaturePtr aBase = feature();
@@ -1055,4 +1234,24 @@ void SketchAPI_Sketch::dump(ModelHighAPI_Dumper& theDumper) const
   // dump sketch's subfeatures
   CompositeFeaturePtr aCompFeat = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aBase);
   theDumper.processSubs(aCompFeat, true);
+
+  // if face order differs to the order generated by SketchBuilder,
+  // dump the list of faces for correct execution of the script
+  if (isCustomFacesOrder(aCompFeat)) {
+    std::list<std::list<ResultPtr> > aFaces;
+    edgesOfSketchFaces(aCompFeat, aFaces);
+
+    const std::string& aSketchName = theDumper.name(aBase);
+    std::string aMethodName(".changeFacesOrder");
+    std::string aSpaceShift(aSketchName.size() + aMethodName.size(), ' ');
+
+    theDumper << aSketchName << aMethodName << "([";
+    for (std::list<std::list<ResultPtr> >::iterator aFIt = aFaces.begin();
+         aFIt != aFaces.end(); ++aFIt) {
+      if (aFIt != aFaces.begin())
+        theDumper << ",\n" << aSpaceShift << "  ";
+      theDumper << *aFIt;
+    }
+    theDumper << "\n" << aSpaceShift << " ])" << std::endl;
+  }
 }