From 82b778ce7a74acd9487eed62a62084184344a047 Mon Sep 17 00:00:00 2001 From: azv Date: Fri, 17 May 2019 09:57:42 +0300 Subject: [PATCH] Task 3.10. BuildEdge from two points --- src/BuildAPI/BuildAPI_Edge.cpp | 37 +++++- src/BuildAPI/BuildAPI_Edge.h | 22 +++- src/BuildPlugin/BuildPlugin_Edge.cpp | 108 ++++++++++++++++-- src/BuildPlugin/BuildPlugin_Edge.h | 41 +++++++ src/BuildPlugin/CMakeLists.txt | 1 + src/BuildPlugin/Test/TestEdge_ByPoints.py | 51 +++++++++ src/BuildPlugin/edge_widget.xml | 37 ++++-- .../icons/edge_by_points_32x32.png | Bin 0 -> 705 bytes .../icons/edge_by_segments_32x32.png | Bin 0 -> 461 bytes 9 files changed, 277 insertions(+), 20 deletions(-) create mode 100644 src/BuildPlugin/Test/TestEdge_ByPoints.py create mode 100644 src/BuildPlugin/icons/edge_by_points_32x32.png create mode 100644 src/BuildPlugin/icons/edge_by_segments_32x32.png diff --git a/src/BuildAPI/BuildAPI_Edge.cpp b/src/BuildAPI/BuildAPI_Edge.cpp index cd8052f30..3371f01ea 100644 --- a/src/BuildAPI/BuildAPI_Edge.cpp +++ b/src/BuildAPI/BuildAPI_Edge.cpp @@ -35,10 +35,26 @@ BuildAPI_Edge::BuildAPI_Edge(const std::shared_ptr& theFeature : ModelHighAPI_Interface(theFeature) { if(initialize()) { + fillAttribute(BuildPlugin_Edge::CREATION_BY_SEGMENTS(), mycreationMethod); setBase(theBaseObjects); } } +//================================================================================================== +BuildAPI_Edge::BuildAPI_Edge(const std::shared_ptr& theFeature, + const ModelHighAPI_Selection& theFirstPoint, + const ModelHighAPI_Selection& theSecondPoint) +: ModelHighAPI_Interface(theFeature) +{ + if(initialize()) { + fillAttribute(BuildPlugin_Edge::CREATION_BY_POINTS(), mycreationMethod); + fillAttribute(theFirstPoint, myfirstPoint); + fillAttribute(theSecondPoint, mysecondPoint); + + execute(); + } +} + //================================================================================================== BuildAPI_Edge::~BuildAPI_Edge() { @@ -59,8 +75,17 @@ void BuildAPI_Edge::dump(ModelHighAPI_Dumper& theDumper) const FeaturePtr aBase = feature(); std::string aPartName = theDumper.name(aBase->document()); - theDumper << aBase << " = model.addEdge(" << aPartName << ", " - << aBase->selectionList(BuildPlugin_Edge::BASE_OBJECTS_ID()) << ")" << std::endl; + theDumper << aBase << " = model.addEdge(" << aPartName << ", "; + + AttributeStringPtr aCreationMethod = aBase->string(BuildPlugin_Edge::CREATION_METHOD()); + if (aCreationMethod && aCreationMethod->isInitialized() && + aCreationMethod->value() == BuildPlugin_Edge::CREATION_BY_POINTS()) { + theDumper << aBase->selection(BuildPlugin_Edge::FIRST_POINT()) << ", " + << aBase->selection(BuildPlugin_Edge::SECOND_POINT()); + } + else + theDumper << aBase->selectionList(BuildPlugin_Edge::BASE_OBJECTS_ID()); + theDumper << ")" << std::endl; } //================================================================================================== @@ -70,3 +95,11 @@ EdgePtr addEdge(const std::shared_ptr& thePart, std::shared_ptr aFeature = thePart->addFeature(BuildAPI_Edge::ID()); return EdgePtr(new BuildAPI_Edge(aFeature, theBaseObjects)); } + +EdgePtr addEdge(const std::shared_ptr& thePart, + const ModelHighAPI_Selection& theFirstPoint, + const ModelHighAPI_Selection& theSecondPoint) +{ + std::shared_ptr aFeature = thePart->addFeature(BuildAPI_Edge::ID()); + return EdgePtr(new BuildAPI_Edge(aFeature, theFirstPoint, theSecondPoint)); +} diff --git a/src/BuildAPI/BuildAPI_Edge.h b/src/BuildAPI/BuildAPI_Edge.h index d5c016399..11a7fa902 100644 --- a/src/BuildAPI/BuildAPI_Edge.h +++ b/src/BuildAPI/BuildAPI_Edge.h @@ -44,13 +44,25 @@ public: explicit BuildAPI_Edge(const std::shared_ptr& theFeature, const std::list& theBaseObjects); + /// Constructor by points. + BUILDAPI_EXPORT + explicit BuildAPI_Edge(const std::shared_ptr& theFeature, + const ModelHighAPI_Selection& theFirstPoint, + const ModelHighAPI_Selection& theSecondPoint); + /// Destructor. BUILDAPI_EXPORT virtual ~BuildAPI_Edge(); - INTERFACE_1(BuildPlugin_Edge::ID(), + INTERFACE_4(BuildPlugin_Edge::ID(), baseObjects, BuildPlugin_Edge::BASE_OBJECTS_ID(), - ModelAPI_AttributeSelectionList, /** Base objects */) + ModelAPI_AttributeSelectionList, /** Base objects */, + creationMethod, BuildPlugin_Edge::CREATION_METHOD(), + ModelAPI_AttributeString, /** Creation method */, + firstPoint, BuildPlugin_Edge::FIRST_POINT(), + ModelAPI_AttributeSelection, /** First point */, + secondPoint, BuildPlugin_Edge::SECOND_POINT(), + ModelAPI_AttributeSelection, /** Second point */) /// Modify base attribute of the feature. BUILDAPI_EXPORT @@ -69,5 +81,11 @@ typedef std::shared_ptr EdgePtr; BUILDAPI_EXPORT EdgePtr addEdge(const std::shared_ptr& thePart, const std::list& theBaseObjects); +/// \ingroup CPPHighAPI +/// \brief Create Edge feature. +BUILDAPI_EXPORT +EdgePtr addEdge(const std::shared_ptr& thePart, + const ModelHighAPI_Selection& theFirstPoint, + const ModelHighAPI_Selection& theSecondPoint); #endif // BuildAPI_Edge_H_ diff --git a/src/BuildPlugin/BuildPlugin_Edge.cpp b/src/BuildPlugin/BuildPlugin_Edge.cpp index c7928d083..0f85ae3e4 100644 --- a/src/BuildPlugin/BuildPlugin_Edge.cpp +++ b/src/BuildPlugin/BuildPlugin_Edge.cpp @@ -20,11 +20,35 @@ #include "BuildPlugin_Edge.h" #include +#include #include +#include +#include #include +#include #include +#include +#include +#include + +static bool getShape(const AttributeSelectionPtr theAttribute, + GeomShapePtr& theShape, + std::string& theError) +{ + theShape = theAttribute->value(); + if (!theShape.get()) { + ResultPtr aContext = theAttribute->context(); + if (!aContext.get()) { + theError = "Error: Attribute has empty context."; + return false; + } + theShape = aContext->shape(); + } + return true; +} + //================================================================================================= BuildPlugin_Edge::BuildPlugin_Edge() { @@ -34,11 +58,30 @@ BuildPlugin_Edge::BuildPlugin_Edge() void BuildPlugin_Edge::initAttributes() { data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId()); + + data()->addAttribute(CREATION_METHOD(), ModelAPI_AttributeString::typeId()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CREATION_METHOD()); + + data()->addAttribute(FIRST_POINT(), ModelAPI_AttributeSelection::typeId()); + data()->addAttribute(SECOND_POINT(), ModelAPI_AttributeSelection::typeId()); } //================================================================================================= void BuildPlugin_Edge::execute() { + AttributeStringPtr aCreationMethod = string(CREATION_METHOD()); + if (aCreationMethod && aCreationMethod->isInitialized() && + aCreationMethod->value() == CREATION_BY_POINTS()) + edgeByPoints(); + else + edgesBySegments(); +} + +//================================================================================================= +void BuildPlugin_Edge::edgesBySegments() +{ + string(CREATION_METHOD())->setValue(CREATION_BY_SEGMENTS()); + // Get base objects list. AttributeSelectionListPtr aSelectionList = selectionList(BASE_OBJECTS_ID()); if(!aSelectionList.get()) { @@ -52,18 +95,14 @@ void BuildPlugin_Edge::execute() // Collect base shapes. ListOfShape aListOfShapes; + std::string aError; int aResultIndex = 0; for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) { AttributeSelectionPtr aSelection = aSelectionList->value(anIndex); - GeomShapePtr aShape = aSelection->value(); - if(!aShape.get()) { - ResultPtr aContext = aSelection->context(); - if(!aContext.get()) { - setError("Error: Attribute has empty context."); - return; - } - - aShape = aContext->shape(); + GeomShapePtr aShape; + if (!getShape(aSelection, aShape, aError)) { + setError(aError); + return; } if(!aShape.get()) { setError("Error: Empty shape selected."); @@ -98,3 +137,54 @@ void BuildPlugin_Edge::execute() removeResults(aResultIndex); } + +void BuildPlugin_Edge::edgeByPoints() +{ + // Get base points. + AttributeSelectionPtr aFirstPointAttr = selection(FIRST_POINT()); + AttributeSelectionPtr aSecondPointAttr = selection(SECOND_POINT()); + if (!aFirstPointAttr.get() || !aSecondPointAttr.get()) { + setError("Error: Not enough points selected."); + return; + } + + std::string aError; + GeomShapePtr aFirstShape, aSecondShape; + if (!getShape(aFirstPointAttr, aFirstShape, aError) || + !getShape(aSecondPointAttr, aSecondShape, aError)) { + setError(aError); + return; + } + if (!aFirstShape.get() || !aSecondShape.get()) { + setError("Error: Empty shape selected."); + return; + } + + if (!aFirstShape->isVertex() || !aSecondShape->isVertex()) { + setError("Error: Selected shape has wrong type. Only vertices acceptable."); + return; + } + + int aResultIndex = 0; + + GeomEdgePtr anEdge = GeomAlgoAPI_EdgeBuilder::line(aFirstShape->vertex()->point(), + aSecondShape->vertex()->point()); + if (!anEdge.get()) { + setError("Error: Algorithm failed."); + return; + } + + // Store result. + ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex); + aResultBody->store(anEdge); + // History of vertices + GeomAPI_ShapeExplorer anExp(anEdge, GeomAPI_Shape::VERTEX); + GeomShapePtr aStartVertex = anExp.current(); + anExp.next(); + GeomShapePtr anEndVertex = anExp.current(); + aResultBody->modified(aFirstShape, aStartVertex); + aResultBody->modified(aSecondShape, anEndVertex); + + setResult(aResultBody, aResultIndex++); + removeResults(aResultIndex); +} diff --git a/src/BuildPlugin/BuildPlugin_Edge.h b/src/BuildPlugin/BuildPlugin_Edge.h index e1f7594dc..27f1665ba 100644 --- a/src/BuildPlugin/BuildPlugin_Edge.h +++ b/src/BuildPlugin/BuildPlugin_Edge.h @@ -54,11 +54,52 @@ public: return MY_KIND; } + /// Attribute name for creation method. + inline static const std::string& CREATION_METHOD() + { + static const std::string MY_CREATION_METHOD_ID("creation_method"); + return MY_CREATION_METHOD_ID; + } + + /// Value for creation method. + inline static const std::string& CREATION_BY_SEGMENTS() + { + static const std::string MY_CREATION_METHOD_ID("by_segments"); + return MY_CREATION_METHOD_ID; + } + + /// Value for creation method. + inline static const std::string& CREATION_BY_POINTS() + { + static const std::string MY_CREATION_METHOD_ID("by_points"); + return MY_CREATION_METHOD_ID; + } + + /// Attribute name for the first point. + inline static const std::string& FIRST_POINT() + { + static const std::string MY_FIRST_POINT_ID("first_point"); + return MY_FIRST_POINT_ID; + } + + /// Attribute name for the second point. + inline static const std::string& SECOND_POINT() + { + static const std::string MY_SECOND_POINT_ID("second_point"); + return MY_SECOND_POINT_ID; + } + /// 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(); + +private: + /// Build edges by the set of segments + void edgesBySegments(); + /// Build edge by two points. + void edgeByPoints(); }; #endif diff --git a/src/BuildPlugin/CMakeLists.txt b/src/BuildPlugin/CMakeLists.txt index f22f6598b..25bc5a013 100644 --- a/src/BuildPlugin/CMakeLists.txt +++ b/src/BuildPlugin/CMakeLists.txt @@ -108,6 +108,7 @@ INSTALL(DIRECTORY icons/ DESTINATION ${SHAPER_INSTALL_XML_RESOURCES}/icons/Build ADD_UNIT_TESTS(TestVertex.py TestVertex_ErrorMsg.py TestEdge.py + TestEdge_ByPoints.py TestEdge_ErrorMsg.py TestWire.py TestWire_ErrorMsg.py diff --git a/src/BuildPlugin/Test/TestEdge_ByPoints.py b/src/BuildPlugin/Test/TestEdge_ByPoints.py new file mode 100644 index 000000000..f5185f141 --- /dev/null +++ b/src/BuildPlugin/Test/TestEdge_ByPoints.py @@ -0,0 +1,51 @@ +# Copyright (C) 2014-2019 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 + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchLine_1 = Sketch_1.addLine(30, -30, -20, -30) +SketchLine_2 = Sketch_1.addLine(-20, -30, -20, 35) +SketchLine_3 = Sketch_1.addLine(-20, 35, 30, 35) +SketchLine_4 = Sketch_1.addLine(30, 35, 30, -30) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint()) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) +SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint()) +SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result()) +SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result()) +SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result()) +SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result()) +model.do() +Edge_1 = model.addEdge(Part_1_doc, model.selection("VERTEX", "Sketch_1/SketchLine_2_StartVertex"), model.selection("VERTEX", "Sketch_1/SketchLine_4_StartVertex")) +Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], model.selection(), 10, 0) +Edge_2 = model.addEdge(Part_1_doc, model.selection("VERTEX", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_2][Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_1][Extrusion_1_1/To_Face]"), model.selection("VERTEX", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_4][Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_3][Extrusion_1_1/To_Face]")) +Edge_3_objects = [model.selection("EDGE", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_1][Extrusion_1_1/To_Face]"), model.selection("EDGE", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_4][Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_1]"), model.selection("EDGE", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_4][Extrusion_1_1/From_Face]")] +Edge_3 = model.addEdge(Part_1_doc, Edge_3_objects) +model.end() + +assert(Edge_1.feature().error() == "") +assert(Edge_2.feature().error() == "") +assert(Edge_3.feature().error() == "") + +assert(model.checkPythonDump()) diff --git a/src/BuildPlugin/edge_widget.xml b/src/BuildPlugin/edge_widget.xml index 3aa7d16c2..be0885578 100644 --- a/src/BuildPlugin/edge_widget.xml +++ b/src/BuildPlugin/edge_widget.xml @@ -1,9 +1,32 @@ - - - + + + + + + + + + + + + + + + + + + diff --git a/src/BuildPlugin/icons/edge_by_points_32x32.png b/src/BuildPlugin/icons/edge_by_points_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..469f9d8e0894d018ce0c7326a1453d6fc25db5cf GIT binary patch literal 705 zcmV;y0zUnTP)4uI$c@)CVX{BN7)rFv^I z=L4Kfw(JvMV~tA|`SJ^`hY5?1NUUx7D`)x&NE*A+nYjfwTYB8dolNnKoAsV{@>I6? z!ksM?duxpLfEMd~t<^XlG(RD+IkBu8y<=v3K-hF+yRW44-m&dmrUC9r=e>0RpjJx| zO!Sr*+W`?#(1fPiOHG@aHV6S=b#f8CZ?Mi707(szME&TIleKDjrdBP_0DKR~^G@DW zyKVw#jRXJyMDvdOWW5qJALq9RZNXyin9&}fQXc^xbaLKm-HsPhO4g*UH}=n-p89Mx zd?otz2fwn^2W{#caB}k(1-uI4wt~FXz*&GAA_4)0xV-7F+#0Mi0?-u)?`_$MQ(Rtd z1KW*BQva?tGC+{{uo0;Vql!lYFd-fqz?66>0F&ZCz&Q})=hXU;N%3C-q;sCH1e3|u z)ZsoqC#wP+FewfIf92;+uK3Eylu9PQA^LjYPkx?2EUyIDjXe2I^uK}-ejYWtI}p~- zjRA!9b7KHNI6sdXKbeu6_nwjXRJY@WRHJ!UwYibh_O%^9f4AvZN+SgTfa&b~;;?=` n5`gaH5Pm*VfPWEV|2h2uiZ%Y;)zs0E00000NkvXXu0mjfYa=#h literal 0 HcmV?d00001 diff --git a/src/BuildPlugin/icons/edge_by_segments_32x32.png b/src/BuildPlugin/icons/edge_by_segments_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..abdccd7c83b95a7276d83723802dfc92401f06f9 GIT binary patch literal 461 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzmSQK*5Dp-y;YjHK@;M7UB8!3Q zuY)k7lg8`{prB-lYeY$Kep*R+Vo@qXd3m{BW?pu2a$-TMUVc&f>~}U&3=E83o-U3d z5v@n38~PnK5NX>lK2iFDUI(Ad0_Jp%B+Z~5Zt51EGc4FPEV{SQxm@ka(noBLl{^gw z3#_(%o@1xktg3!r{{PRvGJ&Cdk?z;{ZFa8lzwP&qb*}a%P43vd`Sau4g+FknGd3Mq z^Oog7*8M++q8b(y-?!M!FrmDB$%$j;x34t4JX)$;z_zDh+Wq?nG??~1Fy|`Yef4qf zi&{0YC5H|susS{1m%%3_@ax&W47F&1&2NAdXUF%NdXvSv9j)KpfmdKI;Vst0Qc^> Ay#N3J literal 0 HcmV?d00001 -- 2.39.2