Salome HOME
Issue #2308: 1.1.2.4 Faces in “Union”
authordbv <dbv@opencascade.com>
Wed, 29 Nov 2017 16:36:59 +0000 (19:36 +0300)
committerdbv <dbv@opencascade.com>
Wed, 29 Nov 2017 16:37:16 +0000 (19:37 +0300)
Now Union allows to select faces with shared edges. Only results and sub-results allowed for selection.

src/FeaturesPlugin/CMakeLists.txt
src/FeaturesPlugin/FeaturesPlugin_Union.cpp
src/FeaturesPlugin/FeaturesPlugin_Validators.cpp
src/FeaturesPlugin/Test/TestUnionFaces.py [new file with mode: 0644]
src/FeaturesPlugin/union_widget.xml
src/GeomAlgoAPI/CMakeLists.txt
src/GeomAlgoAPI/GeomAlgoAPI_UnifySameDomain.cpp [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_UnifySameDomain.h [new file with mode: 0644]

index 81552dd4c0bb078bf4ff638fcac386a27e7f95d7..d527286bb8f73fc659bddf2c70240d84f1ceef29 100644 (file)
@@ -161,6 +161,7 @@ ADD_UNIT_TESTS(TestExtrusion.py
                TestSerialBoolean.py
                TestIntersection.py
                TestUnion.py
+               TestUnionFaces.py
                TestRemoveSubShapes.py
                TestRemoveSubShapes2.py
                TestPipe.py
index 2b3188ddcbd4d5f4fcc439063fa034cc734974a5..66bef610ccf6784882a93a7291050995f306fa57 100644 (file)
 #include <GeomAlgoAPI_Boolean.h>
 #include <GeomAlgoAPI_MakeShapeList.h>
 #include <GeomAlgoAPI_PaveFiller.h>
+#include <GeomAlgoAPI_UnifySameDomain.h>
 
 #include <GeomAPI_ShapeExplorer.h>
+#include <GeomAPI_ShapeIterator.h>
 
 #include <ModelAPI_AttributeSelectionList.h>
 #include <ModelAPI_ResultCompSolid.h>
@@ -87,7 +89,7 @@ void FeaturesPlugin_Union::execute()
     anObjects.insert(anObjects.end(), aUsedInOperationSolids.begin(), aUsedInOperationSolids.end());
 
     // Collect solids from compsolid which will not be modified in boolean operation.
-    for(GeomAPI_ShapeExplorer anExp(aCompSolid, GeomAPI_Shape::SOLID); anExp.more(); anExp.next()) {
+    for(GeomAPI_ShapeIterator anExp(aCompSolid); anExp.more(); anExp.next()) {
       std::shared_ptr<GeomAPI_Shape> aSolidInCompSolid = anExp.current();
       ListOfShape::iterator anIt = aUsedInOperationSolids.begin();
       for(; anIt != aUsedInOperationSolids.end(); anIt++) {
@@ -107,31 +109,36 @@ void FeaturesPlugin_Union::execute()
   }
 
   // Fuse objects.
+  std::shared_ptr<GeomAlgoAPI_MakeShape> anAlgo;
   ListOfShape aTools;
-  aTools.splice(aTools.begin(), anObjects, anObjects.begin());
-  std::shared_ptr<GeomAlgoAPI_Boolean> aFuseAlgo(new GeomAlgoAPI_Boolean(anObjects,
-                                                            aTools,
-                                                            GeomAlgoAPI_Boolean::BOOL_FUSE));
+  if (anObjects.front()->shapeType() == GeomAPI_Shape::SOLID) {
+    aTools.splice(aTools.begin(), anObjects, anObjects.begin());
+    anAlgo.reset(new GeomAlgoAPI_Boolean(anObjects,
+                 aTools,
+                 GeomAlgoAPI_Boolean::BOOL_FUSE));
+  } else {
+    anAlgo.reset(new GeomAlgoAPI_UnifySameDomain(anObjects));
+  }
 
   // Checking that the algorithm worked properly.
   GeomAlgoAPI_MakeShapeList aMakeShapeList;
   GeomAPI_DataMapOfShapeShape aMapOfShapes;
-  if(!aFuseAlgo->isDone()) {
+  if(!anAlgo->isDone()) {
     setError("Error: Boolean algorithm failed.");
     return;
   }
-  if(aFuseAlgo->shape()->isNull()) {
+  if(anAlgo->shape()->isNull()) {
     setError("Error: Resulting shape is Null.");
     return;
   }
-  if(!aFuseAlgo->isValid()) {
+  if(!anAlgo->isValid()) {
     setError("Error: Resulting shape is not valid.");
     return;
   }
 
-  GeomShapePtr aShape = aFuseAlgo->shape();
-  aMakeShapeList.appendAlgo(aFuseAlgo);
-  aMapOfShapes.merge(aFuseAlgo->mapOfSubShapes());
+  GeomShapePtr aShape = anAlgo->shape();
+  aMakeShapeList.appendAlgo(anAlgo);
+  aMapOfShapes.merge(anAlgo->mapOfSubShapes());
 
   // Store original shapes for naming.
   anObjects.splice(anObjects.begin(), aTools);
@@ -161,18 +168,21 @@ void FeaturesPlugin_Union::execute()
   }
 
   // Store result and naming.
-  const int aModifyTag = 1;
-  const int aDeletedTag = 2;
-  /// sub solids will be placed at labels 3, 4, etc. if result is compound of solids
-  const int aSubsolidsTag = 3;
+  const int aModifyEdgeTag = 1;
+  const int aModifyFaceTag = 2;
+  const int aDeletedTag = 3;
+  /// sub solids will be placed at labels 4, 5 etc. if result is compound of solids
+  const int aSubsolidsTag = 4;
   const std::string aModName = "Modified";
 
   std::shared_ptr<ModelAPI_ResultBody> aResultBody = document()->createBody(data());
   aResultBody->storeModified(anObjects.front(), aShape, aSubsolidsTag);
 
   for(ListOfShape::const_iterator anIter = anObjects.begin(); anIter != anObjects.end(); ++anIter) {
+    aResultBody->loadAndOrientModifiedShapes(&aMakeShapeList, *anIter, GeomAPI_Shape::EDGE,
+                                             aModifyEdgeTag, aModName, aMapOfShapes);
     aResultBody->loadAndOrientModifiedShapes(&aMakeShapeList, *anIter, GeomAPI_Shape::FACE,
-                                             aModifyTag, aModName, aMapOfShapes);
+                                             aModifyFaceTag, aModName, aMapOfShapes);
     aResultBody->loadDeletedShapes(&aMakeShapeList, *anIter, GeomAPI_Shape::FACE, aDeletedTag);
   }
 
index ddcdfacf20b3ffc666907b81ced3ef6328998b79..853037100234b21d18cd5330d293e58593c780bd 100644 (file)
@@ -845,11 +845,28 @@ bool FeaturesPlugin_ValidatorUnionSelection::isValid(const AttributePtr& theAttr
   for(int anIndex = 0; anIndex < aBaseObjectsAttrList->size(); ++anIndex) {
     bool isSameFound = false;
     AttributeSelectionPtr anAttrSelectionInList = aBaseObjectsAttrList->value(anIndex);
+    ResultPtr aContext = anAttrSelectionInList->context();
+
+    ResultConstructionPtr aConstruction =
+      std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
+    if(aConstruction.get()) {
+      theError = "Error: Result construction not allowed for selection.";
+      return false;
+    }
+
+    GeomShapePtr aShape = anAttrSelectionInList->value();
+    GeomShapePtr aContextShape = aContext->shape();
+    if (aShape.get() && aContextShape.get() && !aContextShape->isEqual(aShape)) {
+      theError = "Error: Local selection not allowed.";
+      return false;
+    }
+
     ResultCompSolidPtr aResult =
-      std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(anAttrSelectionInList->context());
+      std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aContext);
     if(!aResult.get()) {
       continue;
     }
+
     if(aResult->numberOfSubs() > 0) {
       theError = "Error: Whole compsolids not allowed for selection.";
       return false;
@@ -882,17 +899,27 @@ bool FeaturesPlugin_ValidatorUnionArguments::isValid(
   }
 
   // Get all shapes.
+  GeomAPI_Shape::ShapeType aType = GeomAPI_Shape::COMPSOLID;
   ListOfShape aBaseShapesList;
   for(int anIndex = 0; anIndex < aBaseObejctsAttrList->size(); ++anIndex) {
     AttributeSelectionPtr anAttrSelectionInList = aBaseObejctsAttrList->value(anIndex);
     GeomShapePtr aShape = anAttrSelectionInList->value();
+    if (!aShape.get()) {
+      continue;
+    }
     aBaseShapesList.push_back(aShape);
+    aType = aShape->shapeType() == GeomAPI_Shape::FACE ? GeomAPI_Shape::SHELL :
+                                                         GeomAPI_Shape::COMPSOLID;
   }
 
-  // Make componud and find connected.
+  // Make compound and find connected.
   GeomShapePtr aCompound = GeomAlgoAPI_CompoundBuilder::compound(aBaseShapesList);
   ListOfShape aCombined, aFree;
-  GeomAlgoAPI_ShapeTools::combineShapes(aCompound, GeomAPI_Shape::COMPSOLID, aCombined, aFree);
+  GeomAlgoAPI_ShapeTools::combineShapes(
+    aCompound,
+    aType,
+    aCombined,
+    aFree);
 
   if(aFree.size() > 0 || aCombined.size() > 1) {
     theError = "Error: Not all shapes have shared topology.";
diff --git a/src/FeaturesPlugin/Test/TestUnionFaces.py b/src/FeaturesPlugin/Test/TestUnionFaces.py
new file mode 100644 (file)
index 0000000..3bbd55f
--- /dev/null
@@ -0,0 +1,45 @@
+## Copyright (C) 2014-2017  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
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## 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
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchCircle_1 = Sketch_1.addCircle(-5.197255574614073, 0.1732418524871273, 67.586529314451)
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchCircle_1_2")])
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("FACE", "Face_1_1"), model.selection("FACE", "PartSet/YOZ"), model.selection("FACE", "PartSet/XOZ")])
+Union_1 = model.addUnion(Part_1_doc, [model.selection("FACE", "Partition_1_1_3"), model.selection("FACE", "Partition_1_1_4")])
+model.do()
+model.end()
+
+from GeomAPI import GeomAPI_Shape
+
+model.testNbResults(Union_1, 1)
+model.testNbSubResults(Union_1, [3])
+model.testNbSubShapes(Union_1, GeomAPI_Shape.SOLID, [0])
+model.testNbSubShapes(Union_1, GeomAPI_Shape.FACE, [3])
+model.testNbSubShapes(Union_1, GeomAPI_Shape.EDGE, [10])
+model.testNbSubShapes(Union_1, GeomAPI_Shape.VERTEX, [20])
+
+assert(model.checkPythonDump())
index 1de6e9a6ea243d82ed5026a01d94c50fdd2c5050..2d14a54bd2515186a1ed85813ce7a01d0f8b7bdd 100644 (file)
@@ -23,7 +23,7 @@ email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com
   <multi_selector id="base_objects"
     label="Base objects:"
     tooltip="Select solids for union."
-    type_choice="solids compsolids"
+    type_choice="faces solids compsolids"
     use_choice="false"
     concealment="true">
     <validator id="FeaturesPlugin_ValidatorUnionSelection"/>
index 78ca7b9d6f3d226184b19d46e5327797c9de3204..aa563452be9c29f5aa92b63c8de5e1b16c97aab6 100644 (file)
@@ -73,6 +73,7 @@ SET(PROJECT_HEADERS
     GeomAlgoAPI_Symmetry.h
     GeomAlgoAPI_Scale.h
     GeomAlgoAPI_Circ2dBuilder.h
+    GeomAlgoAPI_UnifySameDomain.h
 )
 
 SET(PROJECT_SOURCES
@@ -124,6 +125,7 @@ SET(PROJECT_SOURCES
     GeomAlgoAPI_Symmetry.cpp
     GeomAlgoAPI_Scale.cpp
     GeomAlgoAPI_Circ2dBuilder.cpp
+    GeomAlgoAPI_UnifySameDomain.cpp
 )
 
 SET(PROJECT_LIBRARIES
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_UnifySameDomain.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_UnifySameDomain.cpp
new file mode 100644 (file)
index 0000000..8e8238a
--- /dev/null
@@ -0,0 +1,106 @@
+// Copyright (C) 2014-2017  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
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// 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
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "GeomAlgoAPI_UnifySameDomain.h"
+
+#include <GeomAlgoAPI_CompoundBuilder.h>
+#include <GeomAlgoAPI_ShapeTools.h>
+
+#include <ShapeUpgrade_UnifySameDomain.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS_Shape.hxx>
+
+//==================================================================================================
+GeomAlgoAPI_UnifySameDomain::GeomAlgoAPI_UnifySameDomain(const ListOfShape& theShapes)
+{
+  build(theShapes);
+}
+
+void GeomAlgoAPI_UnifySameDomain::build(const ListOfShape& theShapes)
+{
+  if(theShapes.empty()) {
+    return;
+  }
+
+  // Make compound.
+  GeomShapePtr aCompound = GeomAlgoAPI_CompoundBuilder::compound(theShapes);
+  ListOfShape aCombined, aFree;
+  GeomAlgoAPI_ShapeTools::combineShapes(
+    aCompound,
+    GeomAPI_Shape::SHELL,
+    aCombined,
+    aFree);
+
+  if(aFree.size() > 0 || aCombined.size() > 1) {
+    return;
+  }
+
+  const TopoDS_Shape& aShell = aCombined.front()->impl<TopoDS_Shape>();
+
+  ShapeUpgrade_UnifySameDomain* aUnifyAlgo = new ShapeUpgrade_UnifySameDomain();
+  this->setImpl(aUnifyAlgo);
+
+  aUnifyAlgo->Initialize(aShell);
+  aUnifyAlgo->UnifyFacesAndEdges();
+  aUnifyAlgo->Build();
+
+  TopoDS_Shape aResult = aUnifyAlgo->Shape();
+  if (aResult.IsNull()) {
+    return;
+  }
+
+  if (aResult.ShapeType() == TopAbs_SHELL) {
+    int aNb = 0;
+    TopoDS_Iterator anIt(aResult);
+    for (; anIt.More(); anIt.Next()) {
+      ++aNb;
+    }
+
+    if (aNb == 1) {
+      anIt.Initialize(aResult);
+      aResult = anIt.Value();
+    }
+  }
+
+  std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape());
+  aShape->setImpl(new TopoDS_Shape(aResult));
+  this->setShape(aShape);
+  this->setDone(true);
+}
+
+//==================================================================================================
+void GeomAlgoAPI_UnifySameDomain::modified(const std::shared_ptr<GeomAPI_Shape> theShape,
+                                  ListOfShape& theHistory)
+{
+  if(!theShape.get()) {
+    return;
+  }
+
+  const TopoDS_Shape& aShape = theShape->impl<TopoDS_Shape>();
+  const ShapeUpgrade_UnifySameDomain& aUnifyAlgo = this->impl<ShapeUpgrade_UnifySameDomain>();
+
+  TopoDS_Shape aModifiedShape = aUnifyAlgo.Generated(aShape);
+
+  for(TopExp_Explorer anExp(aModifiedShape, aShape.ShapeType()); anExp.More(); anExp.Next()) {
+    GeomShapePtr aGeomShape(new GeomAPI_Shape());
+    aGeomShape->setImpl(new TopoDS_Shape(anExp.Current()));
+    theHistory.push_back(aGeomShape);
+  }
+}
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_UnifySameDomain.h b/src/GeomAlgoAPI/GeomAlgoAPI_UnifySameDomain.h
new file mode 100644 (file)
index 0000000..a183666
--- /dev/null
@@ -0,0 +1,49 @@
+// Copyright (C) 2014-2017  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
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// 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
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef GeomAlgoAPI_UnifySameDomain_H_
+#define GeomAlgoAPI_UnifySameDomain_H_
+
+#include "GeomAlgoAPI.h"
+#include "GeomAlgoAPI_MakeShape.h"
+
+#include <GeomAPI_Shape.h>
+
+/// \class GeomAlgoAPI_UnifySameDomain
+/// \ingroup DataAlgo
+/// \brief This tool tries to unify faces and edges of the shape which lies on the same geometry.
+class GeomAlgoAPI_UnifySameDomain: public GeomAlgoAPI_MakeShape
+{
+public:
+  /// Constructor.
+  GEOMALGOAPI_EXPORT GeomAlgoAPI_UnifySameDomain(const ListOfShape& theShapes);
+
+  /// \return the list of shapes modified from the shape \a theShape.
+  /// \param[in] theShape base shape.
+  /// \param[out] theHistory modified shapes.
+  GEOMALGOAPI_EXPORT virtual void modified(const std::shared_ptr<GeomAPI_Shape> theShape,
+                                           ListOfShape& theHistory);
+
+private:
+  /// Builds resulting shape.
+  void build(const ListOfShape& theShapes);
+};
+
+#endif