Salome HOME
Merge branch 'BR_internationalization'
authorvsv <vitaly.smetannikov@opencascade.com>
Tue, 7 Jun 2016 09:31:09 +0000 (12:31 +0300)
committervsv <vitaly.smetannikov@opencascade.com>
Tue, 7 Jun 2016 09:31:09 +0000 (12:31 +0300)
Conflicts:
src/Model/Model_SelectionNaming.cpp
src/ModuleBase/ModuleBase_Tools.cpp

106 files changed:
CMakeLists.txt
solver.sh
src/BuildPlugin/BuildPlugin_Face.cpp
src/BuildPlugin/BuildPlugin_SubShapes.cpp
src/BuildPlugin/BuildPlugin_Wire.cpp
src/BuildPlugin/subshapes_widget.xml
src/Config/CMakeLists.txt
src/FeaturesPlugin/CMakeLists.txt
src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.cpp
src/FeaturesPlugin/FeaturesPlugin_Partition.cpp
src/FeaturesPlugin/FeaturesPlugin_Pipe.cpp
src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp
src/FeaturesPlugin/FeaturesPlugin_RemoveSubShapes.cpp [new file with mode: 0644]
src/FeaturesPlugin/FeaturesPlugin_RemoveSubShapes.h [new file with mode: 0644]
src/FeaturesPlugin/FeaturesPlugin_Validators.cpp
src/FeaturesPlugin/FeaturesPlugin_Validators.h
src/FeaturesPlugin/boolean_widget.xml
src/FeaturesPlugin/extrusion_widget.xml
src/FeaturesPlugin/extrusionfuse_widget.xml
src/FeaturesPlugin/icons/remove_subshapes.png [new file with mode: 0644]
src/FeaturesPlugin/partition_widget.xml
src/FeaturesPlugin/pipe_widget.xml
src/FeaturesPlugin/plugin-Features.xml
src/FeaturesPlugin/remove_subshapes_widget.xml [new file with mode: 0644]
src/FeaturesPlugin/revolution_widget.xml
src/FeaturesPlugin/revolutionfuse_widget.xml
src/GeomAPI/GeomAPI_Shape.cpp
src/GeomAlgoAPI/GeomAlgoAPI_MakeSweep.h
src/GeomAlgoAPI/GeomAlgoAPI_Pipe.cpp
src/GeomAlgoAPI/GeomAlgoAPI_Prism.cpp
src/GeomAlgoAPI/GeomAlgoAPI_Revolution.cpp
src/GeomAlgoAPI/GeomAlgoAPI_ShapeBuilder.cpp
src/GeomAlgoAPI/GeomAlgoAPI_ShapeBuilder.h
src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp
src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h
src/GeomValidators/CMakeLists.txt
src/GeomValidators/GeomValidators_BodyShapes.cpp
src/GeomValidators/GeomValidators_MinObjectsSelected.cpp [new file with mode: 0644]
src/GeomValidators/GeomValidators_MinObjectsSelected.h [new file with mode: 0644]
src/GeomValidators/GeomValidators_Plugin.cpp
src/GeomValidators/GeomValidators_ShapeType.cpp
src/GeomValidators/GeomValidators_ShapeType.h
src/Model/Model_AttributeRefAttrList.cpp
src/Model/Model_Document.cpp
src/Model/Model_ResultBody.cpp
src/Model/Model_ResultBody.h
src/Model/Model_SelectionNaming.cpp
src/Model/Model_Update.cpp
src/ModelAPI/CMakeLists.txt
src/ModelAPI/ModelAPI.i
src/ModelAPI/ModelAPI_ResultBody.cpp
src/ModelAPI/ModelAPI_ResultBody.h
src/ModelAPI/ModelAPI_Tools.cpp
src/ModelAPI/ModelAPI_Tools.h
src/ModelAPI/Test/Test1512.py [new file with mode: 0755]
src/ModuleBase/CMakeLists.txt
src/ModuleBase/ModuleBase_Dialog.cpp
src/ModuleBase/ModuleBase_Dialog.h
src/ModuleBase/ModuleBase_FilterValidated.cpp
src/ModuleBase/ModuleBase_IModule.h
src/ModuleBase/ModuleBase_ModelDialogWidget.h [new file with mode: 0644]
src/ModuleBase/ModuleBase_ModelWidget.cpp
src/ModuleBase/ModuleBase_ModelWidget.h
src/ModuleBase/ModuleBase_OperationFeature.cpp
src/ModuleBase/ModuleBase_ResultPrs.cpp
src/ModuleBase/ModuleBase_Tools.cpp
src/ModuleBase/ModuleBase_Tools.h
src/ParametersPlugin/ParametersPlugin_EvalListener.cpp
src/ParametersPlugin/ParametersPlugin_WidgetParamsMgr.cpp
src/ParametersPlugin/ParametersPlugin_WidgetParamsMgr.h
src/PartSet/PartSet_IconFactory.cpp
src/PartSet/PartSet_Module.cpp
src/PartSet/PartSet_Module.h
src/PartSet/PartSet_OperationPrs.cpp
src/PartSet/PartSet_ResultSketchPrs.cpp
src/PartSet/PartSet_ResultSketchPrs.h
src/PartSet/PartSet_SketcherMgr.cpp
src/PartSet/PartSet_SketcherMgr.h
src/PartSet/PartSet_Validators.cpp
src/PythonAPI/examples/Platine.py
src/SketchPlugin/SketchPlugin_Arc.cpp
src/SketchPlugin/plugin-Sketch.xml
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Builder.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ParameterWrapper.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp
src/SketchSolver/SketchSolver_ConstraintMiddle.cpp
src/SketchSolver/SketchSolver_ConstraintMirror.cpp
src/SketchSolver/SketchSolver_Group.cpp
src/SketchSolver/SketchSolver_Manager.cpp
src/SketchSolver/SketchSolver_Storage.cpp
src/SketchSolver/SketchSolver_Storage.h
src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Storage.cpp
src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Storage.h
src/SketcherPrs/SketcherPrs_Tools.h
src/XGUI/XGUI_ContextMenuMgr.h
src/XGUI/XGUI_DataModel.cpp
src/XGUI/XGUI_Displayer.cpp
src/XGUI/XGUI_ModuleConnector.cpp
src/XGUI/XGUI_ObjectsBrowser.cpp
src/XGUI/XGUI_OperationMgr.cpp
src/XGUI/XGUI_PropertyPanel.cpp
src/XGUI/XGUI_SelectionMgr.cpp
src/XGUI/XGUI_Tools.cpp
src/XGUI/XGUI_Tools.h
src/XGUI/XGUI_Workshop.cpp

index 30d8f301d275df269f1c64e3223da6def76b09c9..4a24cfde48c3e721a172bf80bec93ac8b52b5e15 100644 (file)
@@ -1,7 +1,7 @@
 CMAKE_MINIMUM_REQUIRED(VERSION 2.8.10)
 
 PROJECT (SHAPER)
-SET (SHAPER_Version 2.3.0)
+SET (SHAPER_Version 2.3.1)
 
 SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMakeCommon" ${CMAKE_MODULE_PATH})
 
index 2e6ed445ee3c0c059f76d14b9dc27b491e0bc173..98482e8ddd1f76377475c38835374989a21e9a2f 100755 (executable)
--- a/solver.sh
+++ b/solver.sh
@@ -2,7 +2,7 @@
 #
 # Modify plugins.xml to switch solver
 
-export PLUGINS_PATH=${PLUGINS_PATH:-${SHAPER_ROOT_DIR}/plugins/plugins.xml}
+export PLUGINS_PATH=${PLUGINS_PATH:-${SHAPER_ROOT_DIR}/share/salome/resources/shaper/plugins.xml}
 
 while [[ $# > 0 ]]; do
   key="$1"
index 14314ddbaaa2e77f71989bcef38dac407d780bf4..fddd223f053a505c2d48cb5b063e7b2a70dbb38f 100644 (file)
@@ -65,9 +65,13 @@ void BuildPlugin_Face::execute()
   // Get wires from faces.
   ListOfShape aWires;
   for(ListOfShape::const_iterator anIt = aFaces.cbegin(); anIt != aFaces.cend(); ++anIt) {
-    for(GeomAPI_ShapeExplorer anExp(*anIt, GeomAPI_Shape::WIRE); anExp.more(); anExp.next()) {
-      aWires.push_back(anExp.current());
-    }
+    aWires.push_back(GeomAlgoAPI_ShapeTools::getFaceOuterWire(*anIt));
+    //for(GeomAPI_ShapeExplorer anExp(*anIt, GeomAPI_Shape::WIRE); anExp.more(); anExp.next()) {
+    //  if(anExp.current()->orientation() == GeomAPI_Shape::REVERSED) {
+    //    continue;
+    //  }
+    //  aWires.push_back(anExp.current());
+    //}
   }
 
   // Make faces with holes.
index 000fb19e34cb48c77d0abdb621c4ee4416f3ae9e..ebbe753ba399013a53324d0db56337176fe8d58c 100644 (file)
@@ -42,10 +42,11 @@ void BuildPlugin_SubShapes::attributeChanged(const std::string& theID)
     if(!aShapeAttrSelection.get() || !aSubShapesAttrList.get()) {
       return;
     }
-    ResultPtr aContext = aShapeAttrSelection->context();
 
     aSubShapesAttrList->clear();
 
+    ResultPtr aContext = aShapeAttrSelection->context();
+
     GeomShapePtr aBaseShape = aShapeAttrSelection->value();
     if(!aBaseShape.get()) {
       return;
@@ -103,7 +104,7 @@ void BuildPlugin_SubShapes::execute()
 
   // Copy sub-shapes from list to new shape.
   if(!aShapesToAdd.empty()) {
-    aBuilder.add(aResultShape, aShapesToAdd);
+    aBuilder.addInternal(aResultShape, aShapesToAdd);
     aResultShape = aBuilder.shape();
   }
 
index f16de3d49394a013c0c375077ee6d0ee2f755979..6acb80b235d9adaa03896da81799fbe910459172 100644 (file)
@@ -150,28 +150,29 @@ bool BuildPlugin_Wire::addContour()
     std::shared_ptr<GeomAPI_Edge> anEdgeInList(new GeomAPI_Edge(aSelection->value()));
 
     ResultConstructionPtr aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aSelection->context());
-    std::shared_ptr<GeomAPI_PlanarEdges> aPlanarEdges = std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aConstruction->shape());
 
-    // Iterate on faces and add face with this edge.
-    std::shared_ptr<GeomAPI_Face> aFoundFace;
+    // Iterate on wires and add wire with this edge.
+    std::shared_ptr<GeomAPI_Shape> aFoundWire;
     for(int anIndex = 0; anIndex < aConstruction->facesNum(); ++anIndex) {
       std::shared_ptr<GeomAPI_Face> aFace = aConstruction->face(anIndex);
-      for(GeomAPI_ShapeExplorer anExp(aFace, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
-        std::shared_ptr<GeomAPI_Edge> anEdgeOnFace(new GeomAPI_Edge(anExp.current()));
-        if(anEdgeInList->isEqual(anEdgeOnFace)) {
-          aFoundFace = aFace;
-          break;
+      for(GeomAPI_ShapeExplorer aWireExp(aFace, GeomAPI_Shape::WIRE); aWireExp.more(); aWireExp.next()) {
+        GeomShapePtr aWireOnFace = aWireExp.current();
+        for(GeomAPI_ShapeExplorer anExp(aWireOnFace, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
+          std::shared_ptr<GeomAPI_Edge> anEdgeOnFace(new GeomAPI_Edge(anExp.current()));
+          if(anEdgeInList->isEqual(anEdgeOnFace)) {
+            aFoundWire = aWireOnFace;
+            break;
+          }
         }
       }
-
-      if(aFoundFace.get()) {
+      if(aFoundWire.get()) {
         break;
       }
     }
 
-    // If face with the same edge found. Add all other edges to list.
-    if(aFoundFace.get()) {
-      for(GeomAPI_ShapeExplorer anExp(aFoundFace, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
+    // If wire with the same edge found. Add all other edges to list.
+    if(aFoundWire.get()) {
+      for(GeomAPI_ShapeExplorer anExp(aFoundWire, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
         std::shared_ptr<GeomAPI_Edge> anEdgeOnFace(new GeomAPI_Edge(anExp.current()));
         ListOfShape::const_iterator anEdgesIt = anAddedEdges.cbegin();
         for(; anEdgesIt != anAddedEdges.cend(); ++anEdgesIt) {
index 2548d39c5484ec1270125e3b6dd5d2dceec70cd8..ec7320e65b4ec858a4455ea2f2df43e2a1b01203 100644 (file)
@@ -5,7 +5,8 @@
                   label="Shape:"
                   tooltip="Select a shape to modify."
                   shape_types="objects"
-                  concealment="true">
+                  concealment="true"
+                  greed="true">
     <validator id="GeomValidators_ShapeType" parameters="wire,face"/>
   </shape_selector>
   <multi_selector id="subshapes"
index 9d82189428ba94308282c6bc36af3658ae0d24ed..5e0123e9c57aca894ffb7004a54f2eb352a6b1e8 100644 (file)
@@ -69,7 +69,7 @@ TARGET_LINK_LIBRARIES(Config ${PROJECT_LIBRARIES})
 # Prepare plugins.xml
 
 # the solver to activate after installation
-SET(DEFAULT_SOLVER "SolveSpace")
+SET(DEFAULT_SOLVER "PlaneGCS")
 
 # the list of all solvers
 SET(SOLVERS "SolveSpace" "PlaneGCS")
index a58b83a3930d37bd0a5ae03ad41c1f246dedf9a5..bb7849f33f0464e876b3917fe67b8cb320ae1f6f 100644 (file)
@@ -26,6 +26,7 @@ SET(PROJECT_HEADERS
     FeaturesPlugin_RevolutionFuse.h
     FeaturesPlugin_ValidatorTransform.h
     FeaturesPlugin_Validators.h
+    FeaturesPlugin_RemoveSubShapes.h
 )
 
 SET(PROJECT_SOURCES
@@ -50,6 +51,7 @@ SET(PROJECT_SOURCES
     FeaturesPlugin_RevolutionFuse.cpp
     FeaturesPlugin_ValidatorTransform.cpp
     FeaturesPlugin_Validators.cpp
+    FeaturesPlugin_RemoveSubShapes.cpp
 )
 
 SET(XML_RESOURCES
@@ -68,6 +70,7 @@ SET(XML_RESOURCES
   placement_widget.xml
   intersection_widget.xml
   pipe_widget.xml
+  remove_subshapes_widget.xml
 )
 
 INCLUDE_DIRECTORIES(
index 309a4bd9d673ab947f8beb6062ec11ca5bf1ea04..fd16671cfcfe941a3881485a93739b894e30e0a3 100644 (file)
 #include <map>
 #include <sstream>
 
+static void storeSubShape(ResultBodyPtr theResultBody,
+                          const GeomShapePtr theShape,
+                          const GeomAPI_Shape::ShapeType theType,
+                          const std::shared_ptr<GeomAPI_DataMapOfShapeShape> theMapOfSubShapes,
+                          const std::string theName,
+                          int& theShapeIndex,
+                          int& theTag);
+
 //=================================================================================================
 void FeaturesPlugin_CompositeSketch::initCompositeSketchAttribtues(const int theInitFlags)
 {
@@ -134,8 +142,7 @@ void FeaturesPlugin_CompositeSketch::getBaseShapes(ListOfShape& theBaseShapesLis
     GeomShapePtr aBaseShape = aBaseObjectSelection->value();
     if(aBaseShape.get() && !aBaseShape->isNull()) {
       GeomAPI_Shape::ShapeType aST = aBaseShape->shapeType();
-      if(aST != GeomAPI_Shape::VERTEX && aST != GeomAPI_Shape::EDGE && aST != GeomAPI_Shape::WIRE &&
-         aST != GeomAPI_Shape::FACE && aST != GeomAPI_Shape::SHELL) {
+      if(aST == GeomAPI_Shape::SOLID || aST == GeomAPI_Shape::COMPSOLID) {
         setError("Error: Selected shapes has unsupported type.");
         return;
       }
@@ -199,7 +206,7 @@ void FeaturesPlugin_CompositeSketch::getBaseShapes(ListOfShape& theBaseShapesLis
   }
 
   // Searching faces with common edges.
-  if(theIsMakeShells) {
+  if(theIsMakeShells && aBaseFacesList.size() > 1) {
     ListOfShape aShells;
     ListOfShape aFreeFaces;
     GeomShapePtr aFacesCompound = GeomAlgoAPI_CompoundBuilder::compound(aBaseFacesList);
@@ -267,7 +274,6 @@ void FeaturesPlugin_CompositeSketch::storeGenerationHistory(ResultBodyPtr theRes
   switch(aBaseShapeType) {
     case GeomAPI_Shape::VERTEX: {
       aShapeTypeToExplode = GeomAPI_Shape::VERTEX;
-      aGenName += "Edge";
       break;
     }
     case GeomAPI_Shape::EDGE:
@@ -287,12 +293,21 @@ void FeaturesPlugin_CompositeSketch::storeGenerationHistory(ResultBodyPtr theRes
     case GeomAPI_Shape::FACE:
     case GeomAPI_Shape::SHELL: {
       aShapeTypeToExplode = GeomAPI_Shape::EDGE;
-      aGenName += "Face";
       break;
     }
+    case GeomAPI_Shape::COMPOUND: {
+      aShapeTypeToExplode = GeomAPI_Shape::COMPOUND;
+    }
+  }
+
+  if(aShapeTypeToExplode == GeomAPI_Shape::VERTEX || aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
+    theResultBody->loadAndOrientGeneratedShapes(theMakeShape.get(), theBaseShape, GeomAPI_Shape::VERTEX,
+                                                theTag++, aGenName + "Edge", *aMapOfSubShapes.get());
+  }
+  if(aShapeTypeToExplode == GeomAPI_Shape::EDGE || aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
+    theResultBody->loadAndOrientGeneratedShapes(theMakeShape.get(), theBaseShape, GeomAPI_Shape::EDGE,
+                                                theTag++, aGenName + "Face", *aMapOfSubShapes.get());
   }
-  theResultBody->loadAndOrientGeneratedShapes(theMakeShape.get(), theBaseShape, aShapeTypeToExplode,
-                                              theTag++, aGenName, *aMapOfSubShapes.get());
 
   std::shared_ptr<GeomAlgoAPI_MakeSweep> aMakeSweep = std::dynamic_pointer_cast<GeomAlgoAPI_MakeSweep>(theMakeShape);
   if(aMakeSweep.get()) {
@@ -332,21 +347,50 @@ void FeaturesPlugin_CompositeSketch::storeShapes(ResultBodyPtr theResultBody,
       aShapeTypeStr = "Face";
       break;
     }
+    case GeomAPI_Shape::COMPOUND: {
+      aShapeTypeToExplore = GeomAPI_Shape::COMPOUND;
+      break;
+    }
   }
 
   // Store shapes.
   int aShapeIndex = 1;
-  std::string aName = theName + aShapeTypeStr;
+  int aFaceIndex = 1;
   for(ListOfShape::const_iterator anIt = theShapes.cbegin(); anIt != theShapes.cend(); ++anIt) {
     GeomShapePtr aShape = *anIt;
-    for(GeomAPI_ShapeExplorer anExp(aShape, aShapeTypeToExplore); anExp.more(); anExp.next()) {
-      GeomShapePtr aSubShape = anExp.current();
-      if(theMapOfSubShapes->isBound(aSubShape)) {
-        aSubShape = theMapOfSubShapes->find(aSubShape);
-      }
-      std::ostringstream aStr;
-      aStr << aName << "_" << aShapeIndex++;
-      theResultBody->generated(aSubShape, aStr.str(), theTag++);
+
+    if(aShapeTypeToExplore == GeomAPI_Shape::COMPOUND) {
+      std::string aName = theName + (aShape->shapeType() == GeomAPI_Shape::EDGE ? "Edge" : "Face");
+      storeSubShape(theResultBody,
+                    aShape,
+                    aShape->shapeType(),
+                    theMapOfSubShapes,
+                    aName,
+                    aShape->shapeType() == GeomAPI_Shape::EDGE ? aShapeIndex : aFaceIndex,
+                    theTag);
+    } else {
+      std::string aName = theName + aShapeTypeStr;
+      storeSubShape(theResultBody, aShape, aShapeTypeToExplore,
+                    theMapOfSubShapes, aName, aShapeIndex, theTag);
+    }
+  }
+}
+
+void storeSubShape(ResultBodyPtr theResultBody,
+                   const GeomShapePtr theShape,
+                   const GeomAPI_Shape::ShapeType theType,
+                   const std::shared_ptr<GeomAPI_DataMapOfShapeShape> theMapOfSubShapes,
+                   const std::string theName,
+                   int& theShapeIndex,
+                   int& theTag)
+{
+  for(GeomAPI_ShapeExplorer anExp(theShape, theType); anExp.more(); anExp.next()) {
+    GeomShapePtr aSubShape = anExp.current();
+    if(theMapOfSubShapes->isBound(aSubShape)) {
+      aSubShape = theMapOfSubShapes->find(aSubShape);
     }
+    std::ostringstream aStr;
+    aStr << theName << "_" << theShapeIndex++;
+    theResultBody->generated(aSubShape, aStr.str(), theTag++);
   }
-}
\ No newline at end of file
+}
index 7d5e2e90c5f23d1e5f5ad882df715cc45b17f50f..a105bd1db8f71b1d0670cd959411c1d6c0a9aa67 100755 (executable)
@@ -56,6 +56,13 @@ void FeaturesPlugin_Partition::execute()
       anObjects.push_back(anObject);
     }
   }
+
+  if(anObjects.empty()) {
+    static const std::string aFeatureError = "Error: No objects for partition.";
+    setError(aFeatureError);
+    return;
+  }
+
   std::list<std::shared_ptr<GeomAPI_Pnt> > aBoundingPoints = GeomAlgoAPI_ShapeTools::getBoundingBox(anObjects, 1.0);
 
   // Resize planes.
@@ -138,6 +145,7 @@ void FeaturesPlugin_Partition::storeResult(const ListOfShape& theObjects,
   // Store modified shape.
   if(aBaseShape->isEqual(theResultShape)) {
     aResultBody->store(theResultShape);
+    setResult(aResultBody, theIndex);
     return;
   }
 
index 101034de0cbf5300e9680c46d4c75805f30fb1e0..ca171dd01688e8105dea871d4a18588fb29e7761 100644 (file)
 #include <map>
 #include <sstream>
 
-//=================================================================================================
+static void storeSubShape(ResultBodyPtr theResultBody,
+                          const GeomShapePtr theShape,
+                          const GeomAPI_Shape::ShapeType theType,
+                          const std::shared_ptr<GeomAPI_DataMapOfShapeShape> theMapOfSubShapes,
+                          const std::string theName,
+                          int& theShapeIndex,
+                          int& theTag);
+
+//==================================================================================================
 FeaturesPlugin_Pipe::FeaturesPlugin_Pipe()
 {
 }
 
-//=================================================================================================
+//==================================================================================================
 void FeaturesPlugin_Pipe::initAttributes()
 {
   data()->addAttribute(CREATION_METHOD(), ModelAPI_AttributeString::typeId());
@@ -41,7 +49,7 @@ void FeaturesPlugin_Pipe::initAttributes()
   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), LOCATIONS_ID());
 }
 
-//=================================================================================================
+//==================================================================================================
 void FeaturesPlugin_Pipe::execute()
 {
   // Getting creation method.
@@ -253,7 +261,7 @@ void FeaturesPlugin_Pipe::execute()
   removeResults(aResultIndex);
 }
 
-//=================================================================================================
+//==================================================================================================
 void FeaturesPlugin_Pipe::storeResult(const std::shared_ptr<GeomAPI_Shape> theBaseShape,
                                       GeomAlgoAPI_Pipe& thePipeAlgo,
                                       const int theResultIndex)
@@ -274,7 +282,6 @@ void FeaturesPlugin_Pipe::storeResult(const std::shared_ptr<GeomAPI_Shape> theBa
   switch(aBaseShapeType) {
     case GeomAPI_Shape::VERTEX: {
       aShapeTypeToExplode = GeomAPI_Shape::VERTEX;
-      aGenName += "Edge";
       break;
     }
     case GeomAPI_Shape::EDGE:
@@ -294,10 +301,22 @@ void FeaturesPlugin_Pipe::storeResult(const std::shared_ptr<GeomAPI_Shape> theBa
     case GeomAPI_Shape::FACE:
     case GeomAPI_Shape::SHELL: {
       aShapeTypeToExplode = GeomAPI_Shape::EDGE;
-      aGenName += "Face";
       break;
     }
+    case GeomAPI_Shape::COMPOUND: {
+      aShapeTypeToExplode = GeomAPI_Shape::COMPOUND;
+    }
+  }
+
+  if(aShapeTypeToExplode == GeomAPI_Shape::VERTEX || aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
+    aResultBody->loadAndOrientGeneratedShapes(&thePipeAlgo, theBaseShape, GeomAPI_Shape::VERTEX,
+                                              aGenTag++, aGenName + "Edge", *aMapOfSubShapes.get());
+  }
+  if(aShapeTypeToExplode == GeomAPI_Shape::EDGE || aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
+    aResultBody->loadAndOrientGeneratedShapes(&thePipeAlgo, theBaseShape, GeomAPI_Shape::EDGE,
+                                              aGenTag++, aGenName + "Face", *aMapOfSubShapes.get());
   }
+
   aResultBody->loadAndOrientGeneratedShapes(&thePipeAlgo, theBaseShape, aShapeTypeToExplode, aGenTag++, aGenName, *aMapOfSubShapes.get());
 
   // Store from shapes.
@@ -311,7 +330,7 @@ void FeaturesPlugin_Pipe::storeResult(const std::shared_ptr<GeomAPI_Shape> theBa
   setResult(aResultBody, theResultIndex);
 }
 
-//=================================================================================================
+//==================================================================================================
 void FeaturesPlugin_Pipe::storeResult(const ListOfShape& theBaseShapes,
                                       GeomAlgoAPI_Pipe& thePipeAlgo,
                                       const int theResultIndex)
@@ -369,7 +388,7 @@ void FeaturesPlugin_Pipe::storeResult(const ListOfShape& theBaseShapes,
   setResult(aResultBody, theResultIndex);
 }
 
-//=================================================================================================
+//==================================================================================================
 void FeaturesPlugin_Pipe::storeShapes(ResultBodyPtr theResultBody,
                                       const GeomAPI_Shape::ShapeType theBaseShapeType,
                                       const std::shared_ptr<GeomAPI_DataMapOfShapeShape> theMapOfSubShapes,
@@ -397,21 +416,51 @@ void FeaturesPlugin_Pipe::storeShapes(ResultBodyPtr theResultBody,
       aShapeTypeStr = "Face";
       break;
     }
+    case GeomAPI_Shape::COMPOUND: {
+      aShapeTypeToExplore = GeomAPI_Shape::COMPOUND;
+      break;
+    }
   }
 
   // Store shapes.
   int aShapeIndex = 1;
-  std::string aName = theName + aShapeTypeStr;
+  int aFaceIndex = 1;
   for(ListOfShape::const_iterator anIt = theShapes.cbegin(); anIt != theShapes.cend(); ++anIt) {
-    std::shared_ptr<GeomAPI_Shape> aShape = *anIt;
-    for(GeomAPI_ShapeExplorer anExp(aShape, aShapeTypeToExplore); anExp.more(); anExp.next()) {
-      std::shared_ptr<GeomAPI_Shape> aSubShape = anExp.current();
-      if(theMapOfSubShapes->isBound(aSubShape)) {
-        aSubShape = theMapOfSubShapes->find(aSubShape);
-      }
-      std::ostringstream aStr;
-      aStr << aName << "_" << aShapeIndex++;
-      theResultBody->generated(aSubShape, aStr.str(), theTag++);
+    GeomShapePtr aShape = *anIt;
+
+    if(aShapeTypeToExplore == GeomAPI_Shape::COMPOUND) {
+      std::string aName = theName + (aShape->shapeType() == GeomAPI_Shape::EDGE ? "Edge" : "Face");
+      storeSubShape(theResultBody,
+                    aShape,
+                    aShape->shapeType(),
+                    theMapOfSubShapes,
+                    aName,
+                    aShape->shapeType() == GeomAPI_Shape::EDGE ? aShapeIndex : aFaceIndex,
+                    theTag);
+    } else {
+      std::string aName = theName + aShapeTypeStr;
+      storeSubShape(theResultBody, aShape, aShapeTypeToExplore,
+                    theMapOfSubShapes, aName, aShapeIndex, theTag);
+    }
+  }
+}
+
+//==================================================================================================
+void storeSubShape(ResultBodyPtr theResultBody,
+                   const GeomShapePtr theShape,
+                   const GeomAPI_Shape::ShapeType theType,
+                   const std::shared_ptr<GeomAPI_DataMapOfShapeShape> theMapOfSubShapes,
+                   const std::string theName,
+                   int& theShapeIndex,
+                   int& theTag)
+{
+  for(GeomAPI_ShapeExplorer anExp(theShape, theType); anExp.more(); anExp.next()) {
+    GeomShapePtr aSubShape = anExp.current();
+    if(theMapOfSubShapes->isBound(aSubShape)) {
+      aSubShape = theMapOfSubShapes->find(aSubShape);
     }
+    std::ostringstream aStr;
+    aStr << theName << "_" << theShapeIndex++;
+    theResultBody->generated(aSubShape, aStr.str(), theTag++);
   }
 }
index 75ee7ff6666f67e38d96f9f8f2d6d68e6cb70857..d42ede130fe27114837435ce2cd1bad0f8f3148c 100644 (file)
@@ -12,6 +12,7 @@
 #include <FeaturesPlugin_Partition.h>
 #include <FeaturesPlugin_Pipe.h>
 #include <FeaturesPlugin_Placement.h>
+#include <FeaturesPlugin_RemoveSubShapes.h>
 #include <FeaturesPlugin_Revolution.h>
 #include <FeaturesPlugin_RevolutionCut.h>
 #include <FeaturesPlugin_RevolutionFuse.h>
@@ -48,6 +49,12 @@ FeaturesPlugin_Plugin::FeaturesPlugin_Plugin()
                               new FeaturesPlugin_ValidatorBooleanSelection);
   aFactory->registerValidator("FeaturesPlugin_ValidatorPartitionSelection",
                               new FeaturesPlugin_ValidatorPartitionSelection);
+  aFactory->registerValidator("FeaturesPlugin_ValidatorRemoveSubShapesSelection",
+                              new FeaturesPlugin_ValidatorRemoveSubShapesSelection);
+  aFactory->registerValidator("FeaturesPlugin_ValidatorRemoveSubShapesResult",
+                              new FeaturesPlugin_ValidatorRemoveSubShapesResult);
+  aFactory->registerValidator("FeaturesPlugin_ValidatorPipePath",
+                              new FeaturesPlugin_ValidatorPipePath);
 
   // register this plugin
   ModelAPI_Session::get()->registerPlugin(this);
@@ -83,6 +90,8 @@ FeaturePtr FeaturesPlugin_Plugin::createFeature(string theFeatureID)
     return FeaturePtr(new FeaturesPlugin_RevolutionCut);
   } else if (theFeatureID == FeaturesPlugin_RevolutionFuse::ID()) {
     return FeaturePtr(new FeaturesPlugin_RevolutionFuse);
+  } else if (theFeatureID == FeaturesPlugin_RemoveSubShapes::ID()) {
+    return FeaturePtr(new FeaturesPlugin_RemoveSubShapes);
   }
 
   // feature of such kind is not found
diff --git a/src/FeaturesPlugin/FeaturesPlugin_RemoveSubShapes.cpp b/src/FeaturesPlugin/FeaturesPlugin_RemoveSubShapes.cpp
new file mode 100644 (file)
index 0000000..84541fc
--- /dev/null
@@ -0,0 +1,113 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        FeaturesPlugin_RemoveSubShapes.cpp
+// Created:     14 April 2016
+// Author:      Dmitry Bobylev
+
+#include "FeaturesPlugin_RemoveSubShapes.h"
+
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_ResultBody.h>
+#include <ModelAPI_ResultCompSolid.h>
+#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Validator.h>
+
+#include <GeomAPI_ShapeIterator.h>
+
+#include <GeomAlgoAPI_ShapeBuilder.h>
+#include <GeomAlgoAPI_ShapeTools.h>
+
+//==================================================================================================
+FeaturesPlugin_RemoveSubShapes::FeaturesPlugin_RemoveSubShapes()
+{
+}
+
+//==================================================================================================
+void FeaturesPlugin_RemoveSubShapes::initAttributes()
+{
+  data()->addAttribute(BASE_SHAPE_ID(), ModelAPI_AttributeSelection::typeId());
+
+  data()->addAttribute(SUBSHAPES_ID(), ModelAPI_AttributeSelectionList::typeId());
+}
+
+void FeaturesPlugin_RemoveSubShapes::attributeChanged(const std::string& theID)
+{
+  ModelAPI_Feature::attributeChanged(theID);
+
+  if(theID == BASE_SHAPE_ID()) {
+    AttributeSelectionPtr aShapeAttrSelection = selection(BASE_SHAPE_ID());
+    AttributeSelectionListPtr aSubShapesAttrList = selectionList(SUBSHAPES_ID());
+    if(!aShapeAttrSelection.get() || !aSubShapesAttrList.get()) {
+      return;
+    }
+
+    aSubShapesAttrList->clear();
+
+    ResultPtr aContext = aShapeAttrSelection->context();
+    ResultCompSolidPtr aResultCompSolid = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aContext);
+    if(!aResultCompSolid.get()) {
+      return;
+    }
+
+    GeomShapePtr aBaseShape = aShapeAttrSelection->value();
+    if(!aBaseShape.get()) {
+      aBaseShape = aContext->shape();
+    }
+    if(!aBaseShape.get()) {
+      return;
+    }
+    GeomAPI_Shape::ShapeType aShapeType = aBaseShape->shapeType();
+    if(aShapeType != GeomAPI_Shape::WIRE
+        && aShapeType != GeomAPI_Shape::SHELL
+        && aShapeType != GeomAPI_Shape::COMPSOLID
+        && aShapeType != GeomAPI_Shape::COMPOUND) {
+      return;
+    }
+    for(GeomAPI_ShapeIterator anIt(aBaseShape); anIt.more(); anIt.next()) {
+      GeomShapePtr aSubShape = anIt.current();
+      const int aNumOfSubs = aResultCompSolid->numberOfSubs();
+      if(aNumOfSubs == 0) {
+        aSubShapesAttrList->append(aContext, aSubShape);
+      } else {
+        for(int anIndex = 0; anIndex < aResultCompSolid->numberOfSubs(); ++anIndex) {
+          ResultBodyPtr aSubResult = aResultCompSolid->subResult(anIndex);
+          if(aSubResult->shape()->isEqual(aSubShape)) {
+            aSubShapesAttrList->append(aSubResult, aSubShape);
+            break;
+          }
+        }
+      }
+    }
+  }
+}
+
+//==================================================================================================
+void FeaturesPlugin_RemoveSubShapes::execute()
+{
+  // Get base shape and sub-shapes list.
+  AttributeSelectionPtr aShapeAttrSelection = selection(BASE_SHAPE_ID());
+  AttributeSelectionListPtr aSubShapesAttrList = selectionList(SUBSHAPES_ID());
+  if(!aShapeAttrSelection.get() || !aSubShapesAttrList.get()) {
+    return;
+  }
+
+  // Copy base shape.
+  GeomShapePtr aBaseShape = aShapeAttrSelection->value();
+  if(!aBaseShape.get()) {
+    return;
+  }
+  GeomShapePtr aResultShape = aBaseShape->emptyCopied();
+
+  // Copy sub-shapes from list to new shape.
+  for(int anIndex = 0; anIndex < aSubShapesAttrList->size(); ++anIndex) {
+    AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
+    GeomShapePtr aShapeToAdd = anAttrSelectionInList->value();
+    GeomAlgoAPI_ShapeBuilder::add(aResultShape, aShapeToAdd);
+  }
+
+  // Store result.
+  ResultBodyPtr aResultBody = document()->createBody(data());
+  aResultBody->storeModified(aBaseShape, aResultShape);
+  setResult(aResultBody);
+}
diff --git a/src/FeaturesPlugin/FeaturesPlugin_RemoveSubShapes.h b/src/FeaturesPlugin/FeaturesPlugin_RemoveSubShapes.h
new file mode 100644 (file)
index 0000000..b5e1158
--- /dev/null
@@ -0,0 +1,62 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        FeaturesPlugin_RemoveSubShapes.h
+// Created:     23 May 2016
+// Author:      Dmitry Bobylev
+
+#ifndef FeaturesPlugin_RemoveSubShapes_H_
+#define FeaturesPlugin_RemoveSubShapes_H_
+
+#include "FeaturesPlugin.h"
+
+#include <ModelAPI_Feature.h>
+
+/// \class FeaturesPlugin_RemoveSubShapes
+/// \ingroup Plugins
+/// \brief Feature for removing sub-shapes from collections(wire, shell, compsolid, compound).
+class FeaturesPlugin_RemoveSubShapes: public ModelAPI_Feature
+{
+public:
+  /// Use plugin manager for features creation
+  FeaturesPlugin_RemoveSubShapes();
+
+  /// Feature kind.
+  inline static const std::string& ID()
+  {
+    static const std::string MY_ID("Remove_SubShapes");
+    return MY_ID;
+  }
+
+  /// Attribute name of base shape.
+  inline static const std::string& BASE_SHAPE_ID()
+  {
+    static const std::string MY_BASE_SHAPE_ID("base_shape");
+    return MY_BASE_SHAPE_ID;
+  }
+
+  /// Attribute name of sub-shapes.
+  inline static const std::string& SUBSHAPES_ID()
+  {
+    static const std::string MY_SUBSHAPES_ID("subshapes");
+    return MY_SUBSHAPES_ID;
+  }
+
+  /// \return the kind of a feature.
+  FEATURESPLUGIN_EXPORT virtual const std::string& getKind()
+  {
+    static std::string MY_KIND = FeaturesPlugin_RemoveSubShapes::ID();
+    return MY_KIND;
+  }
+
+  /// Request for initialization of data model of the feature: adding all attributes.
+  FEATURESPLUGIN_EXPORT virtual void initAttributes();
+
+  /// Called on change of any argument-attribute of this object.
+  /// \param[in] theID identifier of changed attribute.
+  FEATURESPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
+
+  /// Creates a new part document if needed.
+  FEATURESPLUGIN_EXPORT virtual void execute();
+};
+
+#endif
index 73c132e0d6a0aae3232f43734bbc164682b45451..2ab3adbb06d75f78451ff4e0abf2e655636eb5b0 100644 (file)
@@ -12,6 +12,7 @@
 #include <ModelAPI_AttributeString.h>
 #include <ModelAPI_AttributeReference.h>
 #include <ModelAPI_Feature.h>
+#include <ModelAPI_ResultCompSolid.h>
 #include <ModelAPI_ResultConstruction.h>
 
 #include <GeomValidators_BodyShapes.h>
 #include <GeomAPI_DataMapOfShapeShape.h>
 #include <GeomAPI_PlanarEdges.h>
 #include <GeomAPI_ShapeExplorer.h>
+#include <GeomAPI_ShapeIterator.h>
+
+#include <GeomAlgoAPI_ShapeBuilder.h>
+#include <GeomAlgoAPI_ShapeTools.h>
 #include <GeomAlgoAPI_WireBuilder.h>
 
+//==================================================================================================
+bool FeaturesPlugin_ValidatorPipePath::isValid(const AttributePtr& theAttribute,
+                                               const std::list<std::string>& theArguments,
+                                               std::string& theError) const
+{
+  AttributeSelectionPtr aPathAttrSelection = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
+  if(!aPathAttrSelection.get()) {
+    theError = "Error: This validator can only work with path selector in \"Pipe\" feature.";
+    return false;
+  }
+
+  GeomShapePtr aPathShape = aPathAttrSelection->value();
+  ResultPtr aContext = aPathAttrSelection->context();
+  if(!aContext.get()) {
+    theError = "Error: Empty context.";
+    return false;
+  }
+  GeomShapePtr aContextShape = aContext->shape();
+  if(aPathShape.get() && aPathShape->shapeType() == GeomAPI_Shape::WIRE && !aPathShape->isEqual(aContextShape)) {
+    theError = "Error: Local selection of wires not allowed.";
+    return false;
+  }
+
+  return true;
+}
+
 //==================================================================================================
 bool FeaturesPlugin_ValidatorPipeLocations::isValid(const std::shared_ptr<ModelAPI_Feature>& theFeature,
                                                     const std::list<std::string>& theArguments,
@@ -33,13 +64,13 @@ bool FeaturesPlugin_ValidatorPipeLocations::isValid(const std::shared_ptr<ModelA
   static const std::string aLocationsID = "locations_objects";
 
   if(theFeature->getKind() != "Pipe") {
-    theError = "Feature \"" + theFeature->getKind() + "\" does not supported by this validator.";
+    theError = "Error: Feature \"" + theFeature->getKind() + "\" does not supported by this validator.";
     return false;
   }
 
   AttributeStringPtr aCreationMethodAttr = theFeature->string(aCreationMethodID);
   if(!aCreationMethodAttr.get()) {
-    theError = "Could not get \"" + aCreationMethodID + "\" attribute.";
+    theError = "Error: Could not get \"" + aCreationMethodID + "\" attribute.";
     return false;
   }
 
@@ -49,18 +80,18 @@ bool FeaturesPlugin_ValidatorPipeLocations::isValid(const std::shared_ptr<ModelA
 
   AttributeSelectionListPtr aBaseObjectsSelectionList = theFeature->selectionList(aBaseObjectsID);
   if(!aBaseObjectsSelectionList.get()) {
-    theError = "Could not get \"" + aBaseObjectsID + "\" attribute.";
+    theError = "Error: Could not get \"" + aBaseObjectsID + "\" attribute.";
     return false;
   }
 
   AttributeSelectionListPtr aLocationsSelectionList = theFeature->selectionList(aLocationsID);
   if(!aLocationsSelectionList.get()) {
-    theError = "Could not get \"" + aBaseObjectsID + "\" attribute.";
+    theError = "Error: Could not get \"" + aBaseObjectsID + "\" attribute.";
     return false;
   }
 
   if(aLocationsSelectionList->size() > 0 && aLocationsSelectionList->size() != aBaseObjectsSelectionList->size()) {
-    theError = "Number of locations should be the same as base objects.";
+    theError = "Error: Number of locations should be the same as base objects.";
     return false;
   }
 
@@ -79,14 +110,14 @@ bool FeaturesPlugin_ValidatorBaseForGeneration::isValid(const AttributePtr& theA
                                                         std::string& theError) const
 {
   if(theArguments.empty()) {
-    theError = "Validator parameters is empty.";
+    theError = "Error: Validator parameters is empty.";
     return false;
   }
 
   // Checking attribute.
   if(!isValidAttribute(theAttribute, theArguments, theError)) {
     if(theError.empty()) {
-      theError = "Attribute contains unacceptable shape.";
+      theError = "Error: Attribute contains unacceptable shape.";
     }
     return false;
   }
@@ -99,43 +130,65 @@ bool FeaturesPlugin_ValidatorBaseForGeneration::isValid(const AttributePtr& theA
     AttributeSelectionListPtr aListAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
     for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
       AttributeSelectionPtr aSelectionAttr = aListAttr->value(anIndex);
-      ResultConstructionPtr aContext = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aSelectionAttr->context());
+      ResultPtr aContext = aSelectionAttr->context();
       if(!aContext.get()) {
-        // It is not a result construction, continue.
+        theError = "Error: Empty context.";
+        return false;
+      }
+
+      ResultConstructionPtr aResultConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
+      if(!aResultConstruction.get()) {
+        // It is not a result construction. If shape is compound check that it contains only faces and edges.
+        GeomShapePtr aShape = aSelectionAttr->value();
+        if(!aShape.get()) {
+          aShape = aContext->shape();
+        }
+
+        if(aShape->shapeType() == GeomAPI_Shape::COMPOUND) {
+          for(GeomAPI_ShapeIterator anIt(aShape); anIt.more(); anIt.next()) {
+            GeomShapePtr aSubShape = anIt.current();
+            if(aSubShape->shapeType() != GeomAPI_Shape::EDGE
+                && aSubShape->shapeType() != GeomAPI_Shape::FACE) {
+              theError = "Error: Compound should contain only faces and edges.";
+              return false;
+            }
+          }
+        }
+
         continue;
       }
 
       GeomShapePtr aShape = aSelectionAttr->value();
-      GeomShapePtr aContextShape = aContext->shape();
+      GeomShapePtr aContextShape = aResultConstruction->shape();
       if(!aShape.get()) {
         // Whole sketch selected.
-        if(aSelectedSketchesFromObjects.find(aContext) != aSelectedSketchesFromObjects.cend()) {
-          theError = "Object from this sketch is already selected. Sketch is not allowed for selection.";
+        if(aSelectedSketchesFromObjects.find(aResultConstruction) != aSelectedSketchesFromObjects.cend()) {
+          theError = "Error: Object from this sketch is already selected. Sketch is not allowed for selection.";
           return false;
         }
 
-        aSelectedSketches.insert(aContext);
+        aSelectedSketches.insert(aResultConstruction);
       } else {
         // Object from sketch selected.
-        if(aSelectedSketches.find(aContext) != aSelectedSketches.cend()) {
-          theError = "Whole sketch with this object is already selected. Don't allow to select this object.";
+        if(aSelectedSketches.find(aResultConstruction) != aSelectedSketches.cend()) {
+          theError = "Error: Whole sketch with this object is already selected. Don't allow to select this object.";
           return false;
         }
 
         for(GeomAPI_ShapeExplorer anExp(aShape, GeomAPI_Shape::WIRE); anExp.more(); anExp.next()) {
           GeomShapePtr aWire = anExp.current();
           if(aWire->orientation() != GeomAPI_Shape::FORWARD) {
-            theError = "Wire with wrong orientation selected.";
+            theError = "Error: Wire with wrong orientation selected.";
             return false;
           }
 
           if(aSelectedWiresFromObjects.isBound(aWire)) {
-            theError = "Objects with such wire already selected. Don't allow to select this object.";
+            theError = "Error: Objects with such wire already selected. Don't allow to select this object.";
             return false;
           }
 
           aSelectedWiresFromObjects.bind(aWire, aWire);
-          aSelectedSketchesFromObjects.insert(aContext);
+          aSelectedSketchesFromObjects.insert(aResultConstruction);
         }
       }
     }
@@ -150,7 +203,7 @@ bool FeaturesPlugin_ValidatorBaseForGeneration::isValidAttribute(const Attribute
                                                                  std::string& theError) const
 {
   if(!theAttribute.get()) {
-    theError = "Empty attribute.";
+    theError = "Error: Empty attribute.";
     return false;
   }
 
@@ -168,7 +221,7 @@ bool FeaturesPlugin_ValidatorBaseForGeneration::isValidAttribute(const Attribute
     AttributeSelectionPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
     ResultPtr aContext = anAttr->context();
     if(!aContext.get()) {
-      theError = "Attribute have empty context.";
+      theError = "Error: Attribute have empty context.";
       return false;
     }
 
@@ -178,7 +231,7 @@ bool FeaturesPlugin_ValidatorBaseForGeneration::isValidAttribute(const Attribute
       aShape = aContextShape;
     }
     if(!aShape.get()) {
-      theError = "Empty shape selected";
+      theError = "Error: Empty shape selected";
       return false;
     }
 
@@ -186,7 +239,7 @@ bool FeaturesPlugin_ValidatorBaseForGeneration::isValidAttribute(const Attribute
     if(aConstruction.get()) {
       // Construciotn selected. Check that is is not infinite.
       if(aConstruction->isInfinite()) {
-        theError = "Infinite constructions is not allowed as base.";
+        theError = "Error: Infinite constructions is not allowed as base.";
         return false;
       }
 
@@ -207,14 +260,14 @@ bool FeaturesPlugin_ValidatorBaseForGeneration::isValidAttribute(const Attribute
 
     if(!aShape->isEqual(aContextShape)) {
       // Local selection on body does not allowed.
-      theError = "Selected shape is in the local selection. Only global selection is allowed.";
+      theError = "Error: Selected shape is in the local selection. Only global selection is allowed.";
       return false;
     }
 
     // Check that object is a shape with allowed type.
     GeomValidators_ShapeType aShapeTypeValidator;
     if(!aShapeTypeValidator.isValid(anAttr, theArguments, theError)) {
-      theError = "Selected shape has unacceptable type. Acceptable types are: faces or wires on sketch, "
+      theError = "Error: Selected shape has unacceptable type. Acceptable types are: faces or wires on sketch, "
                  "whole sketch(if it has at least one face), and whole objects with shape types: ";
       std::list<std::string>::const_iterator anIt = theArguments.cbegin();
       theError += *anIt;
@@ -225,7 +278,7 @@ bool FeaturesPlugin_ValidatorBaseForGeneration::isValidAttribute(const Attribute
     }
 
   } else {
-    theError = "Following attribute does not supported: " + anAttributeType + ".";
+    theError = "Error: Attribute \"" + anAttributeType + "\" does not supported by this validator.";
     return false;
   }
 
@@ -238,11 +291,11 @@ bool FeaturesPlugin_ValidatorCompositeLauncher::isValid(const AttributePtr& theA
                                                         std::string& theError) const
 {
   if (theAttribute->attributeType() != ModelAPI_AttributeReference::typeId()) {
-    theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed";
+    theError = "Error: The attribute with the " + theAttribute->attributeType() + " type is not processed";
     return false;
   }
   if (theArguments.size() != 2) {
-    theError = "Wrong parameters in XML definition for " + theAttribute->attributeType() + " type";
+    theError = "Error: Wrong parameters in XML definition for " + theAttribute->attributeType() + " type";
     return false;
   }
   // first argument is for the base attribute, second - for skipping feature kind
@@ -283,7 +336,7 @@ bool FeaturesPlugin_ValidatorCanBeEmpty::isValid(const std::shared_ptr<ModelAPI_
                                                  std::string& theError) const
 {
   if(theArguments.size() != 2) {
-    theError = "Validator should be used with 2 parameters for extrusion.";
+    theError = "Error: Validator should be used with 2 parameters for extrusion.";
     return false;
   }
 
@@ -298,7 +351,7 @@ bool FeaturesPlugin_ValidatorCanBeEmpty::isValid(const std::shared_ptr<ModelAPI_
 
   AttributeSelectionPtr aSelAttr = theFeature->selection(*anArgsIt);
   if(!aSelAttr.get()) {
-    theError = "Could not get selection attribute \"" + *anArgsIt + "\".";
+    theError = "Error: Could not get selection attribute \"" + *anArgsIt + "\".";
     return false;
   }
 
@@ -306,7 +359,7 @@ bool FeaturesPlugin_ValidatorCanBeEmpty::isValid(const std::shared_ptr<ModelAPI_
   if(!aShape.get()) {
     ResultPtr aContext = aSelAttr->context();
     if(!aContext.get()) {
-      theError = "Base objects list contains vertex or edge, so attribute \"" + *anArgsIt
+      theError = "Error: Base objects list contains vertex or edge, so attribute \"" + *anArgsIt
                + "\" can not be used with default value. Select direction for extrusion.";
       return false;
     }
@@ -315,7 +368,7 @@ bool FeaturesPlugin_ValidatorCanBeEmpty::isValid(const std::shared_ptr<ModelAPI_
   }
 
   if(!aShape.get()) {
-    theError = "Base objects list contains vertex or edge, so attribute \"" + *anArgsIt
+    theError = "Error: Base objects list contains vertex or edge, so attribute \"" + *anArgsIt
               + "\" can not be used with default value. Select direction for extrusion.";
     return false;
   }
@@ -382,7 +435,7 @@ bool FeaturesPlugin_ValidatorBooleanSelection::isValid(const AttributePtr& theAt
 {
   AttributeSelectionListPtr anAttrSelectionList = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
   if(!anAttrSelectionList.get()) {
-    theError = "Error: this validator can only work with selection list attributes in Boolean feature.";
+    theError = "Error: This validator can only work with selection list attributes in \"Boolean\" feature.";
     return false;
   }
   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
@@ -391,12 +444,12 @@ bool FeaturesPlugin_ValidatorBooleanSelection::isValid(const AttributePtr& theAt
   for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
     AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
     if(!anAttrSelection.get()) {
-      theError = "Error: empty attribute selection.";
+      theError = "Error: Empty attribute selection.";
       return false;
     }
     ResultPtr aContext = anAttrSelection->context();
     if(!aContext.get()) {
-      theError = "Error: empty selection context.";
+      theError = "Error: Empty selection context.";
       return false;
     }
     ResultConstructionPtr aResultConstruction =
@@ -410,7 +463,7 @@ bool FeaturesPlugin_ValidatorBooleanSelection::isValid(const AttributePtr& theAt
       aShape = aContext->shape();
     }
     if(!aShape.get()) {
-      theError = "Error: empty shape.";
+      theError = "Error: Empty shape.";
       return false;
     }
     int aShapeType = aShape->shapeType();
@@ -421,14 +474,14 @@ bool FeaturesPlugin_ValidatorBooleanSelection::isValid(const AttributePtr& theAt
          aShapeType != GeomAPI_Shape::SOLID &&
          aShapeType != GeomAPI_Shape::COMPSOLID &&
          aShapeType != GeomAPI_Shape::COMPOUND) {
-        theError = "Error: selected shape has the wrong type.";
+        theError = "Error: Selected shape has the wrong type.";
         return false;
       }
     } else {
       if(aShapeType != GeomAPI_Shape::SOLID &&
          aShapeType != GeomAPI_Shape::COMPSOLID &&
          aShapeType != GeomAPI_Shape::COMPOUND) {
-        theError = "Error: selected shape has the wrong type.";
+        theError = "Error: Selected shape has the wrong type.";
         return false;
       }
     }
@@ -442,31 +495,149 @@ bool FeaturesPlugin_ValidatorPartitionSelection::isValid(const AttributePtr& the
                                                          const std::list<std::string>& theArguments,
                                                          std::string& theError) const
 {
-  std::string anAttributeType = theAttribute->attributeType();
-  if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
-    AttributeSelectionListPtr aSelectionListAttr =
-        std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
+  AttributeSelectionListPtr anAttrSelectionList = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
+  if(!anAttrSelectionList.get()) {
+    theError = "Error: This validator can only work with selection list in \"Partition\" feature.";
+    return false;
+  }
 
-    for(int anIndex = 0; anIndex < aSelectionListAttr->size(); ++anIndex) {
-      AttributeSelectionPtr aSelectAttr = aSelectionListAttr->value(anIndex);
+  for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
+    AttributeSelectionPtr aSelectAttr = anAttrSelectionList->value(anIndex);
 
-      GeomValidators_BodyShapes aBodyValidator;
-      if(aBodyValidator.isValid(aSelectAttr, theArguments, theError)) {
-        continue;
-      }
+    //GeomValidators_BodyShapes aBodyValidator;
+    //if(aBodyValidator.isValid(aSelectAttr, theArguments, theError)) {
+    //  continue;
+    //}
 
-      GeomValidators_FeatureKind aFeatureKindValidator;
-      if(aFeatureKindValidator.isValid(aSelectAttr, theArguments, theError)) {
-        continue;
-      }
+    GeomValidators_FeatureKind aFeatureKindValidator;
+    if(aFeatureKindValidator.isValid(aSelectAttr, theArguments, theError)) {
+      continue;
+    }
 
-      theError = "Only body shapes and construction planes are allowed for selection.";
+    ResultPtr aContext = aSelectAttr->context();
+    ResultConstructionPtr aResultConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
+    if(aResultConstruction.get()) {
+      theError = "Error: Only body shapes and construction planes are allowed for selection.";
       return false;
     }
-  } else {
-    theError = "This validator supports only " + ModelAPI_AttributeSelectionList::typeId() + " attribute type.";
+
+    ResultCompSolidPtr aResultCompsolid = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aContext);
+    if(aResultCompsolid.get()) {
+      continue;
+    }
+
+    theError = "Error: Only body shapes and construction planes are allowed for selection.";
+    return false;
+  }
+
+  theError = "";
+  return true;
+}
+
+//==================================================================================================
+bool FeaturesPlugin_ValidatorRemoveSubShapesSelection::isValid(const AttributePtr& theAttribute,
+                                                               const std::list<std::string>& theArguments,
+                                                               std::string& theError) const
+{
+  AttributeSelectionListPtr aSubShapesAttrList = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
+  if(!aSubShapesAttrList.get()) {
+    theError = "Error: This validator can only work with selection list in \"Remove Sub-Shapes\" feature.";
+    return false;
+  }
+
+  static const std::string aBaseShapeID = "base_shape";
+  FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
+  AttributeSelectionPtr aShapeAttrSelection = aFeature->selection(aBaseShapeID);
+
+  if(!aShapeAttrSelection.get()) {
+    theError = "Error: Could not get \"" + aBaseShapeID + "\" attribute.";
+    return false;
+  }
+
+  GeomShapePtr aBaseShape = aShapeAttrSelection->value();
+  ResultPtr aContext = aShapeAttrSelection->context();
+  if(!aContext.get()) {
+    theError = "Error: Empty context.";
+    return false;
+  }
+  if(!aBaseShape.get()) {
+    aBaseShape = aContext->shape();
+  }
+  if(!aBaseShape.get()) {
+    theError = "Error: Empty base shape.";
     return false;
   }
 
+  for(int anIndex = 0; anIndex < aSubShapesAttrList->size(); ++anIndex) {
+    bool isSameFound = false;
+    AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
+    GeomShapePtr aShapeToAdd = anAttrSelectionInList->value();
+    for(GeomAPI_ShapeIterator anIt(aBaseShape); anIt.more(); anIt.next()) {
+      if(anIt.current()->isEqual(aShapeToAdd)) {
+        isSameFound = true;
+        break;
+      }
+    }
+    if(!isSameFound) {
+      theError = "Error: Only sub-shapes of selected shape is allowed for selection.";
+      return false;
+    }
+  }
+
   return true;
 }
+
+//==================================================================================================
+bool FeaturesPlugin_ValidatorRemoveSubShapesResult::isValid(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                                                            const std::list<std::string>& theArguments,
+                                                            std::string& theError) const
+{
+  static const std::string aBaseShapeID = "base_shape";
+  static const std::string aSubShapesID = "subshapes";
+
+  if(theFeature->getKind() != "Remove_SubShapes") {
+    theError = "Error: Feature \"" + theFeature->getKind() + "\" does not supported by this validator.";
+    return false;
+  }
+
+  AttributeSelectionPtr aShapeAttrSelection = theFeature->selection(aBaseShapeID);
+  if(!aShapeAttrSelection.get()) {
+    theError = "Error: Could not get \"" + aBaseShapeID + "\" attribute.";
+    return false;
+  }
+
+  AttributeSelectionListPtr aSubShapesAttrList = theFeature->selectionList(aSubShapesID);
+  if(!aSubShapesAttrList.get()) {
+    theError = "Error: Could not get \"" + aSubShapesID + "\" attribute.";
+    return false;
+  }
+
+  // Copy base shape.
+  GeomShapePtr aBaseShape = aShapeAttrSelection->value();
+  if(!aBaseShape.get()) {
+    return false;
+  }
+  GeomShapePtr aResultShape = aBaseShape->emptyCopied();
+
+  // Copy sub-shapes from list to new shape.
+  for(int anIndex = 0; anIndex < aSubShapesAttrList->size(); ++anIndex) {
+    AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
+    GeomShapePtr aShapeToAdd = anAttrSelectionInList->value();
+    GeomAlgoAPI_ShapeBuilder::add(aResultShape, aShapeToAdd);
+  }
+
+  // Check new shape.
+  if(!GeomAlgoAPI_ShapeTools::isShapeValid(aResultShape)) {
+    theError = "Error: Resulting shape is not valid.";
+    return false;
+  }
+
+  return true;
+}
+
+//==================================================================================================
+bool FeaturesPlugin_ValidatorRemoveSubShapesResult::isNotObligatory(std::string theFeature,
+                                                                    std::string theAttribute)
+{
+  return false;
+}
index 905eec5c62fd1deff58f48ff177b538e6dce5564..da6180e58a7357b8fb4f176e10d5a707dc683b25 100644 (file)
 #include <ModelAPI_AttributeValidator.h>
 #include <ModelAPI_FeatureValidator.h>
 
+/// \class FeaturesPlugin_ValidatorPipePath
+/// \ingroup Validators
+/// \brief A validator for selection pipe path.
+class FeaturesPlugin_ValidatorPipePath: public ModelAPI_AttributeValidator
+{
+public:
+  //! \return True if the attribute is valid.
+  //! \param[in] theAttribute the checked attribute.
+  //! \param[in] theArguments arguments of the attribute.
+  //! \param[out] theError error message.
+   virtual bool isValid(const AttributePtr& theAttribute,
+                        const std::list<std::string>& theArguments,
+                        std::string& theError) const;
+};
+
 /// \class FeaturesPlugin_ValidatorPipeLocations
 /// \ingroup Validators
 /// \brief Validator for the pipe locations.
@@ -35,7 +50,7 @@ class FeaturesPlugin_ValidatorPipeLocations: public ModelAPI_FeatureValidator
 class FeaturesPlugin_ValidatorBaseForGeneration: public ModelAPI_AttributeValidator
 {
 public:
-  //! Returns true if attribute has selection type listed in the parameter arguments.
+  //! \return true if attribute has selection type listed in the parameter arguments.
   //! \param[in] theAttribute the checked attribute.
   //! \param[in] theArguments arguments of the attribute.
   //! \param[out] theError error message.
@@ -55,7 +70,7 @@ private:
 class FeaturesPlugin_ValidatorCompositeLauncher: public ModelAPI_AttributeValidator
 {
 public:
-  //! Returns true if attribute has selection type listed in the parameter arguments.
+  //! \return true if attribute has selection type listed in the parameter arguments.
   //! \param[in] theAttribute the checked attribute.
   //! \param[in] theArguments arguments of the attribute.
   //! \param[out] theError error message.
@@ -71,7 +86,7 @@ public:
 class FeaturesPlugin_ValidatorCanBeEmpty: public ModelAPI_FeatureValidator
 {
 public:
-  //! Returns true if attribute listed in the parameter arguments are planar.
+  //! \return true if attribute listed in the parameter arguments are planar.
   //! \param[in] theFeature the checked feature.
   //! \param[in] theArguments arguments of the attribute.
   //! \param[out] theError error message.
@@ -79,7 +94,7 @@ public:
                        const std::list<std::string>& theArguments,
                        std::string& theError) const;
 
-  /// Returns true if the attribute in feature is not obligatory for the feature execution
+  /// \return true if the attribute in feature is not obligatory for the feature execution
   virtual bool isNotObligatory(std::string theFeature, std::string theAttribute);
 
 private:
@@ -110,7 +125,23 @@ class FeaturesPlugin_ValidatorPartitionSelection: public ModelAPI_AttributeValid
 {
 public:
   /// \return True if the attribute is valid. It checks whether the selection
-  /// is acceptable for boolean operation.
+  /// is acceptable for operation.
+  /// \param[in] theAttribute an attribute to check.
+  /// \param[in] theArguments a filter parameters.
+  /// \param[out] theError error message.
+  virtual bool isValid(const AttributePtr& theAttribute,
+                       const std::list<std::string>& theArguments,
+                       std::string& theError) const;
+};
+
+/// \class FeaturesPlugin_ValidatorRemoveSubShapesSelection
+/// \ingroup Validators
+/// \brief Validates selection for "Remove Sub-Shapes" feature.
+class FeaturesPlugin_ValidatorRemoveSubShapesSelection: public ModelAPI_AttributeValidator
+{
+public:
+  /// \return True if the attribute is valid. It checks whether the selection
+  /// is acceptable for operation.
   /// \param[in] theAttribute an attribute to check.
   /// \param[in] theArguments a filter parameters.
   /// \param[out] theError error message.
@@ -119,4 +150,22 @@ public:
                        std::string& theError) const;
 };
 
+/// \class FeaturesPlugin_ValidatorRemoveSubShapesResult
+/// \ingroup Validators
+/// \brief Validator for the Remove Sub-Shapes feature.
+class FeaturesPlugin_ValidatorRemoveSubShapesResult: public ModelAPI_FeatureValidator
+{
+ public:
+  //! \return true if result is valid shape.
+  //! \param theFeature the checked feature
+  //! \param theArguments arguments of the feature (not used)
+  //! \param theError error message
+  virtual bool isValid(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                       const std::list<std::string>& theArguments,
+                       std::string& theError) const;
+
+  /// \return true if the attribute in feature is not obligatory for the feature execution
+  virtual bool isNotObligatory(std::string theFeature, std::string theAttribute);
+};
+
 #endif
index 5ccf5998bc3a5cd8e97e5558fdfaae29c5cca3a3..d24a8af36658b9c617520799a085a75c436e4275 100644 (file)
@@ -6,9 +6,9 @@
     buttons_dir="horizontal"
     label="Operation type"
     tooltip="Type of boolean operation"
-    string_list="Cut Fuse Common Fill Smash"
+    string_list="Cut Fuse Common Smash"
     use_in_title="true"
-    icons_list="icons/Features/bool_cut.png icons/Features/bool_fuse.png icons/Features/bool_common.png icons/Features/bool_fill.png icons/Features/bool_smash.png"
+    icons_list="icons/Features/bool_cut.png icons/Features/bool_fuse.png icons/Features/bool_common.png icons/Features/bool_smash.png"
     default="0"
   />
   <multi_selector id="main_objects"
index d52aae72a7bb12ed84d5a2f780ddf5435f295d4c..5951fccb1ee1558a076a91ad49e1e0bb3e5d0b20 100644 (file)
@@ -15,7 +15,7 @@
                   tooltip="Select a base objects"
                   type_choice="wires faces objects"
                   concealment="true">
-    <validator id="FeaturesPlugin_ValidatorBaseForGeneration" parameters="vertex,edge,wire,face,shell"/>
+    <validator id="FeaturesPlugin_ValidatorBaseForGeneration" parameters="vertex,edge,wire,face,shell,compound"/>
   </multi_selector>
   <shape_selector id="direction_object"
                   icon="icons/Features/axis.png"
index daccc15c1f452a410b29264dcb2bfe41aabb619b..4098b79028fd8538f0acc792cfeccd18b1f5adc0 100644 (file)
@@ -16,7 +16,7 @@
       icon="icons/Features/sketch.png"
       tooltip="Select a sketch face"
       type_choice="wires faces objects">
-      <validator id="FeaturesPlugin_ValidatorBaseForGeneration" parameters="vertex,edge,wire,face,shell"/>
+      <validator id="FeaturesPlugin_ValidatorBaseForGeneration" parameters="vertex,edge,wire,face,shell,compound"/>
     </multi_selector>
     <shape_selector id="direction_object"
                     icon="icons/Features/axis.png"
diff --git a/src/FeaturesPlugin/icons/remove_subshapes.png b/src/FeaturesPlugin/icons/remove_subshapes.png
new file mode 100644 (file)
index 0000000..98d7a8c
Binary files /dev/null and b/src/FeaturesPlugin/icons/remove_subshapes.png differ
index 593b19864311b7cea196634a60867dd6336c8c41..b2c8250cc5aad90c1dca8206a221e31e32f85941 100755 (executable)
@@ -8,4 +8,5 @@
     concealment="true">
     <validator id="FeaturesPlugin_ValidatorPartitionSelection" parameters="Plane"/>
   </multi_selector>
+  <validator id="GeomValidators_MinObjectsSelected" parameters="base_objects,2"/>
 </source>
index 591b9e420a0fa615dfa6e26a10b392225f374956..53165ae7c8c01b1b0ea4fbe2dcbb5e7413f3d209 100644 (file)
@@ -7,12 +7,13 @@
                   type_choice="wires faces objects"
                   use_choice="false"
                   concealment="true">
-    <validator id="FeaturesPlugin_ValidatorBaseForGeneration" parameters="vertex,edge,wire,face,shell"/>
+    <validator id="FeaturesPlugin_ValidatorBaseForGeneration" parameters="vertex,edge,wire,face,shell,compound"/>
   </multi_selector>
   <shape_selector id="path_object"
                   label="Path object:"
                   tooltip="Select an edge or wire for path"
                   shape_types="edge wire">
+    <validator id="FeaturesPlugin_ValidatorPipePath"/>
   </shape_selector>
   <toolbox id="creation_method">
     <box id="simple" title="Simple pipe by objects and path" icon="icons/Features/pipe_simple_32x32.png"/>
index 411397b8f418bf7f4efccf51fd48237ab8e51df4..5a70482677608f35c3423cc3242061bb15ba0b6e 100644 (file)
@@ -38,6 +38,9 @@
                auto_preview="false">
           <source path="partition_widget.xml"/>
       </feature>
+      <feature id="Remove_SubShapes" title="Remove Sub-Shapes" tooltip="Allows to remove sub-shapes from wires, shells, compsolids and compounds" icon="icons/Features/remove_subshapes.png">
+          <source path="remove_subshapes_widget.xml"/>
+      </feature>
       <feature id="Intersection" title="Intersection" tooltip="Intersect objects with tools" icon="icons/Features/intersection.png">
           <source path="intersection_widget.xml"/>
       </feature>
diff --git a/src/FeaturesPlugin/remove_subshapes_widget.xml b/src/FeaturesPlugin/remove_subshapes_widget.xml
new file mode 100644 (file)
index 0000000..9300b9a
--- /dev/null
@@ -0,0 +1,21 @@
+<!-- Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+<source>
+  <shape_selector id="base_shape"
+                  label="Shape:"
+                  tooltip="Select a shape to modify."
+                  shape_types="objects"
+                  concealment="true"
+                  greed="true">
+    <validator id="GeomValidators_ShapeType" parameters="wire,shell,compsolid,compound"/>
+    <validator id="GeomValidators_BodyShapes"/>
+  </shape_selector>
+  <multi_selector id="subshapes"
+                  label="Sub-Shapes:"
+                  tooltip="Select shapes to keep."
+                  type_choice="vertices edges wires faces shells solids compsolids compounds"
+                  clear_in_neutral_point="false">
+    <validator id="FeaturesPlugin_ValidatorRemoveSubShapesSelection"/>
+  </multi_selector>
+  <validator id="FeaturesPlugin_ValidatorRemoveSubShapesResult"/>
+</source>
index 9cb27ef7369c464b61fe94819d3c77fa3a7b335b..fe52d714f061c15b3846f11db73cb86bc1b4e916 100644 (file)
@@ -15,7 +15,7 @@
                   tooltip="Select a base objects"
                   type_choice="wires faces objects"
                   concealment="true">
-    <validator id="FeaturesPlugin_ValidatorBaseForGeneration" parameters="vertex,edge,wire,face,shell"/>
+    <validator id="FeaturesPlugin_ValidatorBaseForGeneration" parameters="vertex,edge,wire,face,shell,compound"/>
   </multi_selector>
   <shape_selector id="axis_object"
                   icon="icons/Features/axis.png"
index 1a6055aca205263df7e037be158d4e44de67adfa..614db45418456722c9cdee7a0d4ae634ef57166b 100644 (file)
@@ -16,7 +16,7 @@
       icon="icons/Features/sketch.png"
       tooltip="Select a sketch face"
       type_choice="wires faces objects">
-      <validator id="FeaturesPlugin_ValidatorBaseForGeneration" parameters="vertex,edge,wire,face,shell"/>
+      <validator id="FeaturesPlugin_ValidatorBaseForGeneration" parameters="vertex,edge,wire,face,shell,compound"/>
     </multi_selector>
     <shape_selector id="axis_object"
                     icon="icons/Features/axis.png"
index 0ee2a087c67a17b2d790f8e8b4df1b12d5a89255..43627a1dd56a1281fadcec7db90295ec647be12c 100644 (file)
@@ -131,15 +131,21 @@ bool GeomAPI_Shape::isConnectedTopology() const
     NCollection_List<TopoDS_Shape> aNew; // very new connected to new connected
     NCollection_List<TopoDS_Shape>::Iterator aNotIter(aNotConnected);
     while(aNotIter.More()) {
+      // optimization to avoid TopExp_Explorer double-cycle, collect all vertices in the list first
+      NCollection_List<TopoDS_Shape> aNotVertices;
+      for(TopExp_Explorer anExp1(aNotIter.Value(), TopAbs_VERTEX); anExp1.More(); anExp1.Next()) {
+        aNotVertices.Append(anExp1.Current());
+      }
+
       bool aConnected =  false;
       NCollection_List<TopoDS_Shape>::Iterator aNewIter(aNewConnected);
       for(; !aConnected && aNewIter.More(); aNewIter.Next()) {
         // checking topological connecion of aNotIter and aNewIter (if shapes are connected, vertices are connected for sure)
-        TopExp_Explorer anExp1(aNotIter.Value(), TopAbs_VERTEX);
-        for(; !aConnected && anExp1.More(); anExp1.Next()) {
-          TopExp_Explorer anExp2(aNewIter.Value(), TopAbs_VERTEX);
-          for(; anExp2.More(); anExp2.Next()) {
-            if (anExp1.Current().IsSame(anExp2.Current())) {
+        TopExp_Explorer anExp2(aNewIter.Value(), TopAbs_VERTEX);
+        for(; !aConnected && anExp2.More(); anExp2.Next()) {
+          NCollection_List<TopoDS_Shape>::Iterator aNotIter(aNotVertices);
+          for(; aNotIter.More(); aNotIter.Next()) {
+            if (aNotIter.Value().IsSame(anExp2.Current())) {
               aConnected = true;
               break;
             }
index 2006c87462b7334858ece234bc1f0b835ecf63e6..05623740b622cd0837c1dcd4f412fec1f2f48c27 100644 (file)
@@ -27,30 +27,30 @@ class GeomAlgoAPI_MakeSweep : public GeomAlgoAPI_MakeShapeList
 {
 public:
   /// \returns the list of from shapes.
-  GEOMALGOAPI_EXPORT virtual const ListOfShape& fromShapes() const;
+  GEOMALGOAPI_EXPORT const ListOfShape& fromShapes() const;
 
   /// \return the list of to shapes.
-  GEOMALGOAPI_EXPORT virtual const ListOfShape& toShapes() const;
-
-protected:
-  /// Empty constructor.
-  GeomAlgoAPI_MakeSweep() : GeomAlgoAPI_MakeShapeList() {};
+  GEOMALGOAPI_EXPORT const ListOfShape& toShapes() const;
 
   /// \brief Adds a shape to list of from shape.
   /// \param[in] theShape a shape to add.
-  void addFromShape(const std::shared_ptr<GeomAPI_Shape> theShape);
+  GEOMALGOAPI_EXPORT void addFromShape(const std::shared_ptr<GeomAPI_Shape> theShape);
 
   /// \brief Sets from shapes
   /// \param[in] theListOfShapes list of from shapes.
-  void setFromShapes(const ListOfShape& theListOfShapes);
+  GEOMALGOAPI_EXPORT void setFromShapes(const ListOfShape& theListOfShapes);
 
   /// \brief Adds a face to list of to shape.
   /// \param[in] theShape a face to add.
-  void addToShape(const std::shared_ptr<GeomAPI_Shape> theShape);
+  GEOMALGOAPI_EXPORT void addToShape(const std::shared_ptr<GeomAPI_Shape> theShape);
 
   /// \brief Sets to shapes
   /// \param[in] theListOfShapes list of to shapes.
-  void setToShapes(const ListOfShape& theListOfShapes);
+  GEOMALGOAPI_EXPORT void setToShapes(const ListOfShape& theListOfShapes);
+
+protected:
+  /// Empty constructor.
+  GeomAlgoAPI_MakeSweep() : GeomAlgoAPI_MakeShapeList() {};
 
 private:
   ListOfShape myFromShapes;
index c24a9600e785d820670c89c942a6752f1e39a2dc..04b310006af1f7ef84c917153b5fdece5c2b2bfb 100644 (file)
@@ -30,15 +30,16 @@ static bool getBase(TopoDS_Shape& theBaseOut,
 static bool getPath(TopoDS_Wire& thePathOut,
                     const GeomShapePtr thePathShape);
 static bool buildPipe(BRepOffsetAPI_MakePipeShell* thePipeBuilder);
+static ListOfShape getListFromShape(const TopoDS_Shape& theShape);
 
-//=================================================================================================
+//==================================================================================================
 GeomAlgoAPI_Pipe::GeomAlgoAPI_Pipe(const GeomShapePtr theBaseShape,
                                    const GeomShapePtr thePathShape)
 {
   build(theBaseShape, thePathShape);
 }
 
-//=================================================================================================
+//==================================================================================================
 GeomAlgoAPI_Pipe::GeomAlgoAPI_Pipe(const GeomShapePtr theBaseShape,
                                    const GeomShapePtr thePathShape,
                                    const GeomShapePtr theBiNormal)
@@ -46,7 +47,7 @@ GeomAlgoAPI_Pipe::GeomAlgoAPI_Pipe(const GeomShapePtr theBaseShape,
   build(theBaseShape, thePathShape, theBiNormal);
 }
 
-//=================================================================================================
+//==================================================================================================
 GeomAlgoAPI_Pipe::GeomAlgoAPI_Pipe(const ListOfShape& theBaseShapes,
                                    const ListOfShape& theLocations,
                                    const GeomShapePtr thePathShape)
@@ -54,7 +55,7 @@ GeomAlgoAPI_Pipe::GeomAlgoAPI_Pipe(const ListOfShape& theBaseShapes,
   build(theBaseShapes, theLocations, thePathShape);
 }
 
-//=================================================================================================
+//==================================================================================================
 void GeomAlgoAPI_Pipe::build(const GeomShapePtr theBaseShape,
                              const GeomShapePtr thePathShape)
 {
@@ -69,7 +70,7 @@ void GeomAlgoAPI_Pipe::build(const GeomShapePtr theBaseShape,
   TopAbs_ShapeEnum aBaseShapeType = aBaseShape.ShapeType();
   if(aBaseShapeType != TopAbs_VERTEX && aBaseShapeType != TopAbs_EDGE &&
      aBaseShapeType != TopAbs_WIRE && aBaseShapeType != TopAbs_FACE &&
-     aBaseShapeType != TopAbs_SHELL) {
+     aBaseShapeType != TopAbs_SHELL && aBaseShapeType != TopAbs_COMPOUND) {
     return;
   }
 
@@ -94,11 +95,8 @@ void GeomAlgoAPI_Pipe::build(const GeomShapePtr theBaseShape,
   this->initialize(aPipeBuilder);
 
   // Setting naming.
-  GeomShapePtr aFromShape(new GeomAPI_Shape), aToShape(new GeomAPI_Shape);
-  aFromShape->setImpl(new TopoDS_Shape(aPipeBuilder->FirstShape()));
-  aToShape->setImpl(new TopoDS_Shape(aPipeBuilder->LastShape()));
-  this->addFromShape(aFromShape);
-  this->addToShape(aToShape);
+  this->setToShapes(getListFromShape(aPipeBuilder->LastShape()));
+  this->setFromShapes(getListFromShape(aPipeBuilder->FirstShape()));
 
   // Setting result.
   TopoDS_Shape aResult = aPipeBuilder->Shape();
@@ -109,7 +107,7 @@ void GeomAlgoAPI_Pipe::build(const GeomShapePtr theBaseShape,
   this->setDone(true);
 }
 
-//=================================================================================================
+//==================================================================================================
 void GeomAlgoAPI_Pipe::build(const GeomShapePtr theBaseShape,
                              const GeomShapePtr thePathShape,
                              const GeomShapePtr theBiNormal)
@@ -164,18 +162,15 @@ void GeomAlgoAPI_Pipe::build(const GeomShapePtr theBaseShape,
     }
   }
   TopoDS_Shape aResult = aPipeBuilder->Shape();
+  if(aResult.IsNull()) {
+    return;
+  }
 
   // Setting naming.
-  GeomShapePtr aFromShape(new GeomAPI_Shape), aToShape(new GeomAPI_Shape);
-  aFromShape->setImpl(new TopoDS_Shape(aPipeBuilder->FirstShape()));
-  aToShape->setImpl(new TopoDS_Shape(aPipeBuilder->LastShape()));
-  this->addFromShape(aFromShape);
-  this->addToShape(aToShape);
+  this->setToShapes(getListFromShape(aPipeBuilder->LastShape()));
+  this->setFromShapes(getListFromShape(aPipeBuilder->FirstShape()));
 
   // Setting result.
-  if(aResult.IsNull()) {
-    return;
-  }
   aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
   GeomShapePtr aGeomSh(new GeomAPI_Shape());
   aGeomSh->setImpl(new TopoDS_Shape(aResult));
@@ -183,7 +178,7 @@ void GeomAlgoAPI_Pipe::build(const GeomShapePtr theBaseShape,
   this->setDone(true);
 }
 
-//=================================================================================================
+//==================================================================================================
 void GeomAlgoAPI_Pipe::build(const ListOfShape& theBaseShapes,
                              const ListOfShape& theLocations,
                              const GeomShapePtr thePathShape)
@@ -275,7 +270,7 @@ void GeomAlgoAPI_Pipe::build(const ListOfShape& theBaseShapes,
   this->setDone(true);
 }
 
-//=================================================================================================
+//==================================================================================================
 void GeomAlgoAPI_Pipe::generated(const GeomShapePtr theShape,
                                  ListOfShape& theHistory)
 {
@@ -283,7 +278,7 @@ void GeomAlgoAPI_Pipe::generated(const GeomShapePtr theShape,
 }
 
 // Auxilary functions:
-//=================================================================================================
+//==================================================================================================
 bool getBase(TopoDS_Shape& theBaseOut,
              TopAbs_ShapeEnum& theBaseTypeOut,
              const GeomShapePtr theBaseShape)
@@ -313,7 +308,7 @@ bool getBase(TopoDS_Shape& theBaseOut,
   return true;
 }
 
-//=================================================================================================
+//==================================================================================================
 bool getPath(TopoDS_Wire& thePathOut,
              const GeomShapePtr thePathShape)
 {
@@ -338,7 +333,7 @@ bool getPath(TopoDS_Wire& thePathOut,
   return true;
 }
 
-//=================================================================================================
+//==================================================================================================
 bool buildPipe(BRepOffsetAPI_MakePipeShell* thePipeBuilder)
 {
   thePipeBuilder->Build();
@@ -354,3 +349,24 @@ bool buildPipe(BRepOffsetAPI_MakePipeShell* thePipeBuilder)
 
   return isDone == Standard_True;
 }
+
+//==================================================================================================
+ListOfShape getListFromShape(const TopoDS_Shape& theShape)
+{
+  ListOfShape aList;
+
+  TopAbs_ShapeEnum aType = theShape.ShapeType();
+  if(aType == TopAbs_WIRE || aType == TopAbs_SHELL || aType == TopAbs_COMPOUND) {
+    for(TopoDS_Iterator anIt(theShape); anIt.More(); anIt.Next()) {
+      GeomShapePtr aGeomShape(new GeomAPI_Shape());
+      aGeomShape->setImpl(new TopoDS_Shape(anIt.Value()));
+      aList.push_back(aGeomShape);
+    }
+  } else {
+    GeomShapePtr aGeomShape(new GeomAPI_Shape());
+    aGeomShape->setImpl(new TopoDS_Shape(theShape));
+    aList.push_back(aGeomShape);
+  }
+
+  return aList;
+}
index 0c0136f170cc35a52f49a55d343703fdbe55711c..49204ee9032404f5fc90e19786ca27e61c2f2617 100644 (file)
 #include <TopoDS_Solid.hxx>
 #include <TopTools_ListIteratorOfListOfShape.hxx>
 
-//=================================================================================================
+
+static void storeGenerationHistory(GeomAlgoAPI_Prism* thePrismAlgo,
+                                   const TopoDS_Shape& theBase,
+                                   const TopAbs_ShapeEnum theType,
+                                   BRepPrimAPI_MakePrism* thePrismBuilder);
+
+static void storeGenerationHistory(GeomAlgoAPI_Prism* thePrismAlgo,
+                                   const TopoDS_Shape& theResult,
+                                   const TopAbs_ShapeEnum theType,
+                                   const TopoDS_Face& theToFace,
+                                   const TopoDS_Face& theFromFace);
+
+
+//==================================================================================================
 GeomAlgoAPI_Prism::GeomAlgoAPI_Prism(const GeomShapePtr theBaseShape,
                                      const double       theToSize,
                                      const double       theFromSize)
@@ -47,7 +60,7 @@ GeomAlgoAPI_Prism::GeomAlgoAPI_Prism(const GeomShapePtr theBaseShape,
   build(theBaseShape, std::shared_ptr<GeomAPI_Dir>(), GeomShapePtr(), theToSize, GeomShapePtr(), theFromSize);
 }
 
-//=================================================================================================
+//==================================================================================================
 GeomAlgoAPI_Prism::GeomAlgoAPI_Prism(const GeomShapePtr                 theBaseShape,
                                      const std::shared_ptr<GeomAPI_Dir> theDirection,
                                      const double                       theToSize,
@@ -56,7 +69,7 @@ GeomAlgoAPI_Prism::GeomAlgoAPI_Prism(const GeomShapePtr                 theBaseS
   build(theBaseShape, theDirection, GeomShapePtr(), theToSize, GeomShapePtr(), theFromSize);
 }
 
-//=================================================================================================
+//==================================================================================================
 GeomAlgoAPI_Prism::GeomAlgoAPI_Prism(const GeomShapePtr theBaseShape,
                                      const GeomShapePtr theToShape,
                                      const double       theToSize,
@@ -66,7 +79,7 @@ GeomAlgoAPI_Prism::GeomAlgoAPI_Prism(const GeomShapePtr theBaseShape,
   build(theBaseShape, std::shared_ptr<GeomAPI_Dir>(), theToShape, theToSize, theFromShape, theFromSize);
 }
 
-//=================================================================================================
+//==================================================================================================
 GeomAlgoAPI_Prism::GeomAlgoAPI_Prism(const GeomShapePtr                 theBaseShape,
                                      const std::shared_ptr<GeomAPI_Dir> theDirection,
                                      const GeomShapePtr                 theToShape,
@@ -77,7 +90,7 @@ GeomAlgoAPI_Prism::GeomAlgoAPI_Prism(const GeomShapePtr                 theBaseS
   build(theBaseShape, theDirection, theToShape, theToSize, theFromShape, theFromSize);
 }
 
-//=================================================================================================
+//==================================================================================================
 void GeomAlgoAPI_Prism::build(const GeomShapePtr&                theBaseShape,
                               const std::shared_ptr<GeomAPI_Dir> theDirection,
                               const GeomShapePtr&                theToShape,
@@ -106,6 +119,9 @@ void GeomAlgoAPI_Prism::build(const GeomShapePtr&                theBaseShape,
     case TopAbs_SHELL:
       aShapeTypeToExp = TopAbs_FACE;
       break;
+    case TopAbs_COMPOUND:
+      aShapeTypeToExp = TopAbs_COMPOUND;
+      break;
     default:
       return;
   }
@@ -193,13 +209,11 @@ void GeomAlgoAPI_Prism::build(const GeomShapePtr&                theBaseShape,
     aResult = aPrismBuilder->Shape();
 
     // Setting naming.
-    for(TopExp_Explorer anExp(aMovedBase, aShapeTypeToExp); anExp.More(); anExp.Next()) {
-      const TopoDS_Shape& aShape = anExp.Current();
-      GeomShapePtr aFromShape(new GeomAPI_Shape), aToShape(new GeomAPI_Shape);
-      aFromShape->setImpl(new TopoDS_Shape(aPrismBuilder->FirstShape(aShape)));
-      aToShape->setImpl(new TopoDS_Shape(aPrismBuilder->LastShape(aShape)));
-      this->addFromShape(aFromShape);
-      this->addToShape(aToShape);
+    if(aShapeTypeToExp == TopAbs_COMPOUND) {
+      storeGenerationHistory(this, aMovedBase, TopAbs_EDGE, aPrismBuilder);
+      storeGenerationHistory(this, aMovedBase, TopAbs_FACE, aPrismBuilder);
+    } else {
+      storeGenerationHistory(this, aMovedBase, aShapeTypeToExp, aPrismBuilder);
     }
   } else {
     GeomShapePtr aBoundingFromShape = theFromShape ? theFromShape : aBasePlane;
@@ -349,7 +363,7 @@ void GeomAlgoAPI_Prism::build(const GeomShapePtr&                theBaseShape,
     if(aResult.ShapeType() == TopAbs_COMPOUND) {
       aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
     }
-    if(aShapeTypeToExp == TopAbs_FACE) {
+    if(aShapeTypeToExp == TopAbs_FACE || aShapeTypeToExp == TopAbs_COMPOUND) {
       const TopTools_ListOfShape& aToShapes = aToCutBuilder->Modified(aToShape);
       for(TopTools_ListIteratorOfListOfShape anIt(aToShapes); anIt.More(); anIt.Next()) {
         GeomShapePtr aGeomSh(new GeomAPI_Shape());
@@ -373,7 +387,7 @@ void GeomAlgoAPI_Prism::build(const GeomShapePtr&                theBaseShape,
     if(aResult.ShapeType() == TopAbs_COMPOUND) {
       aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
     }
-    if(aShapeTypeToExp == TopAbs_FACE) {
+    if(aShapeTypeToExp == TopAbs_FACE || aShapeTypeToExp == TopAbs_COMPOUND) {
       const TopTools_ListOfShape& aFromShapes = aFromCutBuilder->Modified(aFromShape);
       for(TopTools_ListIteratorOfListOfShape anIt(aFromShapes); anIt.More(); anIt.Next()) {
         GeomShapePtr aGeomSh(new GeomAPI_Shape());
@@ -383,37 +397,11 @@ void GeomAlgoAPI_Prism::build(const GeomShapePtr&                theBaseShape,
     }
 
     // Naming for extrusion from vertex, edge.
-    for(TopExp_Explorer anExp(aResult, aShapeTypeToExp); anExp.More(); anExp.Next()) {
-      const TopoDS_Shape& aShape = anExp.Current();
-      GeomShapePtr aGeomSh(new GeomAPI_Shape());
-      if(aShapeTypeToExp == TopAbs_VERTEX) {
-        gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aShape));
-        IntTools_Context anIntTools;
-        if(anIntTools.IsValidPointForFace(aPnt, aToFace, Precision::Confusion()) == Standard_True) {
-          aGeomSh->setImpl(new TopoDS_Shape(aShape));
-          this->addToShape(aGeomSh);
-        }
-        if(anIntTools.IsValidPointForFace(aPnt, aFromFace, Precision::Confusion()) == Standard_True) {
-          aGeomSh->setImpl(new TopoDS_Shape(aShape));
-          this->addFromShape(aGeomSh);
-        }
-      } else if(aShapeTypeToExp == TopAbs_EDGE) {
-        TopoDS_Edge anEdge = TopoDS::Edge(aShape);
-        BRepLib_CheckCurveOnSurface anEdgeCheck(anEdge, aToFace);
-        anEdgeCheck.Perform();
-        if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
-          aGeomSh->setImpl(new TopoDS_Shape(aShape));
-          this->addToShape(aGeomSh);
-        }
-        anEdgeCheck.Init(anEdge, aFromFace);
-        anEdgeCheck.Perform();
-        if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
-          aGeomSh->setImpl(new TopoDS_Shape(aShape));
-          this->addFromShape(aGeomSh);
-        }
-      } else {
-        break;
-      }
+    if(aShapeTypeToExp == TopAbs_COMPOUND) {
+      storeGenerationHistory(this, aResult, TopAbs_EDGE, aToFace, aFromFace);
+      storeGenerationHistory(this, aResult, TopAbs_FACE, aToFace, aFromFace);
+    } else {
+      storeGenerationHistory(this, aResult, aShapeTypeToExp, aToFace, aFromFace);
     }
 
     if(aResult.ShapeType() == TopAbs_COMPOUND) {
@@ -438,3 +426,61 @@ void GeomAlgoAPI_Prism::build(const GeomShapePtr&                theBaseShape,
   this->setShape(aGeomSh);
   this->setDone(true);
 }
+
+// Auxilary functions:
+//==================================================================================================
+void storeGenerationHistory(GeomAlgoAPI_Prism* thePrismAlgo,
+                            const TopoDS_Shape& theBase,
+                            const TopAbs_ShapeEnum theType,
+                            BRepPrimAPI_MakePrism* thePrismBuilder)
+{
+  for(TopExp_Explorer anExp(theBase, theType); anExp.More(); anExp.Next()) {
+    const TopoDS_Shape& aShape = anExp.Current();
+    GeomShapePtr aFromShape(new GeomAPI_Shape), aToShape(new GeomAPI_Shape);
+    aFromShape->setImpl(new TopoDS_Shape(thePrismBuilder->FirstShape(aShape)));
+    aToShape->setImpl(new TopoDS_Shape(thePrismBuilder->LastShape(aShape)));
+    thePrismAlgo->addFromShape(aFromShape);
+    thePrismAlgo->addToShape(aToShape);
+  }
+}
+
+//==================================================================================================
+void storeGenerationHistory(GeomAlgoAPI_Prism* thePrismAlgo,
+                            const TopoDS_Shape& theResult,
+                            const TopAbs_ShapeEnum theType,
+                            const TopoDS_Face& theToFace,
+                            const TopoDS_Face& theFromFace)
+{
+  for(TopExp_Explorer anExp(theResult, theType); anExp.More(); anExp.Next()) {
+    const TopoDS_Shape& aShape = anExp.Current();
+    GeomShapePtr aGeomSh(new GeomAPI_Shape());
+    if(theType == TopAbs_VERTEX) {
+      gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aShape));
+      IntTools_Context anIntTools;
+      if(anIntTools.IsValidPointForFace(aPnt, theToFace, Precision::Confusion()) == Standard_True) {
+        aGeomSh->setImpl(new TopoDS_Shape(aShape));
+        thePrismAlgo->addToShape(aGeomSh);
+      }
+      if(anIntTools.IsValidPointForFace(aPnt, theFromFace, Precision::Confusion()) == Standard_True) {
+        aGeomSh->setImpl(new TopoDS_Shape(aShape));
+        thePrismAlgo->addFromShape(aGeomSh);
+      }
+    } else if(theType == TopAbs_EDGE) {
+      TopoDS_Edge anEdge = TopoDS::Edge(aShape);
+      BRepLib_CheckCurveOnSurface anEdgeCheck(anEdge, theToFace);
+      anEdgeCheck.Perform();
+      if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
+        aGeomSh->setImpl(new TopoDS_Shape(aShape));
+        thePrismAlgo->addToShape(aGeomSh);
+      }
+      anEdgeCheck.Init(anEdge, theFromFace);
+      anEdgeCheck.Perform();
+      if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
+        aGeomSh->setImpl(new TopoDS_Shape(aShape));
+        thePrismAlgo->addFromShape(aGeomSh);
+      }
+    } else {
+      break;
+    }
+  }
+}
index 50f49e2f9e9c2d859d54551607f446054988bac4..b6bc188eb31df6716fecf47f466ecd6a0b8ac89f 100644 (file)
@@ -56,7 +56,25 @@ static gp_Pnt centreOfMass(const TopoDS_Shape& theShape);
 /// \return solid.
 static TopoDS_Shape findClosest(const TopoDS_Shape& theShape, const gp_Pnt& thePoint);
 
-//=================================================================================================
+static void storeGenerationHistory(GeomAlgoAPI_Revolution* theRevolutionAlgo,
+                                   const TopoDS_Shape& theBase,
+                                   const TopAbs_ShapeEnum theType,
+                                   BRepPrimAPI_MakeRevol* theRevolBuilder);
+
+static void storeGenerationHistory(GeomAlgoAPI_Revolution* theRevolutionAlgo,
+                                   const TopoDS_Shape& theResult,
+                                   const TopAbs_ShapeEnum theType,
+                                   const TopoDS_Shape& theToFace,
+                                   const TopoDS_Shape& theFromFace);
+
+static void storeGenerationHistory(GeomAlgoAPI_Revolution* theRevolutionAlgo,
+                                   const TopoDS_Shape& theResult,
+                                   const TopAbs_ShapeEnum theType,
+                                   const TopoDS_Shape& theRotatedBoundingFace,
+                                   const TopoDS_Shape& theModifiedBaseShape,
+                                   const bool theIsFromFaceSet);
+
+//==================================================================================================
 GeomAlgoAPI_Revolution::GeomAlgoAPI_Revolution(const GeomShapePtr                 theBaseShape,
                                                const std::shared_ptr<GeomAPI_Ax1> theAxis,
                                                const double                       theToAngle,
@@ -65,7 +83,7 @@ GeomAlgoAPI_Revolution::GeomAlgoAPI_Revolution(const GeomShapePtr
   build(theBaseShape, theAxis, GeomShapePtr(), theToAngle, GeomShapePtr(), theFromAngle);
 }
 
-//=================================================================================================
+//==================================================================================================
 GeomAlgoAPI_Revolution::GeomAlgoAPI_Revolution(const GeomShapePtr                 theBaseShape,
                                                const std::shared_ptr<GeomAPI_Ax1> theAxis,
                                                const GeomShapePtr                 theToShape,
@@ -76,7 +94,7 @@ GeomAlgoAPI_Revolution::GeomAlgoAPI_Revolution(const GeomShapePtr
   build(theBaseShape, theAxis, theToShape, theToAngle, theFromShape, theFromAngle);
 }
 
-//=================================================================================================
+//==================================================================================================
 void GeomAlgoAPI_Revolution::build(const GeomShapePtr&                 theBaseShape,
                                    const std::shared_ptr<GeomAPI_Ax1>& theAxis,
                                    const GeomShapePtr&                 theToShape,
@@ -105,6 +123,9 @@ void GeomAlgoAPI_Revolution::build(const GeomShapePtr&                 theBaseSh
     case TopAbs_SHELL:
       aShapeTypeToExp = TopAbs_FACE;
       break;
+    case TopAbs_COMPOUND:
+      aShapeTypeToExp = TopAbs_COMPOUND;
+      break;
     default:
       return;
   }
@@ -187,13 +208,11 @@ void GeomAlgoAPI_Revolution::build(const GeomShapePtr&                 theBaseSh
     aResult = aRevolBuilder->Shape();
 
     // Setting naming.
-    for(TopExp_Explorer anExp(aRotatedBase, aShapeTypeToExp); anExp.More(); anExp.Next()) {
-      const TopoDS_Shape& aShape = anExp.Current();
-      GeomShapePtr aFromShape(new GeomAPI_Shape), aToShape(new GeomAPI_Shape);
-      aFromShape->setImpl(new TopoDS_Shape(aRevolBuilder->FirstShape(aShape)));
-      aToShape->setImpl(new TopoDS_Shape(aRevolBuilder->LastShape(aShape)));
-      this->addFromShape(aFromShape);
-      this->addToShape(aToShape);
+    if(aShapeTypeToExp == TopAbs_COMPOUND) {
+      storeGenerationHistory(this, aRotatedBase, TopAbs_EDGE, aRevolBuilder);
+      storeGenerationHistory(this, aRotatedBase, TopAbs_FACE, aRevolBuilder);
+    } else {
+      storeGenerationHistory(this, aRotatedBase, aShapeTypeToExp, aRevolBuilder);
     }
   } else if(theFromShape && theToShape) { // Case 2: When both bounding planes were set.
     // Making revolution to the 360 angle.
@@ -285,47 +304,11 @@ void GeomAlgoAPI_Revolution::build(const GeomShapePtr&                 theBaseSh
     aResult = findClosest(aResult, aBaseCentre);
 
     // Setting naming.
-    for(TopExp_Explorer anExp(aResult, aShapeTypeToExp); anExp.More (); anExp.Next ()) {
-      const TopoDS_Shape& aShape = anExp.Current();
-      GeomShapePtr aGeomSh(new GeomAPI_Shape());
-      if(aShapeTypeToExp == TopAbs_VERTEX) {
-        gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aShape));
-        IntTools_Context anIntTools;
-        if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(aRotatedToFace), Precision::Confusion()) == Standard_True) {
-          aGeomSh->setImpl(new TopoDS_Shape(aShape));
-          this->addToShape(aGeomSh);
-        }
-        if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(aRotatedFromFace), Precision::Confusion()) == Standard_True) {
-          aGeomSh->setImpl(new TopoDS_Shape(aShape));
-          this->addFromShape(aGeomSh);
-        }
-      } else if(aShapeTypeToExp == TopAbs_EDGE) {
-        TopoDS_Edge anEdge = TopoDS::Edge(aShape);
-        BRepLib_CheckCurveOnSurface anEdgeCheck(anEdge, TopoDS::Face(aRotatedToFace));
-        anEdgeCheck.Perform();
-        if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
-          aGeomSh->setImpl(new TopoDS_Shape(aShape));
-          this->addToShape(aGeomSh);
-        }
-        anEdgeCheck.Init(anEdge, TopoDS::Face(aRotatedFromFace));
-        anEdgeCheck.Perform();
-        if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
-          aGeomSh->setImpl(new TopoDS_Shape(aShape));
-          this->addFromShape(aGeomSh);
-        }
-      } else {
-        Handle(Geom_Surface) aFaceSurface = BRep_Tool::Surface(TopoDS::Face(aShape));
-        Handle(Geom_Surface) aFromSurface = BRep_Tool::Surface(TopoDS::Face(aRotatedFromFace));
-        Handle(Geom_Surface) aToSurface = BRep_Tool::Surface(TopoDS::Face(aRotatedToFace));
-        if(aFaceSurface == aFromSurface) {
-          aGeomSh->setImpl(new TopoDS_Shape(aShape));
-          this->addFromShape(aGeomSh);
-        }
-        if(aFaceSurface == aToSurface) {
-          aGeomSh->setImpl(new TopoDS_Shape(aShape));
-          this->addToShape(aGeomSh);
-        }
-      }
+    if(aShapeTypeToExp == TopAbs_COMPOUND) {
+      storeGenerationHistory(this, aResult, TopAbs_EDGE, aRotatedToFace, aRotatedFromFace);
+      storeGenerationHistory(this, aResult, TopAbs_FACE, aRotatedToFace, aRotatedFromFace);
+    } else {
+      storeGenerationHistory(this, aResult, aShapeTypeToExp, aRotatedToFace, aRotatedFromFace);
     }
   } else { //Case 3: When only one bounding plane was set.
     // Making revolution to the 360 angle.
@@ -393,7 +376,7 @@ void GeomAlgoAPI_Revolution::build(const GeomShapePtr&                 theBaseSh
     }
 
     // Setting naming.
-    if(aShapeTypeToExp == TopAbs_FACE) {
+    if(aShapeTypeToExp == TopAbs_FACE || aShapeTypeToExp == TopAbs_COMPOUND) {
       const TopTools_ListOfShape& aBndShapes = aBoundingCutBuilder->Modified(aBoundingFace);
       for(TopTools_ListIteratorOfListOfShape anIt(aBndShapes); anIt.More(); anIt.Next()) {
         GeomShapePtr aShape(new GeomAPI_Shape());
@@ -455,7 +438,7 @@ void GeomAlgoAPI_Revolution::build(const GeomShapePtr&                 theBaseSh
         if(aResult.ShapeType() == TopAbs_COMPOUND) {
           aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
         }
-        if(aShapeTypeToExp == TopAbs_FACE) {
+        if(aShapeTypeToExp == TopAbs_FACE || aShapeTypeToExp == TopAbs_COMPOUND) {
           const TopTools_ListOfShape& aBsShapes = aBaseCutBuilder->Modified(aBoundingFace);
           for(TopTools_ListIteratorOfListOfShape anIt(aBsShapes); anIt.More(); anIt.Next()) {
             GeomShapePtr aShape(new GeomAPI_Shape());
@@ -481,47 +464,11 @@ void GeomAlgoAPI_Revolution::build(const GeomShapePtr&                 theBaseSh
     aResult = findClosest(aResult, aBaseCentre);
 
     // Setting naming.
-    for(TopExp_Explorer anExp(aResult, aShapeTypeToExp); anExp.More (); anExp.Next ()) {
-      const TopoDS_Shape& aShape = anExp.Current();
-      GeomShapePtr aGeomSh(new GeomAPI_Shape());
-      if(aShapeTypeToExp == TopAbs_VERTEX) {
-        gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aShape));
-        IntTools_Context anIntTools;
-        if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(aRotatedBoundingFace), Precision::Confusion()) == Standard_True) {
-          aGeomSh->setImpl(new TopoDS_Shape(aShape));
-          isFromFaceSet ? this->addFromShape(aGeomSh) : this->addToShape(aGeomSh);
-        }
-        if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(aModifiedBaseShape), Precision::Confusion()) == Standard_True) {
-          aGeomSh->setImpl(new TopoDS_Shape(aShape));
-          isFromFaceSet ? this->addToShape(aGeomSh) : this->addFromShape(aGeomSh);
-        }
-      } else if(aShapeTypeToExp == TopAbs_EDGE) {
-        TopoDS_Edge anEdge = TopoDS::Edge(aShape);
-        BRepLib_CheckCurveOnSurface anEdgeCheck(anEdge, TopoDS::Face(aRotatedBoundingFace));
-        anEdgeCheck.Perform();
-        if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
-          aGeomSh->setImpl(new TopoDS_Shape(aShape));
-          isFromFaceSet ? this->addFromShape(aGeomSh) : this->addToShape(aGeomSh);
-        }
-        anEdgeCheck.Init(anEdge, TopoDS::Face(aModifiedBaseShape));
-        anEdgeCheck.Perform();
-        if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
-          aGeomSh->setImpl(new TopoDS_Shape(aShape));
-          isFromFaceSet ? this->addToShape(aGeomSh) : this->addFromShape(aGeomSh);
-        }
-      } else {
-        Handle(Geom_Surface) aFaceSurface = BRep_Tool::Surface(TopoDS::Face(aShape));
-        Handle(Geom_Surface) aBoundingSurface = BRep_Tool::Surface(TopoDS::Face(aRotatedBoundingFace));
-        Handle(Geom_Surface) aBaseSurface = BRep_Tool::Surface(TopoDS::Face(aModifiedBaseShape));
-        if(aFaceSurface == aBoundingSurface) {
-          aGeomSh->setImpl(new TopoDS_Shape(aShape));
-          isFromFaceSet ? this->addFromShape(aGeomSh) : this->addToShape(aGeomSh);
-        }
-        if(aFaceSurface == aBaseSurface) {
-          aGeomSh->setImpl(new TopoDS_Shape(aShape));
-          isFromFaceSet ? this->addToShape(aGeomSh) : this->addFromShape(aGeomSh);
-        }
-      }
+    if(aShapeTypeToExp == TopAbs_COMPOUND) {
+      storeGenerationHistory(this, aResult, TopAbs_EDGE, aRotatedBoundingFace, aModifiedBaseShape, isFromFaceSet);
+      storeGenerationHistory(this, aResult, TopAbs_FACE, aRotatedBoundingFace, aModifiedBaseShape, isFromFaceSet);
+    } else {
+      storeGenerationHistory(this, aResult, aShapeTypeToExp, aRotatedBoundingFace, aModifiedBaseShape, isFromFaceSet);
     }
   }
 
@@ -536,7 +483,7 @@ void GeomAlgoAPI_Revolution::build(const GeomShapePtr&                 theBaseSh
   this->setDone(true);
 }
 
-//=================================================================================================
+//==================================================================================================
 TopoDS_Face makeFaceFromPlane(gp_Pln& thePlane, const gp_Pnt& thePoint)
 {
   if(!thePlane.Contains(thePoint, Precision::Confusion())) {
@@ -551,7 +498,7 @@ TopoDS_Face makeFaceFromPlane(gp_Pln& thePlane, const gp_Pnt& thePoint)
   return aResultFace;
 }
 
-//=================================================================================================
+//==================================================================================================
 TopoDS_Solid makeSolidFromShape(const TopoDS_Shape& theShape)
 {
   TopoDS_Shell aShell;
@@ -570,7 +517,7 @@ TopoDS_Solid makeSolidFromShape(const TopoDS_Shape& theShape)
   return aSolid;
 }
 
-//=================================================================================================
+//==================================================================================================
 gp_Pnt centreOfMass(const TopoDS_Shape& theShape)
 {
   TopAbs_ShapeEnum aShType = theShape.ShapeType();
@@ -587,7 +534,7 @@ gp_Pnt centreOfMass(const TopoDS_Shape& theShape)
   return aGProps.CentreOfMass();
 }
 
-//=================================================================================================
+//==================================================================================================
 TopoDS_Shape findClosest(const TopoDS_Shape& theShape, const gp_Pnt& thePoint)
 {
   TopoDS_Shape aResult = theShape;
@@ -610,3 +557,121 @@ TopoDS_Shape findClosest(const TopoDS_Shape& theShape, const gp_Pnt& thePoint)
 
   return aResult;
 }
+
+//==================================================================================================
+void storeGenerationHistory(GeomAlgoAPI_Revolution* theRevolutionAlgo,
+                            const TopoDS_Shape& theBase,
+                            const TopAbs_ShapeEnum theType,
+                            BRepPrimAPI_MakeRevol* theRevolBuilder)
+{
+  for(TopExp_Explorer anExp(theBase, theType); anExp.More(); anExp.Next()) {
+    const TopoDS_Shape& aShape = anExp.Current();
+    GeomShapePtr aFromShape(new GeomAPI_Shape), aToShape(new GeomAPI_Shape);
+    aFromShape->setImpl(new TopoDS_Shape(theRevolBuilder->FirstShape(aShape)));
+    aToShape->setImpl(new TopoDS_Shape(theRevolBuilder->LastShape(aShape)));
+    theRevolutionAlgo->addFromShape(aFromShape);
+    theRevolutionAlgo->addToShape(aToShape);
+  }
+}
+
+//==================================================================================================
+void storeGenerationHistory(GeomAlgoAPI_Revolution* theRevolutionAlgo,
+                            const TopoDS_Shape& theResult,
+                            const TopAbs_ShapeEnum theType,
+                            const TopoDS_Shape& theToFace,
+                            const TopoDS_Shape& theFromFace)
+{
+  for(TopExp_Explorer anExp(theResult, theType); anExp.More (); anExp.Next ()) {
+    const TopoDS_Shape& aShape = anExp.Current();
+    GeomShapePtr aGeomSh(new GeomAPI_Shape());
+    if(theType == TopAbs_VERTEX) {
+      gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aShape));
+      IntTools_Context anIntTools;
+      if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(theToFace), Precision::Confusion()) == Standard_True) {
+        aGeomSh->setImpl(new TopoDS_Shape(aShape));
+        theRevolutionAlgo->addToShape(aGeomSh);
+      }
+      if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(theFromFace), Precision::Confusion()) == Standard_True) {
+        aGeomSh->setImpl(new TopoDS_Shape(aShape));
+        theRevolutionAlgo->addFromShape(aGeomSh);
+      }
+    } else if(theType == TopAbs_EDGE) {
+      TopoDS_Edge anEdge = TopoDS::Edge(aShape);
+      BRepLib_CheckCurveOnSurface anEdgeCheck(anEdge, TopoDS::Face(theToFace));
+      anEdgeCheck.Perform();
+      if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
+        aGeomSh->setImpl(new TopoDS_Shape(aShape));
+        theRevolutionAlgo->addToShape(aGeomSh);
+      }
+      anEdgeCheck.Init(anEdge, TopoDS::Face(theFromFace));
+      anEdgeCheck.Perform();
+      if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
+        aGeomSh->setImpl(new TopoDS_Shape(aShape));
+        theRevolutionAlgo->addFromShape(aGeomSh);
+      }
+    } else {
+      Handle(Geom_Surface) aFaceSurface = BRep_Tool::Surface(TopoDS::Face(aShape));
+      Handle(Geom_Surface) aFromSurface = BRep_Tool::Surface(TopoDS::Face(theFromFace));
+      Handle(Geom_Surface) aToSurface = BRep_Tool::Surface(TopoDS::Face(theToFace));
+      if(aFaceSurface == aFromSurface) {
+        aGeomSh->setImpl(new TopoDS_Shape(aShape));
+        theRevolutionAlgo->addFromShape(aGeomSh);
+      }
+      if(aFaceSurface == aToSurface) {
+        aGeomSh->setImpl(new TopoDS_Shape(aShape));
+        theRevolutionAlgo->addToShape(aGeomSh);
+      }
+    }
+  }
+}
+
+void storeGenerationHistory(GeomAlgoAPI_Revolution* theRevolutionAlgo,
+                            const TopoDS_Shape& theResult,
+                            const TopAbs_ShapeEnum theType,
+                            const TopoDS_Shape& theRotatedBoundingFace,
+                            const TopoDS_Shape& theModifiedBaseShape,
+                            const bool theIsFromFaceSet)
+{
+  for(TopExp_Explorer anExp(theResult, theType); anExp.More (); anExp.Next ()) {
+    const TopoDS_Shape& aShape = anExp.Current();
+    GeomShapePtr aGeomSh(new GeomAPI_Shape());
+    if(theType == TopAbs_VERTEX) {
+      gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aShape));
+      IntTools_Context anIntTools;
+      if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(theRotatedBoundingFace), Precision::Confusion()) == Standard_True) {
+        aGeomSh->setImpl(new TopoDS_Shape(aShape));
+        theIsFromFaceSet ? theRevolutionAlgo->addFromShape(aGeomSh) : theRevolutionAlgo->addToShape(aGeomSh);
+      }
+      if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(theModifiedBaseShape), Precision::Confusion()) == Standard_True) {
+        aGeomSh->setImpl(new TopoDS_Shape(aShape));
+        theIsFromFaceSet ? theRevolutionAlgo->addToShape(aGeomSh) : theRevolutionAlgo->addFromShape(aGeomSh);
+      }
+    } else if(theType == TopAbs_EDGE) {
+      TopoDS_Edge anEdge = TopoDS::Edge(aShape);
+      BRepLib_CheckCurveOnSurface anEdgeCheck(anEdge, TopoDS::Face(theRotatedBoundingFace));
+      anEdgeCheck.Perform();
+      if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
+        aGeomSh->setImpl(new TopoDS_Shape(aShape));
+        theIsFromFaceSet ? theRevolutionAlgo->addFromShape(aGeomSh) : theRevolutionAlgo->addToShape(aGeomSh);
+      }
+      anEdgeCheck.Init(anEdge, TopoDS::Face(theModifiedBaseShape));
+      anEdgeCheck.Perform();
+      if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
+        aGeomSh->setImpl(new TopoDS_Shape(aShape));
+        theIsFromFaceSet ? theRevolutionAlgo->addToShape(aGeomSh) : theRevolutionAlgo->addFromShape(aGeomSh);
+      }
+    } else {
+      Handle(Geom_Surface) aFaceSurface = BRep_Tool::Surface(TopoDS::Face(aShape));
+      Handle(Geom_Surface) aBoundingSurface = BRep_Tool::Surface(TopoDS::Face(theRotatedBoundingFace));
+      Handle(Geom_Surface) aBaseSurface = BRep_Tool::Surface(TopoDS::Face(theModifiedBaseShape));
+      if(aFaceSurface == aBoundingSurface) {
+        aGeomSh->setImpl(new TopoDS_Shape(aShape));
+        theIsFromFaceSet ? theRevolutionAlgo->addFromShape(aGeomSh) : theRevolutionAlgo->addToShape(aGeomSh);
+      }
+      if(aFaceSurface == aBaseSurface) {
+        aGeomSh->setImpl(new TopoDS_Shape(aShape));
+        theIsFromFaceSet ? theRevolutionAlgo->addToShape(aGeomSh) : theRevolutionAlgo->addFromShape(aGeomSh);
+      }
+    }
+  }
+}
index c8a63bf911bb228059d895cb07fe11da307ead2b..d710493b9cb46abc2374678f7aa5eb55bf7a0b93 100644 (file)
@@ -105,8 +105,8 @@ void GeomAlgoAPI_ShapeBuilder::removeInternal(const std::shared_ptr<GeomAPI_Shap
 }
 
 //==================================================================================================
-void GeomAlgoAPI_ShapeBuilder::add(const std::shared_ptr<GeomAPI_Shape> theShape,
-                                   const ListOfShape& theShapesToAdd)
+void GeomAlgoAPI_ShapeBuilder::addInternal(const std::shared_ptr<GeomAPI_Shape> theShape,
+                                           const ListOfShape& theShapesToAdd)
 {
   // Get base shape.
   if(!theShape.get()) {
index 55ecaa3c5bf8d609dbf3d4161ed1c86b861c56c3..cd64980f435210c5dca9288299d85a6ea12df646 100644 (file)
@@ -37,11 +37,11 @@ class GeomAlgoAPI_ShapeBuilder: public GeomAlgoAPI_MakeShapeList
    /// \param[in] theShape base shape.
    GEOMALGOAPI_EXPORT void removeInternal(const std::shared_ptr<GeomAPI_Shape> theShape);
 
-   /// \brief Store new shape as result of adding theShapesToAdd to theShape.
+   /// \brief Store new shape as result of adding theShapesToAdd to theShape as internal shapes.
    /// \param[in] theShape base shape.
    /// \param[in] theShapesToAdd shapes which will be added.
-   GEOMALGOAPI_EXPORT void add(const std::shared_ptr<GeomAPI_Shape> theShape,
-                               const ListOfShape& theShapesToAdd);
+   GEOMALGOAPI_EXPORT void addInternal(const std::shared_ptr<GeomAPI_Shape> theShape,
+                                       const ListOfShape& theShapesToAdd);
 };
 
 #endif
index 7f407d6778f19bb900b07e0cd1222a32484f48bf..21530babb2dd0694624728d1e0616285b98b8cb3 100644 (file)
 #include <BRepBuilderAPI_FindPlane.hxx>
 #include <BRepBuilderAPI_MakeEdge.hxx>
 #include <BRepBuilderAPI_MakeFace.hxx>
+#include <BRepCheck_Analyzer.hxx>
 #include <BRepExtrema_DistShapeShape.hxx>
 #include <BRepGProp.hxx>
+#include <BRepTools.hxx>
 #include <BRepTopAdaptor_FClass2d.hxx>
 #include <Geom_Curve.hxx>
 #include <Geom2d_Curve.hxx>
@@ -319,13 +321,17 @@ std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeTools::groupSharedTopology(const
   aBuilder.MakeCompound(aCompound);
   ListOfShape aCompSolids, aFreeSolids;
   for(NCollection_Vector<NCollection_List<TopoDS_Shape>>::Iterator anIt(aGroups); anIt.More(); anIt.Next()) {
-    TopoDS_Compound aGroupCompound = makeCompound(anIt.Value());
+    NCollection_List<TopoDS_Shape> aGroup = anIt.Value();
     GeomShapePtr aGeomShape(new GeomAPI_Shape());
-    aGeomShape->setImpl(new TopoDS_Shape(aGroupCompound));
-    aGeomShape = GeomAlgoAPI_ShapeTools::combineShapes(aGeomShape,
-                                                       GeomAPI_Shape::COMPSOLID,
-                                                       aCompSolids,
-                                                       aFreeSolids);
+    if(aGroup.Size() == 1) {
+      aGeomShape->setImpl(new TopoDS_Shape(aGroup.First()));
+    } else {
+      aGeomShape->setImpl(new TopoDS_Shape(makeCompound(anIt.Value())));
+      aGeomShape = GeomAlgoAPI_ShapeTools::combineShapes(aGeomShape,
+                                                         GeomAPI_Shape::COMPSOLID,
+                                                         aCompSolids,
+                                                         aFreeSolids);
+    }
     aBuilder.Add(aCompound, aGeomShape->impl<TopoDS_Shape>());
   }
 
@@ -599,3 +605,32 @@ bool GeomAlgoAPI_ShapeTools::isSubShapeInsideShape(const std::shared_ptr<GeomAPI
 
   return true;
 }
+
+//==================================================================================================
+bool GeomAlgoAPI_ShapeTools::isShapeValid(const std::shared_ptr<GeomAPI_Shape> theShape)
+{
+  if(!theShape.get()) {
+    return false;
+  }
+
+  BRepCheck_Analyzer aChecker(theShape->impl<TopoDS_Shape>());
+  return (aChecker.IsValid() == Standard_True);
+}
+
+//==================================================================================================
+std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeTools::getFaceOuterWire(const std::shared_ptr<GeomAPI_Shape> theFace)
+{
+  GeomShapePtr anOuterWire;
+
+  if(!theFace.get() || !theFace->isFace()) {
+    return anOuterWire;
+  }
+
+  TopoDS_Face aFace = TopoDS::Face(theFace->impl<TopoDS_Shape>());
+  TopoDS_Wire aWire = BRepTools::OuterWire(aFace);
+
+  anOuterWire.reset(new GeomAPI_Shape());
+  anOuterWire->setImpl(new TopoDS_Shape(aWire));
+
+  return anOuterWire;
+}
index 3d62588f7360ec40e5719e5109c761fba4226f96..bc02ecb92b9c25160fcf384cc2309376bec1545b 100644 (file)
@@ -90,6 +90,13 @@ public:
   /// \return true if edge inside the face.
   GEOMALGOAPI_EXPORT static bool isSubShapeInsideShape(const std::shared_ptr<GeomAPI_Shape> theSubShape,
                                                        const std::shared_ptr<GeomAPI_Shape> theBaseShape);
+
+  /// \return true if theShape is valid.
+  GEOMALGOAPI_EXPORT static bool isShapeValid(const std::shared_ptr<GeomAPI_Shape> theShape);
+
+  /// \return outer wire for face. If theShape has different type returns empty pointer.
+  GEOMALGOAPI_EXPORT static std::shared_ptr<GeomAPI_Shape> getFaceOuterWire(const std::shared_ptr<GeomAPI_Shape> theFace);
+
 };
 
 #endif
index 03b6952b6fda0ea3ff3ae5e627295f905f483fb5..f7f7d29e030018018a58814ad059ba06500ec9da 100644 (file)
@@ -19,6 +19,7 @@ SET(PROJECT_HEADERS
     GeomValidators_ZeroOffset.h
     GeomValidators_Different.h
     GeomValidators_IntersectionSelection.h
+    GeomValidators_MinObjectsSelected.h
 )
 
 SET(PROJECT_SOURCES
@@ -37,6 +38,7 @@ SET(PROJECT_SOURCES
     GeomValidators_ZeroOffset.cpp
     GeomValidators_Different.cpp
     GeomValidators_IntersectionSelection.cpp
+    GeomValidators_MinObjectsSelected.cpp
 )
 
 SET(PROJECT_LIBRARIES
index 13e95ace0ffc8bbb0be3a5178414575bced770c8..18bd9918a59949e9634eda8708923eb10f27695a 100644 (file)
@@ -15,24 +15,34 @@ bool GeomValidators_BodyShapes::isValid(const AttributePtr& theAttribute,
                                         std::string& theError) const
 {
   std::string anAttributeType = theAttribute->attributeType();
-  if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
-    AttributeSelectionListPtr aSelectionListAttr = 
-                      std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
-    // all context objects should not be sketch entities
-    for(int anIndex = 0, aSize = aSelectionListAttr->size(); anIndex < aSize; ++anIndex) {
-      AttributeSelectionPtr aSelectAttr = aSelectionListAttr->value(anIndex);
-      ResultPtr aContext = aSelectAttr->context();
-      if(!aContext.get()) {
-        theError = "Error: Context is empty.";
-        return false;
-      }
+  if(anAttributeType == ModelAPI_AttributeSelection::typeId()) {
+    AttributeSelectionPtr anAttrSelection =
+      std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
+    ResultPtr aContext = anAttrSelection->context();
+    if(!aContext.get()) {
+      theError = "Error: Context is empty.";
+      return false;
+    }
+
+    ResultConstructionPtr aResultConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
+    if(aResultConstruction.get()) {
+      theError = "Error: Result construction selected.";
+      return false;
+    }
+  } else if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
+    AttributeSelectionListPtr anAttrSelectionList =
+      std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
 
-      ResultConstructionPtr aResultConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
-      if(aResultConstruction.get()) {
-        theError = "Error: Result construction selected.";
+    // All objects should not be result constructions.
+    for(int anIndex = 0, aSize = anAttrSelectionList->size(); anIndex < aSize; ++anIndex) {
+      AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
+      if(!isValid(anAttrSelection, theArguments, theError)) {
         return false;
       }
     }
+  } else {
+    theError = "Error: Attribute \"" + anAttributeType + "\" does not supported by this validator.";
+    return false;
   }
 
   return true;
diff --git a/src/GeomValidators/GeomValidators_MinObjectsSelected.cpp b/src/GeomValidators/GeomValidators_MinObjectsSelected.cpp
new file mode 100644 (file)
index 0000000..58e39b3
--- /dev/null
@@ -0,0 +1,45 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        GeomValidators_MinObjectsSelected.cpp
+// Created:     30 June 2015
+// Author:      Dmitry Bobylev
+
+#include <GeomValidators_MinObjectsSelected.h>
+
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_AttributeSelectionList.h>
+
+//=================================================================================================
+bool GeomValidators_MinObjectsSelected::isValid(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                                                const std::list<std::string>& theArguments,
+                                                std::string& theError) const
+{
+  if(theArguments.size() != 2) {
+    theError = "Error: Wrong number of arguments (expected 2): selection list id and min number of objects";
+    return false;
+  }
+
+  std::string aSelectionListId = theArguments.front();
+  AttributeSelectionListPtr anAttrSelList = theFeature->selectionList(aSelectionListId);
+  if(!anAttrSelList.get()) {
+    theError = "Error: Could not get attribute \"" + aSelectionListId + "\".";
+    return false;
+  }
+  int anObjectsNb = anAttrSelList->size();
+
+  int aMinObjectsNb = atoi(theArguments.back().c_str());
+
+  if(anObjectsNb < aMinObjectsNb) {
+    theError = "Error: Attribute \"" + aSelectionListId + "\" should contain at least "
+      + theArguments.back() + " items.";
+    return false;
+  }
+
+  return true;
+}
+
+//=================================================================================================
+bool GeomValidators_MinObjectsSelected::isNotObligatory(std::string theFeature, std::string theAttribute)
+{
+  return false;
+}
diff --git a/src/GeomValidators/GeomValidators_MinObjectsSelected.h b/src/GeomValidators/GeomValidators_MinObjectsSelected.h
new file mode 100644 (file)
index 0000000..cdcb20a
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        GeomValidators_MinObjectsSelected.h
+// Created:     30 June 2015
+// Author:      Dmitry Bobylev
+
+#ifndef GeomValidators_MinObjectsSelected_H
+#define GeomValidators_MinObjectsSelected_H
+
+#include <GeomValidators.h>
+#include <ModelAPI_Feature.h>
+#include <ModelAPI_FeatureValidator.h>
+
+/// \class GeomValidators_MinObjectsSelected
+/// \ingroup Validators
+/// \brief Validates number of objects in selection list.
+class GeomValidators_MinObjectsSelected : public ModelAPI_FeatureValidator
+{
+public:
+  /// \return true if selection list has enough objects.
+  /// \param[in] theFeature the validated feature.
+  /// \param[in] theArguments the arguments in the configuration file for this validator.
+  /// \param[out] theError error message.
+  /// \returns true if feature is valid.
+  GEOMVALIDATORS_EXPORT virtual bool isValid(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                                             const std::list<std::string>& theArguments,
+                                             std::string& theError) const;
+
+  /// \return true if the attribute in feature is not obligatory for the feature execution.
+  GEOMVALIDATORS_EXPORT virtual bool isNotObligatory(std::string theFeature, std::string theAttribute);
+};
+
+#endif
index fcdd134e12e97ed10ce5d365abef95ab97f25d20..9b99ffc852230d5d43f259e6262172cfe818016a 100644 (file)
@@ -14,6 +14,7 @@
 #include <GeomValidators_ZeroOffset.h>
 #include <GeomValidators_IntersectionSelection.h>
 #include <GeomValidators_FeatureKind.h>
+#include <GeomValidators_MinObjectsSelected.h>
 
 #include <ModelAPI_Session.h>
 #include <ModelAPI_Validator.h>
@@ -39,6 +40,7 @@ GeomValidators_Plugin::GeomValidators_Plugin()
   aFactory->registerValidator("GeomValidators_ZeroOffset", new GeomValidators_ZeroOffset);
   aFactory->registerValidator("GeomValidators_IntersectionSelection", new GeomValidators_IntersectionSelection);
   aFactory->registerValidator("GeomValidators_FeatureKind", new GeomValidators_FeatureKind);
+  aFactory->registerValidator("GeomValidators_MinObjectsSelected", new GeomValidators_MinObjectsSelected);
 
   // register this plugin
   ModelAPI_Session::get()->registerPlugin(this);
index b4495c2fb90296b15d72a8b74d4380282badbcae..8bc0d9fbdd6c9db30d44e7c08dae6d69ca80ea69 100755 (executable)
@@ -25,16 +25,18 @@ static EdgeTypes MyShapeTypes;
 GeomValidators_ShapeType::TypeOfShape GeomValidators_ShapeType::shapeType(const std::string& theType)
 {
   if (MyShapeTypes.size() == 0) {
-    MyShapeTypes["empty"]  = Empty;
-    MyShapeTypes["vertex"] = Vertex;
-    MyShapeTypes["edge"]   = Edge;
-    MyShapeTypes["line"]   = Line;
-    MyShapeTypes["circle"] = Circle;
-    MyShapeTypes["wire"]   = Wire;
-    MyShapeTypes["face"]   = Face;
-    MyShapeTypes["plane"]  = Plane;
-    MyShapeTypes["shell"]  = Shell;
-    MyShapeTypes["solid"]  = Solid;
+    MyShapeTypes["empty"]     = Empty;
+    MyShapeTypes["vertex"]    = Vertex;
+    MyShapeTypes["edge"]      = Edge;
+    MyShapeTypes["line"]      = Line;
+    MyShapeTypes["circle"]    = Circle;
+    MyShapeTypes["wire"]      = Wire;
+    MyShapeTypes["face"]      = Face;
+    MyShapeTypes["plane"]     = Plane;
+    MyShapeTypes["shell"]     = Shell;
+    MyShapeTypes["solid"]     = Solid;
+    MyShapeTypes["compsolid"] = CompSolid;
+    MyShapeTypes["compound"]  = Compound;
   }
   std::string aType = std::string(theType.c_str());
   if (MyShapeTypes.find(aType) != MyShapeTypes.end())
@@ -224,6 +226,9 @@ bool GeomValidators_ShapeType::isValidShape(const GeomShapePtr theShape,
       aValid = theShape->isSolid() || theShape->isCompSolid() ||
                theShape->isCompoundOfSolids();
       break;
+    case CompSolid:
+      aValid = theShape->shapeType() == GeomAPI_Shape::COMPSOLID;
+      break;
     case Compound:
       aValid = theShape->isCompound();
       break;
index 297b3fb25400c7fa558a39360b326d65b8e27252..3d2c60e65b9557f83ab0a36b96ed93ee47db88e6 100644 (file)
@@ -36,6 +36,7 @@ class GeomValidators_ShapeType : public ModelAPI_AttributeValidator
     Plane,
     Shell,
     Solid,
+    CompSolid,
     Compound,
     AnyShape
   };
index 94b301921473300427d5ca36df0e908f74aa61b3..3cfd46274cc54ce37279d6dd3242c9185c9806be 100755 (executable)
@@ -142,10 +142,13 @@ std::list<std::pair<ObjectPtr, AttributePtr> > Model_AttributeRefAttrList::list(
     TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
     for (; aLIter.More(); aLIter.Next(), anIDIter.Next()) {
       ObjectPtr anObj;
-      if (!aLIter.Value().IsNull())
+      if (!aLIter.Value().IsNull()) {
         anObj = aDoc->objects()->object(aLIter.Value());
-      aResult.push_back(std::pair<ObjectPtr, AttributePtr>(anObj, 
-        anObj->data()->attribute(TCollection_AsciiString(anIDIter.Value()).ToCString())));
+        aResult.push_back(std::pair<ObjectPtr, AttributePtr>(anObj, 
+          anObj->data()->attribute(TCollection_AsciiString(anIDIter.Value()).ToCString())));
+      } else {
+        aResult.push_back(std::pair<ObjectPtr, AttributePtr>(ObjectPtr(), AttributePtr()));
+      }
     }
   }
   return aResult;
index ac473ce216f07c9a20872aaf4c0ce6c95f3627f7..0c40c27230db30754d8036b080f676fbbbf0cb2a 100755 (executable)
@@ -43,6 +43,7 @@
 #include <TNaming_SameShapeIterator.hxx>
 #include <TNaming_Iterator.hxx>
 #include <TNaming_NamedShape.hxx>
+#include <TNaming_Tool.hxx>
 #include <TopExp_Explorer.hxx>
 
 #include <climits>
@@ -1292,6 +1293,8 @@ static Handle(TNaming_NamedShape) searchForOriginalShape(TopoDS_Shape theShape,
   while(!theShape.IsNull()) { // searching for the very initial shape that produces this one
     TopoDS_Shape aShape = theShape;
     theShape.Nullify();
+    if (!TNaming_Tool::HasLabel(aMain, aShape)) // to avoid crash of TNaming_SameShapeIterator if pure shape does not exists
+      break;
     for(TNaming_SameShapeIterator anIter(aShape, aMain); anIter.More(); anIter.Next()) {
       TDF_Label aNSLab = anIter.Label();
       Handle(TNaming_NamedShape) aNS;
index 5fb26d84309209720f6c8689237aa89c7e4aa759..714d984e8e49e631abd123e79fa6304c49354d61 100644 (file)
@@ -19,6 +19,7 @@ Model_ResultBody::Model_ResultBody()
 {
   myBuilder = new Model_BodyBuilder(this);
   myWasConcealed = false;
+  myConnect = ConnectionNotComputed;
 }
 
 void Model_ResultBody::initAttributes()
index bbb23da35ed80a810fa26396569f16852fe75baf..be5ac8e1dba9c7eae478450aacd1654c94559e0f 100644 (file)
@@ -32,6 +32,7 @@ class Model_ResultBody : public ModelAPI_ResultBody
   /// Flag that stores the previous state of "concealed": if it is changed,
   /// The event is used to redisplay the body.
   bool myWasConcealed;
+
 public:
   /// Request for initialization of data model of the result: adding all attributes
   virtual void initAttributes();
index 232834edc02cdbd889ae80dd582561b083c1fc33..c577080b136565379a1a3e006e05db9dfb84acbe 100644 (file)
@@ -261,31 +261,44 @@ std::string Model_SelectionNaming::namingName(ResultPtr& theContext,
 TopAbs_ShapeEnum translateType (const std::string& theType)
 {
   // map from the textual shape types to OCCT enumeration
-  static std::map<std::string, TopAbs_ShapeEnum> MyShapeTypes;
-  if (MyShapeTypes.size() == 0) {
-    MyShapeTypes["face"] = TopAbs_FACE;
-    MyShapeTypes["faces"] = TopAbs_FACE;
-    MyShapeTypes["vertex"] = TopAbs_VERTEX;
-    MyShapeTypes["vertices"] = TopAbs_VERTEX;
-    MyShapeTypes["wire"] = TopAbs_WIRE;
-    MyShapeTypes["edge"] = TopAbs_EDGE;
-    MyShapeTypes["edges"] = TopAbs_EDGE;
-    MyShapeTypes["shell"] = TopAbs_SHELL;
-    MyShapeTypes["solid"] = TopAbs_SOLID;
-    MyShapeTypes["solids"] = TopAbs_SOLID;
-    MyShapeTypes["FACE"] = TopAbs_FACE;
-    MyShapeTypes["FACES"] = TopAbs_FACE;
-    MyShapeTypes["VERTEX"] = TopAbs_VERTEX;
-    MyShapeTypes["VERTICES"] = TopAbs_VERTEX;
-    MyShapeTypes["WIRE"] = TopAbs_WIRE;
-    MyShapeTypes["EDGE"] = TopAbs_EDGE;
-    MyShapeTypes["EDGES"] = TopAbs_EDGE;
-    MyShapeTypes["SHELL"] = TopAbs_SHELL;
-    MyShapeTypes["SOLID"] = TopAbs_SOLID;
-    MyShapeTypes["SOLIDS"] = TopAbs_SOLID;
+  static std::map<std::string, TopAbs_ShapeEnum> aShapeTypes;
+
+  if(aShapeTypes.size() == 0) {
+    aShapeTypes["compound"]   = TopAbs_COMPOUND;
+    aShapeTypes["compounds"]  = TopAbs_COMPOUND;
+    aShapeTypes["compsolid"]  = TopAbs_COMPSOLID;
+    aShapeTypes["compsolids"] = TopAbs_COMPSOLID;
+    aShapeTypes["solid"]      = TopAbs_SOLID;
+    aShapeTypes["solids"]     = TopAbs_SOLID;
+    aShapeTypes["shell"]      = TopAbs_SHELL;
+    aShapeTypes["shells"]     = TopAbs_SHELL;
+    aShapeTypes["face"]       = TopAbs_FACE;
+    aShapeTypes["faces"]      = TopAbs_FACE;
+    aShapeTypes["wire"]       = TopAbs_WIRE;
+    aShapeTypes["wires"]      = TopAbs_WIRE;
+    aShapeTypes["edge"]       = TopAbs_EDGE;
+    aShapeTypes["edges"]      = TopAbs_EDGE;
+    aShapeTypes["vertex"]     = TopAbs_VERTEX;
+    aShapeTypes["vertices"]   = TopAbs_VERTEX;
+    aShapeTypes["COMPOUND"]   = TopAbs_COMPOUND;
+    aShapeTypes["COMPOUNDS"]  = TopAbs_COMPOUND;
+    aShapeTypes["COMPSOLID"]  = TopAbs_COMPSOLID;
+    aShapeTypes["COMPSOLIDS"] = TopAbs_COMPSOLID;
+    aShapeTypes["SOLID"]      = TopAbs_SOLID;
+    aShapeTypes["SOLIDS"]     = TopAbs_SOLID;
+    aShapeTypes["SHELL"]      = TopAbs_SHELL;
+    aShapeTypes["SHELLS"]     = TopAbs_SHELL;
+    aShapeTypes["FACE"]       = TopAbs_FACE;
+    aShapeTypes["FACES"]      = TopAbs_FACE;
+    aShapeTypes["WIRE"]       = TopAbs_WIRE;
+    aShapeTypes["WIRES"]      = TopAbs_WIRE;
+    aShapeTypes["EDGE"]       = TopAbs_EDGE;
+    aShapeTypes["EDGES"]      = TopAbs_EDGE;
+    aShapeTypes["VERTEX"]     = TopAbs_VERTEX;
+    aShapeTypes["VERTICES"]   = TopAbs_VERTEX;
   }
-  if (MyShapeTypes.find(theType) != MyShapeTypes.end())
-    return MyShapeTypes[theType];
+  if (aShapeTypes.find(theType) != aShapeTypes.end())
+    return aShapeTypes[theType];
   Events_InfoMessage("Model_SelectionNaming", "Shape type defined in XML is not implemented!").send();
   return TopAbs_SHAPE;
 }
index 53a308d3c8ac2b9d9936026d246a311b28400397..2eb0e7dbe24b9532ae527ec2e36b08c79cdd8346 100755 (executable)
@@ -109,7 +109,8 @@ bool Model_Update::addModified(FeaturePtr theFeature, FeaturePtr theReason) {
   bool aIsDisabled = theFeature->isDisabled();
   if (!aIsDisabled) {
     std::set<std::shared_ptr<ModelAPI_Feature> > aNewSet;
-    if (theFeature->data()->execState() == ModelAPI_StateMustBeUpdated) {
+    if (theFeature->data()->execState() == ModelAPI_StateMustBeUpdated ||
+        theFeature->data()->execState() == ModelAPI_StateInvalidArgument) { // issue 1519
       // do not forget that in this case all were the reasons
       aNewSet.insert(theFeature);
     } else {
index 90006d1d04dbab4720545aea427eb0b50fe8d9ac..27298e20e11eb9eee2904c776a11ffea179a2437 100644 (file)
@@ -128,4 +128,5 @@ ADD_UNIT_TESTS(TestConstants.py
                TestUndoRedo.py
                TestDocument.py
                Test1064.py
-               TestResults.py)
+               TestResults.py
+               Test1512.py)
index f05afc1f0c732c027c0122ae69b9347cd603bbe9..b8fcaaa9def05582d3620e2704d2676a09d2f14a 100644 (file)
 template<class T1, class T2> std::shared_ptr<T1> shared_ptr_cast(std::shared_ptr<T2> theObject);
 %template(featureToCompositeFeature) shared_ptr_cast<ModelAPI_CompositeFeature, ModelAPI_Feature>;
 %template(objectToFeature) shared_ptr_cast<ModelAPI_Feature, ModelAPI_Object>;
+%template(objectToResult) shared_ptr_cast<ModelAPI_Result, ModelAPI_Object>;
 %template(compositeFeatureToFeature) shared_ptr_cast<ModelAPI_Feature, ModelAPI_CompositeFeature>;
 
 %template(modelAPI_Result) shared_ptr_cast<ModelAPI_Result, ModelAPI_Object>;
index 6792f18bc335dd0bdc7c07b89e9aad0468e7a60e..bdf9947d2f93324f8e75c1c3bfd55a2bd343739b 100644 (file)
@@ -12,6 +12,7 @@
 ModelAPI_ResultBody::ModelAPI_ResultBody()
 : myBuilder(0)
 {
+  myConnect = ConnectionNotComputed;
 }
 
 ModelAPI_ResultBody::~ModelAPI_ResultBody()
@@ -29,6 +30,7 @@ void ModelAPI_ResultBody::store(const std::shared_ptr<GeomAPI_Shape>& theShape,
                                 const bool theIsStoreSameShapes)
 {
   myBuilder->store(theShape, theIsStoreSameShapes);
+  myConnect = ConnectionNotComputed;
 
   static Events_Loop* aLoop = Events_Loop::loop();
   static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
@@ -40,6 +42,7 @@ void ModelAPI_ResultBody::storeGenerated(const std::shared_ptr<GeomAPI_Shape>& t
                                  const std::shared_ptr<GeomAPI_Shape>& theToShape)
 {
   myBuilder->storeGenerated(theFromShape, theToShape);
+  myConnect = ConnectionNotComputed;
 
   static Events_Loop* aLoop = Events_Loop::loop();
   static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
@@ -52,6 +55,7 @@ void ModelAPI_ResultBody::storeModified(const std::shared_ptr<GeomAPI_Shape>& th
                             const int theDecomposeSolidsTag)
 {
   myBuilder->storeModified(theOldShape, theNewShape, theDecomposeSolidsTag);
+  myConnect = ConnectionNotComputed;
 
   static Events_Loop* aLoop = Events_Loop::loop();
   static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
@@ -62,6 +66,7 @@ void ModelAPI_ResultBody::storeModified(const std::shared_ptr<GeomAPI_Shape>& th
 void ModelAPI_ResultBody::storeWithoutNaming(const std::shared_ptr<GeomAPI_Shape>& theShape)
 {
   myBuilder->storeWithoutNaming(theShape);
+  myConnect = ConnectionNotComputed;
 
   static Events_Loop* aLoop = Events_Loop::loop();
   static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
@@ -142,3 +147,11 @@ void ModelAPI_ResultBody::loadDisconnectedVertexes(std::shared_ptr<GeomAPI_Shape
 {
   myBuilder->loadDisconnectedVertexes(theShape, theName, theTag);
 }
+
+bool ModelAPI_ResultBody::isConnectedTopology()
+{
+  if (myConnect == ConnectionNotComputed) {
+    myConnect = shape()->isConnectedTopology() ? IsConnected : IsNotConnected;
+  }
+  return myConnect == IsConnected;
+}
index ad5846e0f10a84927141a7b1f729b954c35d2bad..119978c6f5a896a0cc24f2c2259f6344be9f1471 100644 (file)
@@ -44,6 +44,15 @@ public:
     return RESULT_BODY_COLOR;
   }
 
+  /// Iternal enumeration for storage the information of connected topology flag
+  enum ConnectedTopologyFlag {
+    ConnectionNotComputed, ///< not yet computed
+    IsConnected,           ///< the topology is connected
+    IsNotConnected         ///< the topology is connected
+  };
+  /// Keeps (not persistently) the connected topology flag
+  ConnectedTopologyFlag myConnect;
+
   /// \brief Stores the shape (called by the execution method).
   /// param[in] theShape shape to store.
   /// param[in] theIsStoreSameShapes if false stores reference to the same shape if it is already in document.
@@ -118,6 +127,10 @@ public:
   // is equal to the given shape
   MODELAPI_EXPORT virtual bool isLatestEqual(const std::shared_ptr<GeomAPI_Shape>& theShape) = 0;
 
+  /// Returns true is the topology is connected. Cashes this information for the current shape,
+  /// so it is more effective to use this method than directly GeomAPI_Shape.
+  MODELAPI_EXPORT virtual bool isConnectedTopology();
+
 protected:
   /// Default constructor accessible only from Model_Objects
   MODELAPI_EXPORT ModelAPI_ResultBody();
index 658def2ef133c08390ec5b53cda62c6861b08f35..f80d20e1b9a9250448009e4923ae56baf8c62eb6 100755 (executable)
@@ -159,14 +159,9 @@ bool findVariable(FeaturePtr theSearcher, const std::string& theName, double& ou
     return true;
   DocumentPtr aRootDocument = aSession->moduleDocument();
   if (aDocument != aRootDocument) {
-    ResultPtr aPartResult = findPartResult(aRootDocument, aDocument);
-    if (aPartResult.get()) {
-      FeaturePtr aPartFeature;
-      if (theSearcher.get()) // only if the relative search is needed
-        aPartFeature = aRootDocument->feature(aPartResult);
-      if (findVariable(aRootDocument, aPartFeature, theName, outValue, theParam))
-        return true;
-    }
+    // any parameters in PartSet is okindependently on the Part position (issu #1504)
+    if (findVariable(aRootDocument, FeaturePtr(), theName, outValue, theParam))
+      return true;
   }
   return false;
 }
@@ -358,6 +353,27 @@ void allResults(const FeaturePtr& theFeature, std::list<ResultPtr>& theResults)
   }
 }
 
+//******************************************************************
+bool allDocumentsActivated(std::string& theNotActivatedNames)
+{
+  theNotActivatedNames = "";
+  bool anAllPartActivated = true;
+
+  DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+  int aSize = aRootDoc->size(ModelAPI_ResultPart::group());
+  for (int i = 0; i < aSize; i++) {
+    ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultPart::group(), i);
+    ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObject);
+    if (!aPart->isActivated()) {
+      anAllPartActivated = false;
+      if (!theNotActivatedNames.empty())
+        theNotActivatedNames += ", ";
+      theNotActivatedNames += aObject->data()->name().c_str();
+    }
+  }
+  return anAllPartActivated;
+}
+
 bool removeFeaturesAndReferences(const std::set<FeaturePtr>& theFeatures,
                                  const bool theFlushRedisplay,
                                  const bool theUseComposite,
@@ -549,5 +565,3 @@ void findRefsToFeatures(const std::set<FeaturePtr>& theFeatures,
 }
 
 } // namespace ModelAPI_Tools
-
-
index 9085e6d776d699c2f02be326e3c303ab42112011..00f6cd4fd570611ac0d997cd911bbdf913e5a273 100755 (executable)
@@ -100,6 +100,13 @@ MODELAPI_EXPORT bool hasSubResults(const ResultPtr& theResult);
 */
 MODELAPI_EXPORT void allResults(const FeaturePtr& theFeature, std::list<ResultPtr>& theResults);
 
+/*!
+ Returns true if there are no parts in the document, which are not activated
+ \param theNotActivatedNames out string which contains not activated names
+ \return a boolean value
+ */
+MODELAPI_EXPORT bool allDocumentsActivated(std::string& theNotActivatedNames);
+
 
 /*! Removes features from the document
 * \param theFeatures a list of features to be removed
diff --git a/src/ModelAPI/Test/Test1512.py b/src/ModelAPI/Test/Test1512.py
new file mode 100755 (executable)
index 0000000..25f843a
--- /dev/null
@@ -0,0 +1,151 @@
+"""
+      Test1512.py
+      Unit test for testing the correct selection of feature by the faces after the BOPs applied
+
+"""
+#=========================================================================
+# Initialization of the test
+#=========================================================================
+from ModelAPI import *
+from GeomDataAPI import *
+from GeomAlgoAPI import *
+from GeomAPI import *
+
+__updated__ = "2016-05-31"
+
+aSession = ModelAPI_Session.get()
+aPartSet = aSession.moduleDocument()
+
+#=========================================================================
+# Create a part
+#=========================================================================
+aSession.startOperation()
+aPartFeature = aPartSet.addFeature("Part")
+aSession.finishOperation()
+assert (len(aPartFeature.results()) == 1)
+aPart = aSession.activeDocument()
+
+#=========================================================================
+# Create a sketch rectangle in PartSet
+#=========================================================================
+aSession.startOperation()
+aSketchFeature = featureToCompositeFeature(aPart.addFeature("Sketch"))
+aXOYPlane = objectToResult(aPartSet.objectByName("Construction", "XOY"))
+aSketchFeature.selection("External").setValue(aXOYPlane, None)
+# Create lines
+aLine1 = aSketchFeature.addFeature("SketchLine")
+geomDataAPI_Point2D(aLine1.attribute("StartPoint")).setValue(0, 0)
+geomDataAPI_Point2D(aLine1.attribute("EndPoint")).setValue(200, 0)
+aLine2 = aSketchFeature.addFeature("SketchLine")
+geomDataAPI_Point2D(aLine2.attribute("StartPoint")).setValue(200, 0)
+geomDataAPI_Point2D(aLine2.attribute("EndPoint")).setValue(200, 100)
+aLine3 = aSketchFeature.addFeature("SketchLine")
+geomDataAPI_Point2D(aLine3.attribute("StartPoint")).setValue(200, 100)
+geomDataAPI_Point2D(aLine3.attribute("EndPoint")).setValue(0, 100)
+aLine4 = aSketchFeature.addFeature("SketchLine")
+geomDataAPI_Point2D(aLine4.attribute("StartPoint")).setValue(0, 100)
+geomDataAPI_Point2D(aLine4.attribute("EndPoint")).setValue(0, 0)
+aSession.finishOperation()
+
+#=========================================================================
+# Make extrusion on rectangle
+#=========================================================================
+aSession.startOperation()
+aBox = aPart.addFeature("Extrusion")
+aBox.selectionList("base").append(aSketchFeature.firstResult(), None)
+aBox.string("CreationMethod").setValue("BySizes")
+aBox.real("to_size").setValue(50)
+aBox.real("from_size").setValue(0)
+aSession.finishOperation()
+
+#=========================================================================
+# Create a cylindrical sketch for a big hole
+#=========================================================================
+aSession.startOperation()
+aSketchFeature2 = featureToCompositeFeature(aPart.addFeature("Sketch"))
+aSketchFeature2.selection("External").setValue(aXOYPlane, None);
+aCirc1 = aSketchFeature2.addFeature("SketchCircle")
+geomDataAPI_Point2D(aCirc1.attribute("CircleCenter")).setValue(100, 50)
+aCirc1.real("CircleRadius").setValue(40)
+aSession.finishOperation()
+
+#=========================================================================
+# Make extrusion on a big circle
+#=========================================================================
+aSession.startOperation()
+aHoleExt = aPart.addFeature("Extrusion")
+aHoleExt.selectionList("base").append(aSketchFeature2.firstResult(), None)
+aHoleExt.string("CreationMethod").setValue("BySizes")
+aHoleExt.real("to_size").setValue(60)
+aHoleExt.real("from_size").setValue(0)
+aSession.finishOperation()
+
+#=========================================================================
+# Do cut a hole from a box
+#=========================================================================
+aSession.startOperation()
+aCut1 = aPart.addFeature("Boolean")
+aCut1.selectionList("main_objects").append(aBox.firstResult(), None)
+aCut1.selectionList("tool_objects").append(aHoleExt.firstResult(), None)
+aCut1.integer("bool_type").setValue(0) # cut
+aSession.finishOperation()
+
+#=========================================================================
+# Create a cylindrical sketch for a small tower
+#=========================================================================
+aSession.startOperation()
+aSketchFeature3 = featureToCompositeFeature(aPart.addFeature("Sketch"))
+aSketchFeature3.selection("External").setValue(aXOYPlane, None);
+aCirc2 = aSketchFeature3.addFeature("SketchCircle")
+geomDataAPI_Point2D(aCirc2.attribute("CircleCenter")).setValue(20, 20)
+aCirc2.real("CircleRadius").setValue(10)
+aSession.finishOperation()
+
+#=========================================================================
+# Make extrusion on a small circle
+#=========================================================================
+aSession.startOperation()
+aTower = aPart.addFeature("Extrusion")
+aTower.selectionList("base").append(aSketchFeature3.firstResult(), None)
+aTower.string("CreationMethod").setValue("BySizes")
+aTower.real("to_size").setValue(100)
+aTower.real("from_size").setValue(0)
+aSession.finishOperation()
+
+#=========================================================================
+# Do fuse with a tower. Tower must be an argument (not tool) to add the problem to the faces owners detection.
+#=========================================================================
+aSession.startOperation()
+aFuse = aPart.addFeature("Boolean")
+aFuse.selectionList("main_objects").append(aTower.firstResult(), None)
+aFuse.selectionList("tool_objects").append(aCut1.firstResult(), None)
+aFuse.integer("bool_type").setValue(1) # fuse
+aSession.finishOperation()
+
+#=========================================================================
+# Create a group feature to use the selection attribute for selection of faces by the name.
+#=========================================================================
+def check_owner(selection, topology_type, feature):
+  aSession.startOperation()
+  aGroup = aPart.addFeature("Group")
+  aGroup.selectionList("group_list").append(selection, topology_type)
+  aFace = aGroup.selectionList("group_list").value(0).value()
+  aTestFeature = aPart.producedByFeature(aFuse.firstResult(), aFace)
+  assert(aTestFeature.name() == feature.name())
+  aSession.abortOperation()
+
+# check faces
+check_owner("Extrusion_1_1/Generated_Face_1", "face", aBox)
+check_owner("Boolean_2_1/Modified_3", "face", aBox)
+check_owner("Boolean_1_1/Modified_1", "face", aHoleExt)
+check_owner("Boolean_2_1/Modified_2", "face", aTower)
+# check edges without ambiguity
+check_owner("Boolean_2_1/Modified_3&Extrusion_1_1/Generated_Face_2", "edge", aBox)
+check_owner("Boolean_2_1/Modified_2&Extrusion_3_1/To_Face_1_1", "edge", aTower)
+
+# check the connected topology method: solid is not a compound of connected topology
+assert(aFuse.firstResult().shape().isConnectedTopology() == False)
+
+#=========================================================================
+# End of test
+#=========================================================================
index 0e3066310eb0dfed016bb8e6c189c0f433a0f0e8..c4fc1a27659b647728e65899f565f8190490cc83 100644 (file)
@@ -62,6 +62,7 @@ SET(PROJECT_HEADERS
   ModuleBase_WidgetValidator.h
   ModuleBase_IconFactory.h
   ModuleBase_Dialog.h
+  ModuleBase_ModelDialogWidget.h
 )
 
 SET(PROJECT_SOURCES
index 5a3db14f8de4ed5a978b3d865051f8f1d7b2f8bb..1e148ac72aaad07adc83eef581fd75d43dbe77cc 100644 (file)
@@ -6,6 +6,7 @@
 #include "ModuleBase_IWorkshop.h"
 #include "ModuleBase_IPropertyPanel.h"
 #include "ModuleBase_PageWidget.h"
+#include "ModuleBase_ModelDialogWidget.h"
 
 #include <ModelAPI_Session.h>
 #include <ModelAPI_Events.h>
@@ -52,9 +53,6 @@ ModuleBase_Dialog::ModuleBase_Dialog(ModuleBase_IWorkshop* theParent, const QStr
 
   aFactory.createWidget(aPage, false);
   myWidgets = aFactory.getModelWidgets();
-  foreach (ModuleBase_ModelWidget* aWidget, myWidgets) {
-    initializeWidget(aWidget);
-  }
 
   QFrame* aFrame = new QFrame(this);
   aFrame->setFrameStyle(QFrame::WinPanel | QFrame::Raised);
@@ -63,19 +61,27 @@ ModuleBase_Dialog::ModuleBase_Dialog(ModuleBase_IWorkshop* theParent, const QStr
   QVBoxLayout* aBtnLayout = new QVBoxLayout(aFrame);
   ModuleBase_Tools::adjustMargins(aBtnLayout);
 
-  QDialogButtonBox* aBtnBox = new QDialogButtonBox(
+  myButtonsBox = new QDialogButtonBox(
     QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, aFrame);
-  aBtnLayout->addWidget(aBtnBox);
+  aBtnLayout->addWidget(myButtonsBox);
+
+  myButtonsBox->button(QDialogButtonBox::Ok)->setIcon(QIcon(":pictures/button_ok.png"));
+  myButtonsBox->button(QDialogButtonBox::Cancel)->setIcon(QIcon(":pictures/button_cancel.png"));
 
-  aBtnBox->button(QDialogButtonBox::Ok)->setIcon(QIcon(":pictures/button_ok.png"));
-  aBtnBox->button(QDialogButtonBox::Cancel)->setIcon(QIcon(":pictures/button_cancel.png"));
+  connect(myButtonsBox, SIGNAL(accepted()), this, SLOT(accept()));
+  connect(myButtonsBox, SIGNAL(rejected()), this, SLOT(reject()));
 
-  connect(aBtnBox, SIGNAL(accepted()), this, SLOT(accept()));
-  connect(aBtnBox, SIGNAL(rejected()), this, SLOT(reject()));
+  foreach (ModuleBase_ModelWidget* aWidget, myWidgets) {
+    initializeWidget(aWidget);
+  }
 }
 
 void ModuleBase_Dialog::initializeWidget(ModuleBase_ModelWidget* theWidget)
 {
+  ModuleBase_ModelDialogWidget* aDlgWgt = dynamic_cast<ModuleBase_ModelDialogWidget*>(theWidget);
+  if (aDlgWgt)
+    aDlgWgt->setDialogButtons(myButtonsBox);
+
   theWidget->setFeature(myFeature);
   theWidget->restoreValue();
 }
index bb58343f6b9fcb054810d7c54f189a6ec99526fc..6112c407a84d88ef6ff5612fc6a332208380f0e4 100644 (file)
@@ -12,6 +12,8 @@
 
 class ModuleBase_IWorkshop;
 class ModuleBase_ModelWidget;
+class QDialogButtonBox;
+
 
 /**
  * \ingroup GUI
@@ -35,7 +37,6 @@ protected:
   /// Redefinition of virtual method
   virtual void showEvent(QShowEvent* theEvent);
 
-
 private:
   /// Initialising of the widget
   void initializeWidget(ModuleBase_ModelWidget* theWidget);
@@ -57,6 +58,9 @@ private:
 
   /// Pointer on active widget
   ModuleBase_ModelWidget* myActiveWidget;
+
+  /// Buttons of the dialog
+  QDialogButtonBox* myButtonsBox;
 };
 
 #endif
index c977072a831a9da84c606555301e3ac4544a0769..bb56ba1491318356fcf5f9d62a5ebfd7983c01ca 100644 (file)
 #include <ModuleBase_WidgetValidated.h>
 #include <ModuleBase_WidgetValidator.h>
 #include <ModuleBase_ViewerPrs.h>
+#include <ModuleBase_Tools.h>
 
 IMPLEMENT_STANDARD_HANDLE(ModuleBase_FilterValidated, SelectMgr_Filter);
 IMPLEMENT_STANDARD_RTTIEXT(ModuleBase_FilterValidated, SelectMgr_Filter);
 
+//#define DEBUG_CURRENT_SELECTION
+
 Standard_Boolean ModuleBase_FilterValidated::IsOk(const Handle(SelectMgr_EntityOwner)& theOwner) const
 {
   bool aValid = true;
   ModuleBase_Operation* anOperation = myWorkshop->module()->currentOperation();
   if (anOperation) {
+#ifdef DEBUG_CURRENT_SELECTION
+    QString aPrefix = "ModuleBase_FilterValidated::IsOk: ";
+    QList<ModuleBase_ViewerPrsPtr> aSelected = myWorkshop->selection()->getSelected(ModuleBase_ISelection::Viewer);
+    QList<ModuleBase_ViewerPrsPtr>::const_iterator anIt = aSelected.begin(), aLast = aSelected.end();
+    QStringList anInfo;
+    ModuleBase_ViewerPrsPtr aPrs;
+    for (; anIt != aLast; anIt++) {
+      aPrs = (*anIt);
+      if (!aPrs.get())
+        continue;
+
+      //GeomShapePtr aShape = aPrs->shape();
+      ObjectPtr anObject = aPrs->object();
+      QString anObjectInfo = anObject.get() ? ModuleBase_Tools::objectInfo(anObject) : "";
+      anInfo.append(anObjectInfo);
+    }
+    QString anInfoStr = anInfo.join(";\t");
+    qDebug(QString("%1: %2, %3").arg(aPrefix).arg(anInfo.size()).arg(anInfoStr).toStdString().c_str());
+#endif
+
     ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel();
     ModuleBase_ModelWidget* aCurrentWidget = aPanel->preselectionWidget();
     if (!aCurrentWidget)
index f65b1d313dbad4bb4e689d3712aaf4b8a83ddf35..f12b751f318881db81973b8bf7069978549bd9c7 100755 (executable)
@@ -183,16 +183,6 @@ class MODULEBASE_EXPORT ModuleBase_IModule : public QObject
   /// \param theObject a model object\r
   virtual bool canActivateSelection(const ObjectPtr& theObject) const;\r
 \r
-  /// Returns true if the given selection mode can be activated for the given presentgation\r
-  /// \param theIO an object presentation\r
-  /// \param theMode selection mode\r
-  virtual bool canActivateSelectionMode(const Handle(AIS_InteractiveObject)& theIO, int theMode) const { return true; }\r
-\r
-  /// Returns true if the given selection mode must be deactivated for the given presentgation in any case\r
-  /// \param theIO an object presentation\r
-  /// \param theMode selection mode\r
-  virtual bool needDeactivateSelectionMode(const Handle(AIS_InteractiveObject)& theIO, int theMode) const { return false; }\r
-\r
   /// Reacts to the delete action in module\r
   /// \returns true if the action is processed\r
   virtual bool deleteObjects() { return false; };\r
@@ -207,6 +197,10 @@ class MODULEBASE_EXPORT ModuleBase_IModule : public QObject
   /// \param theModes a list of modes\r
   virtual void activeSelectionModes(QIntList& theModes) {}\r
 \r
+  /// Appends specific selection modes for the module to the list of types\r
+  /// \param theTypes a selection modes to be extended\r
+  virtual void customSubShapesSelectionModes(QIntList& theTypes) {}\r
+\r
   /// Activate custom presentation for the object. Default realization is empty.\r
   /// \param theFeature a feature instance\r
   /// \param theFlag a flag of level of customization, which means that only part of sub-elements\r
diff --git a/src/ModuleBase/ModuleBase_ModelDialogWidget.h b/src/ModuleBase/ModuleBase_ModelDialogWidget.h
new file mode 100644 (file)
index 0000000..82a3a35
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        ModuleBase_ModelDialogWidget.h
+// Created:     01 June 2016
+// Author:      Vitaly SMETANNIKOV
+
+#ifndef MODULEBASE_MODELDIALOGWIDGET_H
+#define MODULEBASE_MODELDIALOGWIDGET_H
+
+#include "ModuleBase.h"
+#include "ModuleBase_ModelWidget.h"
+
+class QDialogButtonBox;
+
+class MODULEBASE_EXPORT ModuleBase_ModelDialogWidget : public ModuleBase_ModelWidget
+{
+Q_OBJECT
+public:
+  /// Constructor
+  /// \param theParent the parent object
+  /// \param theData the widget configuration. The attribute of the model widget is obtained from
+  /// a low-level API for reading xml definitions of widgets
+  ModuleBase_ModelDialogWidget(QWidget* theParent, const Config_WidgetAPI* theData) :
+                                ModuleBase_ModelWidget(theParent, theData) {}
+
+  /// Set general buttons from dialog
+  /// \param theButtons the dialog buttons
+  void setDialogButtons(QDialogButtonBox* theButtons) { myOkCancelBtn = theButtons; }
+
+protected:
+
+  /// Contains dialog buttons to enable/disable Ok and Cancel buttons
+  QDialogButtonBox* myOkCancelBtn;
+};
+
+#endif
\ No newline at end of file
index 8a85cd6f49d438e2419fb271686611e9721d456d..d82016eacb5c55c5b84c8bf190292627a6699545 100644 (file)
@@ -26,6 +26,8 @@
 
 //#define DEBUG_VALUE_STATE
 
+//#define DEBUG_WIDGET_INSTANCE
+
 ModuleBase_ModelWidget::ModuleBase_ModelWidget(QWidget* theParent,
                                                const Config_WidgetAPI* theData)
     : QWidget(theParent),
@@ -35,6 +37,10 @@ ModuleBase_ModelWidget::ModuleBase_ModelWidget(QWidget* theParent,
       myFlushUpdateBlocked(false),
       myWidgetValidator(0)
 {
+#ifdef DEBUG_WIDGET_INSTANCE
+  qDebug("ModuleBase_ModelWidget::ModuleBase_ModelWidget");
+#endif
+
   myIsInternal = theData->getBooleanAttribute(ATTR_INTERNAL, false);
 
   myDefaultValue = theData->getProperty(ATTR_DEFAULT);
@@ -47,6 +53,13 @@ ModuleBase_ModelWidget::ModuleBase_ModelWidget(QWidget* theParent,
   connect(this, SIGNAL(valuesModified()), this, SLOT(onWidgetValuesModified()));
 }
 
+ModuleBase_ModelWidget::~ModuleBase_ModelWidget()
+{
+#ifdef DEBUG_WIDGET_INSTANCE
+  qDebug("ModuleBase_ModelWidget::~ModuleBase_ModelWidget");
+#endif
+}
+
 bool ModuleBase_ModelWidget::reset()
 {
   bool aResult = resetCustom();
@@ -61,6 +74,12 @@ bool ModuleBase_ModelWidget::isInitialized(ObjectPtr theObject) const
   return theObject->data()->attribute(attributeID())->isInitialized();
 }
 
+void ModuleBase_ModelWidget::processValueState()
+{
+  if (myState == ModifiedInPP || myState == ModifiedInViewer)
+    storeValue();
+}
+
 QString ModuleBase_ModelWidget::getValueStateError() const
 {
   QString anError = "";
@@ -153,6 +172,9 @@ void ModuleBase_ModelWidget::setFeature(const FeaturePtr& theFeature, const bool
 
 bool ModuleBase_ModelWidget::focusTo()
 {
+#ifdef DEBUG_WIDGET_INSTANCE
+  qDebug("ModuleBase_ModelWidget::focusTo");
+#endif
   QList<QWidget*> aControls = getControls();
   QList<QWidget*>::const_iterator anIt = aControls.begin(), aLast = aControls.end();
   bool isFocusAccepted = false;
@@ -168,6 +190,9 @@ bool ModuleBase_ModelWidget::focusTo()
 
 void ModuleBase_ModelWidget::activate()
 {
+#ifdef DEBUG_WIDGET_INSTANCE
+  qDebug("ModuleBase_ModelWidget::activate");
+#endif
   // the control value is stored to the mode by the focus in on the widget
   // we need the value is initialized in order to enable the apply button in the property panel.
   // It should happens in the creation mode only because all fields are filled in the edition mode
@@ -185,11 +210,11 @@ void ModuleBase_ModelWidget::activate()
 
 void ModuleBase_ModelWidget::deactivate()
 {
+#ifdef DEBUG_WIDGET_INSTANCE
+  qDebug("ModuleBase_ModelWidget::deactivate");
+#endif
   myIsValueStateBlocked = false;
-  if (myState == ModifiedInPP || myState == ModifiedInViewer)
-    storeValue();
   myState = Stored;
-
   if (myWidgetValidator)
     myWidgetValidator->activateFilters(false);
 }
@@ -294,6 +319,9 @@ bool ModuleBase_ModelWidget::restoreValue()
 void ModuleBase_ModelWidget::updateObject(ObjectPtr theObject)
 {
   if (!myFlushUpdateBlocked) {
+#ifdef DEBUG_WIDGET_INSTANCE
+    qDebug("ModuleBase_ModelWidget::updateObject");
+#endif
     ModuleBase_Tools::flushUpdated(theObject);
     emit objectUpdated();
   }
@@ -302,6 +330,9 @@ void ModuleBase_ModelWidget::updateObject(ObjectPtr theObject)
 void ModuleBase_ModelWidget::moveObject(ObjectPtr theObj)
 {
   //blockUpdateViewer(true);
+#ifdef DEBUG_WIDGET_INSTANCE
+  qDebug("ModuleBase_ModelWidget::moveObject");
+#endif
 
   static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_MOVED);
   ModelAPI_EventCreator::get()->sendUpdated(theObj, anEvent);
index 97e388511d31ad1cdc3d956402a0238f133bee78..b8417dd6e8d8af7daa229f57a14d5bfe7f76e55b 100644 (file)
@@ -46,9 +46,7 @@ Q_OBJECT
   /// a low-level API for reading xml definitions of widgets
   ModuleBase_ModelWidget(QWidget* theParent, const Config_WidgetAPI* theData);
   /// Destructor
-  virtual ~ModuleBase_ModelWidget()
-  {
-  }
+  virtual ~ModuleBase_ModelWidget();
 
   /// Fills the widget with default values. It calls the resetCustom method and change
   /// the widget state to Reset if the reset is performed.
@@ -85,6 +83,9 @@ Q_OBJECT
   /// \return the enumeration result
   ValueState getValueState() const { return myState; }
 
+  /// Stores the widget value if it is modified
+  void processValueState();
+
   /// Returns an attribute error according to the value state
   /// It exists in all cases excepring the "Store" case
   QString getValueStateError() const;
index e2f2dd6803947e7b8443b81c8c16a11cef5411e6..82cf7906b46389333501c75b28d77f7769f83750 100755 (executable)
@@ -42,6 +42,8 @@
 #include <ModelAPI_AttributeRefList.h>
 #endif
 
+//#define DEBUG_OPERATION_START
+
 #ifdef _DEBUG
 #include <QDebug>
 #endif
@@ -231,6 +233,9 @@ bool ModuleBase_OperationFeature::isDisplayedOnStart(ObjectPtr theObject)
 
 bool ModuleBase_OperationFeature::start()
 {
+#ifdef DEBUG_OPERATION_START
+  qDebug("ModuleBase_OperationFeature::start -- begin");
+#endif
   setIsModified(false);
   QString anId = getDescription()->operationId();
   if (myIsEditing) {
@@ -249,16 +254,26 @@ bool ModuleBase_OperationFeature::start()
       // in order to update commands status in the workshop, to be exact the feature action
       // to be unchecked
       abort();
+#ifdef DEBUG_OPERATION_START
+  qDebug("ModuleBase_OperationFeature::start -- end : IMPOSSIBLE to start");
+#endif
       return false;
     }
   }
   //Already called startOperation();
   emit started();
+#ifdef DEBUG_OPERATION_START
+  qDebug("ModuleBase_OperationFeature::start -- end");
+#endif
   return true;
 }
 
 void ModuleBase_OperationFeature::abort()
 {
+#ifdef DEBUG_OPERATION_START
+  qDebug("ModuleBase_OperationFeature::abort -- begin");
+#endif
+
   emit beforeAborted();
 
   // the viewer update should be blocked in order to avoid the features blinking before they are
@@ -293,10 +308,16 @@ void ModuleBase_OperationFeature::abort()
   Events_Loop::loop()->send(aMsg);
 
   emit aborted();
+#ifdef DEBUG_OPERATION_START
+  qDebug("ModuleBase_OperationFeature::abort -- end");
+#endif
 }
 
 bool ModuleBase_OperationFeature::commit()
 {
+#ifdef DEBUG_OPERATION_START
+  qDebug("ModuleBase_OperationFeature::commit -- begin");
+#endif
   ModuleBase_IPropertyPanel* aPanel = propertyPanel();
   if (aPanel) {
     ModuleBase_ModelWidget* anActiveWidget = aPanel->activeWidget();
@@ -328,8 +349,14 @@ bool ModuleBase_OperationFeature::commit()
     emit committed();
 
     afterCommitOperation();
+#ifdef DEBUG_OPERATION_START
+  qDebug("ModuleBase_OperationFeature::commit -- end : IMPOSSIBLE to commit");
+#endif
     return true;
   }
+#ifdef DEBUG_OPERATION_START
+  qDebug("ModuleBase_OperationFeature::commit -- end");
+#endif
   return false;
 }
 
@@ -356,10 +383,14 @@ ModuleBase_ModelWidget* ModuleBase_OperationFeature::activateByPreselection(
           aWgt = (*aWIt);
           if (aWgt->attributeID() == theGreedAttributeId) {
             aPropertyPanel->setPreselectionWidget(aWgt);
-            aWgt->setSelection(myPreSelection, true);
-            aPropertyPanel->setPreselectionWidget(NULL);
-            aFilledWgt = aWgt;
-            break;
+            if (aWgt->setSelection(myPreSelection, true)) {
+              aPropertyPanel->setPreselectionWidget(NULL);
+              aFilledWgt = aWgt;
+              break;
+            }
+            else { // do not process invalid for greed widget selection
+              break;
+            }
           }
         }
       }
@@ -371,7 +402,7 @@ ModuleBase_ModelWidget* ModuleBase_OperationFeature::activateByPreselection(
           if (!aWgt->canAcceptFocus())
             continue;
           aPropertyPanel->setPreselectionWidget(aWgt);
-          if (!aWgt->setSelection(myPreSelection, true)) {
+          if (myPreSelection.empty() || !aWgt->setSelection(myPreSelection, true)) {
             isSet = false;
             break;
           } else {
index dfd0d1a63db85b085b8de75b0d4731d6ebf27d5d..75c326a27bd3b7a337f3d322706da0ffcc2b536b 100755 (executable)
@@ -71,7 +71,7 @@ void ModuleBase_ResultPrs::Compute(const Handle(PrsMgr_PresentationManager3d)& t
       Set(myOriginalShape);
   }
   // change deviation coefficient to provide more precise circle
-  ModuleBase_Tools::setDefaultDeviationCoefficient(Shape(), Attributes());
+  ModuleBase_Tools::setDefaultDeviationCoefficient(myResult, Attributes());
   AIS_Shape::Compute(thePresentationManager, thePresentation, theMode);
 
   if (!aReadyToDisplay) {
index a17f61e4b37136d48452ad56eefb2495f1719c6a..a4890633ae0cf4a2ad726d83b83a98fa2eeb6fc0 100755 (executable)
@@ -21,6 +21,7 @@
 #include <ModelAPI_AttributeRefList.h>
 #include <ModelAPI_AttributeRefAttrList.h>
 #include <ModelAPI_ResultPart.h>
+#include <ModelAPI_ResultConstruction.h>
 #include <Events_Loop.h>
 
 #include <ModelAPI_Data.h>
@@ -35,6 +36,7 @@
 
 #include <GeomDataAPI_Point2D.h>
 #include <Events_InfoMessage.h>
+#include <GeomAPI_ShapeExplorer.h>
 
 #include <Config_PropManager.h>
 
 #include <string>
 
 const double tolerance = 1e-7;
+const double DEFAULT_DEVIATION_COEFFICIENT = 1.e-4;
 
 //#define DEBUG_ACTIVATE_WINDOW
 //#define DEBUG_SET_FOCUS
+//#define DEBUG_SELECTION_INFO
+
+#ifdef DEBUG_SELECTION_INFO
+#include <ModuleBase_ISelection.h>
+#include <ModuleBase_ViewerPrs.h>
+
+#include <AIS_InteractiveContext.hxx>
+#include <AIS_ListOfInteractive.hxx>
+#include <AIS_ListIteratorOfListOfInteractive.hxx>
+#include <AIS_Shape.hxx>
+#include <TopoDS_Shape.hxx>
+#include <AIS_LocalContext.hxx>
+#include <NCollection_List.hxx>
+#include <StdSelect_BRepOwner.hxx>
+#include <TColStd_ListOfInteger.hxx>
+#include <TColStd_ListIteratorOfListOfInteger.hxx>
+#endif
 
 namespace ModuleBase_Tools {
 
@@ -123,7 +143,7 @@ void setShadowEffect(QWidget* theWidget, const bool isSetEffect)
   else {
     QGraphicsEffect* anEffect = theWidget->graphicsEffect();
     if(anEffect)
-    anEffect->deleteLater();
+      anEffect->deleteLater();
     theWidget->setGraphicsEffect(NULL);
   }
 }
@@ -271,7 +291,7 @@ QString objectInfo(const ObjectPtr& theObj, const bool isUseAttributesInfo)
   if (aFeature.get()) {
     aFeatureStr.append(QString(": %1").arg(aFeature->getKind().c_str()).toStdString().c_str());
     if (aFeature->data()->isValid()) {
-      aFeatureStr.append(QString(", name=%1").arg(aFeature->data()->name().c_str()).toStdString()
+      aFeatureStr.append(QString(", name=%1").arg(theObj->data()->name().c_str()).toStdString()
                                                                                        .c_str());
     }
     if (isUseAttributesInfo) {
@@ -301,28 +321,218 @@ QString objectInfo(const ObjectPtr& theObj, const bool isUseAttributesInfo)
   return aFeatureStr;
 }
 
+#ifdef DEBUG_SELECTION_INFO
+QString getShapeTypeInfo(const int theType)
+{
+  QString anInfo = "Undefined";
+  switch(theType) {
+    case TopAbs_COMPOUND:  anInfo = "compound"; break;
+    case TopAbs_COMPSOLID: anInfo = "compsolid"; break;
+    case TopAbs_SOLID:     anInfo = "solid"; break;
+    case TopAbs_SHELL:     anInfo = "shell"; break;
+    case TopAbs_FACE:      anInfo = "face"; break;
+    case TopAbs_WIRE:      anInfo = "wire"; break;
+    case TopAbs_EDGE:      anInfo = "edge"; break;
+    case TopAbs_VERTEX:    anInfo = "vertex"; break;
+    case TopAbs_SHAPE:     anInfo = "shape"; break;
+    default: break;
+  }
+  return anInfo;
+}
+
+QString getModeInfo(const int theMode)
+{
+  QString anInfo = "Undefined";
+  switch(theMode) {
+    case 0: anInfo = "SHAPE(0)"; break;
+    case 1: anInfo = "VERTEX(1)"; break;
+    case 2: anInfo = "EDGE(2)"; break;
+    case 3: anInfo = "WIRE(3)"; break;
+    case 4: anInfo = "FACE(4)"; break;
+    case 5: anInfo = "SHELL(5)"; break;
+    case 6: anInfo = "SOLID(6)"; break;
+    case 7: anInfo = "COMPSOLID(7)"; break;
+    case 8: anInfo = "COMPOUND(8)"; break;
+    case 100: anInfo = "Sel_Mode_First(100)"; break; //SketcherPrs_Tools
+    case 101: anInfo = "Sel_Constraint(101)"; break;
+    case 102: anInfo = "Sel_Dimension_All(102)"; break;
+    case 103: anInfo = "Sel_Dimension_Line(103)"; break;
+    case 104: anInfo = "Sel_Dimension_Text(104)"; break;
+    default: break;
+  }
+  return anInfo;
+}
+
+QString displayedInteractiveObjects(Handle(AIS_InteractiveContext)& theContext,
+                                    const bool theShapeInfoOnly = true)
+{
+  if (theContext.IsNull())
+    return "";
+  AIS_ListOfInteractive aListOfIO;
+  theContext->DisplayedObjects(aListOfIO, false);
+  QStringList anObjects;
+  AIS_ListIteratorOfListOfInteractive aIt;
+  for (aIt.Initialize(aListOfIO); aIt.More(); aIt.Next()) {
+    Handle(AIS_InteractiveObject) anAISIO = aIt.Value();
+    Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast(anAISIO);
+    if (theShapeInfoOnly && aShapePrs.IsNull())
+      continue;
+
+    QString anInfo = "IO";
+    std::ostringstream aPtrStr;
+    aPtrStr << "[" << anAISIO.Access() << "]";
+    anInfo += aPtrStr.str().c_str();
+
+    if (!aShapePrs.IsNull()) {
+      const TopoDS_Shape& aShape = aShapePrs->Shape();
+      if (aShape.IsNull())
+        Events_Error::throwException("An empty AIS presentation");
+      else
+        anInfo += QString(", shape type: %1").arg(getShapeTypeInfo(aShape.ShapeType()));
+    }
+    TColStd_ListOfInteger aTColModes;
+    theContext->ActivatedModes(anAISIO, aTColModes);
+    TColStd_ListIteratorOfListOfInteger itr( aTColModes );
+    QIntList aModesActivatedForIO;
+    bool isDeactivated = false;
+    QStringList aModes;
+    for (; itr.More(); itr.Next() ) {
+      Standard_Integer aMode = itr.Value();
+      aModes.append(getModeInfo(aMode));
+      //int aShapeMode = (aMode > 8)? aMode : AIS_Shape::SelectionType(aMode);
+    }
+    if (aModes.size() > 0)
+      anInfo += QString(", activated modes: %1").arg(aModes.join(", "));
+
+    anObjects += anInfo;
+  }
+  QString aValue = QString("displayedIO[%1]").arg(anObjects.size());
+  if (anObjects.size() > 0)
+    aValue += QString(":\n  %1").arg(anObjects.join("\n  "));
+  return aValue;
+}
+
+QString activeOwners(Handle(AIS_InteractiveContext)& theContext, const bool theShapeInfoOnly = true)
+{
+  if (theContext.IsNull())
+    return "";
+  Handle(AIS_LocalContext) aLContext = theContext->LocalContext();
+  TCollection_AsciiString aSelectionName = aLContext->SelectionName();
+  aLContext->UnhilightPicked(Standard_False);
+
+  NCollection_List<Handle(SelectBasics_EntityOwner)> anActiveOwners;
+  aLContext->MainSelector()->ActiveOwners(anActiveOwners);
+  NCollection_List<Handle(SelectBasics_EntityOwner)>::Iterator anOwnersIt (anActiveOwners);
+  Handle(SelectMgr_EntityOwner) anOwner;
+  QStringList anObjects;
+  for (; anOwnersIt.More(); anOwnersIt.Next()) {
+    anOwner = Handle(SelectMgr_EntityOwner)::DownCast (anOwnersIt.Value());
+    Handle(StdSelect_BRepOwner) BROwnr = Handle(StdSelect_BRepOwner)::DownCast(anOwner);
+    if (theShapeInfoOnly && BROwnr.IsNull())
+      continue;
+
+    QString anInfo = "Owner";
+    std::ostringstream aPtrStr;
+    aPtrStr << "[" << anOwner.Access() << "]";
+    anInfo += aPtrStr.str().c_str();
+
+    Handle(AIS_InteractiveObject) aAISObj = 
+          Handle(AIS_InteractiveObject)::DownCast(anOwner->Selectable());
+    if (!aAISObj.IsNull()) {
+      std::ostringstream aPtrStr;
+      aPtrStr << "[" << aAISObj.Access() << "]";
+      anInfo += QString(", selectable(IO): %1").arg(aPtrStr.str().c_str());
+    }
+
+    if (!BROwnr.IsNull() && BROwnr->HasShape()) {
+      const TopoDS_Shape& aShape = BROwnr->Shape();
+      if (aShape.IsNull())
+        Events_Error::throwException("An empty AIS presentation");
+      else
+        anInfo += QString(", shape type: %1").arg(getShapeTypeInfo(aShape.ShapeType()));
+    }
+    anObjects += anInfo;
+  }
+  QString aValue = QString("activeOwners[%1]").arg(anObjects.size());
+  if (anObjects.size() > 0)
+    aValue += QString(":\n  %1").arg(anObjects.join("\n  "));
+  return aValue;
+}
+
+QString selectedOwners(Handle(AIS_InteractiveContext)& theContext, const bool theShapeInfoOnly = true)
+{
+  QStringList anObjects;
+  if (theContext.IsNull())
+    return "";
+
+  QList<long> aSelectedIds; // Remember of selected address in order to avoid duplicates
+  for (theContext->InitSelected(); theContext->MoreSelected(); theContext->NextSelected()) {
+    Handle(SelectMgr_EntityOwner) anOwner = theContext->SelectedOwner();
+    Handle(StdSelect_BRepOwner) BROwnr = Handle(StdSelect_BRepOwner)::DownCast(anOwner);
+    if (theShapeInfoOnly && BROwnr.IsNull())
+      continue;
+
+    if (aSelectedIds.contains((long)anOwner.Access()))
+      continue;
+    aSelectedIds.append((long)anOwner.Access());
+
+    QString anInfo = "Owner";
+    std::ostringstream aPtrStr;
+    aPtrStr << "[" << anOwner.Access() << "]";
+    anInfo += aPtrStr.str().c_str();
+
+    if (!BROwnr.IsNull() && BROwnr->HasShape()) {
+      const TopoDS_Shape& aShape = BROwnr->Shape();
+      anInfo += QString(", shape type = %1").arg(getShapeTypeInfo(aShape.ShapeType()));
+    }
+    anObjects += anInfo;
+  }
+  QString aValue = QString("selectedOwners[%1]").arg(anObjects.size());
+  if (anObjects.size() > 0)
+    aValue += QString(":\n  %1").arg(anObjects.join("\n  "));
+  return aValue;
+}
+#endif
+
+void selectionInfo(Handle(AIS_InteractiveContext)& theContext, const std::string& thePrefix)
+{
+#ifdef DEBUG_SELECTION_INFO
+  QString aValue = QString("\n\n\nDEBUG_SELECTION_INFO for '%1'\n%2\n%3\n%4")
+                                              .arg(thePrefix.c_str())
+                                              .arg(displayedInteractiveObjects(theContext))
+                                              .arg(activeOwners(theContext))
+                                              .arg(selectedOwners(theContext));
+  qDebug(aValue.toStdString().c_str());
+#endif
+}
+
 typedef QMap<QString, TopAbs_ShapeEnum> ShapeTypes;
-static ShapeTypes MyShapeTypes;
+static ShapeTypes myShapeTypes;
 
 TopAbs_ShapeEnum shapeType(const QString& theType)
 {
-  if (MyShapeTypes.count() == 0) {
-    MyShapeTypes["face"] = TopAbs_FACE;
-    MyShapeTypes["faces"] = TopAbs_FACE;
-    MyShapeTypes["vertex"] = TopAbs_VERTEX;
-    MyShapeTypes["vertices"] = TopAbs_VERTEX;
-    MyShapeTypes["wire"] = TopAbs_WIRE;
-    MyShapeTypes["wires"] = TopAbs_WIRE;
-    MyShapeTypes["edge"] = TopAbs_EDGE;
-    MyShapeTypes["edges"] = TopAbs_EDGE;
-    MyShapeTypes["shell"] = TopAbs_SHELL;
-    MyShapeTypes["solid"] = TopAbs_SOLID;
-    MyShapeTypes["solids"] = TopAbs_SOLID;
-    MyShapeTypes["objects"] = TopAbs_SHAPE;
+  if (myShapeTypes.count() == 0) {
+    myShapeTypes["compound"]   = TopAbs_COMPOUND;
+    myShapeTypes["compounds"]  = TopAbs_COMPOUND;
+    myShapeTypes["compsolid"]  = TopAbs_COMPSOLID;
+    myShapeTypes["compsolids"] = TopAbs_COMPSOLID;
+    myShapeTypes["solid"]      = TopAbs_SOLID;
+    myShapeTypes["solids"]     = TopAbs_SOLID;
+    myShapeTypes["shell"]      = TopAbs_SHELL;
+    myShapeTypes["shells"]     = TopAbs_SHELL;
+    myShapeTypes["face"]       = TopAbs_FACE;
+    myShapeTypes["faces"]      = TopAbs_FACE;
+    myShapeTypes["wire"]       = TopAbs_WIRE;
+    myShapeTypes["wires"]      = TopAbs_WIRE;
+    myShapeTypes["edge"]       = TopAbs_EDGE;
+    myShapeTypes["edges"]      = TopAbs_EDGE;
+    myShapeTypes["vertex"]     = TopAbs_VERTEX;
+    myShapeTypes["vertices"]   = TopAbs_VERTEX;
+    myShapeTypes["objects"]    = TopAbs_SHAPE;
   }
   QString aType = theType.toLower();
-  if (MyShapeTypes.contains(aType))
-    return MyShapeTypes[aType];
+  if(myShapeTypes.contains(aType))
+    return myShapeTypes[aType];
   Events_InfoMessage("ModuleBase_Tools", "Shape type defined in XML is not implemented!").send();
   return TopAbs_SHAPE;
 }
@@ -349,14 +559,46 @@ void checkObjects(const QObjectPtrList& theObjects, bool& hasResult, bool& hasFe
   }
 }
 
+bool setDefaultDeviationCoefficient(std::shared_ptr<GeomAPI_Shape> theGeomShape)
+{
+  if (!theGeomShape.get())
+    return false;
+  // if the shape could not be exploded on faces, it contains only wires, edges, and vertices
+  // correction of deviation for them should not influence to the application performance
+  GeomAPI_ShapeExplorer anExp(theGeomShape, GeomAPI_Shape::FACE);
+  bool anEmpty = anExp.empty();
+  return !anExp.more();
+}
+
+void setDefaultDeviationCoefficient(const std::shared_ptr<ModelAPI_Result>& theResult,
+                                    const Handle(Prs3d_Drawer)& theDrawer)
+{
+  if (!theResult.get())
+    return;
+  bool aUseDeviation = false;
+
+  std::string aResultGroup = theResult->groupName();
+  if (aResultGroup == ModelAPI_ResultConstruction::group())
+    aUseDeviation = true;
+  else if (aResultGroup == ModelAPI_ResultBody::group()) {
+    GeomShapePtr aGeomShape = theResult->shape();
+    if (aGeomShape.get())
+      aUseDeviation = setDefaultDeviationCoefficient(aGeomShape);
+  }
+  if (aUseDeviation)
+    theDrawer->SetDeviationCoefficient(DEFAULT_DEVIATION_COEFFICIENT);
+}
+
 void setDefaultDeviationCoefficient(const TopoDS_Shape& theShape,
                                     const Handle(Prs3d_Drawer)& theDrawer)
 {
   if (theShape.IsNull())
     return;
-  TopAbs_ShapeEnum aType = theShape.ShapeType();
-  if ((aType == TopAbs_EDGE) || (aType == TopAbs_WIRE)) 
-    theDrawer->SetDeviationCoefficient(1.e-4);
+
+  std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape());
+  aGeomShape->setImpl(new TopoDS_Shape(theShape));
+  if (setDefaultDeviationCoefficient(aGeomShape))
+    theDrawer->SetDeviationCoefficient(DEFAULT_DEVIATION_COEFFICIENT);
 }
 
 Quantity_Color color(const std::string& theSection,
@@ -719,6 +961,18 @@ bool isSubOfComposite(const ObjectPtr& theObject, const FeaturePtr& theFeature)
   return isSub;
 }
 
+//**************************************************************
+ResultPtr firstResult(const ObjectPtr& theObject)
+{
+  ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
+  if (!aResult.get()) {
+    FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
+    if (aFeature.get())
+      aResult = aFeature->firstResult();
+  }
+  return aResult;
+}
+
 //**************************************************************
 bool isFeatureOfResult(const FeaturePtr& theFeature, const std::string& theGroupOfResult)
 {
@@ -734,15 +988,42 @@ bool isFeatureOfResult(const FeaturePtr& theFeature, const std::string& theGroup
   return aFirstResult->groupName() == theGroupOfResult;
 }
 
+//**************************************************************
+bool hasModuleDocumentFeature(const std::set<FeaturePtr>& theFeatures)
+{
+  bool aFoundModuleDocumentObject = false;
+  DocumentPtr aModuleDoc = ModelAPI_Session::get()->moduleDocument();
+
+  std::set<FeaturePtr>::const_iterator anIt = theFeatures.begin(), aLast = theFeatures.end();
+  for (; anIt != aLast && !aFoundModuleDocumentObject; anIt++) {
+    FeaturePtr aFeature = *anIt;
+    ResultPtr aResult = ModuleBase_Tools::firstResult(aFeature);
+    if (aResult.get() && aResult->groupName() == ModelAPI_ResultPart::group())
+      continue;
+    aFoundModuleDocumentObject = aFeature->document() == aModuleDoc;
+  }
+
+  return aFoundModuleDocumentObject;
+}
+
 //**************************************************************
 bool askToDelete(const std::set<FeaturePtr> theFeatures,
                  const std::map<FeaturePtr, std::set<FeaturePtr> >& theReferences,
                  QWidget* theParent,
                  std::set<FeaturePtr>& theReferencesToDelete)
 {
+  QString aNotActivatedDocWrn;
+  std::string aNotActivatedNames;
+  if (!ModelAPI_Tools::allDocumentsActivated(aNotActivatedNames)) {
+    if (ModuleBase_Tools::hasModuleDocumentFeature(theFeatures))
+      aNotActivatedDocWrn = QObject::tr("Selected objects can be used in Part documents which are not loaded:%1.\n")
+                            .arg(aNotActivatedNames.c_str());
+  }
+  
   std::set<FeaturePtr> aFeaturesRefsTo;
   std::set<FeaturePtr> aFeaturesRefsToParameter;
   std::set<FeaturePtr> aParameterFeatures;
+  QStringList aPartFeatureNames;
   std::set<FeaturePtr>::const_iterator anIt = theFeatures.begin(),
                                        aLast = theFeatures.end();
   // separate features to references to parameter features and references to others
@@ -751,6 +1032,9 @@ bool askToDelete(const std::set<FeaturePtr> theFeatures,
     if (theReferences.find(aFeature) == theReferences.end())
       continue;
 
+    if (isFeatureOfResult(aFeature, ModelAPI_ResultPart::group()))
+      aPartFeatureNames.append(aFeature->name().c_str());
+
     std::set<FeaturePtr> aRefFeatures;
     std::set<FeaturePtr> aRefList = theReferences.at(aFeature);
     std::set<FeaturePtr>::const_iterator aRefIt = aRefList.begin(), aRefLast = aRefList.end();
@@ -783,7 +1067,7 @@ bool askToDelete(const std::set<FeaturePtr> theFeatures,
     }
   }
   aParamFeatureNames.sort();
-  QStringList aPartFeatureNames, anOtherFeatureNames;
+  QStringList anOtherFeatureNames;
   anIt = theReferencesToDelete.begin();
   aLast = theReferencesToDelete.end();
   for (; anIt != aLast; anIt++) {
@@ -808,6 +1092,8 @@ bool askToDelete(const std::set<FeaturePtr> theFeatures,
   QString aSep = ", ";
   if (!aPartFeatureNames.empty())
     aText += QString(QObject::tr("The following parts will be deleted: %1.\n")).arg(aPartFeatureNames.join(aSep));
+  if (!aNotActivatedDocWrn.isEmpty())
+    aText += aNotActivatedDocWrn;
   if (!anOtherFeatureNames.empty())
     aText += QString(QObject::tr("Selected features are used in the following features: %1.\nThese features will be deleted.\n"))
                      .arg(anOtherFeatureNames.join(aSep));
index b50ec66a1116581d3bef2dfe9b229f183da16085..2e19e0f731e873527fc0d12da6d466a4447bc039 100755 (executable)
@@ -24,6 +24,8 @@
 
 #include <map>
 
+class Handle_AIS_InteractiveContext;
+
 class QWidget;
 class QLayout;
 class QDoubleSpinBox;
@@ -36,63 +38,55 @@ class GeomAPI_Shape;
 
 namespace ModuleBase_Tools {
 
-/*
- * Methods to adjust margins and spacings.
- */
+/// Methods to adjust margins and spacings.
 MODULEBASE_EXPORT void adjustMargins(QWidget* theWidget);
 MODULEBASE_EXPORT void adjustMargins(QLayout* theLayout);
 
 MODULEBASE_EXPORT void zeroMargins(QWidget* theWidget);
 MODULEBASE_EXPORT void zeroMargins(QLayout* theLayout);
 
-/*
- * Calls the same-named Qt method for the given widget.
- * It sets the top-level widget containing this widget to be the active window.
- * An active window is a visible top-level window that has the keyboard input focus.
- * \param theWidget a widget to be activated
- * \param theIndo a debug information
- */
+/// Calls the same-named Qt method for the given widget.
+/// It sets the top-level widget containing this widget to be the active window.
+/// An active window is a visible top-level window that has the keyboard input focus.
+/// \param theWidget a widget to be activated
+/// \param theIndo a debug information
 MODULEBASE_EXPORT void activateWindow(QWidget* theWidget, const QString& theInfo = QString());
 
-/*
- * Calls the same-named Qt method for the given widget.
- * Gives the keyboard input focus to this widget (or its focus proxy) if this widget or
- * one of its parents is the active window.
- * \param theWidget a widget to be activated
- * \param theIndo a debug information
- */
+/// Calls the same-named Qt method for the given widget.
+/// Gives the keyboard input focus to this widget (or its focus proxy) if this widget or
+/// one of its parents is the active window.
+/// \param theWidget a widget to be activated
+/// \param theIndo a debug information
 MODULEBASE_EXPORT void setFocus(QWidget* theWidget, const QString& theInfo = QString());
 
 
-//! Sets or removes the shadow effect to the widget
-//! \param theWidget a widget to be styled
-//! \param isSetEffect if true, the shadow effect is set, overwise cleared
-//! \return resulting pixmap
+/// Sets or removes the shadow effect to the widget
+/// \param theWidget a widget to be styled
+/// \param isSetEffect if true, the shadow effect is set, overwise cleared
+/// \return resulting pixmap
 MODULEBASE_EXPORT void setShadowEffect(QWidget* theWidget, const bool isSetEffect);
 
-/**
- * \ingroup GUI
- * Methods to modify a resource pixmap
- */
+/// \ingroup GUI
+/// Methods to modify a resource pixmap
 
-//! Create composite pixmap. 
-//! Pixmap \a theAdditionalIcon is drawn over pixmap \a dest with coordinates
-//! specified relatively to the upper left corner of \a theIcon.
+/// Create composite pixmap. 
+/// Pixmap \a theAdditionalIcon is drawn over pixmap \a dest with coordinates
+/// specified relatively to the upper left corner of \a theIcon.
 
-//! \param theAdditionalIcon resource text of the additional pixmap
-//! \param theIcon resource text of the background pixmap
-//! \return resulting pixmap
+/// \param theAdditionalIcon resource text of the additional pixmap
+/// \param theIcon resource text of the background pixmap
+/// \return resulting pixmap
 MODULEBASE_EXPORT QPixmap composite(const QString& theAdditionalIcon, const QString& theIcon);
 
-//! Generates the pixmap lighter than the resources pixmap. 
-//! Pixmap \a theIcon is lighted according to the given value.
-//! If the lighter value is greater than 100, this functions returns a lighter pixmap.
-//! Setting lighter value to 150 returns a color that is 50% brighter. If the factor is less than 100,
-//! the return pixmap is darker. If the factor is 0 or negative, the return pixmap is unspecified.
+/// Generates the pixmap lighter than the resources pixmap. 
+/// Pixmap \a theIcon is lighted according to the given value.
+/// If the lighter value is greater than 100, this functions returns a lighter pixmap.
+/// Setting lighter value to 150 returns a color that is 50% brighter. If the factor is less than 100,
+/// the return pixmap is darker. If the factor is 0 or negative, the return pixmap is unspecified.
 
-//! \param resource text of the pixmap
-//! \param theLighterValue a lighter factor
-//! \return resulting pixmap
+/// \param resource text of the pixmap
+/// \param theLighterValue a lighter factor
+/// \return resulting pixmap
 MODULEBASE_EXPORT QPixmap lighter(const QString& theIcon, const int theLighterValue = 200);
 
 /// Sets programmatically the value to the spin box without emitting any signals(e.g. valueChanged)
@@ -140,6 +134,12 @@ MODULEBASE_EXPORT QAction* createAction(const QIcon& theIcon, const QString& the
 /// \return a string
 MODULEBASE_EXPORT QString objectInfo(const ObjectPtr& theObj, const bool isUseAttributesInfo = false);
 
+/// Converts the AIS context information in a string information.
+/// \param theContext a viewer context
+/// \param thePrefix additional information where the method is called
+MODULEBASE_EXPORT void selectionInfo(Handle_AIS_InteractiveContext& theContext,
+                                     const std::string& thePrefix);
+
 /// Converts string value (name of shape type) to shape enum value
 /// \param theType - string with shape type name
 /// \return TopAbs_ShapeEnum value
@@ -150,36 +150,39 @@ MODULEBASE_EXPORT TopAbs_ShapeEnum shapeType(const QString& theType);
 /// \return boolean result
 MODULEBASE_EXPORT bool isSubResult(ObjectPtr theObject);
 
-/*!
-Check types of objects which are in the given list
-\param theObjects the list of objects
-\param hasResult will be set to true if list contains Result objects
-\param hasFeature will be set to true if list contains Feature objects
-\param hasParameter will be set to true if list contains Parameter objects
-\param hasCompositeOwner will be set to true if list contains Sub-Feature objects
-*/
+/// Check types of objects which are in the given list
+/// \param theObjects the list of objects
+/// \param hasResult will be set to true if list contains Result objects
+/// \param hasFeature will be set to true if list contains Feature objects
+/// \param hasParameter will be set to true if list contains Parameter objects
+/// \param hasCompositeOwner will be set to true if list contains Sub-Feature objects
 MODULEBASE_EXPORT void checkObjects(const QObjectPtrList& theObjects, bool& hasResult,
                            bool& hasFeature, bool& hasParameter, bool& hasCompositeOwner);
 
-/*! Sets the default coeffient into the driver calculated accordingly the shape type.
-It provides 1.e-4 for a shape withe Edge shape type
-\param theShape a shape to define the deviation coeffient, 
-\param theDrawer a drawer
-*/
+/// Sets the default coeffient into the driver calculated accordingly the shape type.
+/// It provides 1.e-4 for results of construction type
+/// \param theResult a result object to define the deviation coeffient
+/// \param theDrawer a drawer
+MODULEBASE_EXPORT void setDefaultDeviationCoefficient(
+                           const std::shared_ptr<ModelAPI_Result>& theResult,
+                           const Handle(Prs3d_Drawer)& theDrawer);
+
+/// Sets the default coeffient into the driver calculated accordingly the shape type.
+/// It provides 1.e-4 for a shape withe Edge shape type
+/// \param theShape a shape to define the deviation coeffient, 
+/// \param theDrawer a drawer
 MODULEBASE_EXPORT void setDefaultDeviationCoefficient(const TopoDS_Shape& theShape,
                                                       const Handle(Prs3d_Drawer)& theDrawer);
 
-/*! Obtains the color from the property manager and converts it to the OCCT color
-\param theSection a property section
-\param theName a property item name
-\param theDefault a default color value
-\return quantity color
-*/
+/// Obtains the color from the property manager and converts it to the OCCT color
+/// \param theSection a property section
+/// \param theName a property item name
+/// \param theDefault a default color value
+/// \return quantity color
 MODULEBASE_EXPORT Quantity_Color color(const std::string& theSection,
                                        const std::string& theName,
                                        const std::string& theDefault);
 
-
 /// Returns the object from the attribute
 /// \param theObj an object
 MODULEBASE_EXPORT ObjectPtr getObject(const AttributePtr& theAttribute);
@@ -247,54 +250,56 @@ MODULEBASE_EXPORT void blockUpdateViewer(const bool theValue);
 MODULEBASE_EXPORT QString wrapTextByWords(const QString& theValue, QWidget* theWidget,
                                              int theMaxLineInPixels = 150);
 
-/*!
-  Returns a container of referenced feature to the current object in the object document.
-  \param theObject an object, which will be casted to a feature type
-  \param theRefFeatures an output container
- */
+/// Returns a container of referenced feature to the current object in the object document.
+/// \param theObject an object, which will be casted to a feature type
+/// \param theRefFeatures an output container
 void MODULEBASE_EXPORT refsToFeatureInFeatureDocument(const ObjectPtr& theObject,
                                                       std::set<FeaturePtr>& theRefFeatures);
 
 
-/*!
- Returns true if the object if a sub child of the feature. The feature is casted to the
- composite one. If it is possible, the sub object check happens. The method is applyed
- recursively to the feature subs.
- \param theObject a candidate to be a sub object
- \param theFeature a candidate to be a composite feature
- \return a boolean value
- */
+/// Returns true if the object if a sub child of the feature. The feature is casted to the
+/// composite one. If it is possible, the sub object check happens. The method is applyed
+/// recursively to the feature subs.
+/// \param theObject a candidate to be a sub object
+/// \param theFeature a candidate to be a composite feature
+/// \return a boolean value
 bool MODULEBASE_EXPORT isSubOfComposite(const ObjectPtr& theObject, const FeaturePtr& theFeature);
 
 
-/*!
-* Returns true if the result is a sub object of some composite object
-* \param theObject a result object
-* \returns boolean value
-*/
+/// Returns true if the result is a sub object of some composite object
+/// \param theObject a result object
+/// \returns boolean value
 bool MODULEBASE_EXPORT isSubOfComposite(const ObjectPtr& theObject);
 
 
-/*!
-* Shows a dialog box about references. Ask whether they should be also removed.
-* \param theFeatures a list of features
-* \param theReferences a map of all references to the features
-* \param theParent a parent widget for the question message box
-* \param theReferencesToDelete an out set for references features to be removed
-* \return true if in message box answer is Yes
-*/
+/// Returns first result of the feature: the object itself if it is a result of
+/// first result of the object's feature
+/// \param theObject an object
+/// \return first result or NULL
+std::shared_ptr<ModelAPI_Result> MODULEBASE_EXPORT firstResult(const ObjectPtr& theObject);
+
+/// Returns true if the list contains at least one feature from the module document(PartSet)
+/// The Part features are skipped.
+/// \param theFeatures a list of features
+/// \bool true if it is found
+bool MODULEBASE_EXPORT hasModuleDocumentFeature(const std::set<FeaturePtr>& theFeatures);
+
+/// Shows a dialog box about references. Ask whether they should be also removed.
+/// \param theFeatures a list of features
+/// \param theReferences a map of all references to the features
+/// \param theParent a parent widget for the question message box
+/// \param theReferencesToDelete an out set for references features to be removed
+/// \return true if in message box answer is Yes
 bool MODULEBASE_EXPORT askToDelete(const std::set<FeaturePtr> aFeatures,
                                    const std::map<FeaturePtr, std::set<FeaturePtr> >& theReferences,
                                    QWidget* theParent,
                                    std::set<FeaturePtr>& theReferencesToDelete);
 
-/*!
-* Converts a list of objects to set of corresponded features. If object is result, it is ingored
-* because the feauture only might be removed. But if result is in a parameter group, the feature
-* of this parameter is to be removed
-* \param theObjects a list of objects
-* \param theFeatures an out conteiner of features
-*/
+/// Converts a list of objects to set of corresponded features. If object is result, it is ingored
+/// because the feauture only might be removed. But if result is in a parameter group, the feature
+/// of this parameter is to be removed
+/// \param theObjects a list of objects
+/// \param theFeatures an out conteiner of features
 void MODULEBASE_EXPORT convertToFeatures(const QObjectPtrList& theObjects, std::set<FeaturePtr>& theFeatures);
 
 }
index fe2665b1081f8678cc5467613489a3a472f3f654..fcd4b0dc808076245064ae35cd336edc6675e9e7 100644 (file)
@@ -26,6 +26,8 @@
 #include <GeomDataAPI_Point.h>
 #include <GeomDataAPI_Point2D.h>
 
+#include <QMessageBox>
+
 #include <string>
 #include <set>
 #include <sstream>
@@ -380,6 +382,18 @@ void ParametersPlugin_EvalListener::processObjectRenamedEvent(
   if (!aParameter.get())
     return;
 
+  std::string aNotActivatedNames;
+  if (!ModelAPI_Tools::allDocumentsActivated(aNotActivatedNames)) {
+    QMessageBox::StandardButton aRes = QMessageBox::warning(0, QObject::tr("Warning"),
+               QObject::tr("Selected objects can be used in Part documents which are not loaded: \
+%1. Whould you like to continue?").arg(aNotActivatedNames.c_str()),
+               QMessageBox::No | QMessageBox::Yes, QMessageBox::No);
+    if (aRes != QMessageBox::Yes) {
+      setParameterName(aResultParameter, aMessage->oldName());
+      return;
+    }
+  }
+
   // try to update the parameter feature according the new name
   setParameterName(aResultParameter, aMessage->newName());
   // TODO(spo): replace with ModelAPI_Session::get()->validators()->validate(aParameter, ParametersPlugin_Parameter::VARIABLE_ID())
index a340cdb3e6e9fc1bec3824cb465811c1c463a237..35df874aa38e0c19babc2394b6a69b2e2c839578 100644 (file)
@@ -30,6 +30,7 @@
 #include <QTimer>
 #include <QEvent>
 #include <QKeyEvent>
+#include <QDialogButtonBox>
 
 enum ColumnType {
   Col_Name,
@@ -155,7 +156,7 @@ void ParametersPlugin_TreeWidget::closeEditor(QWidget* theEditor, QAbstractItemD
 /////////////////////////////////////////////////////////////////////////////////////////////////
 
 ParametersPlugin_WidgetParamsMgr::ParametersPlugin_WidgetParamsMgr(QWidget* theParent, const Config_WidgetAPI* theData)
-  : ModuleBase_ModelWidget(theParent, theData)
+  : ModuleBase_ModelDialogWidget(theParent, theData)
 {
   QVBoxLayout* aLayout = new QVBoxLayout(this);
 
@@ -304,7 +305,7 @@ void ParametersPlugin_WidgetParamsMgr::updateFeaturesPart()
 void ParametersPlugin_WidgetParamsMgr::updateParametersPart()
 {
   updateItem(myParameters, parametersItems(myParametersList));
-  bool aIsValid = checkIsValid();
+  bool aIsValid = isValid();
   enableButtons(aIsValid);
 }
 
@@ -417,7 +418,7 @@ void ParametersPlugin_WidgetParamsMgr::onCloseEditor(QWidget* theEditor,
           aText.replace(" ", "");
         }
         if (hasName(aText)) {
-          myMessage = tr("Name %1 already exists.").arg(aText);
+          myMessage = tr("Name '%1' already exists.").arg(aText);
           QTimer::singleShot(50, this, SLOT(sendWarning()));
           return;
         }
@@ -454,9 +455,11 @@ void ParametersPlugin_WidgetParamsMgr::onCloseEditor(QWidget* theEditor,
   aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
   aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
 
-  if (aColumn == Col_Equation)
+  if (aColumn != Col_Comment)
     updateParametersPart();
   updateFeaturesPart();
+          
+  onSelectionChanged();
 }
 
 void ParametersPlugin_WidgetParamsMgr::updateItem(QTreeWidgetItem* theItem, 
@@ -696,13 +699,16 @@ bool ParametersPlugin_WidgetParamsMgr::hasName(const QString& theName) const
 void ParametersPlugin_WidgetParamsMgr::sendWarning()
 {
   QMessageBox::warning(this, tr("Warning"), myMessage);
+  QTreeWidgetItem* aItem = myTable->currentItem();
+  if (aItem)
+    myTable->editItem(aItem);
 }
 
 void ParametersPlugin_WidgetParamsMgr::onSelectionChanged()
 {
-  bool isValid = checkIsValid();
-  if (isValid) {
-    QList<QTreeWidgetItem*> aItemsList = myTable->selectedItems();
+  QList<QTreeWidgetItem*> aItemsList = myTable->selectedItems();
+  bool aIsValid = isValid();
+  if (aIsValid) {
     bool isParameter = false;
     foreach(QTreeWidgetItem* aItem, aItemsList) {
       if (aItem->parent() == myParameters) {
@@ -711,15 +717,16 @@ void ParametersPlugin_WidgetParamsMgr::onSelectionChanged()
       }
     }
     myInsertBtn->setEnabled(isParameter);
-    myRemoveBtn->setEnabled(isParameter);
+    //myRemoveBtn->setEnabled(isParameter);
     myUpBtn->setEnabled(isParameter);
     myDownBtn->setEnabled(isParameter);
   } else {
     myInsertBtn->setEnabled(false);
-    myRemoveBtn->setEnabled(false);
+    //myRemoveBtn->setEnabled(false);
     myUpBtn->setEnabled(false);
     myDownBtn->setEnabled(false);
   }
+  myRemoveBtn->setEnabled(!aItemsList.isEmpty());
 }
 
 void ParametersPlugin_WidgetParamsMgr::enableButtons(bool theEnable)
@@ -733,9 +740,10 @@ void ParametersPlugin_WidgetParamsMgr::enableButtons(bool theEnable)
     myUpBtn->setEnabled(theEnable);
     myDownBtn->setEnabled(theEnable);
   }
+  myOkCancelBtn->button(QDialogButtonBox::Ok)->setEnabled(theEnable);
 }
 
-bool ParametersPlugin_WidgetParamsMgr::checkIsValid()
+bool ParametersPlugin_WidgetParamsMgr::isValid()
 {
   QTreeWidgetItem* aItem;
   bool aIsValid = true;
index 8e32c3767b5046418d04a098070ecb0576eba1d0..0606cf092d52c7a943f1e9266df89c45dc032bf0 100644 (file)
@@ -7,7 +7,7 @@
 #ifndef ParametersPlugin_WidgetParamsMgr_H_
 #define ParametersPlugin_WidgetParamsMgr_H_
 
-#include <ModuleBase_ModelWidget.h>
+#include <ModuleBase_ModelDialogWidget.h>
 #include <QModelIndex>
 #include <QAbstractItemDelegate>
 #include <QTreeWidget>
@@ -43,7 +43,7 @@ protected slots:
  * \ingroup GUI
  * Represent a content of the property panel to show/modify parameters of some feature.
  */
-class ParametersPlugin_WidgetParamsMgr : public ModuleBase_ModelWidget
+class ParametersPlugin_WidgetParamsMgr : public ModuleBase_ModelDialogWidget
 {
  Q_OBJECT
 public:
@@ -119,14 +119,15 @@ private:
 
   void updateParametersPart();
 
+  /// Returns true if values in the widget are valid
+  bool isValid();
+
   /// Returns true if parameter with the given name already exists
   bool hasName(const QString& theName) const;
 
   /// Enable or disable buttons for parameters managemnt
   void enableButtons(bool theEnable);
 
-  bool checkIsValid();
-
   QList<QStringList> featuresItems(const QList<FeaturePtr>& theFeatures, QList<FeaturePtr>& theFeatureList) const;
   QList<QStringList> parametersItems(const QList<FeaturePtr>& theFeatures) const;
 
index 2beae8cc10aeb6646be0bc8fb87daefded454a96..1636a6ca234bf5c34ce2b8c8edeb4c3c7de0cea9 100644 (file)
@@ -79,8 +79,12 @@ QIcon PartSet_IconFactory::getIcon(ObjectPtr theObj)
     GeomShapePtr aShape = aResult->shape();
     if(aShape.get()) {
       switch(aShape->shapeType()) {
-        case GeomAPI_Shape::COMPOUND:  return aShape->isConnectedTopology() ?
-                QIcon(":pictures/compoundofsolids.png") : QIcon(":pictures/compound.png");
+        case GeomAPI_Shape::COMPOUND: {
+          ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aResult);
+          if (aBody.get() && aBody->isConnectedTopology())
+            return QIcon(":pictures/compoundofsolids.png");
+          return QIcon(":pictures/compound.png");
+        }
         case GeomAPI_Shape::COMPSOLID: return QIcon(":pictures/compsolid.png");
         case GeomAPI_Shape::SOLID:     return QIcon(":pictures/solid.png");
         case GeomAPI_Shape::SHELL:     return QIcon(":pictures/shell.png");
index b8b46fb90555be4072ae17092e1e5d3c6fd0e798..f53edf79b0b553ce577e56f3702a4375b11d7592 100755 (executable)
@@ -446,8 +446,9 @@ bool PartSet_Module::canApplyAction(const ObjectPtr& theObject, const QString& t
   if (theActionId == "MOVE_CMD") {
     FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
     if (aFeature) {
+      ResultPtr aResult = ModuleBase_Tools::firstResult(aFeature);
       // part features can not be moved in the history.
-      if (aFeature->getKind() == PartSetPlugin_Part::ID())
+      if (aResult.get() && aResult->groupName() == ModelAPI_ResultPart::group())
         aValid = false;
     }
   }
@@ -526,6 +527,14 @@ void PartSet_Module::activeSelectionModes(QIntList& theModes)
     PartSet_SketcherMgr::sketchSelectionModes(theModes);
 }
 
+void PartSet_Module::customSubShapesSelectionModes(QIntList& theTypes)
+{
+  if (theTypes.contains(TopAbs_FACE))
+    theTypes.append(SketcherPrs_Tools::Sel_Sketch_Face);
+  if (theTypes.contains(TopAbs_WIRE))
+    theTypes.append(SketcherPrs_Tools::Sel_Sketch_Wire);
+}
+
 bool PartSet_Module::isMouseOverWindow()
 {
   return mySketchMgr->isMouseOverWindow();
@@ -817,6 +826,8 @@ bool PartSet_Module::canCommitOperation() const
 void PartSet_Module::launchOperation(const QString& theCmdId)
 {
   storeConstraintsState(theCmdId.toStdString());
+  updateConstraintsState(theCmdId.toStdString());
+
   ModuleBase_IModule::launchOperation(theCmdId);
 }
 
@@ -828,6 +839,10 @@ void PartSet_Module::storeConstraintsState(const std::string& theFeatureKind)
                                                   mySketchMgr->showConstraintStates();
     myHasConstraintShown = aShownStates;
   }
+}
+
+void PartSet_Module::updateConstraintsState(const std::string& theFeatureKind)
+{
   if (PartSet_SketcherMgr::constraintsIdList().contains(theFeatureKind.c_str())) {
     // Show constraints if a constraint was anOperation
     mySketchMgr->updateBySketchParameters(PartSet_Tools::Geometrical, true);
@@ -1322,38 +1337,3 @@ void PartSet_Module::setDefaultConstraintShown()
   myHasConstraintShown[PartSet_Tools::Dimensional] = true;
   myHasConstraintShown[PartSet_Tools::Expressions] = false;
 }
-
-//******************************************************
-bool PartSet_Module::canActivateSelectionMode(const Handle(AIS_InteractiveObject)& theIO, int theMode) const
-{
-  /*if (theMode == TopAbs_FACE) {
-    Handle(PartSet_ResultSketchPrs) aSketchPrs = Handle(PartSet_ResultSketchPrs)::DownCast(theIO);
-    if (!aSketchPrs.IsNull()) {
-        ModuleBase_Operation* anOperation = myWorkshop->currentOperation();
-        if (anOperation) {
-          ModuleBase_IPropertyPanel* aPropPanel = anOperation->propertyPanel();
-          if (aPropPanel) {
-            ModuleBase_ModelWidget* aModelWgt = aPropPanel->activeWidget();
-            ModuleBase_WidgetSelector* aWgtSelector = dynamic_cast<ModuleBase_WidgetSelector*>(aModelWgt);
-            if (aWgtSelector) {
-              return aWgtSelector->isFilterActivated();
-            } else
-              return true;
-          } else
-            return false;
-        } else
-          return false;
-    }
-  }*/
-  return true; 
-}
-
-//******************************************************
-bool PartSet_Module::needDeactivateSelectionMode(const Handle(AIS_InteractiveObject)& theIO, int theMode) const
-{
-  if (theMode == TopAbs_FACE) {
-   // Handle(PartSet_ResultSketchPrs) aSketchPrs = Handle(PartSet_ResultSketchPrs)::DownCast(theIO);
-   // return !aSketchPrs.IsNull();
-  }
-  return false;
-}
index 0c03bede41507900529d9a2cf4f46a27efdb95ad..f6d8fa9210ff5e3dc27fec135e5f0a6f9f2e8fc1 100755 (executable)
@@ -189,6 +189,10 @@ public:
   /// \param theModes a list of modes
   virtual void activeSelectionModes(QIntList& theModes);
 
+  /// Appends specific selection modes for the module to the list of types
+  /// \param theTypes a selection modes to be extended
+  virtual void customSubShapesSelectionModes(QIntList& theTypes);
+
   /// Returns whether the mouse enter the viewer's window
   /// \return true if items are added and there is no necessity to provide standard menu
   bool isMouseOverWindow();
@@ -307,16 +311,6 @@ public:
   /// \return theAttribute
   virtual AttributePtr findAttribute(const ObjectPtr& theObject, const GeomShapePtr& theGeomShape);
 
-  /// Returns true if the given selection mode can be activated for the given presentgation
-  /// \param theIO an object presentation
-  /// \param theMode selection mode
-  virtual bool canActivateSelectionMode(const Handle(AIS_InteractiveObject)& theIO, int theMode) const;
-
-  /// Returns true if the given selection mode must be deactivated for the given presentgation in any case
-  /// \param theIO an object presentation
-  /// \param theMode selection mode
-  virtual bool needDeactivateSelectionMode(const Handle(AIS_InteractiveObject)& theIO, int theMode) const;
-
 public slots:
   /// Redefines the parent method in order to customize the next case:
   /// If the sketch nested operation is active and the presentation is not visualized in the viewer,
@@ -361,6 +355,11 @@ protected:
   /// \param theFeatureKindId a feature kind
   void storeConstraintsState(const std::string& theFeatureKindId);
 
+  /// If the feature kind is a geometrical or dimensional constraint, set visible state for
+  /// all types of constraints
+  /// \param theFeatureKindId a feature kind
+  void updateConstraintsState(const std::string& theFeatureKind);
+
   /// Register validators for this module
   virtual void registerValidators();
 
index 10d475066d66cbfd9a2f8e5b14087f67bb64b1f1..1f8d0c5606ed6349bc40c2236b9effb03db15400 100755 (executable)
 #include <gp_Pnt.hxx>
 #include <TopoDS_Vertex.hxx>
 #include <BRepBuilderAPI_MakeVertex.hxx>
+#include <BRep_Builder.hxx>
+#include <TopoDS_Compound.hxx>
 
 //#define DEBUG_EMPTY_SHAPE
+//#define DEBUG_OPERATION_PRS
 
 // multi-rotation/translation operation
 //#define DEBUG_HIDE_COPY_ATTRIBUTE
@@ -58,6 +61,9 @@ IMPLEMENT_STANDARD_RTTIEXT(PartSet_OperationPrs, ViewerData_AISShape);
 PartSet_OperationPrs::PartSet_OperationPrs(ModuleBase_IWorkshop* theWorkshop)
 : ViewerData_AISShape(TopoDS_Shape()), myWorkshop(theWorkshop), myUseAISWidth(false)
 {
+#ifdef DEBUG_OPERATION_PRS
+  qDebug("PartSet_OperationPrs::PartSet_OperationPrs");
+#endif
   myShapeColor = Quantity_Color(1, 1, 1, Quantity_TOC_RGB);
 
   // first presentation for having correct Compute until presentation with shapes are set
@@ -86,6 +92,10 @@ void PartSet_OperationPrs::Compute(const Handle(PrsMgr_PresentationManager3d)& t
                                    const Handle(Prs3d_Presentation)& thePresentation, 
                                    const Standard_Integer theMode)
 {
+#ifdef DEBUG_OPERATION_PRS
+  qDebug("PartSet_OperationPrs::Compute -- begin");
+#endif
+
   SetColor(myShapeColor);
   thePresentation->Clear();
   bool aReadyToDisplay = !myShapeToPrsMap.IsEmpty();
@@ -93,10 +103,15 @@ void PartSet_OperationPrs::Compute(const Handle(PrsMgr_PresentationManager3d)& t
   XGUI_Displayer* aDisplayer = XGUI_Tools::workshop(myWorkshop)->displayer();
   Handle(Prs3d_Drawer) aDrawer = Attributes();
   // create presentations on the base of the shapes
+  BRep_Builder aBuilder;
+  TopoDS_Compound aComp;
+  aBuilder.MakeCompound(aComp);
   for(NCollection_DataMap<TopoDS_Shape, Handle(AIS_InteractiveObject)>::Iterator anIter(myShapeToPrsMap);
       anIter.More(); anIter.Next()) {
     const TopoDS_Shape& aShape = anIter.Key();
+    aBuilder.Add(aComp, aShape);
     // change deviation coefficient to provide more precise circle
+    // as there is no result, the shape is processed to correct deviation. To be unified
     ModuleBase_Tools::setDefaultDeviationCoefficient(aShape, aDrawer);
 
     if (myUseAISWidth) {
@@ -113,7 +128,7 @@ void PartSet_OperationPrs::Compute(const Handle(PrsMgr_PresentationManager3d)& t
     }
     StdPrs_WFDeflectionShape::Add(thePresentation, aShape, aDrawer);
   }
-
+  Set(aComp);
   if (!aReadyToDisplay) {
     Events_InfoMessage("PartSet_OperationPrs", 
       "An empty AIS presentation: PartSet_OperationPrs").send();
@@ -121,6 +136,9 @@ void PartSet_OperationPrs::Compute(const Handle(PrsMgr_PresentationManager3d)& t
                 new Events_Message(Events_Loop::eventByName(EVENT_EMPTY_OPERATION_PRESENTATION)));
     Events_Loop::loop()->send(aMsg);
   }
+#ifdef DEBUG_OPERATION_PRS
+  qDebug("PartSet_OperationPrs::Compute -- end");
+#endif
 }
 
 void PartSet_OperationPrs::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection,
index 154ca8d41d9bc671ac9f02525d10d4b78f336e63..d23125683ca8ae9868af9b340982a876810e5b84 100755 (executable)
@@ -18,6 +18,8 @@
 
 #include <SketchPlugin_SketchEntity.h>
 
+#include <SketcherPrs_Tools.h>
+
 #include <Config_PropManager.h>
 
 #include <BRep_Builder.hxx>
@@ -86,7 +88,7 @@ void PartSet_ResultSketchPrs::Compute(const Handle(PrsMgr_PresentationManager3d)
   setAuxiliaryPresentationStyle(false);
 
   // change deviation coefficient to provide more precise circle
-  ModuleBase_Tools::setDefaultDeviationCoefficient(Shape(), Attributes());
+  ModuleBase_Tools::setDefaultDeviationCoefficient(myResult, Attributes());
   AIS_Shape::Compute(thePresentationManager, thePresentation, theMode);
 
   if (!myAuxiliaryCompound.IsNull()) {
@@ -120,15 +122,21 @@ void debugInfo(const TopoDS_Shape& theShape, const TopAbs_ShapeEnum theType)
 #endif
 
 void PartSet_ResultSketchPrs::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection,
-                                            const Standard_Integer aMode)
+                                            const Standard_Integer theMode)
 {
-  if (aMode > 8)
+  int aMode = theMode;
+
+  if (aMode > 8 &&
+      aMode != SketcherPrs_Tools::Sel_Sketch_Face &&
+      aMode != SketcherPrs_Tools::Sel_Sketch_Wire)
     // In order to avoid using custom selection modes
     return;
 
   bool aShapeIsChanged = false;
-  if (aMode == AIS_Shape::SelectionMode(TopAbs_FACE) ||
-      aMode == AIS_Shape::SelectionMode(TopAbs_WIRE)) {
+  if (aMode == SketcherPrs_Tools::Sel_Sketch_Face ||
+      aMode == SketcherPrs_Tools::Sel_Sketch_Wire) {
+    aMode = (aMode == SketcherPrs_Tools::Sel_Sketch_Face) ? AIS_Shape::SelectionMode(TopAbs_FACE)
+                                                          : AIS_Shape::SelectionMode(TopAbs_WIRE);
 #ifdef DEBUG_WIRE
     const TopoDS_Shape& aShape = Shape();
     debugInfo(aShape, TopAbs_VERTEX); // 24
index ddf21d1ecd72d143e2a0bd0be691425b1daf6325..f303adec9999dcfec9b41c35a4335a3b5ee2370c 100755 (executable)
@@ -37,7 +37,7 @@ protected:
 
   /// Redefinition of virtual function
   Standard_EXPORT virtual void ComputeSelection(const Handle(SelectMgr_Selection)& aSelection,
-    const Standard_Integer aMode) ;
+    const Standard_Integer theMode) ;
 
 private:
   /// Appens sensitive and owners for wires of the given shape into selection
index 1a07384b7fa79a6b0f58f12322f1cd4f67b65fd7..7fcebed5a10f52421f9874413936c0f65e1b59a4 100755 (executable)
@@ -37,6 +37,7 @@
 #include <ModuleBase_Operation.h>
 #include <ModuleBase_WidgetEditor.h>
 #include <ModuleBase_ViewerPrs.h>
+#include <ModuleBase_Tools.h>
 
 #include <GeomDataAPI_Point2D.h>
 
@@ -386,6 +387,7 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE
     if (!aContext.IsNull()) {
       // MoveTo in order to highlight current object
       aContext->MoveTo(theEvent->x(), theEvent->y(), theWnd->v3dView());
+      ModuleBase_Tools::selectionInfo(aContext, "PartSet_SketcherMgr::onMousePressed -- MoveTo");
     }
     // Remember highlighted objects for editing
     ModuleBase_ISelection* aSelect = aWorkshop->selection();
@@ -746,34 +748,43 @@ const QStringList& PartSet_SketcherMgr::sketchOperationIdList()
     // TODO
     // SketchRectangle is a python feature, so its ID is passed just as a string
     aIds << "SketchRectangle";
+    aIds.append(replicationsIdList());
     aIds.append(constraintsIdList());
   }
   return aIds;
 }
 
+const QStringList& PartSet_SketcherMgr::replicationsIdList()
+{
+  static QStringList aReplicationIds;
+  if (aReplicationIds.size() == 0) {
+    aReplicationIds << SketchPlugin_ConstraintMirror::ID().c_str();
+    aReplicationIds << SketchPlugin_MultiRotation::ID().c_str();
+    aReplicationIds << SketchPlugin_MultiTranslation::ID().c_str();
+  }
+  return aReplicationIds;
+}
+
 const QStringList& PartSet_SketcherMgr::constraintsIdList()
 {
-  static QStringList aIds;
-  if (aIds.size() == 0) {
-    aIds << SketchPlugin_ConstraintLength::ID().c_str();
-    aIds << SketchPlugin_ConstraintDistance::ID().c_str();
-    aIds << SketchPlugin_ConstraintRigid::ID().c_str();
-    aIds << SketchPlugin_ConstraintRadius::ID().c_str();
-    aIds << SketchPlugin_ConstraintPerpendicular::ID().c_str();
-    aIds << SketchPlugin_ConstraintParallel::ID().c_str();
-    aIds << SketchPlugin_ConstraintHorizontal::ID().c_str();
-    aIds << SketchPlugin_ConstraintVertical::ID().c_str();
-    aIds << SketchPlugin_ConstraintEqual::ID().c_str();
-    aIds << SketchPlugin_ConstraintTangent::ID().c_str();
-    aIds << SketchPlugin_ConstraintCoincidence::ID().c_str();
-    aIds << SketchPlugin_ConstraintMirror::ID().c_str();
-    aIds << SketchPlugin_ConstraintAngle::ID().c_str();
-    aIds << SketchPlugin_MultiRotation::ID().c_str();
-    aIds << SketchPlugin_MultiTranslation::ID().c_str();
-    aIds << SketchPlugin_ConstraintCollinear::ID().c_str();
-    aIds << SketchPlugin_ConstraintMiddle::ID().c_str();
+  static QStringList aConstraintIds;
+  if (aConstraintIds.size() == 0) {
+    aConstraintIds << SketchPlugin_ConstraintLength::ID().c_str();
+    aConstraintIds << SketchPlugin_ConstraintDistance::ID().c_str();
+    aConstraintIds << SketchPlugin_ConstraintRigid::ID().c_str();
+    aConstraintIds << SketchPlugin_ConstraintRadius::ID().c_str();
+    aConstraintIds << SketchPlugin_ConstraintPerpendicular::ID().c_str();
+    aConstraintIds << SketchPlugin_ConstraintParallel::ID().c_str();
+    aConstraintIds << SketchPlugin_ConstraintHorizontal::ID().c_str();
+    aConstraintIds << SketchPlugin_ConstraintVertical::ID().c_str();
+    aConstraintIds << SketchPlugin_ConstraintEqual::ID().c_str();
+    aConstraintIds << SketchPlugin_ConstraintTangent::ID().c_str();
+    aConstraintIds << SketchPlugin_ConstraintCoincidence::ID().c_str();
+    aConstraintIds << SketchPlugin_ConstraintAngle::ID().c_str();
+    aConstraintIds << SketchPlugin_ConstraintCollinear::ID().c_str();
+    aConstraintIds << SketchPlugin_ConstraintMiddle::ID().c_str();
   }
-  return aIds;
+  return aConstraintIds;
 }
 
 void PartSet_SketcherMgr::sketchSelectionModes(QIntList& theModes)
index ed60f1ae16b806644a03ac99d3d1b2282b0ea725..ec9ea8f82d3be2e20df29a2f0540807d549c1e44 100644 (file)
@@ -233,6 +233,9 @@ public:
   /// Returns list of strings which contains id's of sketch operations
   static const QStringList& sketchOperationIdList();
 
+  /// Returns list of strings which contains id's of sketch replication operations
+  static const QStringList& replicationsIdList();
+
   /// Returns list of strings which contains id's of constraints operations
   static const QStringList& constraintsIdList();
 
index 805d6a6210f13c7468f37a131fe5c348077eb70b..9766c0a9ee319424ef0817137272855b5e09d99a 100755 (executable)
@@ -367,15 +367,14 @@ bool PartSet_DifferentObjectsValidator::isValid(const AttributePtr& theAttribute
     AttributeRefAttrPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
     bool isObject = anAttr->isObject();
     ObjectPtr anObject = anAttr->object();
-    AttributePtr anAttributeAttr = anAttr->attr();
 
     anAttrs = aFeature->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
     if (anAttrs.size() > 0) {
-      std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = anAttrs.begin();
-      for(; anAttr != anAttrs.end(); anAttr++) {
-      if ((*anAttr).get() && (*anAttr)->id() != theAttribute->id()) {
+      std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttrIter = anAttrs.begin();
+      for(; anAttrIter != anAttrs.end(); anAttrIter++) {
+      if ((*anAttrIter).get() && (*anAttrIter)->id() != theAttribute->id()) {
           std::shared_ptr<ModelAPI_AttributeRefAttr> aRef =
-                                      std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttr);
+                                      std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttrIter);
           if (aRef->isObject() != isObject)
             continue;
           if (isObject) {
@@ -386,6 +385,7 @@ bool PartSet_DifferentObjectsValidator::isValid(const AttributePtr& theAttribute
             }
           }
           else { // the attribute reference
+            AttributePtr anAttributeAttr = anAttr->attr();
             if (aRef->attr() == anAttributeAttr) {
               theError = errorMessage(EqualAttributes,
                                       anAttributeAttr.get() ? anAttributeAttr->id() : "",
index 9ff45cca55e2da4195d46617e473669266200a8c..bb22d28821444f91420f15882a085424f3794123 100644 (file)
@@ -207,12 +207,12 @@ model.do()
 
 # START DEBUG PURPOSES
 # prepare a study without last operation to trap floating problem with degenerated line
-aPathToStore = os.path.join(os.getcwd(), "Data")
-print aPathToStore
-if not os.path.exists(aPathToStore):
-    os.mkdir(aPathToStore)
-results = ModelAPI.StringList()
-ModelAPI.ModelAPI_Session.get().save(aPathToStore, results)
+#aPathToStore = os.path.join(os.getcwd(), "Data")
+#print aPathToStore
+#if not os.path.exists(aPathToStore):
+#    os.mkdir(aPathToStore)
+#results = ModelAPI.StringList()
+#ModelAPI.ModelAPI_Session.get().save(aPathToStore, results)
 # END DEBUG PURPOSES
 b4 = body_4()
 
index 29031a04b253e4abfd27ecf604f623e5fa52bbe8..aa6e7fb4fe682ea27dff47960d17dd91914175ae 100644 (file)
@@ -106,11 +106,8 @@ void SketchPlugin_Arc::initDerivedClassAttributes()
   data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::typeId());
   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EXTERNAL_ID());
 
-  data()->addAttribute(INVERSED_ID(), ModelAPI_AttributeBoolean::typeId());
-  AttributeBooleanPtr isInversed =
-      std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(attribute(INVERSED_ID()));
-  if (!isInversed->isInitialized())
-    isInversed->setValue(false);
+  AttributeBooleanPtr isInversed = std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(
+    data()->addAttribute(INVERSED_ID(), ModelAPI_AttributeBoolean::typeId()));
 
   // get the initial values
   if (anEndAttr->isInitialized()) {
@@ -118,14 +115,18 @@ void SketchPlugin_Arc::initDerivedClassAttributes()
     myYEndBefore = anEndAttr->y();
   }
 
-  data()->addAttribute(ARC_TYPE(), ModelAPI_AttributeString::typeId());
-  std::dynamic_pointer_cast<ModelAPI_AttributeString>(
-      data()->attribute(ARC_TYPE()))->setValue(ARC_TYPE_CENTER_START_END());
+  AttributeStringPtr anArcType = std::dynamic_pointer_cast<ModelAPI_AttributeString>(
+    data()->addAttribute(ARC_TYPE(), ModelAPI_AttributeString::typeId()));
 
   data()->addAttribute(PASSED_POINT_ID(), GeomDataAPI_Point2D::typeId());
   data()->addAttribute(TANGENT_POINT_ID(), ModelAPI_AttributeRefAttr::typeId());
   data()->addAttribute(RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
   data()->addAttribute(ANGLE_ID(), ModelAPI_AttributeDouble::typeId());
+
+  // set after all to avoid in attributeChanged reference to not existing attributes
+  if (!isInversed->isInitialized())
+    isInversed->setValue(false);
+  anArcType->setValue(ARC_TYPE_CENTER_START_END());
 }
 
 void SketchPlugin_Arc::execute()
index 7c4a4877b1f955bf94d5d9105c3d5b5c8d54c56d..6e9a26dd0729f9c9825527df54f170e78d706f8f 100644 (file)
@@ -98,7 +98,8 @@
             label="Points:"
             tooltip="Select points for fillets"
             type_choice="Vertices"
-            greed ="true">
+            greed = "true"
+            clear_in_neutral_point="false">
           <validator id="SketchPlugin_FilletVertexValidator"/>
         </sketch_multi_selector>
         <doublevalue label="Radius" tooltip="Fillet arc radius" id="ConstraintValue" accept_expressions="0" min="0" use_reset="false">
index 1dbc5ed4983a932f358cc6b5b8bbf3a2616aeb91..027d57a0ad12afdf53a3c6d17b43c32317076651 100644 (file)
@@ -142,8 +142,6 @@ static ConstraintWrapperPtr
 
 
 
-/// \brief Set flags for angle constraint
-static void adjustAngle(ConstraintWrapperPtr theConstraint);
 /// \brief Update mirror points
 static void adjustMirror(ConstraintWrapperPtr theConstraint);
 /// \brief Update a sign of the point-line distance constraint
@@ -342,10 +340,10 @@ std::list<ConstraintWrapperPtr> PlaneGCSSolver_Builder::createMirror(
         std::dynamic_pointer_cast<GCS::Line>(aMirrorLine->entity());
 
     std::list<GCSConstraintPtr> aConstrList;
-    aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintPerpendicular(
-        *(aPoint1->point()), *(aPoint2->point()), aLine->p1, aLine->p2)));
     aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintMidpointOnLine(
         *(aPoint1->point()), *(aPoint2->point()), aLine->p1, aLine->p2)));
+    aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintPerpendicular(
+        *(aPoint1->point()), *(aPoint2->point()), aLine->p1, aLine->p2)));
 
     ConstraintWrapperPtr aSubResult(new PlaneGCSSolver_ConstraintWrapper(
         theConstraint, aConstrList, CONSTRAINT_SYMMETRIC));
@@ -459,9 +457,7 @@ void PlaneGCSSolver_Builder::adjustConstraint(ConstraintWrapperPtr theConstraint
 {
   SketchSolver_ConstraintType aType = theConstraint->type();
   // Update flags and parameters in constraints
-  if (aType == CONSTRAINT_ANGLE)
-    adjustAngle(theConstraint);
-  else if (aType == CONSTRAINT_PT_LINE_DISTANCE)
+  if (aType == CONSTRAINT_PT_LINE_DISTANCE)
     adjustPtLineDistance(theConstraint);
   else if (aType == CONSTRAINT_SYMMETRIC)
     adjustMirror(theConstraint);
@@ -955,9 +951,19 @@ ConstraintWrapperPtr createConstraintAngle(
     std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
 {
   std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
+  bool isLine1Rev = theConstraint->boolean(
+      SketchPlugin_ConstraintAngle::ANGLE_REVERSED_FIRST_LINE_ID())->value();
+  GCS::Point aLine1Pt1 = isLine1Rev ? aLine1->p2 : aLine1->p1;
+  GCS::Point aLine1Pt2 = isLine1Rev ? aLine1->p1 : aLine1->p2;
+
   std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
+  bool isLine2Rev = theConstraint->boolean(
+      SketchPlugin_ConstraintAngle::ANGLE_REVERSED_SECOND_LINE_ID())->value();
+  GCS::Point aLine2Pt1 = isLine2Rev ? aLine2->p2 : aLine2->p1;
+  GCS::Point aLine2Pt2 = isLine2Rev ? aLine2->p1 : aLine2->p2;
+
   GCSConstraintPtr aNewConstr(new GCS::ConstraintL2LAngle(
-      *(aLine1), *(aLine2), theValue->parameter()));
+      aLine1Pt1, aLine1Pt2, aLine2Pt1, aLine2Pt2, theValue->parameter()));
 
   std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
       new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_ANGLE));
@@ -1128,24 +1134,6 @@ ConstraintWrapperPtr createConstraintTangent(
 
 
 
-void adjustAngle(ConstraintWrapperPtr theConstraint)
-{
-  BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
-
-  std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aConstraint =
-    std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(theConstraint);
-
-  bool isReversed[2] = {
-    aConstraint->baseConstraint()->boolean(
-        SketchPlugin_ConstraintAngle::ANGLE_REVERSED_FIRST_LINE_ID())->value(),
-    aConstraint->baseConstraint()->boolean(
-        SketchPlugin_ConstraintAngle::ANGLE_REVERSED_SECOND_LINE_ID())->value()
-  };
-
-  if (isReversed[0] != isReversed[1])
-    aConstraint->setValue(aConstraint->value() - 180.0);
-}
-
 void makeMirrorPoints(EntityWrapperPtr theOriginal,
                       EntityWrapperPtr theMirrored,
                       EntityWrapperPtr theMirrorLine)
index 0a271ffab432c73727f4aaa9f7ed3baf65fd5d2c..9c0dfde11b63ef903a5947aac3d442fb9a266b78 100644 (file)
@@ -16,7 +16,8 @@ PlaneGCSSolver_ParameterWrapper::PlaneGCSSolver_ParameterWrapper(double *const t
 
 PlaneGCSSolver_ParameterWrapper::~PlaneGCSSolver_ParameterWrapper()
 {
-  delete myValue;
+  if (!myProcessing)
+    delete myValue;
 }
 
 void PlaneGCSSolver_ParameterWrapper::setValue(double theValue)
index be98e05d9b2cb58e1e5d4193c5cbee9d4b78003b..9aa18c59211b69bdfe0414f548a6eaf3dc9d18ef 100644 (file)
@@ -15,9 +15,7 @@ PlaneGCSSolver_Solver::~PlaneGCSSolver_Solver()
 
 void PlaneGCSSolver_Solver::clear()
 {
-  std::set<GCS::Constraint*>::const_iterator anIt = myConstraints.begin();
-  for (; anIt != myConstraints.end(); ++anIt)
-    myEquationSystem.removeConstraint(*anIt);
+  myEquationSystem.clear();
   myConstraints.clear();
   myParameters.clear();
 }
@@ -56,15 +54,41 @@ SketchSolver_SolveStatus PlaneGCSSolver_Solver::solve()
     return STATUS_INCONSISTENT;
 
   Events_LongOp::start(this);
-  GCS::SolveStatus aResult = (GCS::SolveStatus)myEquationSystem.solve(myParameters);
+  GCS::SolveStatus aResult = GCS::Success;
+  // if there is a constraint with all attributes constant, set fail status
+  GCS::SET_pD aParameters;
+  aParameters.insert(myParameters.begin(), myParameters.end());
+  std::set<GCS::Constraint*>::const_iterator aConstrIt = myConstraints.begin();
+  for (; aConstrIt != myConstraints.end(); ++aConstrIt) {
+    GCS::VEC_pD aParams = (*aConstrIt)->params();
+    GCS::VEC_pD::const_iterator aPIt = aParams.begin();
+    for (; aPIt != aParams.end(); ++aPIt)
+      if (aParameters.find(*aPIt) != aParameters.end())
+        break;
+    if (aPIt == aParams.end()) {
+      aResult = GCS::Failed;
+    }
+  }
+  // solve equations
+  if (aResult == GCS::Success)
+    aResult = (GCS::SolveStatus)myEquationSystem.solve(myParameters);
+  if (aResult == GCS::Success) {
+    // additionally check redundant constraints
+    GCS::VEC_I aRedundantID;
+    myEquationSystem.getRedundant(aRedundantID);
+    if (!aRedundantID.empty())
+      aResult = GCS::Failed;
+  }
   Events_LongOp::end(this);
 
   SketchSolver_SolveStatus aStatus;
   if (aResult == GCS::Success) {
     myEquationSystem.applySolution();
     aStatus = STATUS_OK;
-  } else
+  } else {
+    undo();
     aStatus = STATUS_FAILED;
+  }
 
   return aStatus;
 }
index 91c4d338151617da543dc93b4130af2146514439..4238120082f85a4d7efb4e646f40bb1b69f17070 100644 (file)
@@ -212,6 +212,10 @@ bool PlaneGCSSolver_Storage::remove(ConstraintWrapperPtr theConstraint)
     std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(theConstraint);
 
   bool isFullyRemoved = true;
+  // remove point-point coincidence
+  if (aConstraint->type() == CONSTRAINT_PT_PT_COINCIDENT)
+    isFullyRemoved = removeCoincidence(theConstraint) && isFullyRemoved;
+  // remove sub-entities
   const std::list<EntityWrapperPtr>& aSubs = aConstraint->entities();
   std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
   for (; aSIt != aSubs.end(); ++ aSIt)
@@ -234,13 +238,21 @@ bool PlaneGCSSolver_Storage::remove(ConstraintWrapperPtr theConstraint)
 
 bool PlaneGCSSolver_Storage::remove(EntityWrapperPtr theEntity)
 {
-  if ((theEntity->baseAttribute() && isUsed(theEntity->baseAttribute())) ||
-      (theEntity->baseFeature() && isUsed(theEntity->baseFeature())))
-    return false;
-
   bool isFullyRemoved = SketchSolver_Storage::remove(theEntity);
-  if (isFullyRemoved && theEntity->id() == myEntityLastID)
-    --myEntityLastID;
+  if (isFullyRemoved) {
+    if (theEntity->type() == ENTITY_ARC) {
+      // remove arc additional constraints
+      std::map<EntityWrapperPtr, std::vector<GCSConstraintPtr> >::iterator
+          aFound = myArcConstraintMap.find(theEntity);
+      if (aFound != myArcConstraintMap.end()) {
+        myRemovedConstraints.insert(myRemovedConstraints.end(),
+            aFound->second.begin(), aFound->second.end());
+        myArcConstraintMap.erase(aFound);
+      }
+    }
+    if (theEntity->id() == myEntityLastID)
+      --myEntityLastID;
+  }
   return isFullyRemoved;
 }
 
@@ -257,6 +269,7 @@ bool PlaneGCSSolver_Storage::remove(ParameterWrapperPtr theParameter)
     if (anIt != myParameters.end()) {
       myParameters.erase(anIt);
       setNeedToResolve(true);
+      aParam->setProcessed(false);
     }
     else {
       for (anIt = myConst.begin(); anIt != myConst.end(); ++anIt)
@@ -265,10 +278,10 @@ bool PlaneGCSSolver_Storage::remove(ParameterWrapperPtr theParameter)
       if (anIt != myConst.end()) {
         myConst.erase(anIt);
         setNeedToResolve(true);
+        aParam->setProcessed(false);
       }
     }
   }
-  aParam->setProcessed(false);
   return true;
 }
 
@@ -361,6 +374,10 @@ void PlaneGCSSolver_Storage::verifyFixed()
 
 void PlaneGCSSolver_Storage::processArc(const EntityWrapperPtr& theArc)
 {
+  // no need to constraint a fixed arc
+  if (theArc->group() == GID_OUTOFGROUP)
+    return;
+
   // Calculate additional parameters necessary for PlaneGCS
   const std::list<EntityWrapperPtr>& aSubs = theArc->subEntities();
   std::list<EntityWrapperPtr>::const_iterator aSubIt = aSubs.begin();
@@ -527,6 +544,7 @@ void PlaneGCSSolver_Storage::initializeSolver(SolverPtr theSolver)
       std::dynamic_pointer_cast<PlaneGCSSolver_Solver>(theSolver);
   if (!aSolver)
     return;
+  aSolver->clear();
 
   if (myExistArc)
     processArcs();
index 826a429af129d5b796ec0b7c9d1fc1b19f1c2aa5..545fa468716157c323ccdbf7cbc92b6762b6666b 100644 (file)
@@ -1,5 +1,10 @@
 #include <SketchSolver_ConstraintMiddle.h>
 
+#include <SketchSolver_Builder.h>
+#include <SketchSolver_Manager.h>
+
+#include <GeomAPI_XY.h>
+
 SketchSolver_ConstraintMiddle::SketchSolver_ConstraintMiddle(ConstraintPtr theConstraint)
   : SketchSolver_Constraint(theConstraint)
 {
index 0bccf4f0495ae3547c4d0c4d7dac714ec3d7d940..4173be33b95136b36085828c58ac1c1a0ea4c583 100644 (file)
@@ -50,6 +50,12 @@ void SketchSolver_ConstraintMirror::getAttributes(
     }
   }
 
+  // Mirrored entities are placed out-of-group by default, due to they are copies.
+  // Place them into current group manually.
+  std::vector<EntityWrapperPtr>::iterator aMirIt = theMirrorEntities.begin();
+  for (; aMirIt != theMirrorEntities.end(); ++aMirIt)
+    (*aMirIt)->setGroup(myGroupID);
+
   if (theBaseEntities.size() > theMirrorEntities.size())
     myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
 }
@@ -105,24 +111,18 @@ void SketchSolver_ConstraintMirror::process()
     aMirConstrList.insert(aMirConstrList.end(), aNewConstraints.begin(), aNewConstraints.end());
   }
 
-  myStorage->addConstraint(myBaseConstraint, aMirConstrList);
   // update mirrored features to be in the current group
   for (aMIt = aMirrorList.begin(); aMIt != aMirrorList.end(); ++aMIt)
     myStorage->update((*aMIt)->baseFeature(), myGroupID);
+  myStorage->addConstraint(myBaseConstraint, aMirConstrList);
 }
 
 
 void SketchSolver_ConstraintMirror::update()
 {
   cleanErrorMsg();
-  AttributeRefListPtr aMirroredRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
-    myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_C()));
-  if (aMirroredRefList->size() != myNumberOfObjects) {
-    remove();
-    process();
-    return;
-  }
-  adjustConstraint();
+  remove();
+  process();
 }
 
 void SketchSolver_ConstraintMirror::adjustConstraint()
index 0471488f38ce6d095e124209d8a031cc7c36ffc2..144adbfe3e40b3b4d2c42ec9f5f3a9f1af4a413f 100644 (file)
@@ -328,7 +328,8 @@ bool SketchSolver_Group::resolveConstraints()
 {
   bool aResolved = false;
   bool isGroupEmpty = isEmpty() && myStorage->isEmpty();
-  if (myStorage->isNeedToResolve() && !isGroupEmpty) {
+  if (myStorage->isNeedToResolve() &&
+      (!isGroupEmpty || !myConflictingConstraints.empty() || myPrevResult == STATUS_FAILED)) {
     if (!mySketchSolver)
       mySketchSolver = SketchSolver_Manager::instance()->builder()->createSolver();
 
@@ -341,7 +342,7 @@ bool SketchSolver_Group::resolveConstraints()
     try {
       if (myStorage->hasDuplicatedConstraint())
         aResult = STATUS_INCONSISTENT;
-      else {
+      else if (!isGroupEmpty) {
         // To avoid overconstraint situation, we will remove temporary constraints one-by-one
         // and try to find the case without overconstraint
         bool isLastChance = false;
@@ -376,10 +377,11 @@ bool SketchSolver_Group::resolveConstraints()
       updateMultiConstraints(myConstraints);
       if (myPrevResult != STATUS_OK || myPrevResult == STATUS_UNKNOWN) {
         getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())->setValue("");
-        // the error message should be changed before sending the message
-        sendMessage(EVENT_SOLVER_REPAIRED, myConflictingConstraints);
+        std::set<ObjectPtr> aConflicting = myConflictingConstraints;
         myConflictingConstraints.clear();
         myPrevResult = STATUS_OK;
+        // the error message should be changed before sending the message
+        sendMessage(EVENT_SOLVER_REPAIRED, aConflicting);
       }
     } else {
       mySketchSolver->undo();
index 4f16f7cd7ebcb594274c1c7c44a5d4042c788071..350ef59abd044764b7c81e6d2c571f9b3e9cc366 100644 (file)
@@ -195,8 +195,9 @@ void SketchSolver_Manager::processEvent(
         }
         if (!(*aGroupIter)->isConsistent()) {  // some constraints were removed, try to split the group
           (*aGroupIter)->splitGroup(aSeparatedGroups);
-          //if (!(*aGroupIter)->getWorkplane()->string(
-          //    SketchPlugin_Sketch::SOLVER_ERROR())->value().empty())
+          if (!(*aGroupIter)->getWorkplane()->string(
+              SketchPlugin_Sketch::SOLVER_ERROR())->value().empty() ||
+              (*aGroupIter)->isFailed())
             aGroupsToResolve.push_back(*aGroupIter);
         }
         aGroupIter++;
@@ -490,7 +491,15 @@ void SketchSolver_Manager::degreesOfFreedom()
   std::list<SketchSolver_Group*>::const_iterator aGroupIt = myGroups.begin();
   for (; aGroupIt != myGroups.end(); ++aGroupIt) {
     CompositeFeaturePtr aSketch = (*aGroupIt)->getWorkplane();
-    if (!aSketch->data()->isValid()) {
+    bool isSketchValid = aSketch->data() && aSketch->data()->isValid();
+
+    if (isSketchValid) {
+      std::shared_ptr<GeomDataAPI_Dir> aNormal =
+          std::dynamic_pointer_cast<GeomDataAPI_Dir>(aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
+      isSketchValid = aNormal && aNormal->isInitialized();
+    }
+
+    if (!isSketchValid) {
       myDoF.erase(aSketch);
       continue;
     }
index 8ef9d9c0ed231236845be9a1f3991340e022fb08..a3b68b0872c4f846313ced95e31a8b17f0e1a190 100644 (file)
@@ -15,6 +15,7 @@
 #include <SketchPlugin_Line.h>
 #include <SketchPlugin_Point.h>
 #include <SketchPlugin_IntersectionPoint.h>
+#include <SketchPlugin_ConstraintCoincidence.h>
 #include <SketchPlugin_ConstraintMirror.h>
 #include <SketchPlugin_ConstraintRigid.h>
 
@@ -463,6 +464,122 @@ bool SketchSolver_Storage::removeEntity(AttributePtr theAttribute)
 }
 
 
+bool SketchSolver_Storage::removeCoincidence(ConstraintWrapperPtr theConstraint)
+{
+  std::list<EntityWrapperPtr> aPoints = theConstraint->entities();
+  std::list<EntityWrapperPtr>::const_iterator aPIt;
+
+  CoincidentPointsMap::iterator aPtPtIt = myCoincidentPoints.begin();
+  for (; aPtPtIt != myCoincidentPoints.end(); ++aPtPtIt) {
+    for (aPIt = aPoints.begin(); aPIt != aPoints.end(); ++aPIt)
+      if (aPtPtIt->first == *aPIt ||
+          aPtPtIt->second.find(*aPIt) != aPtPtIt->second.end())
+        break;
+    if (aPIt != aPoints.end())
+      break;
+  }
+
+  if (aPtPtIt == myCoincidentPoints.end())
+    return true; // already removed
+
+  // Create new copies of coincident points
+  BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
+  std::list<EntityWrapperPtr> aNewPoints;
+  for (aPIt = aPoints.begin(); aPIt != aPoints.end(); ++aPIt)
+    aNewPoints.push_back(aBuilder->createAttribute(
+        (*aPIt)->baseAttribute(), myGroupID, mySketchID));
+
+  // Find all points fallen out of group of coincident points
+  std::map<EntityWrapperPtr, EntityWrapperPtr> aNotCoinc;
+  aNotCoinc[aPtPtIt->first] = EntityWrapperPtr();
+  std::set<EntityWrapperPtr>::const_iterator aTempIt = aPtPtIt->second.begin();
+  for (; aTempIt != aPtPtIt->second.end(); ++aTempIt)
+    aNotCoinc[*aTempIt] = EntityWrapperPtr();
+  std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::iterator
+      aConstrIt = myConstraintMap.begin();
+  for (; aConstrIt != myConstraintMap.end(); ++aConstrIt)
+    if (aConstrIt->first->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
+      AttributeRefAttrPtr aRefAttrA = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+          aConstrIt->first->attribute(SketchPlugin_Constraint::ENTITY_A()));
+      AttributeRefAttrPtr aRefAttrB = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+          aConstrIt->first->attribute(SketchPlugin_Constraint::ENTITY_B()));
+      AttributePtr anAttrA, anAttrB;
+      if (aConstrIt->first->data()->isValid()) {
+        if (!aRefAttrA || !aRefAttrB || aRefAttrA->isObject() || aRefAttrB->isObject())
+          continue;
+        anAttrA = aRefAttrA->attr();
+        anAttrB = aRefAttrB->attr();
+      } else {
+        // obtain attributes from the constraint wrapper
+        ConstraintWrapperPtr aWrapper = aConstrIt->second.front();
+        anAttrA = aWrapper->entities().front()->baseAttribute();
+        anAttrB = aWrapper->entities().back()->baseAttribute();
+      }
+      std::map<AttributePtr, EntityWrapperPtr>::iterator
+          aFound = myAttributeMap.find(anAttrA);
+      if (aFound != myAttributeMap.end())
+        aNotCoinc.erase(aFound->second);
+      aFound = myAttributeMap.find(anAttrB);
+      if (aFound != myAttributeMap.end())
+        aNotCoinc.erase(aFound->second);
+    }
+  if (aNotCoinc.empty())
+    return false;
+  std::list<EntityWrapperPtr>::const_iterator aNewPIt;
+  for (aPIt = aPoints.begin(), aNewPIt = aNewPoints.begin();
+       aPIt != aPoints.end(); ++aPIt, ++aNewPIt) {
+    if (aNotCoinc.find(*aPIt) != aNotCoinc.end())
+      aNotCoinc[*aPIt] = *aNewPIt;
+  }
+
+  // Find all features and constraints uses coincident points
+  std::map<EntityWrapperPtr, EntityWrapperPtr>::iterator aNotCIt;
+  std::set<EntityWrapperPtr> anUpdFeatures;
+  std::map<FeaturePtr, EntityWrapperPtr>::iterator aFIt = myFeatureMap.begin();
+  for (; aFIt != myFeatureMap.end(); ++aFIt) {
+    if (!aFIt->second)
+      continue; // avoid not completed arcs
+    for (aNotCIt = aNotCoinc.begin(); aNotCIt != aNotCoinc.end(); ++aNotCIt) {
+      if (!aNotCIt->second || !aFIt->second->isUsed(aNotCIt->first->baseAttribute()))
+        continue;
+      std::list<EntityWrapperPtr> aSubs = aFIt->second->subEntities();
+      std::list<EntityWrapperPtr>::iterator aSIt = aSubs.begin();
+      bool isUpd = false;
+      for (; aSIt != aSubs.end(); ++aSIt)
+        if (*aSIt == aNotCIt->first) {
+          *aSIt = aNotCIt->second;
+          isUpd = true;
+        }
+      if (isUpd) {
+        aFIt->second->setSubEntities(aSubs);
+        anUpdFeatures.insert(aFIt->second);
+      }
+    }
+  }
+  // update features
+  std::set<EntityWrapperPtr>::iterator anUpdIt = anUpdFeatures.begin();
+  for (; anUpdIt != anUpdFeatures.end(); ++anUpdIt)
+    update(EntityWrapperPtr(*anUpdIt));
+
+  // remove not coincident points
+  for (aNotCIt = aNotCoinc.begin(); aNotCIt != aNotCoinc.end(); ++aNotCIt) {
+    if (aPtPtIt->second.size() <= 1) {
+      myCoincidentPoints.erase(aPtPtIt);
+      break;
+    }
+    if (aPtPtIt->first == aNotCIt->first) {
+      std::set<EntityWrapperPtr> aSlaves = aPtPtIt->second;
+      EntityWrapperPtr aNewMaster = *aSlaves.begin();
+      aSlaves.erase(aSlaves.begin());
+      myCoincidentPoints.erase(aPtPtIt);
+      myCoincidentPoints[aNewMaster] = aSlaves;
+      aPtPtIt = myCoincidentPoints.find(aNewMaster);
+    } else
+      aPtPtIt->second.erase(aNotCIt->first);
+  }
+  return true;
+}
+
 bool SketchSolver_Storage::remove(ConstraintWrapperPtr theConstraint)
 {
   bool isFullyRemoved = true;
@@ -485,8 +602,13 @@ bool SketchSolver_Storage::remove(EntityWrapperPtr theEntity)
     FeaturePtr aBaseFeature = (*anEntIt)->baseFeature();
     if (aBaseFeature)
       isFullyRemoved = SketchSolver_Storage::removeEntity(aBaseFeature) && isFullyRemoved;
-    else
-      isFullyRemoved = SketchSolver_Storage::removeEntity((*anEntIt)->baseAttribute()) && isFullyRemoved;
+    else {
+      AttributePtr aBaseAttr = (*anEntIt)->baseAttribute();
+      if (aBaseAttr)
+        isFullyRemoved = SketchSolver_Storage::removeEntity(aBaseAttr) && isFullyRemoved;
+      else
+        remove(*anEntIt);
+    }
   }
 
   std::list<ParameterWrapperPtr>::const_iterator aParIt = theEntity->parameters().begin();
index 454044c8826f42fea46eee82a5c57d6a89751558..9e2eae02fbf9f94a4b489bed441941996d744dc9 100644 (file)
@@ -37,6 +37,7 @@ private:
 public:
   SketchSolver_Storage(const GroupID& theGroup)
     : myGroupID(theGroup),
+      mySketchID(EID_UNKNOWN),
       myNeedToResolve(false),
       myEventsBlocked(false),
       myExistArc(false)
@@ -189,6 +190,9 @@ protected:
   /// \return \c true if the parameter has been removed
   virtual bool remove(ParameterWrapperPtr theParameter) = 0;
 
+  /// \brief Remove point-point coincidence
+  SKETCHSOLVER_EXPORT bool removeCoincidence(ConstraintWrapperPtr theConstraint);
+
   /// \brief Update the group for the given entity, its sub-entities and parameters
   virtual void changeGroup(EntityWrapperPtr theEntity, const GroupID& theGroup) = 0;
   /// \brief Update the group for the given parameter
@@ -207,6 +211,7 @@ private:
   EntityWrapperPtr getNormal() const;
 
 protected:
+  EntityID mySketchID;     ///< identifier of the sketch
   GroupID myGroupID;       ///< identifier of the group, this storage belongs to
   bool    myNeedToResolve; ///< parameters are changed and group needs to be resolved
   bool    myEventsBlocked; ///< indicates that features do not send events
index 5a27467d98e9d414ba89b476740a3cbfc0996189..805e458dd301fbbb755f47052317e27714872ff5 100644 (file)
@@ -21,7 +21,7 @@
 #include <ModelAPI_AttributeDouble.h>
 #include <ModelAPI_AttributeRefAttr.h>
 #include <SketchPlugin_Arc.h>
-#include <SketchPlugin_ConstraintCoincidence.h>
+#include <SketchPlugin_ConstraintMiddle.h>
 
 /** \brief Search the entity/parameter with specified ID in the list of elements
  *  \param[in] theEntityID unique ID of the element
@@ -76,8 +76,12 @@ bool SolveSpaceSolver_Storage::update(ConstraintWrapperPtr theConstraint)
   std::list<EntityWrapperPtr>::iterator anIt = anEntities.begin();
   for (; anIt != anEntities.end(); ++anIt) {
     isUpdated = update(*anIt) || isUpdated;
-    // do not update constrained entities for Multi constraints
-    if (aSlvsConstr.type == SLVS_C_MULTI_ROTATION || aSlvsConstr.type == SLVS_C_MULTI_TRANSLATION)
+    // do not update constrained entities for Multi constraints,
+    // and for middle point constraint translated to equal lines
+    ConstraintPtr aBaseConstraint = theConstraint->baseConstraint();
+    if (aSlvsConstr.type == SLVS_C_MULTI_ROTATION || aSlvsConstr.type == SLVS_C_MULTI_TRANSLATION ||
+       (aBaseConstraint && aBaseConstraint->getKind() == SketchPlugin_ConstraintMiddle::ID() &&
+        aSlvsConstr.type != SLVS_C_AT_MIDPOINT))
       continue;
 
     Slvs_hEntity anID = (Slvs_hEntity)(*anIt)->id();
@@ -215,7 +219,8 @@ bool SolveSpaceSolver_Storage::update(ParameterWrapperPtr theParameter)
 
 void SolveSpaceSolver_Storage::storeWorkplane(EntityWrapperPtr theSketch)
 {
-  myWorkplaneID = (Slvs_hEntity)theSketch->id();
+  mySketchID = theSketch->id();
+  myWorkplaneID = (Slvs_hEntity)mySketchID;
 
   // Update sub-entities of the sketch
   std::list<EntityWrapperPtr> aSubEntities = theSketch->subEntities();
@@ -244,13 +249,12 @@ void SolveSpaceSolver_Storage::changeGroup(EntityWrapperPtr theEntity, const Gro
   for (; aSIt != aSubs.end(); ++aSIt)
     changeGroup(*aSIt, theGroup);
 
-  if (theEntity->group() != theGroup) {
-    theEntity->setGroup(theGroup);
-    int aPos = Search((Slvs_hEntity)theEntity->id(), myEntities);
-    if (aPos >= 0 && aPos < (int)myEntities.size()) {
-      myEntities[aPos].group = (Slvs_hGroup)theGroup;
+  theEntity->setGroup(theGroup);
+  int aPos = Search((Slvs_hEntity)theEntity->id(), myEntities);
+  if (aPos >= 0 && aPos < (int)myEntities.size()) {
+    if (myEntities[aPos].group != (Slvs_hGroup)theGroup)
       setNeedToResolve(true);
-    }
+    myEntities[aPos].group = (Slvs_hGroup)theGroup;
   }
 }
 
@@ -889,122 +893,6 @@ void SolveSpaceSolver_Storage::initializeSolver(SolverPtr theSolver)
 }
 
 
-bool SolveSpaceSolver_Storage::removeCoincidence(ConstraintWrapperPtr theConstraint)
-{
-  std::list<EntityWrapperPtr> aPoints = theConstraint->entities();
-  std::list<EntityWrapperPtr>::const_iterator aPIt;
-
-  CoincidentPointsMap::iterator aPtPtIt = myCoincidentPoints.begin();
-  for (; aPtPtIt != myCoincidentPoints.end(); ++aPtPtIt) {
-    for (aPIt = aPoints.begin(); aPIt != aPoints.end(); ++aPIt)
-      if (aPtPtIt->first == *aPIt ||
-          aPtPtIt->second.find(*aPIt) != aPtPtIt->second.end())
-        break;
-    if (aPIt != aPoints.end())
-      break;
-  }
-
-  if (aPtPtIt == myCoincidentPoints.end())
-    return true; // already removed
-
-  // Create new copies of coincident points
-  BuilderPtr aBuilder = SolveSpaceSolver_Builder::getInstance();
-  std::list<EntityWrapperPtr> aNewPoints;
-  for (aPIt = aPoints.begin(); aPIt != aPoints.end(); ++aPIt)
-    aNewPoints.push_back(aBuilder->createAttribute(
-        (*aPIt)->baseAttribute(), myGroupID, myWorkplaneID));
-
-  // Find all points fallen out of group of coincident points
-  std::map<EntityWrapperPtr, EntityWrapperPtr> aNotCoinc;
-  aNotCoinc[aPtPtIt->first] = EntityWrapperPtr();
-  std::set<EntityWrapperPtr>::const_iterator aTempIt = aPtPtIt->second.begin();
-  for (; aTempIt != aPtPtIt->second.end(); ++aTempIt)
-    aNotCoinc[*aTempIt] = EntityWrapperPtr();
-  std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::iterator
-      aConstrIt = myConstraintMap.begin();
-  for (; aConstrIt != myConstraintMap.end(); ++aConstrIt)
-    if (aConstrIt->first->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
-      AttributeRefAttrPtr aRefAttrA = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
-          aConstrIt->first->attribute(SketchPlugin_Constraint::ENTITY_A()));
-      AttributeRefAttrPtr aRefAttrB = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
-          aConstrIt->first->attribute(SketchPlugin_Constraint::ENTITY_B()));
-      AttributePtr anAttrA, anAttrB;
-      if (aConstrIt->first->data()->isValid()) {
-        if (!aRefAttrA || !aRefAttrB || aRefAttrA->isObject() || aRefAttrB->isObject())
-          continue;
-        anAttrA = aRefAttrA->attr();
-        anAttrB = aRefAttrB->attr();
-      } else {
-        // obtain attributes from the constraint wrapper
-        ConstraintWrapperPtr aWrapper = aConstrIt->second.front();
-        anAttrA = aWrapper->entities().front()->baseAttribute();
-        anAttrB = aWrapper->entities().back()->baseAttribute();
-      }
-      std::map<AttributePtr, EntityWrapperPtr>::iterator
-          aFound = myAttributeMap.find(anAttrA);
-      if (aFound != myAttributeMap.end())
-        aNotCoinc.erase(aFound->second);
-      aFound = myAttributeMap.find(anAttrB);
-      if (aFound != myAttributeMap.end())
-        aNotCoinc.erase(aFound->second);
-    }
-  if (aNotCoinc.empty())
-    return false;
-  std::list<EntityWrapperPtr>::const_iterator aNewPIt;
-  for (aPIt = aPoints.begin(), aNewPIt = aNewPoints.begin();
-       aPIt != aPoints.end(); ++aPIt, ++aNewPIt) {
-    if (aNotCoinc.find(*aPIt) != aNotCoinc.end())
-      aNotCoinc[*aPIt] = *aNewPIt;
-  }
-
-  // Find all features and constraints uses coincident points
-  std::map<EntityWrapperPtr, EntityWrapperPtr>::iterator aNotCIt;
-  std::set<EntityWrapperPtr> anUpdFeatures;
-  std::map<FeaturePtr, EntityWrapperPtr>::iterator aFIt = myFeatureMap.begin();
-  for (; aFIt != myFeatureMap.end(); ++aFIt) {
-    if (!aFIt->second)
-      continue; // avoid not completed arcs
-    for (aNotCIt = aNotCoinc.begin(); aNotCIt != aNotCoinc.end(); ++aNotCIt) {
-      if (!aNotCIt->second || !aFIt->second->isUsed(aNotCIt->first->baseAttribute()))
-        continue;
-      std::list<EntityWrapperPtr> aSubs = aFIt->second->subEntities();
-      std::list<EntityWrapperPtr>::iterator aSIt = aSubs.begin();
-      bool isUpd = false;
-      for (; aSIt != aSubs.end(); ++aSIt)
-        if (*aSIt == aNotCIt->first) {
-          *aSIt = aNotCIt->second;
-          isUpd = true;
-        }
-      if (isUpd) {
-        aFIt->second->setSubEntities(aSubs);
-        anUpdFeatures.insert(aFIt->second);
-      }
-    }
-  }
-  // update features
-  std::set<EntityWrapperPtr>::iterator anUpdIt = anUpdFeatures.begin();
-  for (; anUpdIt != anUpdFeatures.end(); ++anUpdIt)
-    update(EntityWrapperPtr(*anUpdIt));
-
-  // remove not coincident points
-  for (aNotCIt = aNotCoinc.begin(); aNotCIt != aNotCoinc.end(); ++aNotCIt) {
-    if (aPtPtIt->second.size() <= 1) {
-      myCoincidentPoints.erase(aPtPtIt);
-      break;
-    }
-    if (aPtPtIt->first == aNotCIt->first) {
-      std::set<EntityWrapperPtr> aSlaves = aPtPtIt->second;
-      EntityWrapperPtr aNewMaster = *aSlaves.begin();
-      aSlaves.erase(aSlaves.begin());
-      myCoincidentPoints.erase(aPtPtIt);
-      myCoincidentPoints[aNewMaster] = aSlaves;
-      aPtPtIt = myCoincidentPoints.find(aNewMaster);
-    } else
-      aPtPtIt->second.erase(aNotCIt->first);
-  }
-  return true;
-}
-
 bool SolveSpaceSolver_Storage::remove(ConstraintWrapperPtr theConstraint)
 {
   std::shared_ptr<SolveSpaceSolver_ConstraintWrapper> aConstraint =
index 4de890e9f17c22463b780401fabad9db34502d1b..24cb9f323113eaae7a39de3e27f2443ff0452dfb 100644 (file)
@@ -64,9 +64,6 @@ protected:
   /// \return \c true if the parameter has been removed
   virtual bool remove(ParameterWrapperPtr theParameter);
 
-  /// \brief Remove point-point coincidence
-  bool removeCoincidence(ConstraintWrapperPtr theConstraint);
-
   /// \brief Update the group for the given entity, its sub-entities and parameters
   virtual void changeGroup(EntityWrapperPtr theEntity, const GroupID& theGroup);
   /// \brief Update the group for the given parameter
index a17dc49371c44205dedb472f2a19b7f6b403164b..cfc15dbfc6c06cb1dcc2c4cc9be00870963739e6 100644 (file)
@@ -72,8 +72,14 @@ namespace SketcherPrs_Tools {
     /// Selection mode for line of dimension
     Sel_Dimension_Line,
 
-    /// Selection mode foe text of dimension
-    Sel_Dimension_Text
+    /// Selection mode for text of dimension
+    Sel_Dimension_Text,
+
+    /// Selectiom mode for faces selection on sketch
+    Sel_Sketch_Face,
+
+    /// Selectiom mode for wires selection on sketch
+    Sel_Sketch_Wire
   };
 
   /// Type of angle
index 321c9641e4d84e8d369a75a7001078984280b8c6..53399babb70db7716b96b24eb39dc856f81a2ddb 100644 (file)
@@ -61,6 +61,9 @@ Q_OBJECT
   /// \return a list of group names
   QStringList actionObjectGroups(const QString& theName);
 
+  /// Updates menu for object browser
+  void updateObjectBrowserMenu();
+
   /// Updates menu for viewer
   void updateViewerMenu();
 
@@ -103,9 +106,6 @@ signals:
 
   void addFeatures(QMenu* theMenu) const;
 
-  /// Updates menu for object browser
-  void updateObjectBrowserMenu();
-
   /// Creates menu for object browser
   void buildObjBrowserMenu();
 
index cbba9c920638ff322be328498fe0b343ff452f78..7b66c2bffe1991b8d0ec0ba93a151c4dcc1b11ca 100644 (file)
@@ -726,6 +726,10 @@ Qt::ItemFlags XGUI_DataModel::flags(const QModelIndex& theIndex) const
     // An object
     if (aObj->isDisabled()) 
       return theIndex.column() == 1? Qt::ItemIsSelectable : aNullFlag;
+
+    if (aSession->moduleDocument() != aObj->document())
+      if (aActiveDoc != aObj->document())
+        return theIndex.column() == 1? Qt::ItemIsSelectable : aNullFlag;
     
     bool isCompositeSub = false;
     // An object which is sub-object of a composite object can not be accessible in column 1
index 4c41e5243c7a7f1dbe4f765ee0f72997a5cd4580..851f977a1036ddbe49a6b1016900b789321c0b87 100644 (file)
@@ -149,6 +149,18 @@ bool XGUI_Displayer::display(ObjectPtr theObject, bool theUpdateViewer)
     bool isShading = false;
     if (aPrs.get() != NULL) {
       anAIS = aPrs->getAISObject(anAIS);
+      if (anAIS.get()) {
+        // correct deviation coefficient for 
+        Handle(AIS_InteractiveObject) anAISPrs = anAIS->impl<Handle(AIS_InteractiveObject)>();
+        if (!anAISPrs.IsNull()) {
+          Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast(anAISPrs);
+          if (!aShapePrs.IsNull()) {
+            TopoDS_Shape aShape = aShapePrs->Shape();
+            if (!aShape.IsNull())
+              ModuleBase_Tools::setDefaultDeviationCoefficient(aShape, anAISPrs->Attributes());
+          }
+        }
+      }
     } else {
       ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
       if (aResult.get() != NULL) {
@@ -260,6 +272,7 @@ bool XGUI_Displayer::erase(ObjectPtr theObject, const bool theUpdateViewer)
     if (!anAIS.IsNull()) {
       emit beforeObjectErase(theObject, anObject);
       aContext->Remove(anAIS, false/*update viewer*/);
+      ModuleBase_Tools::selectionInfo(aContext, "XGUI_Displayer::erase -- Remove");
       aErased = true;
     }
   }
@@ -346,6 +359,8 @@ bool XGUI_Displayer::redisplay(ObjectPtr theObject, bool theUpdateViewer)
         aContext->Deactivate(aAISIO, 0);
 #endif
 
+      ModuleBase_Tools::selectionInfo(aContext, "XGUI_Displayer::redisplay -- Redisplay");
+
       if (aNeedToRestoreSelection)
         myWorkshop->module()->restoreSelection();
 
@@ -390,6 +405,7 @@ void XGUI_Displayer::deactivate(ObjectPtr theObject, const bool theUpdateViewer)
     deactivateAIS(anAIS);
     // the selection from the previous activation modes should be cleared manually (#26172)
     aContext->LocalContext()->ClearOutdatedSelection(anAIS, true);
+    ModuleBase_Tools::selectionInfo(aContext, "XGUI_Displayer::deactivate -- ClearOutdatedSelection");
     if (theUpdateViewer)
       updateViewer();
   }
@@ -631,7 +647,7 @@ void XGUI_Displayer::setSelected(const  QList<ModuleBase_ViewerPrsPtr>& theValue
     }
     if (!aShapesToBeSelected.IsEmpty())
       XGUI_Displayer::AddOrRemoveSelectedShapes(aContext, aShapesToBeSelected);
-  } else {
+  } else { // it seems the next code is obsolete as the context is always opened in SHAPER
     aContext->UnhilightCurrents(false);
     aContext->ClearCurrents(false);
     foreach (ModuleBase_ViewerPrsPtr aPrs, theValues) {
@@ -645,6 +661,7 @@ void XGUI_Displayer::setSelected(const  QList<ModuleBase_ViewerPrsPtr>& theValue
       }
     }
   }
+  ModuleBase_Tools::selectionInfo(aContext, "XGUI_Displayer::setSelected -- AddOrRemoveSelected/UnhilightCurrents(no local context)");
   if (theUpdateViewer)
     updateViewer();
 }
@@ -676,6 +693,7 @@ bool XGUI_Displayer::eraseAll(const bool theUpdateViewer)
     if (theUpdateViewer)
       updateViewer();
   }
+  ModuleBase_Tools::selectionInfo(aContext, "XGUI_Displayer::eraseAll -- Remove");
   myResult2AISObjectMap.clear();
 #ifdef DEBUG_DISPLAY
   qDebug("eraseAll");
@@ -690,6 +708,7 @@ void deactivateObject(Handle(AIS_InteractiveContext) theContext,
 {
   if (!theObject.IsNull()) {
     theContext->Deactivate(theObject);
+    ModuleBase_Tools::selectionInfo(theContext, "XGUI_Displayer::deactivateObject -- Deactivate");
     //if (theClear) {
       //theObject->ClearSelected();
       //  theContext->LocalContext()->ClearOutdatedSelection(theObject, true);
@@ -887,11 +906,12 @@ void XGUI_Displayer::activateAIS(const Handle(AIS_InteractiveObject)& theIO,
   if (!aContext.IsNull()) {
     if (myWorkshop->module()) {
       int aMode = (theMode > 8)? theMode : AIS_Shape::SelectionType(theMode);
-      if (myWorkshop->module()->canActivateSelectionMode(theIO, aMode))
-        aContext->Activate(theIO, theMode, false);
+      aContext->Activate(theIO, theMode, false);
     } else
       aContext->Activate(theIO, theMode, false);
 
+    ModuleBase_Tools::selectionInfo(aContext, "XGUI_Displayer::activateAIS -- Activate");
+
 #ifdef DEBUG_ACTIVATE_AIS
     ObjectPtr anObject = getObject(theIO);
     anInfo.append(ModuleBase_Tools::objectInfo((*anIt)));
@@ -910,6 +930,7 @@ void XGUI_Displayer::deactivateAIS(const Handle(AIS_InteractiveObject)& theIO, c
       aContext->Deactivate(theIO);
     else 
       aContext->Deactivate(theIO, theMode);
+    ModuleBase_Tools::selectionInfo(aContext, "XGUI_Displayer::deactivateAIS -- Deactivate");
    
 #ifdef DEBUG_DEACTIVATE_AIS
     ObjectPtr anObject = getObject(theIO);
@@ -978,6 +999,7 @@ bool XGUI_Displayer::eraseAIS(AISObjectPtr theAIS, const bool theUpdateViewer)
     Handle(AIS_InteractiveObject) anAISIO = theAIS->impl<Handle(AIS_InteractiveObject)>();
     if (!anAISIO.IsNull() && aContext->IsDisplayed(anAISIO)) {
       aContext->Remove(anAISIO, false/*update viewer*/);
+      ModuleBase_Tools::selectionInfo(aContext, "XGUI_Displayer::eraseAIS -- Remove");
       aErased = true;
     }
   }
@@ -1160,7 +1182,7 @@ bool XGUI_Displayer::activate(const Handle(AIS_InteractiveObject)& theIO,
   for (; itr.More(); itr.Next() ) {
     Standard_Integer aMode = itr.Value();
     int aShapeMode = (aMode > 8)? aMode : AIS_Shape::SelectionType(aMode);
-    if (!theModes.contains(aMode) || (myWorkshop->module()->needDeactivateSelectionMode(theIO, aShapeMode))) {
+    if (!theModes.contains(aMode)) {
       deactivateAIS(theIO, aMode);
       isDeactivated = true;
     }
@@ -1172,6 +1194,7 @@ bool XGUI_Displayer::activate(const Handle(AIS_InteractiveObject)& theIO,
     // the selection from the previous activation modes should be cleared manually (#26172)
     theIO->ClearSelected();
     aContext->LocalContext()->ClearOutdatedSelection(theIO, true);
+    ModuleBase_Tools::selectionInfo(aContext, "XGUI_Displayer::activate -- ClearSelected/ClearOutdatedSelection");
     // For performance issues
     //if (theUpdateViewer)
     //  updateViewer();
index 9fab49052887fc88866bd1c95b8095b55117d4ee..5fbeebf5e2f980add4cd55df549753374dd69521 100644 (file)
@@ -77,8 +77,11 @@ QObjectPtrList XGUI_ModuleConnector::activeObjects(const QObjectPtrList& theObjL
 
 void XGUI_ModuleConnector::activateSubShapesSelection(const QIntList& theTypes)
 {
+  QIntList aTypes = theTypes;
+
   XGUI_Displayer* aDisp = myWorkshop->displayer();
-  aDisp->activateObjects(theTypes, activeObjects(aDisp->displayedObjects()));
+  myWorkshop->module()->customSubShapesSelectionModes(aTypes);
+  aDisp->activateObjects(aTypes, activeObjects(aDisp->displayedObjects()));
 }
 
 void XGUI_ModuleConnector::deactivateSubShapesSelection()
index 14715346960388ffaaf1677f6dd1f177a7562426..15fba977ca2d02a3318d9a14d981641015534e74 100644 (file)
@@ -423,19 +423,19 @@ void XGUI_ObjectsBrowser::onEditItem()
 {
   QObjectPtrList aSelectedData = selectedObjects();
   if (aSelectedData.size() > 0) {
-    ObjectPtr aFeature = aSelectedData.first();
-    if (aFeature) {  // Selection happens in TreeView
-      QObjectPtrList aList;
-      aList.append(aFeature);
-      // check whether the object can be deleted. There should not be parts which are not loaded
-      if (!XGUI_Tools::canRemoveOrRename((QWidget*)parent(), aList))
+    ObjectPtr anObject = aSelectedData.first();
+    if (anObject.get()) {  // Selection happens in TreeView
+      // check whether the object can be renamed. There should not be parts which are not loaded
+      std::set<FeaturePtr> aFeatures;
+      aFeatures.insert(ModelAPI_Feature::feature(anObject));
+      if (!XGUI_Tools::canRemoveOrRename((QWidget*)parent(), aFeatures))
         return;
 
       // Find index which corresponds the feature
       QModelIndex aIndex;
       foreach(QModelIndex aIdx, selectedIndexes()) {
         ObjectPtr aFea = dataModel()->object(aIdx);
-        if (dataModel()->object(aIdx)->isSame(aFeature)) {
+        if (dataModel()->object(aIdx)->isSame(anObject)) {
           aIndex = aIdx;
           break;
         }
index 3a98d98e9fff1808d0ac74d23ca6719b21fedd9b..b41264d77b160e08096eb11793e6e8ba74ed6d24 100644 (file)
@@ -10,6 +10,7 @@
 #include "XGUI_ErrorMgr.h"
 #include "XGUI_Tools.h"
 #include "XGUI_ObjectsBrowser.h"
+#include "XGUI_ContextMenuMgr.h"
 
 #include <ModuleBase_IPropertyPanel.h>
 #include <ModuleBase_ModelWidget.h>
@@ -686,12 +687,25 @@ bool XGUI_OperationMgr::onProcessDelete(QObject* theObject)
     /// processing delete by workshop
     XGUI_ObjectsBrowser* aBrowser = XGUI_Tools::workshop(myWorkshop)->objectBrowser();
     QWidget* aViewPort = myWorkshop->viewer()->activeViewPort();
-    // property panel child object is processed to process delete performed on Apply button of PP
-    if (theObject == aBrowser->treeView() ||
-        isChildObject(theObject, aViewPort) ||
-        isPPChildObject)
-      XGUI_Tools::workshop(myWorkshop)->deleteObjects();
-    isAccepted = true;
+    bool isToDeleteObject = false;
+    XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop);
+    XGUI_ContextMenuMgr* aContextMenuMgr = aWorkshop->contextMenuMgr();
+    if (theObject == aBrowser->treeView()) {
+      aContextMenuMgr->updateObjectBrowserMenu();
+      isToDeleteObject = aContextMenuMgr->action("DELETE_CMD")->isEnabled();
+    }
+    else if (isChildObject(theObject, aViewPort)) {
+      aContextMenuMgr->updateViewerMenu();
+      isToDeleteObject = aContextMenuMgr->action("DELETE_CMD")->isEnabled();
+    }
+    else if (isPPChildObject) {
+      // property panel child object is processed to process delete performed on Apply button of PP
+      isToDeleteObject = true;
+    }
+    if (isToDeleteObject) {
+      aWorkshop->deleteObjects();
+      isAccepted = true;
+    }
   }
 
   return isAccepted;
index c2c31868351e988817ef03bcfa9a5a7bdf5bea81..10d39b798efacf2a7c4317a8b471de97580f74d7 100755 (executable)
@@ -426,6 +426,7 @@ bool XGUI_PropertyPanel::setActiveWidget(ModuleBase_ModelWidget* theWidget)
   std::string aPreviosAttributeID;
   if(myActiveWidget) {
     aPreviosAttributeID = myActiveWidget->attributeID();
+    myActiveWidget->processValueState();
     myActiveWidget->deactivate();
     myActiveWidget->setHighlighted(false);
   }
index 8bc012412bb24d5698abd829cfc058d8c4b1709a..0d9b701f69cc71de1a2377c56eadfd91c1d533f5 100755 (executable)
@@ -22,6 +22,7 @@
 #include <ModelAPI_ResultCompSolid.h>
 
 #include <ModuleBase_ViewerPrs.h>
+#include <ModuleBase_Tools.h>
 
 #include <SelectMgr_ListIteratorOfListOfFilter.hxx>
 
@@ -64,6 +65,7 @@ void XGUI_SelectionMgr::setSelectedOwners(const SelectMgr_IndexedMapOfOwner& the
       aContext->AddOrRemoveSelected(anOwner, isUpdateViewer);
     }
   }
+  ModuleBase_Tools::selectionInfo(aContext, "XGUI_SelectionMgr::setSelectedOwners -- AddOrRemoveSelected");
 }
 
 //**************************************************************
index b3e1dca321ec14877c55949df0323add655eb3bd..a60b1f2190ac49b646281c1a5fd8f4a8ac93d136 100644 (file)
@@ -6,6 +6,7 @@
 #include "XGUI_Workshop.h"
 
 #include "ModuleBase_IWorkshop.h"
+#include "ModuleBase_Tools.h"
 
 #include <TopoDS_Shape.hxx>
 #include <ModelAPI_Object.h>
@@ -26,6 +27,7 @@
 
 #include <iostream>
 #include <sstream>
+#include <string>
 
 namespace XGUI_Tools {
 //******************************************************************
@@ -102,23 +104,18 @@ std::string featureInfo(FeaturePtr theFeature)
  }
  }*/
 
+
 //******************************************************************
-bool canRemoveOrRename(QWidget* theParent, const QObjectPtrList& theObjects)
+bool canRemoveOrRename(QWidget* theParent, const std::set<FeaturePtr>& theFeatures)
 {
   bool aResult = true;
-  QString aNotActivatedNames;
-  if (!XGUI_Tools::allDocumentsActivated(aNotActivatedNames)) {
-    DocumentPtr aModuleDoc = ModelAPI_Session::get()->moduleDocument();
-    bool aFoundPartSetObject = false;
-    foreach (ObjectPtr aObj, theObjects) {
-      if (aObj->groupName() == ModelAPI_ResultPart::group())
-        continue;
-      aFoundPartSetObject = aObj->document() == aModuleDoc;
-    }
+  std::string aNotActivatedNames;
+  if (!ModelAPI_Tools::allDocumentsActivated(aNotActivatedNames)) {
+    bool aFoundPartSetObject = ModuleBase_Tools::hasModuleDocumentFeature(theFeatures);
     if (aFoundPartSetObject) {
       QMessageBox::StandardButton aRes = QMessageBox::warning(theParent, QObject::tr("Warning"),
                QObject::tr("Selected objects can be used in Part documents which are not loaded: \
-%1. Whould you like to continue?").arg(aNotActivatedNames),
+%1. Whould you like to continue?").arg(aNotActivatedNames.c_str()),
                QMessageBox::No | QMessageBox::Yes, QMessageBox::No);
       aResult = aRes == QMessageBox::Yes;
     }
@@ -145,26 +142,6 @@ bool canRename(const ObjectPtr& theObject, const QString& theName)
   return true;
 }
 
-//******************************************************************
-bool allDocumentsActivated(QString& theNotActivatedNames)
-{
-  bool anAllPartActivated = true;
-  QStringList aRefNames;
-
-  DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
-  int aSize = aRootDoc->size(ModelAPI_ResultPart::group());
-  for (int i = 0; i < aSize; i++) {
-    ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultPart::group(), i);
-    ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObject);
-    if (!aPart->isActivated()) {
-      anAllPartActivated = false;
-      aRefNames.append(aObject->data()->name().c_str());
-    }
-  }
-  theNotActivatedNames = aRefNames.join(", ");
-  return anAllPartActivated;
-}
-
 //**************************************************************
 
 XGUI_Workshop* workshop(ModuleBase_IWorkshop* theWorkshop)
index 9215bf6ace11838d6e885cad9ce5fdbdb1982935..a8d51f2d505745c77f0074bbd656050d32c254ac 100644 (file)
@@ -81,10 +81,10 @@ std::string XGUI_EXPORT featureInfo(FeaturePtr theFeature);
  all objects in the list are not PartSet document.
  It shows the warning control if the result is false.
  \param theParent a parent for the warning control
- \param aList a list of object
+ \param theFeatures a list of checked features
  \return a boolean value
  */
-bool XGUI_EXPORT canRemoveOrRename(QWidget* theParent, const QObjectPtrList& aList);
+bool XGUI_EXPORT canRemoveOrRename(QWidget* theParent, const std::set<FeaturePtr>& theFeatures);
 
 /*! 
  Check possibility to rename object
@@ -93,13 +93,6 @@ bool XGUI_EXPORT canRemoveOrRename(QWidget* theParent, const QObjectPtrList& aLi
  */
 bool canRename(const ObjectPtr& theObject, const QString& theName);
 
-/*!
- Returns true if there are no parts in the document, which are not activated
- \param theNotActivatedNames out string which contains not activated names
- \return a boolean value
- */
-bool XGUI_EXPORT allDocumentsActivated(QString& theNotActivatedNames);
-
 /*!
  Returns converted workshop
  \param theWorkshop an interface workshop
index 88102925242baa5a61eff80d15f1280194679912..f36f9353eab2fd50b598b8d988e7a64f83255cb9 100755 (executable)
@@ -198,7 +198,7 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector)
   //Config_PropManager::registerProp("Visualization", "object_default_color", "Object color",
   //                                 Config_Prop::Color, "225,225,225");
 
-  Config_PropManager::registerProp("Visualization", "result_body_color", "Body color",
+  Config_PropManager::registerProp("Visualization", "result_body_color", "Result color",
                                    Config_Prop::Color, ModelAPI_ResultBody::DEFAULT_COLOR());
   Config_PropManager::registerProp("Visualization", "result_group_color", "Group color",
                                    Config_Prop::Color, ModelAPI_ResultGroup::DEFAULT_COLOR());
@@ -1298,9 +1298,6 @@ void XGUI_Workshop::deleteObjects()
   QObjectPtrList anObjects = mySelector->selection()->selectedObjects();
   if (!abortAllOperations())
     return;
-  // check whether the object can be deleted. There should not be parts which are not loaded
-  if (!XGUI_Tools::canRemoveOrRename(desktop(), anObjects))
-    return;
 
   bool hasResult = false;
   bool hasFeature = false;
@@ -1499,20 +1496,21 @@ void XGUI_Workshop::moveObjects()
   // moving and negative consequences connected with processing of already moved items
   mySelector->clearSelection();
   // check whether the object can be moved. There should not be parts which are not loaded
-  if (!XGUI_Tools::canRemoveOrRename(desktop(), anObjects))
+  std::set<FeaturePtr> aFeatures;
+  ModuleBase_Tools::convertToFeatures(anObjects, aFeatures);
+  if (!XGUI_Tools::canRemoveOrRename(desktop(), aFeatures))
     return;
 
   DocumentPtr anActiveDocument = aMgr->activeDocument();
   FeaturePtr aCurrentFeature = anActiveDocument->currentFeature(true);
-  foreach (ObjectPtr aObject, anObjects) {
-    if (!myModule->canApplyAction(aObject, anActionId))
+  std::set<FeaturePtr>::const_iterator anIt = aFeatures.begin(), aLast = aFeatures.end();
+  for (; anIt != aLast; anIt++) {
+    FeaturePtr aFeature = *anIt;
+    if (!aFeature.get() || !myModule->canApplyAction(aFeature, anActionId))
       continue;
 
-    FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObject);
-    if (aFeature.get()) {
-      anActiveDocument->moveFeature(aFeature, aCurrentFeature);
-      aCurrentFeature = anActiveDocument->currentFeature(true);
-    }
+    anActiveDocument->moveFeature(aFeature, aCurrentFeature);
+    aCurrentFeature = anActiveDocument->currentFeature(true);
   }
   aMgr->finishOperation();
 }