From 8b8d6a8bc075c674a106ab8c484d28058a1f0ea2 Mon Sep 17 00:00:00 2001 From: mzn Date: Thu, 12 Jul 2018 18:50:21 +0300 Subject: [PATCH] Issue #2559: Add Polyline feature to Build plugin for 3D polyline creation. --- src/BuildAPI/BuildAPI.i | 2 + src/BuildAPI/BuildAPI_Polyline.cpp | 83 ++++++++++++ src/BuildAPI/BuildAPI_Polyline.h | 81 +++++++++++ src/BuildAPI/BuildAPI_swig.h | 1 + src/BuildAPI/CMakeLists.txt | 2 + src/BuildPlugin/BuildPlugin_Plugin.cpp | 7 +- src/BuildPlugin/BuildPlugin_Polyline.cpp | 134 +++++++++++++++++++ src/BuildPlugin/BuildPlugin_Polyline.h | 75 +++++++++++ src/BuildPlugin/BuildPlugin_msg_en.ts | 7 + src/BuildPlugin/CMakeLists.txt | 4 + src/BuildPlugin/Test/TestPolyline.py | 141 ++++++++++++++++++++ src/BuildPlugin/icons/feature_polyline.png | Bin 0 -> 672 bytes src/BuildPlugin/icons/feature_wire.png | Bin 672 -> 747 bytes src/BuildPlugin/plugin-Build.xml | 3 + src/BuildPlugin/polyline_widget.xml | 31 +++++ src/BuildPlugin/vertex_widget.xml | 1 - src/GeomAlgoAPI/GeomAlgoAPI_WireBuilder.cpp | 64 +++++++++ src/GeomAlgoAPI/GeomAlgoAPI_WireBuilder.h | 5 + src/PythonAPI/model/build/__init__.py | 2 +- 19 files changed, 640 insertions(+), 3 deletions(-) create mode 100644 src/BuildAPI/BuildAPI_Polyline.cpp create mode 100644 src/BuildAPI/BuildAPI_Polyline.h create mode 100644 src/BuildPlugin/BuildPlugin_Polyline.cpp create mode 100644 src/BuildPlugin/BuildPlugin_Polyline.h create mode 100644 src/BuildPlugin/Test/TestPolyline.py create mode 100644 src/BuildPlugin/icons/feature_polyline.png create mode 100644 src/BuildPlugin/polyline_widget.xml diff --git a/src/BuildAPI/BuildAPI.i b/src/BuildAPI/BuildAPI.i index a9c01420a..22bbb0137 100644 --- a/src/BuildAPI/BuildAPI.i +++ b/src/BuildAPI/BuildAPI.i @@ -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 index 000000000..784d8f91e --- /dev/null +++ b/src/BuildAPI/BuildAPI_Polyline.cpp @@ -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 +// + +#include "BuildAPI_Polyline.h" + +#include +#include + +//================================================================================================== +BuildAPI_Polyline::BuildAPI_Polyline(const std::shared_ptr& theFeature) +: ModelHighAPI_Interface(theFeature) +{ + initialize(); +} + +//================================================================================================== +BuildAPI_Polyline::BuildAPI_Polyline(const std::shared_ptr& theFeature, + const std::list& theBaseObjects, + const bool theIsClosed) +: ModelHighAPI_Interface(theFeature) +{ + if(initialize()) { + setClosed(theIsClosed); + setBase(theBaseObjects); + } +} + +//================================================================================================== +BuildAPI_Polyline::~BuildAPI_Polyline() +{ + +} + +//================================================================================================== +void BuildAPI_Polyline::setBase(const std::list& 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& thePart, + const std::list& theBaseObjects, + const bool theIsClosed) +{ + std::shared_ptr 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 index 000000000..db4e3dc54 --- /dev/null +++ b/src/BuildAPI/BuildAPI_Polyline.h @@ -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 +// + +#ifndef BuildAPI_Polyline_H_ +#define BuildAPI_Polyline_H_ + +#include "BuildAPI.h" + +#include + +#include +#include + +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& theFeature); + + /// Constructor with values. + BUILDAPI_EXPORT + explicit BuildAPI_Polyline(const std::shared_ptr& theFeature, + const std::list& 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& 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 PolylinePtr; + +/// \ingroup CPPHighAPI +/// \brief Create Polyline feature. +BUILDAPI_EXPORT +PolylinePtr addPolyline3D(const std::shared_ptr& thePart, + const std::list& theBaseObjects, + const bool theIsClosed = false); + +#endif // BuildAPI_Polyline_H_ diff --git a/src/BuildAPI/BuildAPI_swig.h b/src/BuildAPI/BuildAPI_swig.h index 616486f64..403589681 100644 --- a/src/BuildAPI/BuildAPI_swig.h +++ b/src/BuildAPI/BuildAPI_swig.h @@ -33,5 +33,6 @@ #include "BuildAPI_SubShapes.h" #include "BuildAPI_Vertex.h" #include "BuildAPI_Wire.h" + #include "BuildAPI_Polyline.h" #endif // FeaturesAPI_swig_H_ diff --git a/src/BuildAPI/CMakeLists.txt b/src/BuildAPI/CMakeLists.txt index 2e0358404..04437e528 100644 --- a/src/BuildAPI/CMakeLists.txt +++ b/src/BuildAPI/CMakeLists.txt @@ -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 diff --git a/src/BuildPlugin/BuildPlugin_Plugin.cpp b/src/BuildPlugin/BuildPlugin_Plugin.cpp index 800884c10..3ec5f1872 100644 --- a/src/BuildPlugin/BuildPlugin_Plugin.cpp +++ b/src/BuildPlugin/BuildPlugin_Plugin.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -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 index 000000000..1efc1058b --- /dev/null +++ b/src/BuildPlugin/BuildPlugin_Polyline.cpp @@ -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 +// + +#include "BuildPlugin_Polyline.h" + +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include + +#include + +//================================================================================================= +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 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 aPnt = GeomAlgoAPI_PointBuilder::point(*aPointsIt); + std::shared_ptr aPntNext = GeomAlgoAPI_PointBuilder::point(*std::next(aPointsIt)); + anEdges.push_back(GeomAlgoAPI_EdgeBuilder::line(aPnt, aPntNext)); + } + + if (isClosed) { + std::shared_ptr aLastPnt = GeomAlgoAPI_PointBuilder::point(aPoints.back()); + std::shared_ptr 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::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 index 000000000..b86e19554 --- /dev/null +++ b/src/BuildPlugin/BuildPlugin_Polyline.h @@ -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 +// + +#ifndef BuildPlugin_Polyline_H_ +#define BuildPlugin_Polyline_H_ + +#include "BuildPlugin.h" + +#include + +/// \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 diff --git a/src/BuildPlugin/BuildPlugin_msg_en.ts b/src/BuildPlugin/BuildPlugin_msg_en.ts index 63c5cc321..de96566f8 100644 --- a/src/BuildPlugin/BuildPlugin_msg_en.ts +++ b/src/BuildPlugin/BuildPlugin_msg_en.ts @@ -446,4 +446,11 @@ Segments and wires list should contain at least 2 items + + Polyline:GeomValidators_MinObjectsSelected + + Error: Attribute "%1" should contain at least %2 items. + Points list should contain at least 2 items + + diff --git a/src/BuildPlugin/CMakeLists.txt b/src/BuildPlugin/CMakeLists.txt index 05a97327d..84beb8008 100644 --- a/src/BuildPlugin/CMakeLists.txt +++ b/src/BuildPlugin/CMakeLists.txt @@ -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 index 000000000..7cca81463 --- /dev/null +++ b/src/BuildPlugin/Test/TestPolyline.py @@ -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 +## + +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 index 0000000000000000000000000000000000000000..70a4a4f503e86c82feea326768bdfaba2b90fe96 GIT binary patch literal 672 zcmV;R0$=@!P);qdw zWK{Nn4T>6Nl-{)zlr2aoqo6MOkSGg+QJ5|WvWT_{irth#R8w2a3rAFw&0-(#o-QhQ zneO#}dCvKr=RE(z;n0>2zyUtja8P8@ivhd`pr{MD7F}M7)}M;e3SbxMbV-p;CjpG9 zYp4+1bpo}QPmJY)Zps`)`jC{ zS&+PwWO)@UQ^~-z z7kWDQ{jQb$4nuFf3k00004XF*Lt006O%3;baP00009a7bBm000ie z000ie0hKEb8<9pRe@jV3K~y+Tg_BE66Hyd~|BjdfVilW+Q*BL*k4jq_)DruMk02@w zA5jw))rC9b&bZa+hJ}f7sjN&iF%bw#T@c!h#1;dk(LPA2c95hLN@)!SVQNe1*tv6y zsI7j<&AD^_^O!SpuS_U{GE7g766+coM`$8~rpAM?+wG9cf91qqf}s{X&yys-=Lzy& z8Pwm7lI05o(bLz5F@FGVx0^=)f)vPPGWh)A8LBulG%GieVne{;;)@lR&18VhV!_#y z7VKoVlBD&J5yZ|+)C@)!1gq9lNrK}zgu`LT7aoD#rA1R~7gZ=?fsgLT!opj!6$*s{ zv40XB9~7pYe+nVSjZlvS$y)Y6n2m*q<6i__9YVl)i9Sh4ZGDpYA7YcKfqLPS|26dp z0#o{3cWz%si2FkJl@PzrV)b=oVh>RqmH0Mj^)2`BKHZ4+b61g`oqm18d{!FuOCa*e-^wNaN+%!56tOPt?0OT9{PQI zU^*~^Y{-JpyL-s+OEl$o`0oj{9kYT})qzX{WL;QK?Ir~b$2(EgIE=uQ2J!hcUiQC1Jllrd=I3k4B4rDdXi#af*Kh$El?rt= zax`pLL9sY17pgXfs@MY16xF7RQ7=liW+5<-nA5zEl4P%pf385C<}s7m@Wvi zh_(uf-IPL9Q(MamM^ux|Vju6GE-HAL?)86p&iS3^JpaSt(3TFs0Y2AoP-N1J0lWvG zs0+9jU0#ZR)}M;e3SbxMbV-p;CjpG9Yp4+1bpo}QPmEPyIC3 zP{;0pOD+J`X>LCZilHy#;`Wk7%(Qtm+*Qj_?+<`6Np`HY=1wh`hw;JZqA3!~y#^4| zH0=03lsjtZraa%=A(_nYj3#||tqlt`p&8URz>D?HBBSvoNxBx~-H+xq{?liX&6Gi~ hNG_8K0+>)I{{W|`s + + + diff --git a/src/BuildPlugin/polyline_widget.xml b/src/BuildPlugin/polyline_widget.xml new file mode 100644 index 000000000..4ac398d02 --- /dev/null +++ b/src/BuildPlugin/polyline_widget.xml @@ -0,0 +1,31 @@ + + + + + + + + diff --git a/src/BuildPlugin/vertex_widget.xml b/src/BuildPlugin/vertex_widget.xml index 629adb174..250af6d49 100644 --- a/src/BuildPlugin/vertex_widget.xml +++ b/src/BuildPlugin/vertex_widget.xml @@ -25,6 +25,5 @@ email : webmaster.salome@opencascade.com - diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_WireBuilder.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_WireBuilder.cpp index a251c76a0..539ddb44a 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_WireBuilder.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_WireBuilder.cpp @@ -20,6 +20,11 @@ #include "GeomAlgoAPI_WireBuilder.h" +#include +#include +#include +#include + #include #include #include @@ -59,3 +64,62 @@ std::shared_ptr GeomAlgoAPI_WireBuilder::wire(const ListOfShape& aResultShape->setImpl(new TopoDS_Shape(aWireBuilder.Wire())); return aResultShape; } + +//================================================================================================= +bool GeomAlgoAPI_WireBuilder::isSelfIntersected(const std::shared_ptr& 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 >::const_iterator anEdgesIt = anEdges.begin(); + for (int i = 0; anEdgesIt != anEdges.end(); ++anEdgesIt, i++) { + std::shared_ptr anEdge1(new GeomAPI_Edge(*anEdgesIt)); + + std::list >::const_iterator anOtherEdgesIt = std::next(anEdgesIt); + for (int j = i + 1; anOtherEdgesIt != anEdges.end(); ++anOtherEdgesIt, j++) { + std::shared_ptr anEdge2(new GeomAPI_Edge(*anOtherEdgesIt)); + GeomShapePtr anInter = anEdge1->intersect(anEdge2); + if (!anInter.get()) { + continue; + } + + bool isOk = false; + + if (anInter->isVertex()) { + std::shared_ptr aVertex(new GeomAPI_Vertex(anInter)); + std::shared_ptr 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 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 diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_WireBuilder.h b/src/GeomAlgoAPI/GeomAlgoAPI_WireBuilder.h index da80433ce..2599083e1 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_WireBuilder.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_WireBuilder.h @@ -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 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& theWire); }; #endif diff --git a/src/PythonAPI/model/build/__init__.py b/src/PythonAPI/model/build/__init__.py index ad57a024e..86fc4f791 100644 --- a/src/PythonAPI/model/build/__init__.py +++ b/src/PythonAPI/model/build/__init__.py @@ -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 -- 2.39.2