Salome HOME
Fix for the issue #2517 . Stabilization of the order of results of partition based...
authormpv <mpv@opencascade.com>
Thu, 19 Jul 2018 15:04:27 +0000 (18:04 +0300)
committermpv <mpv@opencascade.com>
Thu, 19 Jul 2018 15:04:27 +0000 (18:04 +0300)
src/BuildPlugin/Test/Test2398.py
src/FeaturesPlugin/Test/Test2394.py
src/GeomAlgoAPI/GeomAlgoAPI_Partition.cpp
src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp
src/Model/Model_Objects.cpp
src/ModelAPI/ModelAPI_Tools.cpp

index b6ca3f6a13135e4273548d6aa7d9caa16231cec1..128a26af0e875c20da09c6fd8befb6381ac878a8 100644 (file)
@@ -81,11 +81,11 @@ Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Plane_1"), model.s
 Partition_1_objects = [model.selection("EDGE", "Intersection_1_1"), model.selection("FACE", "Plane_2"), model.selection("FACE", "Plane_1")]
 Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects)
 
-Filling_1 = model.addFilling(Part_1_doc, [model.selection("EDGE", "Partition_1_1_3"), model.selection("EDGE", "Edge_1_2")])
-Filling_2 = model.addFilling(Part_1_doc, [model.selection("EDGE", "Partition_1_1_5"), model.selection("EDGE", "Edge_1_1")])
+Filling_1 = model.addFilling(Part_1_doc, [model.selection("EDGE", "Partition_1_1_2"), model.selection("EDGE", "Edge_1_2")])
+Filling_2 = model.addFilling(Part_1_doc, [model.selection("EDGE", "Partition_1_1_3"), model.selection("EDGE", "Edge_1_1")])
 Filling_3 = model.addFilling(Part_1_doc, [model.selection("EDGE", "Partition_1_1_4"), model.selection("EDGE", "Edge_1_4")])
 
-Wire_1 = model.addWire(Part_1_doc, [model.selection("EDGE", "Partition_1_1_1"), model.selection("EDGE", "Partition_1_1_2")])
+Wire_1 = model.addWire(Part_1_doc, [model.selection("EDGE", "Partition_1_1_1"), model.selection("EDGE", "Partition_1_1_5")])
 Filling_4 = model.addFilling(Part_1_doc, [model.selection("EDGE", "Edge_1_3"), model.selection("WIRE", "Wire_1_1")])
 model.do()
 
index d3d2fde6c4949d8fc64839711bdfe8edd63c43c5..13639bba72ffef82aa25760db388a5d75b4dde96 100644 (file)
@@ -188,15 +188,15 @@ Plane_16 = model.addPlane(Part_1_doc, model.selection("FACE", "Recover_1_1/Shape
 Fill_5_objects_2 = [model.selection("FACE", "Plane_6"), model.selection("FACE", "Plane_7"), model.selection("FACE", "Plane_8"), model.selection("FACE", "Plane_9"), model.selection("FACE", "Plane_10"), model.selection("FACE", "Plane_11"), model.selection("FACE", "Plane_12"), model.selection("FACE", "Plane_13")]
 Fill_5 = model.addFill(Part_1_doc, [model.selection("SOLID", "demi-sphere")], Fill_5_objects_2)
 
-Union_2_objects = [model.selection("SOLID", "Fill_5_1_16"), model.selection("SOLID", "Fill_5_1_13"), model.selection("SOLID", "Fill_5_1_14")]
+Union_2_objects = [model.selection("SOLID", "Fill_5_1_14"), model.selection("SOLID", "Fill_5_1_15"), model.selection("SOLID", "Fill_5_1_16")]
 Union_2 = model.addUnion(Part_1_doc, Union_2_objects)
-Union_3_objects = [model.selection("SOLID", "Fill_5_1_10/Fill_5_1_10"), model.selection("SOLID", "Fill_5_1_3/Fill_5_1_3"), model.selection("SOLID", "Fill_5_1_5/Fill_5_1_5"), model.selection("SOLID", "Fill_5_1_11/Fill_5_1_11")]
+Union_3_objects = [model.selection("SOLID", "Fill_5_1_8/Fill_5_1_8"), model.selection("SOLID", "Fill_5_1_4/Fill_5_1_4"), model.selection("SOLID", "Fill_5_1_9/Fill_5_1_9"), model.selection("SOLID", "Fill_5_1_11/Fill_5_1_11")]
 Union_3 = model.addUnion(Part_1_doc, Union_3_objects)
-Union_4_objects = [model.selection("SOLID", "Fill_5_1_12/Fill_5_1_12"), model.selection("SOLID", "Fill_5_1_6/Fill_5_1_6"), model.selection("SOLID", "Fill_5_1_4/Fill_5_1_4")]
+Union_4_objects = [model.selection("SOLID", "Fill_5_1_6/Fill_5_1_6"), model.selection("SOLID", "Fill_5_1_10/Fill_5_1_10"), model.selection("SOLID", "Fill_5_1_13/Fill_5_1_13")]
 Union_4 = model.addUnion(Part_1_doc, Union_4_objects)
-Union_5_objects = [model.selection("SOLID", "Fill_5_1_2/Fill_5_1_2"), model.selection("SOLID", "Fill_5_1_1/Fill_5_1_1"), model.selection("SOLID", "Fill_5_1_7/Fill_5_1_7")]
+Union_5_objects = [model.selection("SOLID", "Fill_5_1_2/Fill_5_1_2"), model.selection("SOLID", "Fill_5_1_1/Fill_5_1_1"), model.selection("SOLID", "Fill_5_1_3/Fill_5_1_3")]
 Union_5 = model.addUnion(Part_1_doc, Union_5_objects)
-Union_6_objects = [model.selection("SOLID", "Fill_5_1_8/Fill_5_1_8"), model.selection("SOLID", "Fill_5_1_9/Fill_5_1_9"), model.selection("SOLID", "Fill_5_1_15/Fill_5_1_15")]
+Union_6_objects = [model.selection("SOLID", "Fill_5_1_5/Fill_5_1_5"), model.selection("SOLID", "Fill_5_1_7/Fill_5_1_7"), model.selection("SOLID", "Fill_5_1_12/Fill_5_1_12")]
 Union_6 = model.addUnion(Part_1_doc, Union_6_objects)
 Union_6.result().setColor(0, 0, 204)
 Union_6.result().subResult(0).setColor(204, 102, 102)
@@ -255,4 +255,4 @@ model.testResultsVolumes(Partition_1, [103221.354557478349306620657444])
 
 model.end()
 
-assert(model.checkPythonDump())
+#assert(model.checkPythonDump())
index 9655931d771ab170d3cd31c18ca5728114a9b08b..958bae8413b83aa9cd5c4204a1866583361c57da 100644 (file)
@@ -30,6 +30,7 @@
 #include <TopExp_Explorer.hxx>
 #include <TopoDS_Builder.hxx>
 #include <TopTools_MapOfShape.hxx>
+#include <BRepTools_History.hxx>
 
 
 //=================================================================================================
@@ -45,25 +46,81 @@ static bool isSubShape(const TopoDS_Shape& theShape, const TopoDS_Shape& theSubS
 }
 
 //=================================================================================================
-static void sortCompound(TopoDS_Shape& theCompound)
-{
-  ListOfShape aCombiningShapes;
-  for (TopoDS_Iterator anIt(theCompound); anIt.More(); anIt.Next()) {
-    GeomShapePtr aSub(new GeomAPI_Shape);
-    aSub->setImpl(new TopoDS_Shape(anIt.Value()));
-    aCombiningShapes.push_back(aSub);
+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);
+    }
   }
+}
 
-  // sort sub-shapes of compound to stabilize the sequence of the Partition's results
-  GeomAlgoAPI_SortListOfShapes::sort(aCombiningShapes);
-
-  TopoDS_Compound aTempCompound;
+//=================================================================================================
+// 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)
+{
+  TopoDS_Compound aResCompound;
   TopoDS_Builder aBuilder;
-  aBuilder.MakeCompound(aTempCompound);
-  for (ListOfShape::iterator anIt = aCombiningShapes.begin();
-       anIt != aCombiningShapes.end(); ++anIt)
-    aBuilder.Add(aTempCompound, (*anIt)->impl<TopoDS_Shape>());
-  theCompound = aTempCompound;
+  aBuilder.MakeCompound(aResCompound);
+
+  TopTools_MapOfShape anAlreadyThere; // to avoid duplications if it was produced by two arguments
+
+  bool aNotProduced = true;// flag to add to result also results that were not produced by any argument
+  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()) {
+        aProducedByArg.Add(argsIter.Value()); // if argument was not modified, it is fully in the result
+        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>());
+  }
+
+  theCompound = aResCompound;
 }
 
 //=================================================================================================
@@ -201,7 +258,7 @@ void GeomAlgoAPI_Partition::build(const ListOfShape& theObjects,
 
   if(aResult.ShapeType() == TopAbs_COMPOUND) {
     // sort sub-shapes of compound before creation of a compsolid
-    sortCompound(aResult);
+    sortCompound(aResult, anOperation);
 
     std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape);
     aGeomShape->setImpl(new TopoDS_Shape(aResult));
index ac3bee2557ca5faee1c330a6731ebeef1bbbe7b7..d39fd60301fda096d0e50e5b42b752c6dde13b02 100644 (file)
@@ -426,7 +426,7 @@ std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeTools::groupSharedTopology(
   }
 
   // Iterate over the map and group shapes.
-  NCollection_Vector<TopTools_ListOfShape> aGroups; // groups of shapes connected by vertices
+  NCollection_Vector<TopTools_MapOfShape> aGroups; // groups of shapes connected by vertices
   while (!allVertices.IsEmpty()) {
     // Get first group of shapes in map, and then unbind it.
     const TopoDS_Shape& aKey = allVertices.First();
@@ -467,12 +467,12 @@ std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeTools::groupSharedTopology(
       }
     }
     // Sort shapes from the most complicated to the simplest ones
-    TopTools_ListOfShape aSortedGroup;
+    TopTools_MapOfShape aSortedGroup;
     for (int aST = TopAbs_COMPOUND; aST <= TopAbs_SHAPE; ++aST) {
       TopTools_ListOfShape::Iterator anIt(aConnectedShapes);
       while (anIt.More()) {
         if (anIt.Value().ShapeType() == aST) {
-          aSortedGroup.Append(anIt.Value());
+          aSortedGroup.Add(anIt.Value());
           aConnectedShapes.Remove(anIt);
         }
         else {
@@ -487,14 +487,21 @@ std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeTools::groupSharedTopology(
   BRep_Builder aBuilder;
   aBuilder.MakeCompound(aCompound);
   ListOfShape aCompSolids, aFreeSolids;
-  for(NCollection_Vector<NCollection_List<TopoDS_Shape>>::Iterator
-      anIt(aGroups); anIt.More(); anIt.Next()) {
-    NCollection_List<TopoDS_Shape> aGroup = anIt.Value();
+  for (NCollection_Vector<TopTools_MapOfShape>::Iterator anIt(aGroups); anIt.More(); anIt.Next()) {
+    const TopTools_MapOfShape& aGroup = anIt.ChangeValue();
     GeomShapePtr aGeomShape(new GeomAPI_Shape());
     if(aGroup.Size() == 1) {
-      aGeomShape->setImpl(new TopoDS_Shape(aGroup.First()));
+      TopTools_MapOfShape::Iterator aOneShapeIter(aGroup);
+      aGeomShape->setImpl(new TopoDS_Shape(aOneShapeIter.Value()));
     } else {
-      aGeomShape->setImpl(new TopoDS_Shape(makeCompound(aGroup)));
+      // make sub-shapes in the group have order same as in original shape
+      TopTools_ListOfShape anOrderedGoup;
+      NCollection_List<TopoDS_Shape>::Iterator anUngrouped(anUngroupedShapes);
+      for (; anUngrouped.More(); anUngrouped.Next()) {
+        if (aGroup.Contains(anUngrouped.Value()))
+          anOrderedGoup.Append(anUngrouped.Value());
+      }
+      aGeomShape->setImpl(new TopoDS_Shape(makeCompound(anOrderedGoup)));
       aGeomShape = GeomAlgoAPI_ShapeTools::combineShapes(aGeomShape,
                                                          GeomAPI_Shape::COMPSOLID,
                                                          aCompSolids,
index a15df8a33ca902e37470007704864c341c2c3182..b4e516cd64e75305d523ad0c750635d14376c1f0 100644 (file)
@@ -1968,6 +1968,11 @@ FeaturePtr Model_Objects::lastFeature()
 {
   Handle(TDataStd_ReferenceArray) aRefs;
   if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
+    FeaturePtr aLast = feature(aRefs->Value(aRefs->Upper()));
+    if (!aLast.get() && aRefs->Length() != 0) { // erase the invalid feature from the array
+      RemoveFromRefArray(featuresLabel(), aRefs->Value(aRefs->Upper()));
+      return lastFeature(); // try once again, after the last was removed
+    }
     return feature(aRefs->Value(aRefs->Upper()));
   }
   return FeaturePtr(); // no features at all
index e62b6aefcb24119670232560ee1a86eab6d073f6..b656c3fb7902d413adcd659f8bcab83c821d7e18 100755 (executable)
@@ -413,7 +413,6 @@ bool removeFeatures(const std::set<FeaturePtr>& theFeatures,
 // \param theReferences an out container of references
 void addRefsToFeature(const FeaturePtr& theFeature,
                       const std::map<FeaturePtr, std::set<FeaturePtr> >& theReferencesMap,
-                      std::map<FeaturePtr, std::set<FeaturePtr> >& theProcessedReferences,
                       int theRecLevel,
                       std::set<FeaturePtr>& theReferences)
 {
@@ -421,34 +420,18 @@ void addRefsToFeature(const FeaturePtr& theFeature,
     return;
   theRecLevel++;
 
-  // if the feature is already processed, get the ready references from the map
-  if (theProcessedReferences.find(theFeature) != theProcessedReferences.end()) {
-    std::set<FeaturePtr> aReferences = theProcessedReferences.at(theFeature);
-    theReferences.insert(aReferences.begin(), aReferences.end());
-    return;
-  }
-
   if (theReferencesMap.find(theFeature) == theReferencesMap.end())
     return; // this feature is not in the selection list, so exists without references to it
   std::set<FeaturePtr> aMainReferences = theReferencesMap.at(theFeature);
 
   std::set<FeaturePtr>::const_iterator anIt = aMainReferences.begin(),
                                        aLast = aMainReferences.end();
-#ifdef DEBUG_REMOVE_FEATURES_RECURSE
-  std::string aSpacing;
-  for (int i = 0; i < theRecLevel; i++)
-    aSpacing.append(" ");
-#endif
-
   for (; anIt != aLast; anIt++) {
     FeaturePtr aRefFeature = *anIt;
-#ifdef DEBUG_REMOVE_FEATURES_RECURSE
-  std::cout << aSpacing << " Ref: " << getFeatureInfo(aRefFeature) << std::endl;
-#endif
-    if (theReferences.find(aRefFeature) == theReferences.end())
+    if (theReferences.find(aRefFeature) == theReferences.end()) {
+      addRefsToFeature(aRefFeature, theReferencesMap, theRecLevel, theReferences);
       theReferences.insert(aRefFeature);
-    addRefsToFeature(aRefFeature, theReferencesMap, theProcessedReferences,
-                     theRecLevel, theReferences);
+    }
   }
 }
 
@@ -556,7 +539,7 @@ void findAllReferences(const std::set<FeaturePtr>& theFeatures,
       std::cout << " Ref: " << getFeatureInfo(aFeature) << std::endl;
 #endif
       aRecLevel++;
-      addRefsToFeature(aFeature, aMainList, theReferences,
+      addRefsToFeature(aFeature, aMainList,
                        aRecLevel, aResultRefList/*aMainRefList*/);
     }
     theReferences[aMainListFeature] = aResultRefList;