From 7eb4c88d46d8fa7d664bc5f505952f4677fd4628 Mon Sep 17 00:00:00 2001 From: jfa Date: Thu, 17 Oct 2019 13:19:33 +0300 Subject: [PATCH] =?utf8?q?Task=20#3016:=203.2=20To=20add=20a=20mode=20?= =?utf8?q?=C2=ABthrough=20all=C2=BB=20for=20features=20RevolutionCut=20and?= =?utf8?q?=20RevolutionFuse?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../FeaturesAPI_RevolutionBoolean.cpp | 60 +++++++++++++++++- .../FeaturesAPI_RevolutionBoolean.h | 30 +++++++++ src/FeaturesPlugin/CMakeLists.txt | 2 + .../FeaturesPlugin_Revolution.cpp | 8 ++- .../FeaturesPlugin_Revolution.h | 7 ++ .../Test/TestRevolutionCut_ThroughAll.py | 60 ++++++++++++++++++ .../Test/TestRevolutionFuse_ThroughAll.py | 60 ++++++++++++++++++ .../doc/TUI_revolutionCutThroughAll.rst | 12 ++++ .../doc/TUI_revolutionFuseThroughAll.rst | 12 ++++ .../examples/revolution_cut_through_all.py | 13 ++++ .../examples/revolution_fuse_through_all.py | 13 ++++ .../revolution_cut_through_all_result.png | Bin 0 -> 17296 bytes .../doc/images/revolution_through_all.png | Bin 0 -> 850 bytes .../doc/revolutionCutFeature.rst | 44 ++++++++++++- .../doc/revolutionFuseFeature.rst | 44 ++++++++++++- .../icons/extrusion_throughall_32x32.png | Bin 0 -> 850 bytes .../icons/revol_throughall_32x32.png | Bin 0 -> 850 bytes src/FeaturesPlugin/revolutioncut_widget.xml | 2 + src/FeaturesPlugin/revolutionfuse_widget.xml | 2 + .../GeomValidators_ZeroOffset.cpp | 1 + 20 files changed, 363 insertions(+), 7 deletions(-) create mode 100644 src/FeaturesPlugin/Test/TestRevolutionCut_ThroughAll.py create mode 100644 src/FeaturesPlugin/Test/TestRevolutionFuse_ThroughAll.py create mode 100644 src/FeaturesPlugin/doc/TUI_revolutionCutThroughAll.rst create mode 100644 src/FeaturesPlugin/doc/TUI_revolutionFuseThroughAll.rst create mode 100644 src/FeaturesPlugin/doc/examples/revolution_cut_through_all.py create mode 100644 src/FeaturesPlugin/doc/examples/revolution_fuse_through_all.py create mode 100644 src/FeaturesPlugin/doc/images/revolution_cut_through_all_result.png create mode 100644 src/FeaturesPlugin/doc/images/revolution_through_all.png create mode 100644 src/FeaturesPlugin/icons/extrusion_throughall_32x32.png create mode 100644 src/FeaturesPlugin/icons/revol_throughall_32x32.png diff --git a/src/FeaturesAPI/FeaturesAPI_RevolutionBoolean.cpp b/src/FeaturesAPI/FeaturesAPI_RevolutionBoolean.cpp index 385244275..3f595c2e9 100644 --- a/src/FeaturesAPI/FeaturesAPI_RevolutionBoolean.cpp +++ b/src/FeaturesAPI/FeaturesAPI_RevolutionBoolean.cpp @@ -94,7 +94,7 @@ void FeaturesAPI_RevolutionBoolean::setAngle(const ModelHighAPI_Double& theAngle //================================================================================================== void FeaturesAPI_RevolutionBoolean::setPlanesAndOffsets(const ModelHighAPI_Selection& theToObject, const ModelHighAPI_Double& theToOffset, - const ModelHighAPI_Selection& theFromObject, + const ModelHighAPI_Selection& theFromObject, const ModelHighAPI_Double& theFromOffset) { fillAttribute(FeaturesPlugin_Revolution::CREATION_METHOD_BY_PLANES(), mycreationMethod); @@ -158,6 +158,8 @@ void FeaturesAPI_RevolutionBoolean::dump(ModelHighAPI_Dumper& theDumper) const theDumper << ", " << anAttrToObject << ", " << anAttrToOffset << ", " << anAttrFromObject << ", " << anAttrFromOffset; + } else { + // Through All } AttributeSelectionListPtr anAttrBoolObjects = @@ -185,6 +187,22 @@ FeaturesAPI_RevolutionCut::FeaturesAPI_RevolutionCut( initialize(); } +//================================================================================================== +FeaturesAPI_RevolutionCut::FeaturesAPI_RevolutionCut( + const std::shared_ptr& theFeature, + const std::list& theBaseObjects, + const ModelHighAPI_Selection& theAxis, + const std::list& theBooleanObjects) +: FeaturesAPI_RevolutionBoolean(theFeature) +{ + if(initialize()) { + fillAttribute(theBaseObjects, mybaseObjects); + fillAttribute(theAxis, myaxis); + fillAttribute(FeaturesPlugin_Revolution::CREATION_METHOD_THROUGH_ALL(), mycreationMethod); + setBooleanObjects(theBooleanObjects); + } +} + //================================================================================================== FeaturesAPI_RevolutionCut::FeaturesAPI_RevolutionCut( const std::shared_ptr& theFeature, @@ -246,6 +264,18 @@ FeaturesAPI_RevolutionCut::FeaturesAPI_RevolutionCut( } } +//================================================================================================== +RevolutionCutPtr addRevolutionCut(const std::shared_ptr& thePart, + const std::list& theBaseObjects, + const ModelHighAPI_Selection& theAxis, + const std::list& theBooleanObjects) +{ + std::shared_ptr aFeature = + thePart->addFeature(FeaturesPlugin_RevolutionCut::ID()); + return RevolutionCutPtr(new FeaturesAPI_RevolutionCut(aFeature, theBaseObjects, + theAxis, theBooleanObjects)); +} + //================================================================================================== RevolutionCutPtr addRevolutionCut(const std::shared_ptr& thePart, const std::list& theBaseObjects, @@ -308,6 +338,22 @@ FeaturesAPI_RevolutionFuse::FeaturesAPI_RevolutionFuse( initialize(); } +//================================================================================================== +FeaturesAPI_RevolutionFuse::FeaturesAPI_RevolutionFuse( + const std::shared_ptr& theFeature, + const std::list& theBaseObjects, + const ModelHighAPI_Selection& theAxis, + const std::list& theBooleanObjects) +: FeaturesAPI_RevolutionBoolean(theFeature) +{ + if(initialize()) { + fillAttribute(theBaseObjects, mybaseObjects); + fillAttribute(theAxis, myaxis); + fillAttribute(FeaturesPlugin_Revolution::CREATION_METHOD_THROUGH_ALL(), mycreationMethod); + setBooleanObjects(theBooleanObjects); + } +} + //================================================================================================== FeaturesAPI_RevolutionFuse::FeaturesAPI_RevolutionFuse( const std::shared_ptr& theFeature, @@ -371,6 +417,18 @@ FeaturesAPI_RevolutionFuse::FeaturesAPI_RevolutionFuse( } } +//================================================================================================== +RevolutionFusePtr addRevolutionFuse(const std::shared_ptr& thePart, + const std::list& theBaseObjects, + const ModelHighAPI_Selection& theAxis, + const std::list& theBooleanObjects) +{ + std::shared_ptr aFeature = + thePart->addFeature(FeaturesPlugin_RevolutionFuse::ID()); + return RevolutionFusePtr(new FeaturesAPI_RevolutionFuse(aFeature, theBaseObjects, + theAxis, theBooleanObjects)); +} + //================================================================================================== RevolutionFusePtr addRevolutionFuse(const std::shared_ptr& thePart, const std::list& theBaseObjects, diff --git a/src/FeaturesAPI/FeaturesAPI_RevolutionBoolean.h b/src/FeaturesAPI/FeaturesAPI_RevolutionBoolean.h index cd7809176..5f636c081 100644 --- a/src/FeaturesAPI/FeaturesAPI_RevolutionBoolean.h +++ b/src/FeaturesAPI/FeaturesAPI_RevolutionBoolean.h @@ -127,6 +127,13 @@ public: FEATURESAPI_EXPORT explicit FeaturesAPI_RevolutionCut(const std::shared_ptr& theFeature); + /// Constructor with values. + FEATURESAPI_EXPORT + explicit FeaturesAPI_RevolutionCut(const std::shared_ptr& theFeature, + const std::list& theBaseObjects, + const ModelHighAPI_Selection& theAxis, + const std::list& theBooleanObjects); + /// Constructor with values. FEATURESAPI_EXPORT explicit FeaturesAPI_RevolutionCut(const std::shared_ptr& theFeature, @@ -159,6 +166,14 @@ public: /// Pointer on RevolutionCut object. typedef std::shared_ptr RevolutionCutPtr; +/// \ingroup CPPHighAPI +/// \brief Create RevolutionCut feature. +FEATURESAPI_EXPORT +RevolutionCutPtr addRevolutionCut(const std::shared_ptr& thePart, + const std::list& theBaseObjects, + const ModelHighAPI_Selection& theAxis, + const std::list& theBooleanObjects); + /// \ingroup CPPHighAPI /// \brief Create RevolutionCut feature. FEATURESAPI_EXPORT @@ -204,6 +219,13 @@ public: FEATURESAPI_EXPORT explicit FeaturesAPI_RevolutionFuse(const std::shared_ptr& theFeature); + /// Constructor with values. + FEATURESAPI_EXPORT + explicit FeaturesAPI_RevolutionFuse(const std::shared_ptr& theFeature, + const std::list& theBaseObjects, + const ModelHighAPI_Selection& theAxis, + const std::list& theBooleanObjects); + /// Constructor with values. FEATURESAPI_EXPORT explicit FeaturesAPI_RevolutionFuse(const std::shared_ptr& theFeature, @@ -236,6 +258,14 @@ public: /// Pointer on RevolutionFuse object. typedef std::shared_ptr RevolutionFusePtr; +/// \ingroup CPPHighAPI +/// \brief Create RevolutionFuse feature. +FEATURESAPI_EXPORT +RevolutionFusePtr addRevolutionFuse(const std::shared_ptr& thePart, + const std::list& theBaseObjects, + const ModelHighAPI_Selection& theAxis, + const std::list& theBooleanObjects); + /// \ingroup CPPHighAPI /// \brief Create RevolutionFuse feature. FEATURESAPI_EXPORT diff --git a/src/FeaturesPlugin/CMakeLists.txt b/src/FeaturesPlugin/CMakeLists.txt index 7640e539a..5316c8c07 100644 --- a/src/FeaturesPlugin/CMakeLists.txt +++ b/src/FeaturesPlugin/CMakeLists.txt @@ -210,9 +210,11 @@ ADD_UNIT_TESTS(TestExtrusion.py TestRevolutionCut.py TestRevolutionCut_ByAngle.py TestRevolutionCut_ByPlanesAndOffsets.py + TestRevolutionCut_ThroughAll.py TestRevolutionFuse.py TestRevolutionFuse_ByAngle.py TestRevolutionFuse_ByPlanesAndOffsets.py + TestRevolutionFuse_ThroughAll.py TestCompositeFeaturesOnCompSolids.py TestPartition.py TestPartition_ErrorMsg.py diff --git a/src/FeaturesPlugin/FeaturesPlugin_Revolution.cpp b/src/FeaturesPlugin/FeaturesPlugin_Revolution.cpp index 9994cd900..1789039f5 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Revolution.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Revolution.cpp @@ -139,12 +139,16 @@ bool FeaturesPlugin_Revolution::makeRevolutions(ListOfShape& theBaseShapes, double aToAngle = 0.0; double aFromAngle = 0.0; - if(string(CREATION_METHOD())->value() == CREATION_METHOD_BY_ANGLES()) { + if (string(CREATION_METHOD())->value() == CREATION_METHOD_BY_ANGLES()) { aToAngle = real(TO_ANGLE_ID())->value(); aFromAngle = real(FROM_ANGLE_ID())->value(); - } else { + } else if (string(CREATION_METHOD())->value() == CREATION_METHOD_BY_PLANES()) { aToAngle = real(TO_OFFSET_ID())->value(); aFromAngle = real(FROM_OFFSET_ID())->value(); + } else if (string(CREATION_METHOD())->value() == CREATION_METHOD_THROUGH_ALL()) { + aToAngle = 360.0; + aFromAngle = 0.0; + } else { } // Getting bounding planes. diff --git a/src/FeaturesPlugin/FeaturesPlugin_Revolution.h b/src/FeaturesPlugin/FeaturesPlugin_Revolution.h index cd0b929fc..820ae3471 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Revolution.h +++ b/src/FeaturesPlugin/FeaturesPlugin_Revolution.h @@ -48,6 +48,13 @@ public: return MY_CREATION_METHOD_ID; } + /// Attribute name for creation method. + inline static const std::string& CREATION_METHOD_THROUGH_ALL() + { + static const std::string MY_CREATION_METHOD_ID("ThroughAll"); + return MY_CREATION_METHOD_ID; + } + /// Attribute name for creation method. inline static const std::string& CREATION_METHOD_BY_ANGLES() { diff --git a/src/FeaturesPlugin/Test/TestRevolutionCut_ThroughAll.py b/src/FeaturesPlugin/Test/TestRevolutionCut_ThroughAll.py new file mode 100644 index 000000000..837f0a4ac --- /dev/null +++ b/src/FeaturesPlugin/Test/TestRevolutionCut_ThroughAll.py @@ -0,0 +1,60 @@ +# Copyright (C) 2018-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 + +import math + +def checkMiddlePoint(shape, x, y, z, tolerance = 1.e-7): + assert(shape is not None) + middlePoint = shape.middlePoint() + assert(math.fabs(middlePoint.x() - x) < tolerance), "{} != {}".format(middlePoint.x(), x) + assert(math.fabs(middlePoint.y() - y) < tolerance), "{} != {}".format(middlePoint.y(), y) + assert(math.fabs(middlePoint.z() - z) < tolerance), "{} != {}".format(middlePoint.z(), z) + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() + +Box_1 = model.addBox(Part_1_doc, 10, 10, 10) +Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 2, 10) +Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Cylinder_1_1")], 5, 5, 0) + +RevolutionCut_1 = model.addRevolutionCut(Part_1_doc, [], model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Top]"), [model.selection("SOLID", "Box_1_1")]) + +Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Translation_1_1/MF:Translated&Cylinder_1_1/Face_2")) +SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "[Translation_1_1/MF:Translated&Cylinder_1_1/Face_1][Translation_1_1/MF:Translated&Cylinder_1_1/Face_2]__cc"), False) +SketchPoint_1 = SketchProjection_1.createdFeature() +SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "[Translation_1_1/MF:Translated&Cylinder_1_1/Face_1][Translation_1_1/MF:Translated&Cylinder_1_1/Face_2]"), False) +SketchCircle_1 = SketchProjection_2.createdFeature() +SketchCircle_2 = Sketch_1.addCircle(5, 5, 2) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_2.center()) +SketchConstraintTangent_1 = Sketch_1.setTangent(SketchCircle_1.results()[1], SketchCircle_2.results()[1]) + +RevolutionCut_1.setNestedSketch(Sketch_1) + +model.do() + +Shape = RevolutionCut_1.results()[0].resultSubShapePair()[0].shape() +checkMiddlePoint(Shape, 5.13562827, 5.0, 5.13562827) + +model.end() + +assert(model.checkPythonDump()) diff --git a/src/FeaturesPlugin/Test/TestRevolutionFuse_ThroughAll.py b/src/FeaturesPlugin/Test/TestRevolutionFuse_ThroughAll.py new file mode 100644 index 000000000..2f1d34213 --- /dev/null +++ b/src/FeaturesPlugin/Test/TestRevolutionFuse_ThroughAll.py @@ -0,0 +1,60 @@ +# Copyright (C) 2018-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 + +import math + +def checkMiddlePoint(shape, x, y, z, tolerance = 1.e-7): + assert(shape is not None) + middlePoint = shape.middlePoint() + assert(math.fabs(middlePoint.x() - x) < tolerance), "{} != {}".format(middlePoint.x(), x) + assert(math.fabs(middlePoint.y() - y) < tolerance), "{} != {}".format(middlePoint.y(), y) + assert(math.fabs(middlePoint.z() - z) < tolerance), "{} != {}".format(middlePoint.z(), z) + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() + +Box_1 = model.addBox(Part_1_doc, 10, 10, 10) +Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 2, 10) +Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Cylinder_1_1")], 5, 5, 0) + +RevolutionFuse_1 = model.addRevolutionFuse(Part_1_doc, [], model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Top]"), [model.selection("SOLID", "Box_1_1")]) + +Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Translation_1_1/MF:Translated&Cylinder_1_1/Face_2")) +SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "[Translation_1_1/MF:Translated&Cylinder_1_1/Face_1][Translation_1_1/MF:Translated&Cylinder_1_1/Face_2]__cc"), False) +SketchPoint_1 = SketchProjection_1.createdFeature() +SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "[Translation_1_1/MF:Translated&Cylinder_1_1/Face_1][Translation_1_1/MF:Translated&Cylinder_1_1/Face_2]"), False) +SketchCircle_1 = SketchProjection_2.createdFeature() +SketchCircle_2 = Sketch_1.addCircle(5, 5, 2) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_2.center()) +SketchConstraintTangent_1 = Sketch_1.setTangent(SketchCircle_1.results()[1], SketchCircle_2.results()[1]) + +RevolutionFuse_1.setNestedSketch(Sketch_1) + +model.do() + +Shape = RevolutionFuse_1.results()[0].resultSubShapePair()[0].shape() +checkMiddlePoint(Shape, 7.01705635, 5.0, 7.01705635) + +model.end() + +assert(model.checkPythonDump()) diff --git a/src/FeaturesPlugin/doc/TUI_revolutionCutThroughAll.rst b/src/FeaturesPlugin/doc/TUI_revolutionCutThroughAll.rst new file mode 100644 index 000000000..b7e158ed4 --- /dev/null +++ b/src/FeaturesPlugin/doc/TUI_revolutionCutThroughAll.rst @@ -0,0 +1,12 @@ + + .. _tui_create_revolution_cut_through_all: + +Create Revolution Cut by 360 degrees +==================================== + +.. literalinclude:: examples/revolution_cut_through_all.py + :linenos: + :language: python + +:download:`Download this script ` + diff --git a/src/FeaturesPlugin/doc/TUI_revolutionFuseThroughAll.rst b/src/FeaturesPlugin/doc/TUI_revolutionFuseThroughAll.rst new file mode 100644 index 000000000..047d25d4c --- /dev/null +++ b/src/FeaturesPlugin/doc/TUI_revolutionFuseThroughAll.rst @@ -0,0 +1,12 @@ + + .. _tui_create_revolution_fuse_through_all: + +Create Revolution Fuse by 360 degrees +===================================== + +.. literalinclude:: examples/revolution_fuse_through_all.py + :linenos: + :language: python + +:download:`Download this script ` + diff --git a/src/FeaturesPlugin/doc/examples/revolution_cut_through_all.py b/src/FeaturesPlugin/doc/examples/revolution_cut_through_all.py new file mode 100644 index 000000000..508147e62 --- /dev/null +++ b/src/FeaturesPlugin/doc/examples/revolution_cut_through_all.py @@ -0,0 +1,13 @@ +from salome.shaper import model + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +Box_1 = model.addBox(Part_1_doc, 10, 10, 10) +Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Box_1_1/Top")) +SketchCircle_1 = Sketch_1.addCircle(5, 5, 2.5) +model.do() +RevolutionCut_1 = model.addRevolutionCut(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Top]"), [model.selection("SOLID", "Box_1_1")]) +model.do() +model.end() diff --git a/src/FeaturesPlugin/doc/examples/revolution_fuse_through_all.py b/src/FeaturesPlugin/doc/examples/revolution_fuse_through_all.py new file mode 100644 index 000000000..fad51a66c --- /dev/null +++ b/src/FeaturesPlugin/doc/examples/revolution_fuse_through_all.py @@ -0,0 +1,13 @@ +from salome.shaper import model + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +Box_1 = model.addBox(Part_1_doc, 10, 10, 10) +Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Box_1_1/Top")) +SketchCircle_1 = Sketch_1.addCircle(5, 5, 2.5) +model.do() +RevolutionFuse_1 = model.addRevolutionFuse(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Top]"), [model.selection("SOLID", "Box_1_1")]) +model.do() +model.end() diff --git a/src/FeaturesPlugin/doc/images/revolution_cut_through_all_result.png b/src/FeaturesPlugin/doc/images/revolution_cut_through_all_result.png new file mode 100644 index 0000000000000000000000000000000000000000..690572198976500dd19e5eef58e33bd2a6110519 GIT binary patch literal 17296 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 NPs`|1l?IOR{{V>{ExZ5# literal 0 HcmV?d00001 diff --git a/src/FeaturesPlugin/doc/images/revolution_through_all.png b/src/FeaturesPlugin/doc/images/revolution_through_all.png new file mode 100644 index 0000000000000000000000000000000000000000..2c1a4b2b73e37080edabcd9699543ec286f40734 GIT binary patch literal 850 zcmV-Y1FigtP)eyF~#ca1uUqyRs!<^mAr9B%H|%AU468HU3A*}={(6>@p# zNQXH<#vI>#UO$zezR=zJP=(@y4_+!?NYc5K003qc#j?dVJMQ(v&v5|0;vQufnvYegn{%dYZUsW@4o4^kzQ+b7 z+lI+h-*~+z5D4sw_1KnY;$3s2*c3DG8-$9By4&gDR5Z#X_cRA&l$M$1=}-p0%HGr< z3eO(-S@ym`IB-FCPkE`9lIOp2eY(!2behKi{0Q8mlSqKiLr`&1_e^=Ik&P|<5QHhK2kxahZ-q)y42?I`y6n)rYUP~Q{9tpG%0zq9Oi(1=0W4~`q?KX zkC(%Fy~Xk-GhjR|N;NIZHBAR_JVEZT!`{9*(L`+@Rn|fPw4FqR5XxXJD7hPD#0Gqb zPx4OtO6QyCOsNPj1Ry4n^gh2<|4onTda?>ER*5d7Wz&Cv6$eP=Ra{t9r8yG?9rkw1 zk^!vAT0IdAh2>l^U5^$3YZhY;^K8Rpirwc9dwVKR`-EEYf8amBKM(M5#Q-+sTVLmy c&=w2u14JqkN^)JDa{vGU07*qoM6N<$f&oB-zW@LL literal 0 HcmV?d00001 diff --git a/src/FeaturesPlugin/doc/revolutionCutFeature.rst b/src/FeaturesPlugin/doc/revolutionCutFeature.rst index b2f5d4704..da86d155e 100644 --- a/src/FeaturesPlugin/doc/revolutionCutFeature.rst +++ b/src/FeaturesPlugin/doc/revolutionCutFeature.rst @@ -18,7 +18,7 @@ The following property panel will be opened: .. centered:: Start sketch -There are two variants of the property panel for Revolution Cut depending on the chosen option: +There are three variants of the property panel for Revolution Cut depending on the chosen option: .. image:: images/revolution_by_angles.png :align: left @@ -28,6 +28,10 @@ There are two variants of the property panel for Revolution Cut depending on the :align: left **By Bounding Planes** revolves objects by specifying bounding planes and angles. +.. image:: images/revolution_through_all.png + :align: left +**Through All** revolves objects by 360 degrees. + By angles -------- @@ -120,4 +124,40 @@ The Result of the operation will be a revolved shape: .. centered:: **Revolution Cut created** -**See Also** a sample TUI Script of :ref:`tui_create_revolution_cut_by_bounding_planes` operation. \ No newline at end of file +**See Also** a sample TUI Script of :ref:`tui_create_revolution_cut_by_bounding_planes` operation. + +Through all +-------- + +.. image:: images/RevolutionCut3.png + :align: center + +.. centered:: + Revolution Cut: revolving through all the space + +- **Base objects** - contains a list of objects selected in the Object Browser or in the Viewer, which will be revolved. +- **Axis** - axis of revolution. +- **Cut from** - contains a list of objects which will but cut with the result of revolution. + +**TUI Commands**: + +.. py:function:: model.addRevolutionCut(part, objectsToRevolve, axis, objectToCut) + + :param part: The current part object. + :param list: A list of objects for revolution. + :param object: An axis. + :param list: A list of objects to cut from. + :return: Created object. + +Result +"""""" + +The Result of the operation will be a revolved shape: + +.. image:: images/revolution_cut_through_all_result.png + :align: center + +.. centered:: + **Revolution Cut created** + +**See Also** a sample TUI Script of :ref:`tui_create_revolution_cut_through_all` operation. diff --git a/src/FeaturesPlugin/doc/revolutionFuseFeature.rst b/src/FeaturesPlugin/doc/revolutionFuseFeature.rst index 3ef022a8a..a608a03d9 100644 --- a/src/FeaturesPlugin/doc/revolutionFuseFeature.rst +++ b/src/FeaturesPlugin/doc/revolutionFuseFeature.rst @@ -18,7 +18,7 @@ The following property panel will be opened: .. centered:: Start sketch -There are two variants of the property panel for Revolution Fuse depending on the chosen option: +There are three variants of the property panel for Revolution Fuse depending on the chosen option: .. image:: images/revolution_by_angles.png :align: left @@ -28,6 +28,10 @@ There are two variants of the property panel for Revolution Fuse depending on th :align: left **By Bounding Planes** revolves objects by specifying bounding planes and angles. +.. image:: images/revolution_through_all.png + :align: left +**Through All** revolves objects by 360 degrees. + By angles -------- @@ -120,4 +124,40 @@ The Result of the operation will be a revolved shape: .. centered:: **Revolution Fuse created** -**See Also** a sample TUI Script of :ref:`tui_create_revolution_fuse_by_bounding_planes` operation. \ No newline at end of file +**See Also** a sample TUI Script of :ref:`tui_create_revolution_fuse_by_bounding_planes` operation. + +Through All +----------- + +.. image:: images/RevolutionFuse3.png + :align: center + +.. centered:: + Revolution Fuse: definition by bounding planes + +- **Base objects** - contains a list of objects selected in the Object Browser or in the Viewer, which will be revolved. +- **Axis** - axis of revolution. +- **Fuse with** - contains a list of objects which will be fused with the result of revolution. + +**TUI Command**: + +.. py:function:: model.addRevolutionFuse(part, objectsToRevolve, axis, objectToFuse) + + :param part: The current part object. + :param list: A list of objects for revolution. + :param object: An axis. + :param list: A list of objects to fuse with. + :return: Created object. + +Result +"""""" + +The Result of the operation will be a revolved shape: + +.. image:: images/revolution_fuse_through_all_result.png + :align: center + +.. centered:: + **Revolution Fuse created** + +**See Also** a sample TUI Script of :ref:`tui_create_revolution_fuse_through_all` operation. diff --git a/src/FeaturesPlugin/icons/extrusion_throughall_32x32.png b/src/FeaturesPlugin/icons/extrusion_throughall_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..2c1a4b2b73e37080edabcd9699543ec286f40734 GIT binary patch literal 850 zcmV-Y1FigtP)eyF~#ca1uUqyRs!<^mAr9B%H|%AU468HU3A*}={(6>@p# zNQXH<#vI>#UO$zezR=zJP=(@y4_+!?NYc5K003qc#j?dVJMQ(v&v5|0;vQufnvYegn{%dYZUsW@4o4^kzQ+b7 z+lI+h-*~+z5D4sw_1KnY;$3s2*c3DG8-$9By4&gDR5Z#X_cRA&l$M$1=}-p0%HGr< z3eO(-S@ym`IB-FCPkE`9lIOp2eY(!2behKi{0Q8mlSqKiLr`&1_e^=Ik&P|<5QHhK2kxahZ-q)y42?I`y6n)rYUP~Q{9tpG%0zq9Oi(1=0W4~`q?KX zkC(%Fy~Xk-GhjR|N;NIZHBAR_JVEZT!`{9*(L`+@Rn|fPw4FqR5XxXJD7hPD#0Gqb zPx4OtO6QyCOsNPj1Ry4n^gh2<|4onTda?>ER*5d7Wz&Cv6$eP=Ra{t9r8yG?9rkw1 zk^!vAT0IdAh2>l^U5^$3YZhY;^K8Rpirwc9dwVKR`-EEYf8amBKM(M5#Q-+sTVLmy c&=w2u14JqkN^)JDa{vGU07*qoM6N<$f&oB-zW@LL literal 0 HcmV?d00001 diff --git a/src/FeaturesPlugin/icons/revol_throughall_32x32.png b/src/FeaturesPlugin/icons/revol_throughall_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..2c1a4b2b73e37080edabcd9699543ec286f40734 GIT binary patch literal 850 zcmV-Y1FigtP)eyF~#ca1uUqyRs!<^mAr9B%H|%AU468HU3A*}={(6>@p# zNQXH<#vI>#UO$zezR=zJP=(@y4_+!?NYc5K003qc#j?dVJMQ(v&v5|0;vQufnvYegn{%dYZUsW@4o4^kzQ+b7 z+lI+h-*~+z5D4sw_1KnY;$3s2*c3DG8-$9By4&gDR5Z#X_cRA&l$M$1=}-p0%HGr< z3eO(-S@ym`IB-FCPkE`9lIOp2eY(!2behKi{0Q8mlSqKiLr`&1_e^=Ik&P|<5QHhK2kxahZ-q)y42?I`y6n)rYUP~Q{9tpG%0zq9Oi(1=0W4~`q?KX zkC(%Fy~Xk-GhjR|N;NIZHBAR_JVEZT!`{9*(L`+@Rn|fPw4FqR5XxXJD7hPD#0Gqb zPx4OtO6QyCOsNPj1Ry4n^gh2<|4onTda?>ER*5d7Wz&Cv6$eP=Ra{t9r8yG?9rkw1 zk^!vAT0IdAh2>l^U5^$3YZhY;^K8Rpirwc9dwVKR`-EEYf8amBKM(M5#Q-+sTVLmy c&=w2u14JqkN^)JDa{vGU07*qoM6N<$f&oB-zW@LL literal 0 HcmV?d00001 diff --git a/src/FeaturesPlugin/revolutioncut_widget.xml b/src/FeaturesPlugin/revolutioncut_widget.xml index a8edd4a49..c3b19383e 100644 --- a/src/FeaturesPlugin/revolutioncut_widget.xml +++ b/src/FeaturesPlugin/revolutioncut_widget.xml @@ -83,6 +83,8 @@ + + + + & if(theFeature->string(*anIt)) { aSelectedMethod = theFeature->string(*anIt)->value(); } + if (aSelectedMethod == "ThroughAll") return true; anIt++; std::string aCreationMethod = *anIt; anIt++; -- 2.39.2