Salome HOME
Issue #2559: Add Polyline feature to Build plugin for 3D polyline creation.
authormzn <mzn@opencascade.com>
Thu, 12 Jul 2018 15:50:21 +0000 (18:50 +0300)
committermzn <mzn@opencascade.com>
Thu, 12 Jul 2018 15:50:21 +0000 (18:50 +0300)
19 files changed:
src/BuildAPI/BuildAPI.i
src/BuildAPI/BuildAPI_Polyline.cpp [new file with mode: 0644]
src/BuildAPI/BuildAPI_Polyline.h [new file with mode: 0644]
src/BuildAPI/BuildAPI_swig.h
src/BuildAPI/CMakeLists.txt
src/BuildPlugin/BuildPlugin_Plugin.cpp
src/BuildPlugin/BuildPlugin_Polyline.cpp [new file with mode: 0644]
src/BuildPlugin/BuildPlugin_Polyline.h [new file with mode: 0644]
src/BuildPlugin/BuildPlugin_msg_en.ts
src/BuildPlugin/CMakeLists.txt
src/BuildPlugin/Test/TestPolyline.py [new file with mode: 0644]
src/BuildPlugin/icons/feature_polyline.png [new file with mode: 0644]
src/BuildPlugin/icons/feature_wire.png
src/BuildPlugin/plugin-Build.xml
src/BuildPlugin/polyline_widget.xml [new file with mode: 0644]
src/BuildPlugin/vertex_widget.xml
src/GeomAlgoAPI/GeomAlgoAPI_WireBuilder.cpp
src/GeomAlgoAPI/GeomAlgoAPI_WireBuilder.h
src/PythonAPI/model/build/__init__.py

index a9c01420ab6a263fa518acca776c195e968200d3..22bbb0137bcd2cac1f1a2082f6e26a1aa7e01686 100644 (file)
@@ -49,6 +49,7 @@
 %shared_ptr(BuildAPI_SubShapes)
 %shared_ptr(BuildAPI_Vertex)
 %shared_ptr(BuildAPI_Wire)
+%shared_ptr(BuildAPI_Polyline)
 
 // all supported interfaces
 %include "BuildAPI_Compound.h"
@@ -61,3 +62,4 @@
 %include "BuildAPI_SubShapes.h"
 %include "BuildAPI_Vertex.h"
 %include "BuildAPI_Wire.h"
+%include "BuildAPI_Polyline.h"
diff --git a/src/BuildAPI/BuildAPI_Polyline.cpp b/src/BuildAPI/BuildAPI_Polyline.cpp
new file mode 100644 (file)
index 0000000..784d8f9
--- /dev/null
@@ -0,0 +1,83 @@
+// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "BuildAPI_Polyline.h"
+
+#include <ModelHighAPI_Dumper.h>
+#include <ModelHighAPI_Tools.h>
+
+//==================================================================================================
+BuildAPI_Polyline::BuildAPI_Polyline(const std::shared_ptr<ModelAPI_Feature>& theFeature)
+: ModelHighAPI_Interface(theFeature)
+{
+  initialize();
+}
+
+//==================================================================================================
+BuildAPI_Polyline::BuildAPI_Polyline(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                                     const std::list<ModelHighAPI_Selection>& theBaseObjects,
+                                     const bool theIsClosed)
+: ModelHighAPI_Interface(theFeature)
+{
+  if(initialize()) {
+    setClosed(theIsClosed);
+    setBase(theBaseObjects);
+  }
+}
+
+//==================================================================================================
+BuildAPI_Polyline::~BuildAPI_Polyline()
+{
+
+}
+
+//==================================================================================================
+void BuildAPI_Polyline::setBase(const std::list<ModelHighAPI_Selection>& theBaseObjects)
+{
+  fillAttribute(theBaseObjects, mybaseObjects);
+
+  execute();
+}
+
+//==================================================================================================
+void BuildAPI_Polyline::setClosed(const bool theIsClosed)
+{
+  fillAttribute(theIsClosed, myclosed);
+}
+
+//==================================================================================================
+void BuildAPI_Polyline::dump(ModelHighAPI_Dumper& theDumper) const
+{
+  FeaturePtr aBase = feature();
+  std::string aPartName = theDumper.name(aBase->document());
+
+  theDumper << aBase << " = model.addPolyline3D(" << aPartName << ", "
+            << aBase->selectionList(BuildPlugin_Polyline::BASE_OBJECTS_ID()) << ", "
+            << closed() << ")" << std::endl;
+}
+
+//==================================================================================================
+PolylinePtr addPolyline3D(const std::shared_ptr<ModelAPI_Document>& thePart,
+                          const std::list<ModelHighAPI_Selection>& theBaseObjects,
+                          const bool theIsClosed)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(BuildAPI_Polyline::ID());
+  return PolylinePtr(new BuildAPI_Polyline(aFeature, theBaseObjects, theIsClosed));
+}
diff --git a/src/BuildAPI/BuildAPI_Polyline.h b/src/BuildAPI/BuildAPI_Polyline.h
new file mode 100644 (file)
index 0000000..db4e3dc
--- /dev/null
@@ -0,0 +1,81 @@
+// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef BuildAPI_Polyline_H_
+#define BuildAPI_Polyline_H_
+
+#include "BuildAPI.h"
+
+#include <BuildPlugin_Polyline.h>
+
+#include <ModelHighAPI_Interface.h>
+#include <ModelHighAPI_Macro.h>
+
+class ModelHighAPI_Selection;
+
+/// \class BuildAPI_Polyline
+/// \ingroup CPPHighAPI
+/// \brief Interface for Polyline feature.
+class BuildAPI_Polyline: public ModelHighAPI_Interface
+{
+public:
+  /// Constructor without values.
+  BUILDAPI_EXPORT
+    explicit BuildAPI_Polyline(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+
+  /// Constructor with values.
+  BUILDAPI_EXPORT
+  explicit BuildAPI_Polyline(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                             const std::list<ModelHighAPI_Selection>& theBaseObjects,
+                             const bool theIsClosed);
+
+  /// Destructor.
+  BUILDAPI_EXPORT
+  virtual ~BuildAPI_Polyline();
+
+  INTERFACE_2(BuildPlugin_Polyline::ID(),
+              baseObjects, BuildPlugin_Polyline::BASE_OBJECTS_ID(),
+              ModelAPI_AttributeSelectionList, /** Base objects */,
+              closed, BuildPlugin_Polyline::CLOSED_ID(),
+              ModelAPI_AttributeBoolean, /** Closed flag */)
+
+  /// Modify base attribute of the feature.
+  BUILDAPI_EXPORT
+  void setBase(const std::list<ModelHighAPI_Selection>& theBaseObjects);
+
+  /// Set closed flag
+  BUILDAPI_EXPORT void setClosed(const bool theIsClosed);
+
+  /// Dump wrapped feature
+  BUILDAPI_EXPORT
+  virtual void dump(ModelHighAPI_Dumper& theDumper) const;
+};
+
+/// Pointer on Polyline object.
+typedef std::shared_ptr<BuildAPI_Polyline> PolylinePtr;
+
+/// \ingroup CPPHighAPI
+/// \brief Create Polyline feature.
+BUILDAPI_EXPORT
+PolylinePtr addPolyline3D(const std::shared_ptr<ModelAPI_Document>& thePart,
+                          const std::list<ModelHighAPI_Selection>& theBaseObjects,
+                          const bool theIsClosed = false);
+
+#endif // BuildAPI_Polyline_H_
index 616486f6446f4d6c81bb65ff709deb67d3618d6f..403589681dc47b4283f648f83584b6460269285d 100644 (file)
@@ -33,5 +33,6 @@
   #include "BuildAPI_SubShapes.h"
   #include "BuildAPI_Vertex.h"
   #include "BuildAPI_Wire.h"
+  #include "BuildAPI_Polyline.h"
 
 #endif // FeaturesAPI_swig_H_
index 2e03584043b04a1c3fe0f478f60c245893c9b80e..04437e5288df6867bd3094f9b1a68035d2a9c7e6 100644 (file)
@@ -32,6 +32,7 @@ SET(PROJECT_HEADERS
   BuildAPI_SubShapes.h
   BuildAPI_Vertex.h
   BuildAPI_Wire.h
+  BuildAPI_Polyline.h
 )
 
 SET(PROJECT_SOURCES
@@ -45,6 +46,7 @@ SET(PROJECT_SOURCES
   BuildAPI_SubShapes.cpp
   BuildAPI_Vertex.cpp
   BuildAPI_Wire.cpp
+  BuildAPI_Polyline.cpp
 )
 
 SET(PROJECT_LIBRARIES
index 800884c1021f81a47c4d2572a1891b2243b26324..3ec5f1872e6f3097fcc0c1153b98819ef69a4b6e 100644 (file)
@@ -26,6 +26,7 @@
 #include <BuildPlugin_Vertex.h>
 #include <BuildPlugin_Edge.h>
 #include <BuildPlugin_Wire.h>
+#include <BuildPlugin_Polyline.h>
 #include <BuildPlugin_Face.h>
 #include <BuildPlugin_Shell.h>
 #include <BuildPlugin_Solid.h>
@@ -70,7 +71,11 @@ FeaturePtr BuildPlugin_Plugin::createFeature(std::string theFeatureID)
     return FeaturePtr(new BuildPlugin_Edge());
   } else if(theFeatureID == BuildPlugin_Wire::ID()) {
     return FeaturePtr(new BuildPlugin_Wire());
-  } else if(theFeatureID == BuildPlugin_Face::ID()) {
+  } else if (theFeatureID == BuildPlugin_Wire::ID()) {
+       return FeaturePtr(new BuildPlugin_Wire());
+  } else if (theFeatureID == BuildPlugin_Polyline::ID()) {
+       return FeaturePtr(new BuildPlugin_Polyline());
+  } else if (theFeatureID == BuildPlugin_Face::ID()) {
     return FeaturePtr(new BuildPlugin_Face());
   } else if(theFeatureID == BuildPlugin_Shell::ID()) {
     return FeaturePtr(new BuildPlugin_Shell());
diff --git a/src/BuildPlugin/BuildPlugin_Polyline.cpp b/src/BuildPlugin/BuildPlugin_Polyline.cpp
new file mode 100644 (file)
index 0000000..1efc105
--- /dev/null
@@ -0,0 +1,134 @@
+// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "BuildPlugin_Polyline.h"
+
+#include <ModelAPI_AttributeBoolean.h>
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_ResultBody.h>
+#include <ModelAPI_ResultConstruction.h>
+
+#include <Events_InfoMessage.h>
+
+#include <GeomAPI_ShapeExplorer.h>
+#include <GeomAlgoAPI_WireBuilder.h>
+
+#include <GeomAlgoAPI_ShapeTools.h>
+#include <GeomAlgoAPI_EdgeBuilder.h>
+#include <GeomAlgoAPI_PointBuilder.h>
+#include <GeomAlgoAPI_WireBuilder.h>
+
+#include <algorithm>
+
+//=================================================================================================
+BuildPlugin_Polyline::BuildPlugin_Polyline()
+{
+}
+
+//=================================================================================================
+void BuildPlugin_Polyline::initAttributes()
+{
+  data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
+  data()->addAttribute(CLOSED_ID(), ModelAPI_AttributeBoolean::typeId());
+}
+
+//=================================================================================================
+void BuildPlugin_Polyline::execute()
+{
+  // Get closed flag value
+  bool isClosed = boolean(CLOSED_ID())->value();
+
+  // Get base objects list.
+  AttributeSelectionListPtr aSelectionList = selectionList(BASE_OBJECTS_ID());
+
+  // Collect points.
+  ListOfShape aPoints;
+  std::set<GeomShapePtr> aContexts;
+  for (int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
+    AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
+               GeomShapePtr aShape = aSelection->value();
+
+    ResultPtr aContext = aSelection->context();
+    aContexts.insert(aContext->shape());
+
+    if (!aShape.get()) {
+      aShape = aContext->shape();
+               }
+
+    aPoints.push_back(aShape);
+       }
+
+  // Prepare a list of edges
+  ListOfShape anEdges;
+
+  ListOfShape::const_iterator aPointsIt = aPoints.begin();
+  for (; aPointsIt != std::prev(aPoints.end()); ++aPointsIt) {
+    std::shared_ptr<GeomAPI_Pnt> aPnt = GeomAlgoAPI_PointBuilder::point(*aPointsIt);
+    std::shared_ptr<GeomAPI_Pnt> aPntNext = GeomAlgoAPI_PointBuilder::point(*std::next(aPointsIt));
+    anEdges.push_back(GeomAlgoAPI_EdgeBuilder::line(aPnt, aPntNext));
+  }
+
+  if (isClosed) {
+    std::shared_ptr<GeomAPI_Pnt> aLastPnt = GeomAlgoAPI_PointBuilder::point(aPoints.back());
+    std::shared_ptr<GeomAPI_Pnt> aFirstPnt = GeomAlgoAPI_PointBuilder::point(aPoints.front());
+    anEdges.push_back(GeomAlgoAPI_EdgeBuilder::line(aLastPnt, aFirstPnt));
+  }
+
+  // Create wire from edges
+  GeomShapePtr aWire = GeomAlgoAPI_WireBuilder::wire(anEdges);
+       if (!aWire.get()) {
+               setError("Error: Result polyline is empty.");
+               return;
+       }
+
+  // Check the wire.
+  if (GeomAlgoAPI_WireBuilder::isSelfIntersected(aWire)) {
+    setError("Error: Result polyline has self-intersections.");
+    return;
+  }
+
+  // Store result.
+  ResultBodyPtr aResultBody = document()->createBody(data());
+  std::set<GeomShapePtr>::const_iterator aContextIt = aContexts.begin();
+  for (; aContextIt != aContexts.end(); aContextIt++) {
+    aResultBody->storeModified(*aContextIt, aWire, aContextIt == aContexts.begin() ? 0 : -2);
+  }
+
+  aPointsIt = aPoints.cbegin();
+  GeomAPI_ShapeExplorer anExp(aWire, GeomAPI_Shape::EDGE);
+  for (; anExp.more() && aPointsIt != aPoints.cend(); anExp.next(), ++aPointsIt) {
+    GeomShapePtr aPoint = *aPointsIt;
+    GeomShapePtr anEdge = anExp.current();
+    aResultBody->generated(aPoint, anEdge, "Edge", 1);
+  }
+
+  if (!isClosed) {
+    ListOfShape aResPoints;
+    anExp.init(aWire, GeomAPI_Shape::VERTEX);
+    for (; anExp.more(); anExp.next()) {
+      aResPoints.push_back(anExp.current());
+    }
+
+    aResultBody->generated(aResPoints.front(), "FirstVertex", 2);
+    aResultBody->generated(aResPoints.back(), "LastVertex", 3);
+  }
+
+  setResult(aResultBody);
+}
diff --git a/src/BuildPlugin/BuildPlugin_Polyline.h b/src/BuildPlugin/BuildPlugin_Polyline.h
new file mode 100644 (file)
index 0000000..b86e195
--- /dev/null
@@ -0,0 +1,75 @@
+// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef BuildPlugin_Polyline_H_
+#define BuildPlugin_Polyline_H_
+
+#include "BuildPlugin.h"
+
+#include <ModelAPI_Feature.h>
+
+/// \class BuildPlugin_Polyline
+/// \ingroup Plugins
+/// \brief Feature for creation of polyline from set of points.
+class BuildPlugin_Polyline : public ModelAPI_Feature
+{
+public:
+       /// Use plugin manager for features creation
+       BuildPlugin_Polyline();
+
+       /// Feature kind.
+       inline static const std::string& ID()
+       {
+               static const std::string MY_ID("Polyline");
+               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;
+       }
+
+  /// Attribute name of closed flag.
+  inline static const std::string& CLOSED_ID()
+  {
+    static const std::string MY_CLOSED_ID("closed");
+    return MY_CLOSED_ID;
+  }
+
+  /// Default value of the closed attribute
+  inline static bool CLOSED_DEFAULT() { return false; }
+
+       /// \return the kind of a feature.
+       BUILDPLUGIN_EXPORT virtual const std::string& getKind()
+       {
+               static std::string MY_KIND = BuildPlugin_Polyline::ID();
+               return MY_KIND;
+       }
+
+       /// Request for initialization of data model of the feature: adding all attributes.
+       BUILDPLUGIN_EXPORT virtual void initAttributes();
+
+       /// Creates a new part document if needed.
+       BUILDPLUGIN_EXPORT virtual void execute();
+};
+
+#endif
index 63c5cc3212e45938cdf63db22038d2686854677e..de96566f8b8610b229190cb2262eb1f643cd9d75 100644 (file)
         <translation>Segments and wires list should contain at least 2 items</translation>
     </message>
   </context>
+  <context>
+    <name>Polyline:GeomValidators_MinObjectsSelected</name>
+    <message>
+        <source>Error: Attribute "%1" should contain at least %2 items.</source>
+        <translation>Points list should contain at least 2 items</translation>
+    </message>
+  </context>
 </TS>
index 05a97327da1386407eb65aa95febb9078521f1fd..84beb80089ce9a52b6ad61b98d95ba5e5c678f90 100644 (file)
@@ -35,6 +35,7 @@ SET(PROJECT_HEADERS
     BuildPlugin_Vertex.h
     BuildPlugin_Edge.h
     BuildPlugin_Wire.h
+       BuildPlugin_Polyline.h
     BuildPlugin_Face.h
     BuildPlugin_Shell.h
     BuildPlugin_Solid.h
@@ -50,6 +51,7 @@ SET(PROJECT_SOURCES
     BuildPlugin_Vertex.cpp
     BuildPlugin_Edge.cpp
     BuildPlugin_Wire.cpp
+       BuildPlugin_Polyline.cpp
     BuildPlugin_Face.cpp
     BuildPlugin_Shell.cpp
     BuildPlugin_Solid.cpp
@@ -65,6 +67,7 @@ SET(XML_RESOURCES
     vertex_widget.xml
     edge_widget.xml
     wire_widget.xml
+       polyline_widget.xml
     face_widget.xml
     shell_widget.xml
     solid_widget.xml
@@ -101,6 +104,7 @@ INSTALL(DIRECTORY icons/ DESTINATION ${SHAPER_INSTALL_XML_RESOURCES}/icons/Build
 ADD_UNIT_TESTS(TestVertex.py
                TestEdge.py
                TestWire.py
+               TestPolyline.py
                TestFace.py
                TestShell.py
                TestSolid.py
diff --git a/src/BuildPlugin/Test/TestPolyline.py b/src/BuildPlugin/Test/TestPolyline.py
new file mode 100644 (file)
index 0000000..7cca814
--- /dev/null
@@ -0,0 +1,141 @@
+## Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+from salome.shaper import model
+
+# Create document
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+
+# Create sketch
+#
+#  2         4
+#
+#       3
+#
+#  1         5
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchPoint_1 = Sketch_1.addPoint(0, 0)
+SketchPoint_2 = Sketch_1.addPoint(0, 50)
+SketchPoint_3 = Sketch_1.addPoint(25, 25)
+SketchPoint_4 = Sketch_1.addPoint(50, 50)
+SketchPoint_5 = Sketch_1.addPoint(50, 0)
+model.do()
+
+# Get sketch points
+base_name = "Sketch_1/Vertex-SketchPoint_"
+p_1, p_2, p_3, p_4, p_5 = [model.selection("VERTEX", base_name + str(i + 1)) for i in range(0, 5)]
+
+# =============================================================================
+# Test 1. Create unclosed polyline 1-2-3-4-5
+# =============================================================================
+Polyline_1 = model.addPolyline3D(Part_1_doc, [p_1, p_2, p_3, p_4, p_5], False)
+model.do()
+
+model.checkBooleansResult(Polyline_1, model, 1, [0], [0], [0], [4], [4*2])
+
+# =============================================================================
+# Test 2. Create closed polyline 1-2-3-4-5-1
+# =============================================================================
+Polyline_2 = model.addPolyline3D(Part_1_doc, [p_1, p_2, p_3, p_4, p_5], True)
+model.do()
+
+model.checkBooleansResult(Polyline_2, model, 1, [0], [0], [0], [5], [5*2])
+
+# =============================================================================
+# Test 3. Try to create self-intersected unclosed polyline 2-5-4-1
+# =============================================================================
+Polyline_3 = model.addPolyline3D(Part_1_doc, [p_2, p_5, p_4, p_1], False)
+model.do()
+
+model.testNbResults(Polyline_3, 0)
+
+# =============================================================================
+# Test 4. Try to create self-intersected closed polyline 2-4-1-5-2
+# =============================================================================
+Polyline_4 = model.addPolyline3D(Part_1_doc, [p_2, p_4, p_1, p_5], True)
+model.do()
+
+model.testNbResults(Polyline_4, 0)
+
+# =============================================================================
+# Test 5. Try to create closed polyline 1-2-1
+# =============================================================================
+Polyline_5 = model.addPolyline3D(Part_1_doc, [p_1, p_2], True)
+model.do()
+
+model.testNbResults(Polyline_5, 0)
+
+# =============================================================================
+# Test 6. Try to create unclosed polyline on a single point 3
+# =============================================================================
+Polyline_6 = model.addPolyline3D(Part_1_doc, [p_3], False)
+model.do()
+
+model.testNbResults(Polyline_6, 0)
+
+# =============================================================================
+# Test 7. Create unclosed polyline on box vertices
+# =============================================================================
+Part_2 = model.addPart(partSet)
+Part_2_doc = Part_2.document()
+Box_1 = model.addBox(Part_2_doc, 10, 10, 10)
+
+point_names = ("Box_1_1/Back&Box_1_1/Left&Box_1_1/Bottom",
+               "Box_1_1/Back&Box_1_1/Left&Box_1_1/Top",
+               "Box_1_1/Front&Box_1_1/Left&Box_1_1/Top",
+               "Box_1_1/Front&Box_1_1/Left&Box_1_1/Bottom",
+               "Box_1_1/Front&Box_1_1/Right&Box_1_1/Bottom",
+               "Box_1_1/Front&Box_1_1/Right&Box_1_1/Top",
+               "Box_1_1/Back&Box_1_1/Right&Box_1_1/Top",
+               "Box_1_1/Back&Box_1_1/Right&Box_1_1/Bottom")
+points = [model.selection("VERTEX", name) for name in point_names]
+
+Polyline_7 = model.addPolyline3D(Part_2_doc, points, False)
+model.do()
+
+model.checkBooleansResult(Polyline_7, model, 1, [0], [0], [0], [7], [7*2])
+
+# =============================================================================
+# Test 8. Create closed polyline on box vertices
+# =============================================================================
+Part_3 = model.addPart(partSet)
+Part_3_doc = Part_3.document()
+Box_1 = model.addBox(Part_3_doc, 10, 10, 10)
+
+points = [model.selection("VERTEX", name) for name in point_names]
+
+Polyline_8 = model.addPolyline3D(Part_3_doc, points, True)
+model.do()
+
+model.checkBooleansResult(Polyline_8, model, 1, [0], [0], [0], [8], [8*2])
+
+# =============================================================================
+# Test 9. Check subshapes naming
+# =============================================================================
+model.testHaveNamingSubshapes(Polyline_1, model, Part_1_doc)
+model.end()
+
+# =============================================================================
+# Test 10. Check Python dump
+# =============================================================================
+assert(model.checkPythonDump())
\ No newline at end of file
diff --git a/src/BuildPlugin/icons/feature_polyline.png b/src/BuildPlugin/icons/feature_polyline.png
new file mode 100644 (file)
index 0000000..70a4a4f
Binary files /dev/null and b/src/BuildPlugin/icons/feature_polyline.png differ
index 70a4a4f503e86c82feea326768bdfaba2b90fe96..ce93ef6822c2dbd41d21db34a0d8e230caee80fd 100644 (file)
Binary files a/src/BuildPlugin/icons/feature_wire.png and b/src/BuildPlugin/icons/feature_wire.png differ
index 2d98507d676a89cf2005c2763b29f5d3a82b967e..e0a60fdd02bfbe2c656301fde93b8d2584709263 100644 (file)
@@ -31,6 +31,9 @@ email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com
       <feature id="Wire" title="Wire" tooltip ="Create a wire from sketch edges, edges and wires objects" icon="icons/Build/feature_wire.png">
         <source path="wire_widget.xml"/>
       </feature>
+      <feature id="Polyline" title="Polyline" tooltip ="Create a polyline from points" icon="icons/Build/feature_polyline.png">
+        <source path="polyline_widget.xml"/>
+      </feature>
       <feature id="Face" title="Face" tooltip ="Create a face from sketch edges, edges and wires objects" icon="icons/Build/feature_face.png">
         <source path="face_widget.xml"/>
       </feature>
diff --git a/src/BuildPlugin/polyline_widget.xml b/src/BuildPlugin/polyline_widget.xml
new file mode 100644 (file)
index 0000000..4ac398d
--- /dev/null
@@ -0,0 +1,31 @@
+<!--
+Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+See http:##www.salome-platform.org/ or
+email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+-->
+
+<source>
+  <multi_selector id="base_objects"
+                  label="Points and vertices:"
+                  tooltip="Select points or vertices objects."
+                  type_choice="vertices"
+                  concealment="true">
+  </multi_selector>
+  <boolvalue id="closed" label="Closed" tooltip="Makes the polyline closed." default="false"/>
+  <validator id="GeomValidators_MinObjectsSelected" parameters="base_objects,2"/>
+</source>
index 629adb174199dfade45c8e30effef273c1997ab2..250af6d497388e7cf3e57593c0c18610316dafb4 100644 (file)
@@ -25,6 +25,5 @@ email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com
                   tooltip="Select vertices on sketch or vertex objects."
                   type_choice="vertices"
                   concealment="true">
-    <validator id="BuildPlugin_ValidatorBaseForBuild" parameters="vertex"/>
   </multi_selector>
 </source>
index a251c76a0455cc080b2c7157f5933c40acae6c17..539ddb44a6d7e1d2f7b75162e6ca351f2e8ed469 100644 (file)
 
 #include "GeomAlgoAPI_WireBuilder.h"
 
+#include <GeomAPI_Edge.h>
+#include <GeomAPI_Pnt.h>
+#include <GeomAPI_Vertex.h>
+#include <GeomAPI_ShapeExplorer.h>
+
 #include <BRepBuilderAPI_MakeWire.hxx>
 #include <TopoDS.hxx>
 #include <TopoDS_Wire.hxx>
@@ -59,3 +64,62 @@ std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_WireBuilder::wire(const ListOfShape&
   aResultShape->setImpl(new TopoDS_Shape(aWireBuilder.Wire()));
   return aResultShape;
 }
+
+//=================================================================================================
+bool GeomAlgoAPI_WireBuilder::isSelfIntersected(const std::shared_ptr<GeomAPI_Shape>& theWire)
+{
+  // Collect edges.
+  ListOfShape anEdges;
+
+  for (GeomAPI_ShapeExplorer anExp(theWire, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
+    GeomShapePtr anEdge = anExp.current();
+    anEdges.push_back(anEdge);
+  }
+
+  // Check intersections between edges pair-wise
+  int aNbEdges = (int)anEdges.size();
+  std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator anEdgesIt = anEdges.begin();
+  for (int i = 0; anEdgesIt != anEdges.end(); ++anEdgesIt, i++) {
+    std::shared_ptr<GeomAPI_Edge> anEdge1(new GeomAPI_Edge(*anEdgesIt));
+
+    std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator anOtherEdgesIt = std::next(anEdgesIt);
+    for (int j = i + 1; anOtherEdgesIt != anEdges.end(); ++anOtherEdgesIt, j++) {
+      std::shared_ptr<GeomAPI_Edge> anEdge2(new GeomAPI_Edge(*anOtherEdgesIt));
+      GeomShapePtr anInter = anEdge1->intersect(anEdge2);
+      if (!anInter.get()) {
+        continue;
+      }
+
+      bool isOk = false;
+
+      if (anInter->isVertex()) {
+        std::shared_ptr<GeomAPI_Vertex> aVertex(new GeomAPI_Vertex(anInter));
+        std::shared_ptr<GeomAPI_Pnt> aPnt = aVertex->point();
+
+        GeomPointPtr aFirstPnt1 = anEdge1->orientation() == GeomAPI_Shape::FORWARD ?
+                                  anEdge1->firstPoint() : anEdge1->lastPoint();
+        GeomPointPtr aLastPnt1 = anEdge1->orientation() == GeomAPI_Shape::FORWARD ?
+                                 anEdge1->lastPoint() : anEdge1->firstPoint();
+        GeomPointPtr aFirstPnt2 = anEdge2->orientation() == GeomAPI_Shape::FORWARD ?
+                                  anEdge2->firstPoint() : anEdge2->lastPoint();
+        GeomPointPtr aLastPnt2 = anEdge2->orientation() == GeomAPI_Shape::FORWARD ?
+                                 anEdge2->lastPoint() : anEdge2->firstPoint();
+
+        std::shared_ptr<GeomAPI_Pnt> aCommonEndPnt;
+        if (aFirstPnt1->isEqual(aLastPnt2)) {
+          aCommonEndPnt = aFirstPnt1;
+        } else if(aLastPnt1->isEqual(aFirstPnt2)) {
+          aCommonEndPnt = aLastPnt1;
+        }
+
+        isOk = aCommonEndPnt && aPnt->isEqual(aCommonEndPnt);
+      }
+
+      if (!isOk) {
+        return true;
+      }
+    }
+  }
+
+  return false;
+}
\ No newline at end of file
index da80433cee497fb41c0460f6ebc7ac6618397b92..2599083e174ac512ca4335d178038a7be9a5497c 100644 (file)
@@ -37,6 +37,11 @@ class GeomAlgoAPI_WireBuilder
    /// 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);
+
+   /// \brief Checks if the wire is self-intersected.
+   /// \param[in] theWire the wire to be checked
+   /// \return true if the wire is self-intersected, otherwise - false.
+   GEOMALGOAPI_EXPORT static bool isSelfIntersected(const std::shared_ptr<GeomAPI_Shape>& theWire);
 };
 
 #endif
index ad57a024e866706854273323bb9baa504efa5d52..86fc4f791d3712250ca8af8ede287fb3ce029fbd 100644 (file)
@@ -1,6 +1,6 @@
 """Package for Build plugin for the Parametric Geometry API of the Modeler.
 """
 
-from BuildAPI import addVertex, addEdge, addWire, addFace, addShell, addSolid, addCompSolid, addCompound
+from BuildAPI import addVertex, addEdge, addWire, addPolyline3D, addFace, addShell, addSolid, addCompSolid, addCompound
 from BuildAPI import addSubShapes
 from BuildAPI import addFilling