From 704b13912d9014fca20c36fe91a389b9d12353e8 Mon Sep 17 00:00:00 2001 From: mzn Date: Fri, 20 Jul 2018 09:09:48 +0300 Subject: [PATCH] Issue #2560: Add Interpolation feature to Build plugin for creation a curve by the list of points. --- src/BuildAPI/BuildAPI.i | 2 + src/BuildAPI/BuildAPI_Interpolation.cpp | 168 ++++++++++++++++ src/BuildAPI/BuildAPI_Interpolation.h | 122 ++++++++++++ src/BuildAPI/BuildAPI_swig.h | 1 + src/BuildAPI/CMakeLists.txt | 2 + src/BuildPlugin/BuildPlugin_Interpolation.cpp | 140 ++++++++++++++ src/BuildPlugin/BuildPlugin_Interpolation.h | 103 ++++++++++ src/BuildPlugin/BuildPlugin_Plugin.cpp | 3 + src/BuildPlugin/BuildPlugin_Polyline.cpp | 1 - src/BuildPlugin/BuildPlugin_msg_en.ts | 7 + src/BuildPlugin/CMakeLists.txt | 4 + src/BuildPlugin/Test/TestInterpolation.py | 180 ++++++++++++++++++ src/BuildPlugin/Test/TestPolyline.py | 21 +- src/BuildPlugin/icons/axis.png | Bin 0 -> 424 bytes .../icons/feature_interpolation.png | Bin 0 -> 215 bytes src/BuildPlugin/interpolation_widget.xml | 50 +++++ src/BuildPlugin/plugin-Build.xml | 3 + src/GeomAPI/GeomAPI_Vertex.h | 2 +- src/GeomAlgoAPI/CMakeLists.txt | 2 + src/GeomAlgoAPI/GeomAlgoAPI_CurveBuilder.cpp | 146 ++++++++++++++ src/GeomAlgoAPI/GeomAlgoAPI_CurveBuilder.h | 50 +++++ src/PythonAPI/model/build/__init__.py | 2 +- 22 files changed, 1004 insertions(+), 5 deletions(-) create mode 100644 src/BuildAPI/BuildAPI_Interpolation.cpp create mode 100644 src/BuildAPI/BuildAPI_Interpolation.h create mode 100644 src/BuildPlugin/BuildPlugin_Interpolation.cpp create mode 100644 src/BuildPlugin/BuildPlugin_Interpolation.h create mode 100644 src/BuildPlugin/Test/TestInterpolation.py create mode 100644 src/BuildPlugin/icons/axis.png create mode 100644 src/BuildPlugin/icons/feature_interpolation.png create mode 100644 src/BuildPlugin/interpolation_widget.xml create mode 100644 src/GeomAlgoAPI/GeomAlgoAPI_CurveBuilder.cpp create mode 100644 src/GeomAlgoAPI/GeomAlgoAPI_CurveBuilder.h diff --git a/src/BuildAPI/BuildAPI.i b/src/BuildAPI/BuildAPI.i index 22bbb0137..dc38f1904 100644 --- a/src/BuildAPI/BuildAPI.i +++ b/src/BuildAPI/BuildAPI.i @@ -50,6 +50,7 @@ %shared_ptr(BuildAPI_Vertex) %shared_ptr(BuildAPI_Wire) %shared_ptr(BuildAPI_Polyline) +%shared_ptr(BuildAPI_Interpolation) // all supported interfaces %include "BuildAPI_Compound.h" @@ -63,3 +64,4 @@ %include "BuildAPI_Vertex.h" %include "BuildAPI_Wire.h" %include "BuildAPI_Polyline.h" +%include "BuildAPI_Interpolation.h" diff --git a/src/BuildAPI/BuildAPI_Interpolation.cpp b/src/BuildAPI/BuildAPI_Interpolation.cpp new file mode 100644 index 000000000..201151d82 --- /dev/null +++ b/src/BuildAPI/BuildAPI_Interpolation.cpp @@ -0,0 +1,168 @@ +// 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_Interpolation.h" + +#include +#include + +//================================================================================================== +BuildAPI_Interpolation::BuildAPI_Interpolation(const std::shared_ptr& theFeature) +: ModelHighAPI_Interface(theFeature) +{ + initialize(); +} + +//================================================================================================== +BuildAPI_Interpolation::BuildAPI_Interpolation(const FeaturePtr& theFeature, + const std::list& theBaseObjects, + const ModelHighAPI_Selection& theStartTangent, + const ModelHighAPI_Selection& theEndTangent, + const bool theIsClosed, + const bool theIsToReorder) +: ModelHighAPI_Interface(theFeature) +{ + if(initialize()) { + setUseTangents(true); + setTangents(theStartTangent, theEndTangent); + setClosed(theIsClosed); + setReorder(theIsToReorder); + setBase(theBaseObjects); + } +} + +//================================================================================================== +BuildAPI_Interpolation::BuildAPI_Interpolation(const FeaturePtr& theFeature, + const std::list& theBaseObjects, + const bool theIsClosed, + const bool theIsToReorder) + : ModelHighAPI_Interface(theFeature) +{ + if (initialize()) { + setClosed(theIsClosed); + setReorder(theIsToReorder); + setUseTangents(false); + setBase(theBaseObjects); + } +} + +//================================================================================================== +BuildAPI_Interpolation::~BuildAPI_Interpolation() +{ +} + +//================================================================================================== +void BuildAPI_Interpolation::setBase(const std::list& theBaseObjects) +{ + fillAttribute(theBaseObjects, mybaseObjects); + + execute(); +} + +//================================================================================================== +void BuildAPI_Interpolation::setClosed(const bool theIsClosed) +{ + fillAttribute(theIsClosed, myclosed); + + execIfBaseNotEmpty(); +} + +void BuildAPI_Interpolation::setReorder(const bool theIsToReorder) +{ + fillAttribute(theIsToReorder, myreorder); + + execIfBaseNotEmpty(); +} + +void BuildAPI_Interpolation::setUseTangents(const bool theIsToUseTangents) +{ + fillAttribute(theIsToUseTangents ? "true" : "", myuseTangents); + + execIfBaseNotEmpty(); +} + +void BuildAPI_Interpolation::setTangents(const ModelHighAPI_Selection& theStartTangent, + const ModelHighAPI_Selection& theEndTangent) +{ + fillAttribute(theStartTangent, mystartTangent); + fillAttribute(theEndTangent, myendTangent); + + execIfBaseNotEmpty(); +} + +//================================================================================================== +void BuildAPI_Interpolation::dump(ModelHighAPI_Dumper& theDumper) const +{ + FeaturePtr aBase = feature(); + std::string aPartName = theDumper.name(aBase->document()); + + AttributeSelectionListPtr anAttrBaseObjects = + aBase->selectionList(BuildPlugin_Interpolation::BASE_OBJECTS_ID()); + AttributeSelectionPtr anAttrStartTangent = + aBase->selection(BuildPlugin_Interpolation::TANGENT_START_ID()); + AttributeSelectionPtr anAttrEndTangent = + aBase->selection(BuildPlugin_Interpolation::TANGENT_END_ID()); + + theDumper << aBase << " = model.addInterpolation(" << aPartName << ", " + << anAttrBaseObjects << ", "; + + if (anAttrStartTangent->isInitialized() && anAttrEndTangent->isInitialized()) { + theDumper << anAttrStartTangent << ", " << anAttrEndTangent << ", "; + } + + theDumper << closed() << ", " << reorder() << ")" << std::endl; +} + +//================================================================================================== +InterpolationPtr addInterpolation(const std::shared_ptr& thePart, + const std::list& theBaseObjects, + const bool theIsClosed, + const bool theIsToReorder) +{ + std::shared_ptr aFeature = thePart->addFeature(BuildAPI_Interpolation::ID()); + return InterpolationPtr(new BuildAPI_Interpolation(aFeature, + theBaseObjects, + theIsClosed, + theIsToReorder)); +} + +//================================================================================================== +InterpolationPtr addInterpolation(const std::shared_ptr& thePart, + const std::list& theBaseObjects, + const ModelHighAPI_Selection& theStartTangent, + const ModelHighAPI_Selection& theEndTangent, + const bool theIsClosed, + const bool theIsToReorder) +{ + std::shared_ptr aFeature = thePart->addFeature(BuildAPI_Interpolation::ID()); + return InterpolationPtr(new BuildAPI_Interpolation(aFeature, + theBaseObjects, + theStartTangent, + theEndTangent, + theIsClosed, + theIsToReorder)); +} + +//================================================================================================== +void BuildAPI_Interpolation::execIfBaseNotEmpty() +{ + if (baseObjects()->size() > 0) + execute(); +} \ No newline at end of file diff --git a/src/BuildAPI/BuildAPI_Interpolation.h b/src/BuildAPI/BuildAPI_Interpolation.h new file mode 100644 index 000000000..e6b5b090b --- /dev/null +++ b/src/BuildAPI/BuildAPI_Interpolation.h @@ -0,0 +1,122 @@ +// 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_Interpolation_H_ +#define BuildAPI_Interpolation_H_ + +#include "BuildAPI.h" + +#include + +#include +#include +#include + +class ModelHighAPI_Selection; + +/// \class BuildAPI_Interpolation +/// \ingroup CPPHighAPI +/// \brief Interface for Interpolation feature. +class BuildAPI_Interpolation : public ModelHighAPI_Interface +{ +public: + /// Constructor without values. + BUILDAPI_EXPORT + explicit BuildAPI_Interpolation(const FeaturePtr& theFeature); + + /// Constructor with values. + BUILDAPI_EXPORT + explicit BuildAPI_Interpolation(const FeaturePtr& theFeature, + const std::list& theBaseObjects, + const ModelHighAPI_Selection& theStartTangent, + const ModelHighAPI_Selection& theEndTangent, + const bool theIsClosed, const bool theIsToReorder); + + /// Constructor with base objects, closed and reorder parameters. + BUILDAPI_EXPORT + explicit BuildAPI_Interpolation(const FeaturePtr& theFeature, + const std::list& theBaseObjects, + const bool theIsClosed, const bool theIsToReorder); + + /// Destructor. + BUILDAPI_EXPORT + virtual ~BuildAPI_Interpolation(); + + INTERFACE_6(BuildPlugin_Interpolation::ID(), + baseObjects, BuildPlugin_Interpolation::BASE_OBJECTS_ID(), + ModelAPI_AttributeSelectionList, /** Base objects */, + closed, BuildPlugin_Interpolation::CLOSED_ID(), + ModelAPI_AttributeBoolean, /** Closed flag */, + reorder, BuildPlugin_Interpolation::REORDER_ID(), + ModelAPI_AttributeBoolean, /** Reorder flag */, + useTangents, BuildPlugin_Interpolation::USE_TANGENTS_ID(), + ModelAPI_AttributeString, /** Use tangents flag */, + startTangent, BuildPlugin_Interpolation::TANGENT_START_ID(), + ModelAPI_AttributeSelection, /** Start point tangent */, + endTangent, BuildPlugin_Interpolation::TANGENT_END_ID(), + ModelAPI_AttributeSelection, /** End point tangent */) + + /// Modify base attribute of the feature. + BUILDAPI_EXPORT + void setBase(const std::list& theBaseObjects); + + /// Set closed flag + BUILDAPI_EXPORT void setClosed(const bool theIsClosed); + + /// Set reorder flag + BUILDAPI_EXPORT void setReorder(const bool theIsToReorder); + + /// Set use tangents flag + BUILDAPI_EXPORT void setUseTangents(const bool theIsToUseTangents); + + /// Set start and end tangents + BUILDAPI_EXPORT void setTangents(const ModelHighAPI_Selection& theStartTangent, + const ModelHighAPI_Selection& theEndTangent); + + /// Dump wrapped feature + BUILDAPI_EXPORT + virtual void dump(ModelHighAPI_Dumper& theDumper) const; + +private: + void execIfBaseNotEmpty(); +}; + +/// Pointer on Interpolation object. +typedef std::shared_ptr InterpolationPtr; + +/// \ingroup CPPHighAPI +/// \brief Create Interpolation feature. +BUILDAPI_EXPORT +InterpolationPtr addInterpolation(const std::shared_ptr& thePart, + const std::list& theBaseObjects, + const bool theIsClosed = false, + const bool theIsToReorder = false); + +/// \ingroup CPPHighAPI +/// \brief Create Interpolation feature using tangents. +BUILDAPI_EXPORT +InterpolationPtr addInterpolation(const std::shared_ptr& thePart, + const std::list& theBaseObjects, + const ModelHighAPI_Selection& theStartTangent, + const ModelHighAPI_Selection& theEndTangent, + const bool theIsClosed = false, + const bool theIsToReorder = false); + +#endif // BuildAPI_Interpolation_H_ diff --git a/src/BuildAPI/BuildAPI_swig.h b/src/BuildAPI/BuildAPI_swig.h index 403589681..75cfeba29 100644 --- a/src/BuildAPI/BuildAPI_swig.h +++ b/src/BuildAPI/BuildAPI_swig.h @@ -34,5 +34,6 @@ #include "BuildAPI_Vertex.h" #include "BuildAPI_Wire.h" #include "BuildAPI_Polyline.h" + #include "BuildAPI_Interpolation.h" #endif // FeaturesAPI_swig_H_ diff --git a/src/BuildAPI/CMakeLists.txt b/src/BuildAPI/CMakeLists.txt index 04437e528..0cc22fed3 100644 --- a/src/BuildAPI/CMakeLists.txt +++ b/src/BuildAPI/CMakeLists.txt @@ -33,6 +33,7 @@ SET(PROJECT_HEADERS BuildAPI_Vertex.h BuildAPI_Wire.h BuildAPI_Polyline.h + BuildAPI_Interpolation.h ) SET(PROJECT_SOURCES @@ -47,6 +48,7 @@ SET(PROJECT_SOURCES BuildAPI_Vertex.cpp BuildAPI_Wire.cpp BuildAPI_Polyline.cpp + BuildAPI_Interpolation.cpp ) SET(PROJECT_LIBRARIES diff --git a/src/BuildPlugin/BuildPlugin_Interpolation.cpp b/src/BuildPlugin/BuildPlugin_Interpolation.cpp new file mode 100644 index 000000000..bc651c9d6 --- /dev/null +++ b/src/BuildPlugin/BuildPlugin_Interpolation.cpp @@ -0,0 +1,140 @@ +// 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_Interpolation.h" + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include + +#include + +//================================================================================================= +BuildPlugin_Interpolation::BuildPlugin_Interpolation() +{ +} + +//================================================================================================= +void BuildPlugin_Interpolation::initAttributes() +{ + data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId()); + data()->addAttribute(CLOSED_ID(), ModelAPI_AttributeBoolean::typeId()); + data()->addAttribute(REORDER_ID(), ModelAPI_AttributeBoolean::typeId()); + data()->addAttribute(USE_TANGENTS_ID(), ModelAPI_AttributeString::typeId()); + data()->addAttribute(TANGENT_START_ID(), ModelAPI_AttributeSelection::typeId()); + data()->addAttribute(TANGENT_END_ID(), ModelAPI_AttributeSelection::typeId()); +} + +//================================================================================================= +static GeomDirPtr selectionToDir(const AttributeSelectionPtr& theSelection) +{ + GeomDirPtr aDir; + GeomEdgePtr anEdge; + + GeomShapePtr aShape = theSelection->value(); + if (!aShape && theSelection->context()) { + aShape = theSelection->context()->shape(); + } + + if (aShape && aShape->isEdge()) { + anEdge = GeomEdgePtr(new GeomAPI_Edge(aShape)); + } + + if (anEdge && anEdge->isLine()) { + aDir = anEdge->line()->direction(); + } + + return aDir; +} + +//================================================================================================= +void BuildPlugin_Interpolation::execute() +{ + // Get closed flag value + bool isClosed = boolean(CLOSED_ID())->value(); + + // Get reorder flag value + bool isToReorder = boolean(REORDER_ID())->value(); + + // Get use tangents flag value + bool isToUseTangents = !string(USE_TANGENTS_ID())->value().empty(); + + // Get tangent for start and end points + GeomDirPtr aDirStart, aDirEnd; + if (isToUseTangents) { + aDirStart = selectionToDir(selection(TANGENT_START_ID())); + aDirEnd = selectionToDir(selection(TANGENT_END_ID())); + } + + // Get base objects list. + AttributeSelectionListPtr aSelectionList = selectionList(BASE_OBJECTS_ID()); + + // Collect points. + std::list aPoints; + std::set aContexts; + for (int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) { + AttributeSelectionPtr aSelection = aSelectionList->value(anIndex); + + GeomShapePtr aContextShape = aSelection->context()->shape(); + aContexts.insert(aContextShape); + + GeomShapePtr aShape = aSelection->value(); + if (!aShape.get()) { + aShape = aContextShape; + } + + GeomPointPtr aPoint = GeomAlgoAPI_PointBuilder::point(aShape); + aPoints.push_back(aPoint); + } + + // Create curve from points + GeomEdgePtr anEdge = + GeomAlgoAPI_CurveBuilder::edge(aPoints, isClosed, isToReorder, aDirStart, aDirEnd); + if (!anEdge.get()) { + setError("Error: Result curve is empty."); + return; + } + + // Store result. + ResultBodyPtr aResultBody = document()->createBody(data()); + std::set::const_iterator aContextIt = aContexts.begin(); + for (; aContextIt != aContexts.end(); aContextIt++) { + aResultBody->storeModified(*aContextIt, anEdge, aContextIt == aContexts.begin() ? 0 : -2); + } + int aVertexIndex = 1; + for (GeomAPI_ShapeExplorer anExp(anEdge, GeomAPI_Shape::VERTEX); anExp.more(); anExp.next()) { + std::string aVertexName = "Vertex_" + std::to_string((long long)aVertexIndex); + aResultBody->generated(anExp.current(), aVertexName, aVertexIndex++); + } + + setResult(aResultBody); +} diff --git a/src/BuildPlugin/BuildPlugin_Interpolation.h b/src/BuildPlugin/BuildPlugin_Interpolation.h new file mode 100644 index 000000000..bdf6df020 --- /dev/null +++ b/src/BuildPlugin/BuildPlugin_Interpolation.h @@ -0,0 +1,103 @@ +// 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_Interpolation_H_ +#define BuildPlugin_Interpolation_H_ + +#include "BuildPlugin.h" + +#include + +/// \class BuildPlugin_Interpolation +/// \ingroup Plugins +/// \brief Feature for creation of interpolation curve from set of points. +class BuildPlugin_Interpolation : public ModelAPI_Feature +{ +public: + /// Use plugin manager for features creation + BuildPlugin_Interpolation(); + + /// Feature kind. + inline static const std::string& ID() + { + static const std::string MY_ID("Interpolation"); + 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; + } + + /// Attribute name of reorder flag. + inline static const std::string& REORDER_ID() + { + static const std::string MY_REORDER_ID("reorder"); + return MY_REORDER_ID; + } + + /// Attribute name of use tangents flag. + inline static const std::string& USE_TANGENTS_ID() + { + static const std::string MY_USE_TANGENTS_ID("use_tangents"); + return MY_USE_TANGENTS_ID; + } + + /// Attribute name of tangent for start point. + inline static const std::string& TANGENT_START_ID() + { + static const std::string MY_TANGENT_START_ID("tangent_start"); + return MY_TANGENT_START_ID; + } + + /// Attribute name of tangent for end point. + inline static const std::string& TANGENT_END_ID() + { + static const std::string MY_TANGENT_END_ID("tangent_end"); + return MY_TANGENT_END_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_Interpolation::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_Plugin.cpp b/src/BuildPlugin/BuildPlugin_Plugin.cpp index 3ec5f1872..fbf02dbc4 100644 --- a/src/BuildPlugin/BuildPlugin_Plugin.cpp +++ b/src/BuildPlugin/BuildPlugin_Plugin.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -75,6 +76,8 @@ FeaturePtr BuildPlugin_Plugin::createFeature(std::string theFeatureID) return FeaturePtr(new BuildPlugin_Wire()); } else if (theFeatureID == BuildPlugin_Polyline::ID()) { return FeaturePtr(new BuildPlugin_Polyline()); + } else if (theFeatureID == BuildPlugin_Interpolation::ID()) { + return FeaturePtr(new BuildPlugin_Interpolation()); } else if (theFeatureID == BuildPlugin_Face::ID()) { return FeaturePtr(new BuildPlugin_Face()); } else if(theFeatureID == BuildPlugin_Shell::ID()) { diff --git a/src/BuildPlugin/BuildPlugin_Polyline.cpp b/src/BuildPlugin/BuildPlugin_Polyline.cpp index 1efc1058b..7d2369c20 100644 --- a/src/BuildPlugin/BuildPlugin_Polyline.cpp +++ b/src/BuildPlugin/BuildPlugin_Polyline.cpp @@ -28,7 +28,6 @@ #include #include -#include #include #include diff --git a/src/BuildPlugin/BuildPlugin_msg_en.ts b/src/BuildPlugin/BuildPlugin_msg_en.ts index de96566f8..a29504da9 100644 --- a/src/BuildPlugin/BuildPlugin_msg_en.ts +++ b/src/BuildPlugin/BuildPlugin_msg_en.ts @@ -453,4 +453,11 @@ Points list should contain at least 2 items + + Interpolation: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 84beb8008..9668399c7 100644 --- a/src/BuildPlugin/CMakeLists.txt +++ b/src/BuildPlugin/CMakeLists.txt @@ -36,6 +36,7 @@ SET(PROJECT_HEADERS BuildPlugin_Edge.h BuildPlugin_Wire.h BuildPlugin_Polyline.h + BuildPlugin_Interpolation.h BuildPlugin_Face.h BuildPlugin_Shell.h BuildPlugin_Solid.h @@ -52,6 +53,7 @@ SET(PROJECT_SOURCES BuildPlugin_Edge.cpp BuildPlugin_Wire.cpp BuildPlugin_Polyline.cpp + BuildPlugin_Interpolation.cpp BuildPlugin_Face.cpp BuildPlugin_Shell.cpp BuildPlugin_Solid.cpp @@ -68,6 +70,7 @@ SET(XML_RESOURCES edge_widget.xml wire_widget.xml polyline_widget.xml + interpolation_widget.xml face_widget.xml shell_widget.xml solid_widget.xml @@ -105,6 +108,7 @@ ADD_UNIT_TESTS(TestVertex.py TestEdge.py TestWire.py TestPolyline.py + TestInterpolation.py TestFace.py TestShell.py TestSolid.py diff --git a/src/BuildPlugin/Test/TestInterpolation.py b/src/BuildPlugin/Test/TestInterpolation.py new file mode 100644 index 000000000..a790170e8 --- /dev/null +++ b/src/BuildPlugin/Test/TestInterpolation.py @@ -0,0 +1,180 @@ +## 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) + +SketchLine_1 = Sketch_1.addLine(0, 0, -45, -45) +SketchLine_2 = Sketch_1.addLine(0, 0, 45, 45) +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)] + +# Get sketch edges +Tangent_1 = model.selection("EDGE", "Sketch_1/Edge-SketchLine_1") +Tangent_2 = model.selection("EDGE", "Sketch_1/Edge-SketchLine_2") + +# ============================================================================= +# Test 1. Create curve 1-2-3-4-5, closed off, reorder off, without tangents +# ============================================================================= +Interpolation_1 = model.addInterpolation(Part_1_doc, [p_1, p_2, p_3, p_4, p_5], False, False) +model.do() + +model.checkBooleansResult(Interpolation_1, model, 1, [0], [0], [0], [1], [2]) + +# # ============================================================================= +# # Test 2. Create curve 1-2-3-4-5-1, closed on, reorder off, without tangents +# # ============================================================================= +Interpolation_2 = model.addInterpolation(Part_1_doc, [p_1, p_2, p_3, p_4, p_5], True, False) +model.do() + +model.checkBooleansResult(Interpolation_2, model, 1, [0], [0], [0], [1], [2]) + +# # ============================================================================= +# # Test 3. Create curve 1-2-3-4, closed off, reorder on, without tangents +# # ============================================================================= +Interpolation_3 = model.addInterpolation(Part_1_doc, [p_1, p_2, p_3, p_4], False, True) +model.do() + +model.checkBooleansResult(Interpolation_3, model, 1, [0], [0], [0], [1], [2]) + +# ============================================================================= +# Test 4. Create curve 1-2-3-5, closed on, reorder on, without tangents +# ============================================================================= +Interpolation_4 = model.addInterpolation(Part_1_doc, [p_1, p_2, p_3, p_5], True, True) +model.do() + +model.checkBooleansResult(Interpolation_4, model, 1, [0], [0], [0], [1], [2]) + +# ============================================================================= +# Test 5. Create curve 1-2-3-4-5, closed off, reorder off, with tangents +# ============================================================================= + +Interpolation_5 = model.addInterpolation(Part_1_doc, [p_1, p_2, p_3, p_4, p_5], + Tangent_1, Tangent_2, False, False) +model.do() + +model.checkBooleansResult(Interpolation_5, model, 1, [0], [0], [0], [1], [2]) + +# ============================================================================= +# Test 6. Try to create closed curve 1-2-1, closed off, reorder off, without tangents +# ============================================================================= +Interpolation_6 = model.addInterpolation(Part_1_doc, [p_1, p_2, p_1], False, False) +model.do() + +# TODO uncomment +#model.testNbResults(Interpolation_6, 0) + +# ============================================================================= +# Test 7. Try to create curve on a single point 3 +# ============================================================================= +Interpolation_7 = model.addInterpolation(Part_1_doc, [p_3], False, False) +model.do() + +model.testNbResults(Interpolation_7, 0) + +# ============================================================================= +# Test 8. Create curve on box vertices, closed off, reorder off, without tangents +# ============================================================================= +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] + +Interpolation_8 = model.addInterpolation(Part_2_doc, points, False, False) +model.do() + +model.checkBooleansResult(Interpolation_8, model, 1, [0], [0], [0], [1], [2]) + +# ============================================================================= +# Test 9. Create curve on box vertices, closed off, reorder off, with tangents +# ============================================================================= +Part_3 = model.addPart(partSet) +Part_3_doc = Part_3.document() +Box_1 = model.addBox(Part_3_doc, 20, 30, 40) + +points = [model.selection("VERTEX", name) for name in point_names] +Tangent_1 = model.selection("EDGE", "Box_1_1/Back&Box_1_1/Top") +Tangent_2 = model.selection("EDGE", "Box_1_1/Left&Box_1_1/Top") + +Interpolation_9 = model.addInterpolation(Part_3_doc, points, + Tangent_1, Tangent_2, False, False) +model.do() + +model.checkBooleansResult(Interpolation_9, model, 1, [0], [0], [0], [1], [2]) + +# ============================================================================= +# Test 10. Create curve using equal vertices +# ============================================================================= +Part_4 = model.addPart(partSet) +Part_4_doc = Part_4.document() + +Point_1 = model.addPoint(Part_4_doc, 0, 0, 0) +Point_2 = model.addPoint(Part_4_doc, 0, 0, 0) +P_1 = model.selection("VERTEX", "Point_1") +P_2 = model.selection("VERTEX", "Point_2") + +# TODO uncomment +#Interpolation_10 = model.addInterpolation(Part_4_doc, [P_1, P_2], +# False, False) +#model.do() +#model.testNbResults(Interpolation_10, 0) + +# ============================================================================= +# Test 11. Check subshapes naming +# ============================================================================= +model.testHaveNamingSubshapes(Interpolation_5, model, Part_1_doc) +model.testHaveNamingSubshapes(Interpolation_9, model, Part_3_doc) +model.end() + +# ============================================================================= +# Test 12. Check Python dump +# ============================================================================= +assert(model.checkPythonDump()) diff --git a/src/BuildPlugin/Test/TestPolyline.py b/src/BuildPlugin/Test/TestPolyline.py index 7cca81463..622523cfb 100644 --- a/src/BuildPlugin/Test/TestPolyline.py +++ b/src/BuildPlugin/Test/TestPolyline.py @@ -130,12 +130,29 @@ model.do() model.checkBooleansResult(Polyline_8, model, 1, [0], [0], [0], [8], [8*2]) # ============================================================================= -# Test 9. Check subshapes naming +# Test 9. Create polyline using equal vertices +# ============================================================================= +Part_4 = model.addPart(partSet) +Part_4_doc = Part_4.document() + +Point_1 = model.addPoint(Part_4_doc, 0, 0, 0) +Point_2 = model.addPoint(Part_4_doc, 0, 0, 0) +P_1 = model.selection("VERTEX", "Point_1") +P_2 = model.selection("VERTEX", "Point_2") + +# TODO uncomment +#Polyline_9 = model.addPolyline3D(Part_4_doc, [P_1, P_2], False) +#model.do() + +#model.testNbResults(Polyline_9, 0) + +# ============================================================================= +# Test 10. Check subshapes naming # ============================================================================= model.testHaveNamingSubshapes(Polyline_1, model, Part_1_doc) model.end() # ============================================================================= -# Test 10. Check Python dump +# Test 11. Check Python dump # ============================================================================= assert(model.checkPythonDump()) \ No newline at end of file diff --git a/src/BuildPlugin/icons/axis.png b/src/BuildPlugin/icons/axis.png new file mode 100644 index 0000000000000000000000000000000000000000..015d270bf903df722969fc04095d01e7464170f5 GIT binary patch literal 424 zcmV;Z0ayNsP)ZyQB{&gHt)}APb$D<$`;Bw z<=IGd6|@2}jR44nl_2W{>niLGG(>C0M$qk=5VZZb{NCl#O7PqW?}1Gq`l)LDrE&IZ zCCIwI1G24R)<7Qm+e;1LUqQwxxr!Vkru1|bo{U8@5A4772>YU#H)g!RL#YyJ(5as{ zhs})KAmjRZl%qI!q#(T*EP+%}DaOG=1!>POh~W^GV&~?x6$cLprrh$fs2m7p#RdkD zwBs)Ty8`11Il&a#*Ws-V43GkLfSIpfG?T#4KVjlm{*eU!7Hj~Iz#XuaRPYHVD`q^4 SbHEe;0000&U>cv7h@-A}f&3S>O>_%)r2R1cVubP0l+XkKaPB#I literal 0 HcmV?d00001 diff --git a/src/BuildPlugin/interpolation_widget.xml b/src/BuildPlugin/interpolation_widget.xml new file mode 100644 index 000000000..4c12f2ea9 --- /dev/null +++ b/src/BuildPlugin/interpolation_widget.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + diff --git a/src/BuildPlugin/plugin-Build.xml b/src/BuildPlugin/plugin-Build.xml index e0a60fdd0..fe7a05ea2 100644 --- a/src/BuildPlugin/plugin-Build.xml +++ b/src/BuildPlugin/plugin-Build.xml @@ -28,6 +28,9 @@ email : webmaster.salome@opencascade.com + + + diff --git a/src/GeomAPI/GeomAPI_Vertex.h b/src/GeomAPI/GeomAPI_Vertex.h index cee8fd66b..cbde7b538 100644 --- a/src/GeomAPI/GeomAPI_Vertex.h +++ b/src/GeomAPI/GeomAPI_Vertex.h @@ -49,7 +49,7 @@ public: /// Returns true if the current edge is geometrically equal to the given edge. GEOMAPI_EXPORT - bool isEqual(const std::shared_ptr theVert) const; + virtual bool isEqual(const std::shared_ptr theVert) const; }; //! Pointer on the object diff --git a/src/GeomAlgoAPI/CMakeLists.txt b/src/GeomAlgoAPI/CMakeLists.txt index 81c0d1f0f..5fc7a5479 100644 --- a/src/GeomAlgoAPI/CMakeLists.txt +++ b/src/GeomAlgoAPI/CMakeLists.txt @@ -77,6 +77,7 @@ SET(PROJECT_HEADERS GeomAlgoAPI_Fillet.h GeomAlgoAPI_SortListOfShapes.h GeomAlgoAPI_Filling.h + GeomAlgoAPI_CurveBuilder.h ) SET(PROJECT_SOURCES @@ -132,6 +133,7 @@ SET(PROJECT_SOURCES GeomAlgoAPI_Fillet.cpp GeomAlgoAPI_SortListOfShapes.cpp GeomAlgoAPI_Filling.cpp + GeomAlgoAPI_CurveBuilder.cpp ) SET(PROJECT_LIBRARIES diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_CurveBuilder.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_CurveBuilder.cpp new file mode 100644 index 000000000..04966cbd6 --- /dev/null +++ b/src/GeomAlgoAPI/GeomAlgoAPI_CurveBuilder.cpp @@ -0,0 +1,146 @@ +// 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 "GeomAlgoAPI_CurveBuilder.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +static void reorder(Handle(TColgp_HArray1OfPnt) thePoints); + +//================================================================================================= +GeomEdgePtr GeomAlgoAPI_CurveBuilder::edge(const std::list& thePoints, + const bool theIsClosed, + const bool theIsToReorder, + const GeomDirPtr& theStartTangent, + const GeomDirPtr& theEndTangent) +{ + // Prepare points array + Handle(TColgp_HArray1OfPnt) aPoints = new TColgp_HArray1OfPnt(1, (int)thePoints.size()); + std::list::const_iterator anIt = thePoints.begin(); + for (int i = 1; anIt != thePoints.end(); anIt++, i++) { + GeomPointPtr aPoint = *anIt; + aPoints->SetValue(i, aPoint->impl()); + } + + // Reorder points if required + if (theIsToReorder) { + reorder(aPoints); + } + + // If the curve to be closed - remove last point if it is too close to the first one + bool isClose = aPoints->First().Distance(aPoints->Last()) <= gp::Resolution(); + if (isClose && theIsClosed) { + aPoints->Resize(aPoints->Lower(), aPoints->Upper() - 1, Standard_True); + } + + // Initialize interpolator + GeomAPI_Interpolate anInterp(aPoints, theIsClosed, gp::Resolution()); + + // Assign tangents if defined + if (theStartTangent && theEndTangent) { + gp_Dir aDir = theStartTangent->impl(); + gp_Vec anInitialTangent(aDir.XYZ()); + aDir = theEndTangent->impl(); + gp_Vec aFinalTangent(aDir.XYZ()); + + anInterp.Load(anInitialTangent, aFinalTangent); + } + + // Compute + if (aPoints->Length() > 1) { + anInterp.Perform(); + } + + // Set result in form of edge + TopoDS_Edge anEdge; + if (anInterp.IsDone()) { + anEdge = BRepBuilderAPI_MakeEdge(anInterp.Curve()).Edge(); + } + + GeomEdgePtr aResultShape(new GeomAPI_Edge); + aResultShape->setImpl(new TopoDS_Shape(anEdge)); + + return aResultShape; +} + +//================ Auxiliary functions ======================================================== +void reorder(Handle(TColgp_HArray1OfPnt) thePoints) +{ + if (thePoints->Length() < 3) { + return; + } + + int aNbPoints = thePoints->Length(); + int aNbDup = 0; + gp_Pnt aPrevPnt = thePoints->Value(1); + for (int i = 1; i < aNbPoints - 1; i++) { + gp_Pnt aPnt = thePoints->Value(i); + int aNearest = 0; + double aMinDist = RealLast(); + for (int j = i + 1; j <= aNbPoints; j++) { + double aDist = aPnt.SquareDistance(thePoints->Value(j)); + if (aDist < aMinDist && (aMinDist - aDist) > Precision::Confusion()) { + aNearest = j; + aMinDist = aDist; + } + } + if (aNearest > 0 && aNearest != i + 1) { + // Keep given order of points to use it in case of equidistant candidates + // .-<---<-. + // / \ + // o o o c o->o->o->o->n o o + // | | | + // i i+1 nearest + gp_Pnt aNearestPnt = thePoints->Value(aNearest); + for (int j = aNearest; j > i + 1; j--) { + thePoints->SetValue(j, thePoints->Value(j - 1)); + } + thePoints->SetValue(i + 1, aNearestPnt); + } + if (aPrevPnt.Distance(thePoints->Value(i + 1)) <= Precision::Confusion()) + aNbDup++; + else + aPrevPnt = thePoints->Value(i + 1); + } + + if (aNbDup > 0) { + Handle(TColgp_HArray1OfPnt) aTmpPoints = new TColgp_HArray1OfPnt(1, aNbPoints - aNbDup); + for (int j = 1, i = 1; i <= aNbPoints; i++) { + if (i == 1 || aPrevPnt.Distance(thePoints->Value(i)) > Precision::Confusion()) { + aTmpPoints->SetValue(j++, thePoints->Value(i)); + aPrevPnt = thePoints->Value(i); + } + } + thePoints = aTmpPoints; + } +} \ No newline at end of file diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_CurveBuilder.h b/src/GeomAlgoAPI/GeomAlgoAPI_CurveBuilder.h new file mode 100644 index 000000000..89c4255bb --- /dev/null +++ b/src/GeomAlgoAPI/GeomAlgoAPI_CurveBuilder.h @@ -0,0 +1,50 @@ +// 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 GeomAlgoAPI_CurveBuilder_H_ +#define GeomAlgoAPI_CurveBuilder_H_ + +#include "GeomAlgoAPI.h" + +#include +#include + +/// \class GeomAlgoAPI_CurveBuilder +/// \ingroup DataAlgo +/// \brief Allows to create interpolation curve. +class GeomAlgoAPI_CurveBuilder +{ + public: + /// \brief Creates an interpolation curve from points. + /// \param[in] thePoints list of points. + /// \param[in] theIsClosed defines whether the curve to be closed. + /// \param[in] theIsToReorder defines whether to change the order of points to construct + /// the shortest curve. + /// \param[in] theStartTangent vector tangent to the start of curve. + /// \param[in] theEndTangent vector tangent to the end of curve. + /// \return Interpolation curve (edge). Empty in case of error or bad input. + GEOMALGOAPI_EXPORT static GeomEdgePtr edge(const std::list& thePoints, + const bool theIsClosed, + const bool theIsToReorder, + const GeomDirPtr& theStartTangent, + const GeomDirPtr& theEndTangent); +}; + +#endif diff --git a/src/PythonAPI/model/build/__init__.py b/src/PythonAPI/model/build/__init__.py index 86fc4f791..52902eda2 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, addPolyline3D, addFace, addShell, addSolid, addCompSolid, addCompound +from BuildAPI import addVertex, addEdge, addInterpolation, addWire, addPolyline3D, addFace, addShell, addSolid, addCompSolid, addCompound from BuildAPI import addSubShapes from BuildAPI import addFilling -- 2.39.2