Salome HOME
updated copyright message
[modules/shaper.git] / src / GeomAlgoAPI / GeomAlgoAPI_Partition.cpp
index 3f0217ed94497cfad123a9228ee91f4efedc76d3..bf5075d38f5b0b7c51acd75428bb17a38c6f6a1c 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+// Copyright (C) 2014-2023  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_Partition.h"
 
 #include <GeomAlgoAPI_DFLoader.h>
 #include <GeomAlgoAPI_ShapeTools.h>
+#include <GeomAlgoAPI_SortListOfShapes.h>
 
 #include <GEOMAlgo_Splitter.hxx>
 
 #include <TopExp_Explorer.hxx>
 #include <TopoDS_Builder.hxx>
 #include <TopTools_MapOfShape.hxx>
+#include <BRepTools_History.hxx>
+
 
 //=================================================================================================
-bool isSubShape(const TopoDS_Shape& theShape, const TopoDS_Shape& theSubShape)
+static bool isSubShape(const TopoDS_Shape& theShape, const TopoDS_Shape& theSubShape)
 {
   for(TopExp_Explorer anExp(theShape, theSubShape.ShapeType()); anExp.More(); anExp.Next()) {
     if(theSubShape.IsSame(anExp.Current())) {
@@ -43,21 +45,92 @@ bool isSubShape(const TopoDS_Shape& theShape, const TopoDS_Shape& theSubShape)
 }
 
 //=================================================================================================
-std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_Partition::make(const ListOfShape& theObjects,
-                                                           const ListOfShape& theTools)
+void getHistorySupportedType(const TopoDS_Shape& theShape, TopTools_ListOfShape& theResult) {
+  if (BRepTools_History::IsSupportedType(theShape)) {
+    theResult.Append(theShape);
+  } else {
+    for (TopoDS_Iterator aSubIter(theShape); aSubIter.More(); aSubIter.Next()) {
+      getHistorySupportedType(aSubIter.Value(), theResult);
+    }
+  }
+}
+
+//=================================================================================================
+// Operation is used for production of ordered sorting: generated/modified from the first argument
+// must be located in hte result first, etc. THis is for the issue #2517
+static void sortCompound(TopoDS_Shape& theCompound, GEOMAlgo_Splitter* theOperation)
 {
-  GeomAlgoAPI_Partition aPartitionAlgo(theObjects, theTools);
-  if(aPartitionAlgo.isDone() && !aPartitionAlgo.shape()->isNull() && aPartitionAlgo.isValid()) {
-    return aPartitionAlgo.shape();
+  TopoDS_Compound aResCompound;
+  TopoDS_Builder aBuilder;
+  aBuilder.MakeCompound(aResCompound);
+
+  TopTools_MapOfShape anAlreadyThere; // to avoid duplications if it was produced by two arguments
+
+  // flag to add to result also results which were not produced by any argument
+  bool aNotProduced = true;
+  TopTools_ListOfShape::Iterator anArgs(theOperation->Arguments());
+  while(aNotProduced || anArgs.More()) {
+    // collect shapes that were produced from the current argument
+    TopTools_MapOfShape aProducedByArg;
+    if (anArgs.More()) {
+      TopTools_ListOfShape allArgs;
+      getHistorySupportedType(anArgs.Value(), allArgs);
+      for (TopTools_ListOfShape::Iterator argsIter(allArgs); argsIter.More(); argsIter.Next()) {
+        // if argument was not modified, it is fully in the result
+        aProducedByArg.Add(argsIter.Value());
+        const TopTools_ListOfShape& aModified = theOperation->Modified(argsIter.Value());
+        for (TopTools_ListOfShape::Iterator aModIter(aModified); aModIter.More(); aModIter.Next()) {
+          aProducedByArg.Add(aModIter.Value());
+        }
+        const TopTools_ListOfShape& aGenerated = theOperation->Generated(argsIter.Value());
+        for (TopTools_ListOfShape::Iterator aGenIter(aGenerated); aGenIter.More(); aGenIter.Next())
+        {
+          aProducedByArg.Add(aGenIter.Value());
+        }
+      }
+      anArgs.Next();
+    }
+    else {
+      aNotProduced = false;
+    }
+
+    ListOfShape aCombiningShapes;
+    for (TopoDS_Iterator anIt(theCompound); anIt.More(); anIt.Next()) {
+      bool aProducedContains = false;
+      if (aNotProduced) { // collect all supported type-shapes of result
+        TopTools_ListOfShape allRes;
+        getHistorySupportedType(anIt.Value(), allRes);
+        for (TopTools_ListOfShape::Iterator aResIter(allRes); aResIter.More(); aResIter.Next()) {
+          if (aProducedByArg.Contains(aResIter.Value())) {
+            aProducedContains = true;
+            break;
+          }
+        }
+      }
+      if ((!aNotProduced || aProducedContains) && anAlreadyThere.Add(anIt.Value())) {
+        GeomShapePtr aSub(new GeomAPI_Shape);
+        aSub->setImpl(new TopoDS_Shape(anIt.Value()));
+        aCombiningShapes.push_back(aSub);
+      }
+    }
+
+    // sort sub-shapes of compound to stabilize the sequence of the Partition's results
+    GeomAlgoAPI_SortListOfShapes::sort(aCombiningShapes);
+
+    for (ListOfShape::iterator anIt = aCombiningShapes.begin();
+      anIt != aCombiningShapes.end(); ++anIt)
+      aBuilder.Add(aResCompound, (*anIt)->impl<TopoDS_Shape>());
   }
-  return std::shared_ptr<GeomAPI_Shape>();
+
+  theCompound = aResCompound;
 }
 
 //=================================================================================================
 GeomAlgoAPI_Partition::GeomAlgoAPI_Partition(const ListOfShape& theObjects,
-                                             const ListOfShape& theTools)
+                                             const ListOfShape& theTools,
+                                             const double theFuzzy)
 {
-  build(theObjects, theTools);
+  build(theObjects, theTools, theFuzzy);
 }
 
 static void prepareShapes(const TopoDS_Shape&   theShape,
@@ -78,7 +151,8 @@ static void prepareShapes(const TopoDS_Shape&   theShape,
 
 //=================================================================================================
 void GeomAlgoAPI_Partition::build(const ListOfShape& theObjects,
-                                  const ListOfShape& theTools)
+                                  const ListOfShape& theTools,
+                                  const double theFuzzy)
 {
   if (theObjects.empty()) {
     return;
@@ -112,19 +186,28 @@ void GeomAlgoAPI_Partition::build(const ListOfShape& theObjects,
   for (ListOfShape::const_iterator
        aToolsIt = theTools.begin(); aToolsIt != theTools.end(); aToolsIt++) {
     const TopoDS_Shape& aShape = (*aToolsIt)->impl<TopoDS_Shape>();
-    anOperation->AddTool(aShape);
+    // #2419: decompose compounds to get the valid result
+    TopTools_ListOfShape aSimpleShapes;
+    prepareShapes(aShape, aSimpleShapes);
+    TopTools_ListIteratorOfListOfShape aSimpleIter(aSimpleShapes);
+    for (; aSimpleIter.More(); aSimpleIter.Next()) {
+      const TopoDS_Shape& aSimpleSh = aSimpleIter.Value();
+      if (ShapesMap.Add(aSimpleSh)) {
+        anOperation->AddTool(aSimpleSh);
+      }
+    }
   }
 
+  // Set parallel processing mode (default is false)
+  Standard_Boolean bRunParallel = Standard_True;
+  anOperation->SetRunParallel(bRunParallel);
+
+  if (theFuzzy > 0) anOperation->SetFuzzyValue(theFuzzy);
+
   // Building and getting result.
   anOperation->Perform();
-#ifdef USE_OCCT_720
   if (anOperation->HasErrors())
     return;
-#else
-  if(anOperation->ErrorStatus() != 0) {
-    return;
-  }
-#endif
   TopoDS_Shape aResult = anOperation->Shape();
 
   if(aResult.ShapeType() == TopAbs_COMPOUND) {
@@ -173,6 +256,9 @@ void GeomAlgoAPI_Partition::build(const ListOfShape& theObjects,
   }
 
   if(aResult.ShapeType() == TopAbs_COMPOUND) {
+    // sort sub-shapes of compound before creation of a compsolid
+    sortCompound(aResult, anOperation);
+
     std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape);
     aGeomShape->setImpl(new TopoDS_Shape(aResult));
     aResult = GeomAlgoAPI_ShapeTools::groupSharedTopology(aGeomShape)->impl<TopoDS_Shape>();