Salome HOME
Issue #1369: Wire feature draft implementation.
authordbv <dbv@opencascade.com>
Fri, 15 Apr 2016 09:08:04 +0000 (12:08 +0300)
committerdbv <dbv@opencascade.com>
Fri, 15 Apr 2016 09:08:19 +0000 (12:08 +0300)
16 files changed:
src/FeaturesPlugin/CMakeLists.txt
src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp
src/FeaturesPlugin/FeaturesPlugin_Validators.cpp
src/FeaturesPlugin/FeaturesPlugin_Validators.h
src/FeaturesPlugin/FeaturesPlugin_Wire.cpp [new file with mode: 0644]
src/FeaturesPlugin/FeaturesPlugin_Wire.h [new file with mode: 0644]
src/FeaturesPlugin/plugin-Features.xml
src/FeaturesPlugin/wire_widget.xml [new file with mode: 0644]
src/GeomAlgoAPI/CMakeLists.txt
src/GeomAlgoAPI/GeomAlgoAPI.i
src/GeomAlgoAPI/GeomAlgoAPI_WireBuilder.cpp [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_WireBuilder.h [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_swig.h
src/PartSet/PartSet_IconFactory.cpp
src/PartSet/PartSet_icons.qrc
src/PartSet/icons/feature_wire.png [new file with mode: 0644]

index 3f940c5c0f6684d2095fae1d11ad5e727d8d72a8..3e9bbfd2733921f22c130d015f2a3059f21e7cad 100644 (file)
@@ -26,6 +26,7 @@ SET(PROJECT_HEADERS
     FeaturesPlugin_RevolutionFuse.h
     FeaturesPlugin_ValidatorTransform.h
     FeaturesPlugin_Validators.h
+    FeaturesPlugin_Wire.h
 )
 
 SET(PROJECT_SOURCES
@@ -50,6 +51,7 @@ SET(PROJECT_SOURCES
     FeaturesPlugin_RevolutionFuse.cpp
     FeaturesPlugin_ValidatorTransform.cpp
     FeaturesPlugin_Validators.cpp
+    FeaturesPlugin_Wire.cpp
 )
 
 SET(XML_RESOURCES
@@ -68,6 +70,7 @@ SET(XML_RESOURCES
   placement_widget.xml
   intersection_widget.xml
   pipe_widget.xml
+  wire_widget.xml
 )
 
 INCLUDE_DIRECTORIES(
index 1de58f332c830f1e5e033d01e3f8cb11afdf55ae..b83fc3339275026dce948b383f70086bdbfda212 100644 (file)
@@ -18,6 +18,7 @@
 #include <FeaturesPlugin_Rotation.h>
 #include <FeaturesPlugin_ValidatorTransform.h>
 #include <FeaturesPlugin_Validators.h>
+#include <FeaturesPlugin_Wire.h>
 
 #include <ModelAPI_Session.h>
 
@@ -44,6 +45,8 @@ FeaturesPlugin_Plugin::FeaturesPlugin_Plugin()
                               new FeaturesPlugin_ValidatorPipeLocations);
   aFactory->registerValidator("FeaturesPlugin_ValidatorCanBeEmpty",
                               new FeaturesPlugin_ValidatorCanBeEmpty);
+  aFactory->registerValidator("FeaturesPlugin_ValidatorBaseForWire",
+                              new FeaturesPlugin_ValidatorBaseForWire);
 
   // register this plugin
   ModelAPI_Session::get()->registerPlugin(this);
@@ -79,6 +82,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_Wire::ID()) {
+    return FeaturePtr(new FeaturesPlugin_Wire);
   }
   // feature of such kind is not found
   return FeaturePtr();
index 0de4d856a96de2bc262914492e50ad51b971cb81..ed019bb64b2018cfc32084f29f9bb1aa0db6a7eb 100644 (file)
 #include <ModelAPI_ResultConstruction.h>
 #include <ModelAPI_AttributeReference.h>
 
+#include <Events_Error.h>
+
 #include <GeomValidators_FeatureKind.h>
 #include <GeomValidators_ShapeType.h>
 
+#include <GeomAPI_PlanarEdges.h>
+#include <GeomAlgoAPI_WireBuilder.h>
+
 //=================================================================================================
 bool FeaturesPlugin_ValidatorPipeLocations::isValid(const std::shared_ptr<ModelAPI_Feature>& theFeature,
                                                     const std::list<std::string>& theArguments,
@@ -312,3 +317,74 @@ bool FeaturesPlugin_ValidatorCanBeEmpty::isShapesCanBeEmpty(const AttributePtr&
 
   return true;
 }
+
+//=================================================================================================
+bool FeaturesPlugin_ValidatorBaseForWire::isValid(const AttributePtr& theAttribute,
+                                                  const std::list<std::string>& theArguments,
+                                                  std::string& theError) const
+{
+  // Get base objects list.
+  if(theAttribute->attributeType() != ModelAPI_AttributeSelectionList::typeId()) {
+    Events_Error::send("Validator does not support attribute type \"" + theAttribute->attributeType()
+      + "\"\n Only \"" + ModelAPI_AttributeSelectionList::typeId() + "\" supported.");
+    return false;
+  }
+  AttributeSelectionListPtr aSelectionList = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
+  if(!aSelectionList.get()) {
+    theError = "Could not get selection list.";
+    return false;
+  }
+  if(aSelectionList->size() == 0) {
+    theError = "Empty selection list.";
+    return false;
+  }
+
+  // Collect base shapes.
+  ListOfShape aListOfShapes;
+  for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
+    AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
+    GeomShapePtr aShape = aSelection->value();
+    if(!aShape.get()) {
+      theError = "Empty shape selected.";
+      return false;
+    }
+
+    // Check that shape has acceptable type.
+    if(aShape->shapeType() != GeomAPI_Shape::EDGE && aShape->shapeType() != GeomAPI_Shape::WIRE) {
+      theError = "Selected shape has wrong type. Only edges and wires acceptable.";
+      return false;
+    }
+
+    // Check that it is edge on sketch.
+    ResultPtr aContext = aSelection->context();
+    if(!aContext.get()) {
+      theError = "Attribute have empty context.";
+      return false;
+    }
+    GeomShapePtr aContextShape = aContext->shape();
+    ResultConstructionPtr aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
+    if(aConstruction.get()) {
+      std::shared_ptr<GeomAPI_PlanarEdges> anEdges = std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aContextShape);
+      if(!anEdges.get()) {
+        // It is not an edge on the sketch.
+        // Check that it is not local selection.
+        if(!aShape->isEqual(aContextShape)) {
+          // Local selection on body does not allowed.
+          theError = "Selected shape is in the local selection. Only global selection is allowed.";
+          return false;
+        }
+      }
+    }
+
+    aListOfShapes.push_back(aShape);
+  }
+
+  // Create wire.
+  GeomShapePtr aWire = GeomAlgoAPI_WireBuilder::wire(aListOfShapes);
+  if(!aWire.get()) {
+    theError = "Result wire empty. Probably it has disconnected edges or non-manifold.";
+    return false;
+  }
+
+  return true;
+}
\ No newline at end of file
index e02b2ee63c2c15055cfb440472066c34ea5cedc2..66006583f85656277ed0d334283aa539eba35fbd 100644 (file)
@@ -88,4 +88,20 @@ private:
                           std::string& theError) const;
 };
 
+/// \class FeaturesPlugin_ValidatorBaseForWire
+/// \ingroup Validators
+/// \brief A validator for selection base shapes for wire. Allows to select edges on sketch and
+/// wires objects that are connected to already selected shapes.
+class FeaturesPlugin_ValidatorBaseForWire: public ModelAPI_AttributeValidator
+{
+public:
+  //! Returns true if attribute is ok.
+  //! \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;
+};
+
 #endif
diff --git a/src/FeaturesPlugin/FeaturesPlugin_Wire.cpp b/src/FeaturesPlugin/FeaturesPlugin_Wire.cpp
new file mode 100644 (file)
index 0000000..6764df6
--- /dev/null
@@ -0,0 +1,69 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        FeaturesPlugin_Wire.cpp
+// Created:     14 April 2016
+// Author:      Dmitry Bobylev
+
+#include "FeaturesPlugin_Wire.h"
+
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_ResultBody.h>
+
+#include <GeomAlgoAPI_WireBuilder.h>
+
+//=================================================================================================
+FeaturesPlugin_Wire::FeaturesPlugin_Wire()
+{
+}
+
+//=================================================================================================
+void FeaturesPlugin_Wire::initAttributes()
+{
+  data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
+}
+
+//=================================================================================================
+void FeaturesPlugin_Wire::execute()
+{
+  // Get base objects list.
+  AttributeSelectionListPtr aSelectionList = selectionList(BASE_OBJECTS_ID());
+  if(!aSelectionList.get()) {
+    setError("Error: Could not get selection list.");
+    return;
+  }
+  if(aSelectionList->size() == 0) {
+    setError("Error: Empty selection list.");
+    return;
+  }
+
+  // Collect base shapes.
+  ListOfShape aListOfShapes;
+  for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
+    AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
+    GeomShapePtr aShape = aSelection->value();
+    if(!aShape.get()) {
+      setError("Error: Empty shape selected.");
+      return;
+    }
+
+    if(aShape->shapeType() != GeomAPI_Shape::EDGE && aShape->shapeType() != GeomAPI_Shape::WIRE) {
+      setError("Error: Selected shape has wrong type. Only edges and wires acceptable.");
+      return;
+    }
+
+    aListOfShapes.push_back(aShape);
+  }
+
+  // Create wire.
+  GeomShapePtr aWire = GeomAlgoAPI_WireBuilder::wire(aListOfShapes);
+  if(!aWire.get()) {
+    setError("Error: Result wire empty. Probably it has disconnected edges or non-manifold.");
+    return;
+  }
+
+  // Store result.
+  ResultBodyPtr aResultBody = document()->createBody(data());
+  aResultBody->store(aWire);
+  setResult(aResultBody);
+}
+
diff --git a/src/FeaturesPlugin/FeaturesPlugin_Wire.h b/src/FeaturesPlugin/FeaturesPlugin_Wire.h
new file mode 100644 (file)
index 0000000..6a265cd
--- /dev/null
@@ -0,0 +1,51 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        FeaturesPlugin_Wire.h
+// Created:     14 April 2016
+// Author:      Dmitry Bobylev
+
+#ifndef FeaturesPlugin_Wire_H_
+#define FeaturesPlugin_Wire_H_
+
+#include "FeaturesPlugin.h"
+
+#include <ModelAPI_Feature.h>
+
+/// \class FeaturesPlugin_Wire
+/// \ingroup Plugins
+/// \brief Feature for creation of wire from sketch edges or existing wires.
+class FeaturesPlugin_Wire: public ModelAPI_Feature
+{
+public:
+  /// Use plugin manager for features creation
+  FeaturesPlugin_Wire();
+
+  /// Feature kind.
+  inline static const std::string& ID()
+  {
+    static const std::string MY_ID("Wire");
+    return MY_ID;
+  }
+
+  /// Attribute name of base objects.
+  inline static const std::string& BASE_OBJECTS_ID()
+  {
+    static const std::string MY_BASE_OBJECTS_ID("base_objects");
+    return MY_BASE_OBJECTS_ID;
+  }
+
+  /// \return the kind of a feature.
+  FEATURESPLUGIN_EXPORT virtual const std::string& getKind()
+  {
+    static std::string MY_KIND = FeaturesPlugin_Wire::ID();
+    return MY_KIND;
+  }
+
+  /// Request for initialization of data model of the feature: adding all attributes.
+  FEATURESPLUGIN_EXPORT virtual void initAttributes();
+
+  /// Creates a new part document if needed.
+  FEATURESPLUGIN_EXPORT virtual void execute();
+};
+
+#endif
index 1c084821d52d6488d418c862b7e2f05a133beef3..0ca6daa429be6be199766ab4e45da42c6a404ce9 100644 (file)
@@ -2,13 +2,15 @@
 
 <plugin>
   <workbench id="Features" document="Part">
+    <group id="Shape">
+      <feature id="Wire" title="Wire" tooltip ="Create a wire from sketch edges and wires objects" icon=":icons/feature_wire.png">
+        <source path="wire_widget.xml"/>
+      </feature>
+    </group>
     <group id="Extrusion">
       <feature id="Extrusion" title="Extrusion" tooltip="Create a solid by extrusion of a face" icon=":icons/extrusion.png">
           <source path="extrusion_widget.xml"/>
       </feature>
-      <!--<feature id="ExtrusionSketch" title="ExtrusionSketch" tooltip="Create a solids by extrusion of a sketch" icon=":icons/extrusionsketch.png">
-          <source path="extrusionsketch_widget.xml"/>
-      </feature>-->
       <feature id="ExtrusionCut" title="ExtrusionCut" tooltip="" icon=":icons/extrusion_cut.png">
         <source path="extrusioncut_widget.xml"/>
       </feature>
@@ -20,9 +22,6 @@
       <feature id="Revolution" title="Revolution" tooltip="Create a solid by revolution of a face" icon=":icons/revol.png">
           <source path="revolution_widget.xml"/>
       </feature>
-      <!--<feature id="RevolutionSketch" title="RevolutionSketch" tooltip="Create a solids by revolution of a sketch" icon=":icons/revolsketch.png">
-          <source path="revolutionsketch_widget.xml"/>
-      </feature>-->
       <feature id="RevolutionCut" title="RevolutionCut" tooltip="" icon=":icons/revol_cut.png">
         <source path="revolutioncut_widget.xml"/>
       </feature>
diff --git a/src/FeaturesPlugin/wire_widget.xml b/src/FeaturesPlugin/wire_widget.xml
new file mode 100644 (file)
index 0000000..6db25b1
--- /dev/null
@@ -0,0 +1,10 @@
+<!-- Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+<source>
+  <multi_selector id="base_objects"
+                  label="Segments and wires:"
+                  tooltip="Select an edges on sketch or wires objects."
+                  type_choice="edges objects">
+    <validator id="FeaturesPlugin_ValidatorBaseForWire"/>
+  </multi_selector>
+</source>
index 74f73a9bbed1d10c9156ecfd1e7dcbb3415610de..84105385f42764f97c25112a439e55a01f27ecaf 100644 (file)
@@ -36,6 +36,7 @@ SET(PROJECT_HEADERS
     GeomAlgoAPI_PaveFiller.h
     GeomAlgoAPI_Intersection.h
     GeomAlgoAPI_Pipe.h
+    GeomAlgoAPI_WireBuilder.h
 )
 
 SET(PROJECT_SOURCES
@@ -68,6 +69,7 @@ SET(PROJECT_SOURCES
     GeomAlgoAPI_PaveFiller.cpp
     GeomAlgoAPI_Intersection.cpp
     GeomAlgoAPI_Pipe.cpp
+    GeomAlgoAPI_WireBuilder.cpp
 )
 
 SET(PROJECT_LIBRARIES
index 95fddd512b0b358a1e39763126537a947e585252..8c9279226a17c8deafb28e56f7947354b3b5c756 100644 (file)
@@ -42,6 +42,7 @@
 %include "GeomAlgoAPI_PaveFiller.h"
 %include "GeomAlgoAPI_Intersection.h"
 %include "GeomAlgoAPI_Pipe.h"
+%include "GeomAlgoAPI_WireBuilder.h"
 
 %typemap(out) std::list< std::shared_ptr< GeomAPI_Shape > >::value_type & {
   $result = SWIG_NewPointerObj(SWIG_as_voidptr(new std::shared_ptr<GeomAPI_Shape>(*$1)), $descriptor(std::shared_ptr<GeomAPI_Shape> *), SWIG_POINTER_OWN | 0 );
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_WireBuilder.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_WireBuilder.cpp
new file mode 100644 (file)
index 0000000..b6b9dec
--- /dev/null
@@ -0,0 +1,42 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        GeomAlgoAPI_WireBuilder.cpp
+// Created:     14 April 2016
+// Author:      Dmitry Bobylev
+
+#include "GeomAlgoAPI_WireBuilder.h"
+
+#include <BRepBuilderAPI_MakeWire.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Wire.hxx>
+
+//=================================================================================================
+std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_WireBuilder::wire(const ListOfShape& theShapes)
+{
+  BRepBuilderAPI_MakeWire aWireBuilder;
+
+  for(ListOfShape::const_iterator anIt = theShapes.cbegin(); anIt != theShapes.cend(); ++anIt) {
+    const TopoDS_Shape& aShape = (*anIt)->impl<TopoDS_Shape>();
+    switch(aShape.ShapeType()) {
+      case TopAbs_EDGE: {
+        aWireBuilder.Add(TopoDS::Edge(aShape));
+        break;
+      }
+      case TopAbs_WIRE: {
+        aWireBuilder.Add(TopoDS::Wire(aShape));
+        break;
+      }
+      default: {
+        return GeomShapePtr();
+      }
+    }
+  }
+
+  if(aWireBuilder.Error() != BRepBuilderAPI_WireDone) {
+    return GeomShapePtr();
+  }
+
+  GeomShapePtr aResultShape(new GeomAPI_Shape());
+  aResultShape->setImpl(new TopoDS_Shape(aWireBuilder.Wire()));
+  return aResultShape;
+}
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_WireBuilder.h b/src/GeomAlgoAPI/GeomAlgoAPI_WireBuilder.h
new file mode 100644 (file)
index 0000000..99256be
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        GeomAlgoAPI_WireBuilder.h
+// Created:     14 April 2016
+// Author:      Dmitry Bobylev
+
+#ifndef GeomAlgoAPI_WireBuilder_H_
+#define GeomAlgoAPI_WireBuilder_H_
+
+#include "GeomAlgoAPI.h"
+
+#include <GeomAPI_Shape.h>
+
+/// \class GeomAlgoAPI_WireBuilder
+/// \ingroup DataAlgo
+/// \brief Allows to create wire-shapes by different parameters.
+class GeomAlgoAPI_WireBuilder
+{
+ public:
+   /// \brief Creates a wire from edges and wires.
+   /// \param[in] theShapes list of shapes. Only edges and wires allowed.
+   /// The edges are not to be consecutive. But they are to be all connected geometrically or topologically.
+   /// \return wire created from theShapes. Empty in case of error or bad input.
+   GEOMALGOAPI_EXPORT static std::shared_ptr<GeomAPI_Shape> wire(const ListOfShape& theShapes);
+};
+
+#endif
index f82daf66d2ee4dbac4bf27e1e41bc56d9bd05511..92327a03d72f79b36a2d4fe80af438695423d230 100644 (file)
@@ -36,6 +36,7 @@
   #include "GeomAlgoAPI_PaveFiller.h"
   #include "GeomAlgoAPI_Intersection.h"
   #include "GeomAlgoAPI_Pipe.h"
+  #include "GeomAlgoAPI_WireBuilder.h"
 
   #include <memory>
   #include <string>
index 3926597d227bf9c548e0affbfc3cd8920024f290..a76105434dffedb6ad0b52bbb33c39f105a366a5 100644 (file)
@@ -77,24 +77,20 @@ QIcon PartSet_IconFactory::getIcon(ObjectPtr theObj)
   ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObj);
   if (aResult.get()) {
     GeomShapePtr aShape = aResult->shape();
-    if (aShape.get()) {
-      if (aShape->isSolid()) 
-        return QIcon(":pictures/solid.png");
-      else if (aShape->isCompound()) 
-        return QIcon(":pictures/compound.png");
-      else if (aShape->isCompoundOfSolids()) 
-        return QIcon(":pictures/compoundofsolids.png");
-      else if (aShape->isCompSolid()) 
-        return QIcon(":pictures/compsolid.png");
-      else if (aShape->isEdge()) 
-        return QIcon(":pictures/edge.png");
-      else if (aShape->isFace()) 
-        return QIcon(":pictures/face.png");
-      else if (aShape->isVertex()) 
-        return QIcon(":pictures/vertex.png");
+    if(aShape.get()) {
+      switch(aShape->shapeType()) {
+        case GeomAPI_Shape::COMPOUND:  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");
+        case GeomAPI_Shape::FACE:      return QIcon(":pictures/face.png");
+        case GeomAPI_Shape::WIRE:      return QIcon(":pictures/wire.png");
+        case GeomAPI_Shape::EDGE:      return QIcon(":pictures/edge.png");
+        case GeomAPI_Shape::VERTEX:    return QIcon(":pictures/vertex.png");
+      }
     }
   }
-  return anIcon;  
+  return anIcon;
 }
 
 void PartSet_IconFactory::processEvent(const std::shared_ptr<Events_Message>& theMessage)
index ff09bfce36743067e33ee04ce4421616b281e3be..fada5b9de22373fb1e611a98e8fda2df4e22e454 100644 (file)
      <file>icons/pipe_simple_32x32.png</file>
      <file>icons/pipe_binormal_32x32.png</file>
      <file>icons/pipe_locations_32x32.png</file>
+     <file>icons/feature_wire.png</file>
  </qresource>
  </RCC>
diff --git a/src/PartSet/icons/feature_wire.png b/src/PartSet/icons/feature_wire.png
new file mode 100644 (file)
index 0000000..87b8556
Binary files /dev/null and b/src/PartSet/icons/feature_wire.png differ