Salome HOME
Task #3079 3.5 Build/Vertex on a whole Sketch
[modules/shaper.git] / src / BuildPlugin / BuildPlugin_Vertex.cpp
index 82f3521ed81ac72dd66859b97c9a7e5a19e83bef..cd14766ed902b40105e2d42c9db29d47c36a09ae 100644 (file)
 #include "BuildPlugin_Vertex.h"
 
 #include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_AttributeBoolean.h>
+#include <ModelAPI_CompositeFeature.h>
 #include <ModelAPI_ResultBody.h>
+#include <ModelAPI_Validator.h>
+#include <ModelAPI_Session.h>
 
 #include <GeomAlgoAPI_Copy.h>
 #include <GeomAlgoAPI_Tools.h>
+#include <GeomAlgoAPI_Partition.h>
+#include <GeomAlgoAPI_ShapeTools.h>
+
+#include <GeomAPI_ShapeExplorer.h>
 
 //=================================================================================================
 BuildPlugin_Vertex::BuildPlugin_Vertex()
@@ -34,62 +42,242 @@ BuildPlugin_Vertex::BuildPlugin_Vertex()
 void BuildPlugin_Vertex::initAttributes()
 {
   data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
+
+  data()->addAttribute(INTERSECT_ID(), ModelAPI_AttributeBoolean::typeId());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), INTERSECT_ID());
+}
+
+//=================================================================================================
+bool BuildPlugin_Vertex::buildVertices(GeomShapePtr theShape,
+                                       bool isIntersect,
+                                       int& theResultIndex)
+{
+  if (!theShape.get()) {
+    setError("Error: Empty shape selected.");
+    return false;
+  }
+
+  if (theShape->shapeType() == GeomAPI_Shape::VERTEX) {
+    // Copy shape.
+    std::shared_ptr<GeomAlgoAPI_Copy> aCopyAlgo(new GeomAlgoAPI_Copy(theShape));
+
+    std::string anError;
+    if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aCopyAlgo, getKind(), anError)) {
+      setError(anError);
+      return false;
+    }
+
+    // Store result.
+    ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
+    aResultBody->storeModified(theShape, aCopyAlgo->shape());
+    setResult(aResultBody, theResultIndex);
+    ++theResultIndex;
+  } else {
+    // Sketch
+    GeomAPI_DataMapOfShapeShape alreadyProcessed;
+
+    // 1. Explode on Vertices
+    for (GeomAPI_ShapeExplorer anExp (theShape, GeomAPI_Shape::VERTEX); anExp.more(); anExp.next()) {
+      GeomShapePtr aSubShape = anExp.current();
+
+      if (alreadyProcessed.bind(aSubShape, aSubShape)) {
+        // Store result.
+        ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
+        aResultBody->storeModified(theShape, aSubShape);
+        setResult(aResultBody, theResultIndex);
+        ++theResultIndex;
+      }
+    }
+
+    // 2. If need intersection points, perform Partition
+    if (isIntersect) {
+      // Partition
+      ListOfShape anObjList, aTools;
+      anObjList.push_back(theShape);
+      std::shared_ptr<GeomAlgoAPI_Partition> aPartitionAlgo (new GeomAlgoAPI_Partition(anObjList, aTools));
+
+      std::string anError;
+      if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aPartitionAlgo, getKind(), anError)) {
+        setError(anError);
+        return false;
+      }
+      GeomShapePtr aSplittedSketch = aPartitionAlgo->shape();
+
+      // Explode on Vertices, skip vertices of initial sketch
+      for (GeomAPI_ShapeExplorer anExp (aSplittedSketch, GeomAPI_Shape::VERTEX); anExp.more(); anExp.next()) {
+        GeomShapePtr aSubShape = anExp.current();
+
+        //if (!theShape->isSubShape(aSubShape)) { // skip vertices of initial sketch
+        if (alreadyProcessed.bind(aSubShape, aSubShape)) {
+          // Store result.
+          ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
+          aResultBody->storeGenerated(anObjList, aSubShape, aPartitionAlgo);
+          setResult(aResultBody, theResultIndex);
+          ++theResultIndex;
+        }
+      }
+    }
+  }
+
+  return true;
 }
 
 //=================================================================================================
+bool BuildPlugin_Vertex::buildVertices(FeaturePtr theFeature,
+                                       bool isIntersect,
+                                       int& theResultIndex)
+{
+  if (theFeature->getKind() != "Sketch") return false;
+
+  // Sub-features
+  CompositeFeaturePtr aComposite =
+    std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);
+  if (!aComposite) return false;
+  int nbSubs = aComposite->numberOfSubs();
+  if (nbSubs < 1) return false;
+
+  // The whole sketch shape
+  ResultPtr aContext = theFeature->firstResult();
+  GeomShapePtr theShape = aContext->shape();
+
+  GeomAPI_DataMapOfShapeShape alreadyProcessed;
+
+  // 1. Explode on Vertices
+  for (GeomAPI_ShapeExplorer anExp (theShape, GeomAPI_Shape::VERTEX); anExp.more(); anExp.next()) {
+    GeomShapePtr aSubShape = anExp.current();
+
+    if (alreadyProcessed.bind(aSubShape, aSubShape)) {
+      // Store result.
+      ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
+      aResultBody->storeModified(theShape, aSubShape);
+      setResult(aResultBody, theResultIndex);
+      ++theResultIndex;
+    }
+  }
+
+  // 2. If need intersection points, perform Partition
+  if (isIntersect) {
+    // Partition
+    ListOfShape anObjList, aTools;
+    anObjList.push_back(theShape);
+    std::shared_ptr<GeomAlgoAPI_Partition> aPartitionAlgo (new GeomAlgoAPI_Partition(anObjList, aTools));
+
+    std::string anError;
+    if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aPartitionAlgo, getKind(), anError)) {
+      setError(anError);
+      return false;
+    }
+    GeomShapePtr aSplittedSketch = aPartitionAlgo->shape();
+
+    // Explode on Vertices, skip vertices of initial sketch
+    for (GeomAPI_ShapeExplorer anExp (aSplittedSketch, GeomAPI_Shape::VERTEX); anExp.more(); anExp.next()) {
+      GeomShapePtr aSubShape = anExp.current();
+
+      //if (!theShape->isSubShape(aSubShape)) { // skip vertices of initial sketch
+      if (alreadyProcessed.bind(aSubShape, aSubShape)) {
+        // Store result.
+        ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
+        aResultBody->storeGenerated(anObjList, aSubShape, aPartitionAlgo);
+        setResult(aResultBody, theResultIndex);
+        ++theResultIndex;
+      }
+    }
+  }
+
+  // 3. Add construction points (centers of circles, etc.)
+  for (int i = 0; i < nbSubs; i++) {
+    FeaturePtr aSubFeature = aComposite->subFeature(i);
+    const std::list<ResultPtr>& aSubResults = aSubFeature->results();
+    std::list<ResultPtr>::const_iterator anItRes = aSubResults.cbegin();
+    // Iterate on all sub-results
+    for (; anItRes != aSubResults.cend(); anItRes++) {
+      ResultPtr aRes = *anItRes;
+      if (aRes.get()) {
+        // Sub-result i
+        GeomShapePtr aSubResShape = aRes->shape();
+
+        for (GeomAPI_ShapeExplorer anExp (aSubResShape, GeomAPI_Shape::VERTEX); anExp.more(); anExp.next()) {
+          GeomShapePtr aSubShape = anExp.current();
+
+          if (alreadyProcessed.bind(aSubShape, aSubShape)) {
+            // Store result.
+            ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
+            aResultBody->storeModified(theShape, aSubShape);
+            setResult(aResultBody, theResultIndex);
+            ++theResultIndex;
+          }
+        }
+      }
+    }
+  }
+
+  return true;
+}
+
 void BuildPlugin_Vertex::execute()
 {
   // Get base objects list.
   AttributeSelectionListPtr aSelectionList = selectionList(BASE_OBJECTS_ID());
-  if(!aSelectionList.get()) {
+  if (!aSelectionList.get()) {
     setError("Error: Could not get selection list.");
     return;
   }
-  if(aSelectionList->size() == 0) {
+  if (aSelectionList->size() == 0) {
     setError("Error: Empty selection list.");
     return;
   }
 
-  // Collect base shapes.
-  ListOfShape aListOfShapes;
+  // Get "Compute intersections" flag value
+  bool isIntersect = false;
+  if (boolean(INTERSECT_ID()).get() && boolean(INTERSECT_ID())->isInitialized()) {
+    isIntersect = boolean(INTERSECT_ID())->value();
+  }
+
+  // Iterate arguments and build results
   int aResultIndex = 0;
-  for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
+  for (int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
     AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
     GeomShapePtr aShape = aSelection->value();
-    if(!aShape.get()) {
+    if (aShape.get()) {
+      // A shape selected
+      if (!buildVertices(aShape, isIntersect, aResultIndex)) return;
+    } else {
       ResultPtr aContext = aSelection->context();
-      if(!aContext.get()) {
-        setError("Error: Attribute has empty context.");
-        return;
+      if (aContext.get()) { // Result selected
+        FeaturePtr aFeature = ModelAPI_Feature::feature(aContext);
+        if (aFeature.get()) {
+          if (aFeature->getKind() == "Sketch") {
+            // Special processing for sketch to build center vertices etc.
+            if (!buildVertices(aFeature, isIntersect, aResultIndex)) return;
+          } else {
+            aShape = aContext->shape();
+            if (!buildVertices(aShape, isIntersect, aResultIndex)) return;
+          }
+        }
+      } else {
+        FeaturePtr aFeature = aSelection->contextFeature();
+        if (aFeature.get()) { // Feature selected
+          if (aFeature->getKind() == "Sketch") {
+            // Special processing for sketch to build center vertices etc.
+            if (!buildVertices(aFeature, isIntersect, aResultIndex)) return;
+          } else {
+            const std::list<ResultPtr>& anArgResults = aFeature->results();
+            std::list<ResultPtr>::const_iterator anItRes = anArgResults.cbegin();
+            // Iterate on all its results
+            for (; anItRes != anArgResults.cend(); anItRes++) {
+              ResultPtr aRes = *anItRes;
+              if (aRes.get()) {
+                // Result i
+                aShape = aRes->shape();
+                if (!buildVertices(aShape, isIntersect, aResultIndex)) return;
+              }
+            }
+          }
+        }
       }
-
-      aShape = aContext->shape();
     }
-    if(!aShape.get()) {
-      setError("Error: Empty shape selected.");
-      return;
-    }
-
-    if(aShape->shapeType() != GeomAPI_Shape::VERTEX) {
-      setError("Error: Selected shape has wrong type. Only vertices acceptable.");
-      return;
-    }
-
-    // Copy shape.
-    std::shared_ptr<GeomAlgoAPI_Copy> aCopyAlgo(new GeomAlgoAPI_Copy(aShape));
-
-    std::string anError;
-    if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aCopyAlgo, getKind(), anError)) {
-      setError(anError);
-      return;
-    }
-
-    // Store result.
-    ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
-    aResultBody->storeModified(aShape, aCopyAlgo->shape());
-    setResult(aResultBody, aResultIndex);
-    ++aResultIndex;
   }
 
+  // Remove extra results from previous execution
   removeResults(aResultIndex);
 }