From 868c6fd2baddaddc9e5d9a75c22491c561c01137 Mon Sep 17 00:00:00 2001 From: cg246364 Date: Wed, 21 Jul 2021 11:39:12 +0200 Subject: [PATCH] Add a new primitive to create a tube with radii and height. --- src/GeomAlgoAPI/CMakeLists.txt | 2 + src/GeomAlgoAPI/GeomAlgoAPI_Sphere.cpp | 20 +- src/GeomAlgoAPI/GeomAlgoAPI_Tube.cpp | 132 ++++++++++++ src/GeomAlgoAPI/GeomAlgoAPI_Tube.h | 57 +++++ src/PrimitivesAPI/CMakeLists.txt | 2 + src/PrimitivesAPI/PrimitivesAPI.i | 2 + src/PrimitivesAPI/PrimitivesAPI_Torus.h | 8 +- src/PrimitivesAPI/PrimitivesAPI_Tube.cpp | 91 ++++++++ src/PrimitivesAPI/PrimitivesAPI_Tube.h | 86 ++++++++ src/PrimitivesAPI/PrimitivesAPI_swig.h | 1 + src/PrimitivesPlugin/CMakeLists.txt | 3 + .../PrimitivesPlugin_Plugin.cpp | 3 + .../PrimitivesPlugin_Sphere.cpp | 3 +- .../PrimitivesPlugin_Sphere.h | 19 +- .../PrimitivesPlugin_Tube.cpp | 78 +++++++ src/PrimitivesPlugin/PrimitivesPlugin_Tube.h | 88 ++++++++ .../PrimitivesPlugin_msg_fr.ts | 201 ++++++++++++++++++ src/PrimitivesPlugin/box_widget.xml | 6 +- src/PrimitivesPlugin/doc/PrimitivesPlugin.rst | 1 + src/PrimitivesPlugin/doc/TUI_tubeFeature.rst | 12 ++ src/PrimitivesPlugin/doc/examples/tube.py | 9 + src/PrimitivesPlugin/doc/images/Sphere.png | Bin 6430 -> 0 bytes .../doc/images/Sphere_button.png | Bin 466 -> 1831 bytes .../doc/images/Sphere_res.png | Bin 17454 -> 0 bytes src/PrimitivesPlugin/doc/images/Tube.png | Bin 0 -> 5163 bytes .../doc/images/Tube_button.png | Bin 0 -> 820 bytes src/PrimitivesPlugin/doc/images/Tube_res.png | Bin 0 -> 6622 bytes .../doc/images/sphere_32x32.png | Bin 1725 -> 2832 bytes .../doc/images/sphere_part_32x32.png | Bin 1265 -> 2484 bytes src/PrimitivesPlugin/doc/tubeFeature.rst | 46 ++++ src/PrimitivesPlugin/icons/sphere.png | Bin 466 -> 1831 bytes src/PrimitivesPlugin/icons/sphere_32x32.png | Bin 1725 -> 2832 bytes .../icons/sphere_part_32x32.png | Bin 1265 -> 2484 bytes src/PrimitivesPlugin/icons/tube.png | Bin 0 -> 820 bytes src/PrimitivesPlugin/plugin-Primitives.xml | 6 + src/PrimitivesPlugin/tube_widget.xml | 26 +++ src/PythonAPI/model/primitives/__init__.py | 2 +- test.API/SHAPER/Primitives/TestTube.py | 66 ++++++ test.API/SHAPER/tests.set | 1 + 39 files changed, 946 insertions(+), 25 deletions(-) create mode 100644 src/GeomAlgoAPI/GeomAlgoAPI_Tube.cpp create mode 100644 src/GeomAlgoAPI/GeomAlgoAPI_Tube.h create mode 100644 src/PrimitivesAPI/PrimitivesAPI_Tube.cpp create mode 100644 src/PrimitivesAPI/PrimitivesAPI_Tube.h create mode 100644 src/PrimitivesPlugin/PrimitivesPlugin_Tube.cpp create mode 100644 src/PrimitivesPlugin/PrimitivesPlugin_Tube.h create mode 100644 src/PrimitivesPlugin/doc/TUI_tubeFeature.rst create mode 100644 src/PrimitivesPlugin/doc/examples/tube.py delete mode 100644 src/PrimitivesPlugin/doc/images/Sphere.png delete mode 100644 src/PrimitivesPlugin/doc/images/Sphere_res.png create mode 100644 src/PrimitivesPlugin/doc/images/Tube.png create mode 100755 src/PrimitivesPlugin/doc/images/Tube_button.png create mode 100644 src/PrimitivesPlugin/doc/images/Tube_res.png create mode 100644 src/PrimitivesPlugin/doc/tubeFeature.rst mode change 100644 => 100755 src/PrimitivesPlugin/icons/sphere.png mode change 100644 => 100755 src/PrimitivesPlugin/icons/sphere_32x32.png mode change 100644 => 100755 src/PrimitivesPlugin/icons/sphere_part_32x32.png create mode 100755 src/PrimitivesPlugin/icons/tube.png create mode 100644 src/PrimitivesPlugin/tube_widget.xml create mode 100644 test.API/SHAPER/Primitives/TestTube.py diff --git a/src/GeomAlgoAPI/CMakeLists.txt b/src/GeomAlgoAPI/CMakeLists.txt index 0c549a45b..4073754d5 100644 --- a/src/GeomAlgoAPI/CMakeLists.txt +++ b/src/GeomAlgoAPI/CMakeLists.txt @@ -91,6 +91,7 @@ SET(PROJECT_HEADERS GeomAlgoAPI_Chamfer.h GeomAlgoAPI_Defeaturing.h GeomAlgoAPI_BoundingBox.h + GeomAlgoAPI_Tube.h ) SET(PROJECT_SOURCES @@ -161,6 +162,7 @@ SET(PROJECT_SOURCES GeomAlgoAPI_Chamfer.cpp GeomAlgoAPI_Defeaturing.cpp GeomAlgoAPI_BoundingBox.cpp + GeomAlgoAPI_Tube.cpp ) SET(PROJECT_LIBRARIES diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Sphere.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Sphere.cpp index 73ca13050..8a9a292ca 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_Sphere.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Sphere.cpp @@ -80,7 +80,7 @@ bool GeomAlgoAPI_Sphere::check() void GeomAlgoAPI_Sphere::build() { myCreatedFaces.clear(); - + if (isSectionSphere) { buildSectionSphere(); } else { @@ -129,7 +129,8 @@ void GeomAlgoAPI_Sphere::buildSectionSphere() gp_Pnt anOrigin(0., 0., 0.); gp_Dir aNormal(-sin(aStartPhiRad), cos(aStartPhiRad), 0.); - //The section is defined by 4 points and up to 4 wires. In the rmin = 0 case, two of the points will actually be the origin + // The section is defined by 4 points and up to 4 wires. In the rmin = 0 case, two of the points + // will actually be the origin double aX = myRMax*sin(myThetaMin * M_PI/180.); double aZ = myRMax*cos(myThetaMin * M_PI/180.); gp_Pnt aTopOuterStart(aX*cos(aStartPhiRad), aX*sin(aStartPhiRad), aZ); @@ -155,9 +156,11 @@ void GeomAlgoAPI_Sphere::buildSectionSphere() anArcOuterBuilder = BRepBuilderAPI_MakeEdge(anOuterCircle, aTopOuterStart, aBaseOuterEnd); anArcOuterBuilder.Build(); - //Two cases : either we need four edges (one being an arc with curvature radius rmin) or we need three (if rmin=0). - // In the later case the top and bottom edges intersect at the origin - // Add the edges to the wire in consecutive order (very important for the face to make sense topologically) + // Two cases : either we need four edges (one being an arc with curvature radius rmin) + // or we need three (if rmin=0). + // In the later case the top and bottom edges intersect at the origin, add the + // edges to the wire in consecutive order (very important for the face to make sense + // topologically) if(myRMin >= Precision::Confusion()){ gp_Circ anInnerCircle(gp_Ax2(anOrigin, aNormal), myRMin); BRepBuilderAPI_MakeEdge anArcInnerBuilder; @@ -202,7 +205,9 @@ void GeomAlgoAPI_Sphere::buildSectionSphere() gp_Ax1 aZAxis(anOrigin, aZDir); // Build the solid using the section face we've created and a revolution builder - BRepPrimAPI_MakeRevol* aRevolBuilder = new BRepPrimAPI_MakeRevol(aFaceBuilder.Face(), aZAxis, myPhiMax * M_PI / 180., Standard_True); + BRepPrimAPI_MakeRevol* aRevolBuilder = new BRepPrimAPI_MakeRevol(aFaceBuilder.Face(), aZAxis, + myPhiMax * M_PI / 180., + Standard_True); if(!aRevolBuilder) { return; myError = "Sphere builder :: section revolution did not succeed"; @@ -213,7 +218,8 @@ void GeomAlgoAPI_Sphere::buildSectionSphere() } // Get the shape, verify it, build a GeomAPI_Shape. - std::shared_ptr aResultShape = std::shared_ptr(new GeomAPI_Shape()) ; + std::shared_ptr aResultShape = + std::shared_ptr(new GeomAPI_Shape()); aResultShape->setImpl(new TopoDS_Shape(aRevolBuilder->Shape())); setShape(aResultShape); diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Tube.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Tube.cpp new file mode 100644 index 000000000..55296f33f --- /dev/null +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Tube.cpp @@ -0,0 +1,132 @@ +// Copyright (C) 2014-2021 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 + +#include + +#include +#include +#include +#include + +#include + +#include + +#include +#include + +//================================================================================================= +GeomAlgoAPI_Tube::GeomAlgoAPI_Tube() +{ +} + +//================================================================================================= +GeomAlgoAPI_Tube::GeomAlgoAPI_Tube(const double theRMin, const double theRMax, const double theZ) +{ + myRMin = theRMin; + myRMax = theRMax; + myZ = theZ; +} + +//================================================================================================= +bool GeomAlgoAPI_Tube::check() +{ + if ((myRMax -myRMin) < Precision::Confusion()) { + myError = "Tube builder :: rmin is greater then or equal to rmax."; + return false; + } else if (myRMin < 0.) { + myError = "Tube builder :: rmin is negative."; + return false; + } else if (myZ < Precision::Confusion()) { + myError = "Tube builder :: z is negative or null."; + return false; + } + + return true; +} + +//================================================================================================= +void GeomAlgoAPI_Tube::build() +{ + buildTube(); +} + +//================================================================================================= +void GeomAlgoAPI_Tube::buildTube() +{ + myCreatedFaces.clear(); + + // Construct the inner and outer circles + gp_Pnt anOrigin(0., 0., 0.); + gp_Dir aNormal(0., 0., 1.); + gp_Circ anInnerCircle(gp_Ax2(anOrigin, aNormal), myRMin); + gp_Circ anOuterCircle(gp_Ax2(anOrigin, aNormal), myRMax); + + // Construct the inner wire + BRepBuilderAPI_MakeEdge anInnerCircleBuilder(anInnerCircle); + anInnerCircleBuilder.Build(); + BRepBuilderAPI_MakeWire anInnerWireBuilder; + anInnerWireBuilder.Add(anInnerCircleBuilder.Edge()); + anInnerWireBuilder.Build(); + TopoDS_Wire anInnerWire(anInnerWireBuilder.Wire()); + + // Construct the outer wire + BRepBuilderAPI_MakeEdge anOuterCircleBuilder(anOuterCircle); + anOuterCircleBuilder.Build(); + BRepBuilderAPI_MakeWire anOuterWireBuilder; + anOuterWireBuilder.Add(anOuterCircleBuilder.Edge()); + anOuterWireBuilder.Build(); + TopoDS_Wire anOuterWire(anOuterWireBuilder.Wire()); + + // Construct the face withe the outer wire + BRepBuilderAPI_MakeFace aFaceBuilder(anOuterWire); + aFaceBuilder.Build(); + TopoDS_Face aFace(aFaceBuilder.Face()); + + // Construct the hole face + BRepAlgo_FaceRestrictor aFaceRestrictor; + aFaceRestrictor.Init(aFace, Standard_False, Standard_True); + aFaceRestrictor.Add(anInnerWire); + aFaceRestrictor.Add(anOuterWire); + aFaceRestrictor.Perform(); + aFace = TopoDS_Face(aFaceRestrictor.Current()); + + // Construct the tube + gp_Vec aVec(aNormal); + gp_Trsf aTrsf; + aTrsf.SetTranslation(aVec * -myZ/2); + BRepBuilderAPI_Transform *aTranformBuilder = new BRepBuilderAPI_Transform(aFace, aTrsf); + if (!aTranformBuilder || !aTranformBuilder->IsDone()) { + myError = "Tube builder :: algorithm failed"; + return; + } + TopoDS_Shape aMovedBase = aTranformBuilder->Shape(); + BRepPrimAPI_MakePrism *aPrismBuilder = new BRepPrimAPI_MakePrism(aMovedBase, aVec * myZ); + + std::shared_ptr aShape = std::shared_ptr(new GeomAPI_Shape()); + aShape->setImpl(new TopoDS_Shape(aPrismBuilder->Shape())); + setShape(aShape); + + setImpl(aPrismBuilder); + setBuilderType(OCCT_BRepBuilderAPI_MakeShape); + + setDone(true); +} diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Tube.h b/src/GeomAlgoAPI/GeomAlgoAPI_Tube.h new file mode 100644 index 000000000..73cfe4881 --- /dev/null +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Tube.h @@ -0,0 +1,57 @@ +// Copyright (C) 2017-2021 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_TUBE_H_ +#define GEOMALGOAPI_TUBE_H_ + +#include + +/**\class GeomAlgoAPI_Tube + * \ingroup DataAlgo + * \brief Allows to create Tube Primitives + */ +class GeomAlgoAPI_Tube : public GeomAlgoAPI_MakeShape +{ + public: + GEOMALGOAPI_EXPORT GeomAlgoAPI_Tube(); + + /// Creates a tube. + /// \param theRMin The inside radius + /// \param theRMax The outside radius + /// \param theZ The heigth + GEOMALGOAPI_EXPORT GeomAlgoAPI_Tube(const double theRMin, + const double theRMax, + const double theZ); + + /// Checks if data for the torus construction is OK. + GEOMALGOAPI_EXPORT bool check(); + + /// Builds the torus. + GEOMALGOAPI_EXPORT void build(); + +private: + /// Builds the the tube with the inside radius, the outside radius and the height. + void buildTube(); + + double myRMin; /// inside radius to create a tube. + double myRMax; /// outside radius to create a tube. + double myZ; /// height to create a tube. +}; + +#endif // GEOMALGOAPI_TUBE_H_ diff --git a/src/PrimitivesAPI/CMakeLists.txt b/src/PrimitivesAPI/CMakeLists.txt index 507b54c45..e6df736f5 100644 --- a/src/PrimitivesAPI/CMakeLists.txt +++ b/src/PrimitivesAPI/CMakeLists.txt @@ -26,6 +26,7 @@ SET(PROJECT_HEADERS PrimitivesAPI_Cylinder.h PrimitivesAPI_Sphere.h PrimitivesAPI_Torus.h + PrimitivesAPI_Tube.h ) SET(PROJECT_SOURCES @@ -34,6 +35,7 @@ SET(PROJECT_SOURCES PrimitivesAPI_Cylinder.cpp PrimitivesAPI_Sphere.cpp PrimitivesAPI_Torus.cpp + PrimitivesAPI_Tube.cpp ) SET(PROJECT_LIBRARIES diff --git a/src/PrimitivesAPI/PrimitivesAPI.i b/src/PrimitivesAPI/PrimitivesAPI.i index 5fa74c454..3e6dc3521 100644 --- a/src/PrimitivesAPI/PrimitivesAPI.i +++ b/src/PrimitivesAPI/PrimitivesAPI.i @@ -43,6 +43,7 @@ %shared_ptr(PrimitivesAPI_Cylinder) %shared_ptr(PrimitivesAPI_Sphere) %shared_ptr(PrimitivesAPI_Torus) +%shared_ptr(PrimitivesAPI_Tube) // all supported interfaces %include "PrimitivesAPI_Box.h" @@ -50,3 +51,4 @@ %include "PrimitivesAPI_Cylinder.h" %include "PrimitivesAPI_Sphere.h" %include "PrimitivesAPI_Torus.h" +%include "PrimitivesAPI_Tube.h" diff --git a/src/PrimitivesAPI/PrimitivesAPI_Torus.h b/src/PrimitivesAPI/PrimitivesAPI_Torus.h index b460da826..9a65372a1 100644 --- a/src/PrimitivesAPI/PrimitivesAPI_Torus.h +++ b/src/PrimitivesAPI/PrimitivesAPI_Torus.h @@ -36,7 +36,7 @@ class ModelHighAPI_Selection; /// \class PrimitivesAPI_Torus /// \ingroup CPPHighAPI -/// \brief Interface for primitive Cone feature. +/// \brief Interface for primitive Torus feature. class PrimitivesAPI_Torus: public ModelHighAPI_Interface { public: @@ -76,11 +76,11 @@ public: virtual void dump(ModelHighAPI_Dumper& theDumper) const; }; -/// Pointer on primitive Cone object +/// Pointer on primitive Torus object typedef std::shared_ptr TorusPtr; /// \ingroup CPPHighAPI -/// \brief Create primitive Cone feature. +/// \brief Create primitive Torus feature. PRIMITIVESAPI_EXPORT TorusPtr addTorus(const std::shared_ptr& thePart, const ModelHighAPI_Selection& theBasePoint, @@ -89,7 +89,7 @@ TorusPtr addTorus(const std::shared_ptr& thePart, const ModelHighAPI_Double& theRingRadius); /// \ingroup CPPHighAPI -/// \brief Create primitive Cone feature. +/// \brief Create primitive Torus feature. PRIMITIVESAPI_EXPORT TorusPtr addTorus(const std::shared_ptr& thePart, const ModelHighAPI_Double& theRadius, diff --git a/src/PrimitivesAPI/PrimitivesAPI_Tube.cpp b/src/PrimitivesAPI/PrimitivesAPI_Tube.cpp new file mode 100644 index 000000000..8bdd639f5 --- /dev/null +++ b/src/PrimitivesAPI/PrimitivesAPI_Tube.cpp @@ -0,0 +1,91 @@ +// Copyright (C) 2017-2021 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 "PrimitivesAPI_Tube.h" + +#include +#include + +//================================================================================================== +PrimitivesAPI_Tube::PrimitivesAPI_Tube(const std::shared_ptr& theFeature) +: ModelHighAPI_Interface(theFeature) +{ + initialize(); +} + +//================================================================================================== +PrimitivesAPI_Tube::PrimitivesAPI_Tube(const std::shared_ptr& theFeature, + const ModelHighAPI_Double& theRMin, + const ModelHighAPI_Double& theRMax, + const ModelHighAPI_Double& theHeight) +: ModelHighAPI_Interface(theFeature) +{ + if (initialize()) { + fillAttribute(theRMin, rmin()); + fillAttribute(theRMax, rmax()); + setHeight(theHeight); + } +} + +//================================================================================================== +PrimitivesAPI_Tube::~PrimitivesAPI_Tube() +{ +} + +//================================================================================================== +void PrimitivesAPI_Tube::setRadius(const ModelHighAPI_Double& theRMin, + const ModelHighAPI_Double& theRMax) +{ + fillAttribute(theRMin, rmin()); + fillAttribute(theRMax, rmax()); + execute(); +} + +//================================================================================================== +void PrimitivesAPI_Tube::setHeight(const ModelHighAPI_Double& theHeight) +{ + fillAttribute(theHeight, height()); + execute(); +} + +//================================================================================================== +void PrimitivesAPI_Tube::dump(ModelHighAPI_Dumper& theDumper) const +{ + FeaturePtr aBase = feature(); + const std::string& aDocName = theDumper.name(aBase->document()); + + theDumper << aBase << " = model.addTube(" << aDocName; + + AttributeDoublePtr anAttrRMin = aBase->real(PrimitivesPlugin_Tube::RMIN_ID()); + AttributeDoublePtr anAttrRMax = aBase->real(PrimitivesPlugin_Tube::RMAX_ID()); + AttributeDoublePtr anAttrHeight = aBase->real(PrimitivesPlugin_Tube::HEIGHT_ID()); + theDumper << ", " << anAttrRMin << ", " << anAttrRMax << ", " << anAttrHeight; + + theDumper << ")" << std::endl; +} + +//================================================================================================== +TubePtr addTube(const std::shared_ptr& thePart, + const ModelHighAPI_Double& theRMin, + const ModelHighAPI_Double& theRMax, + const ModelHighAPI_Double& theHeight) +{ + std::shared_ptr aFeature = thePart->addFeature(PrimitivesAPI_Tube::ID()); + return TubePtr(new PrimitivesAPI_Tube(aFeature, theRMin, theRMax, theHeight)); +} diff --git a/src/PrimitivesAPI/PrimitivesAPI_Tube.h b/src/PrimitivesAPI/PrimitivesAPI_Tube.h new file mode 100644 index 000000000..dd582b18f --- /dev/null +++ b/src/PrimitivesAPI/PrimitivesAPI_Tube.h @@ -0,0 +1,86 @@ +// Copyright (C) 2017-2021 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 PRIMITIVESAPI_TUBE_H_ +#define PRIMITIVESAPI_TUBE_H_ + +#include "PrimitivesAPI.h" + +#include + +#include +#include +#include + + +/// \class PrimitivesAPI_Tube +/// \ingroup CPPHighAPI +/// \brief Interface for primitive Tube feature. +class PrimitivesAPI_Tube: public ModelHighAPI_Interface +{ +public: + /// Constructor without values. + PRIMITIVESAPI_EXPORT + explicit PrimitivesAPI_Tube(const std::shared_ptr& theFeature); + + /// Constructor with values. + PRIMITIVESAPI_EXPORT + explicit PrimitivesAPI_Tube(const std::shared_ptr& theFeature, + const ModelHighAPI_Double& theRMin, + const ModelHighAPI_Double& theRMax, + const ModelHighAPI_Double& theHeight); + + /// Destructor. + PRIMITIVESAPI_EXPORT + virtual ~PrimitivesAPI_Tube(); + + INTERFACE_3(PrimitivesPlugin_Tube::ID(), + rmin, PrimitivesPlugin_Tube::RMIN_ID(), + ModelAPI_AttributeDouble, /** Inner radius */, + rmax, PrimitivesPlugin_Tube::RMAX_ID(), + ModelAPI_AttributeDouble, /** Outer radius */, + height, PrimitivesPlugin_Tube::HEIGHT_ID(), + ModelAPI_AttributeDouble, /** Height */) + + /// Set radius + PRIMITIVESAPI_EXPORT + void setRadius(const ModelHighAPI_Double& theRMin, + const ModelHighAPI_Double& theRMax); + + /// Set height + PRIMITIVESAPI_EXPORT + void setHeight(const ModelHighAPI_Double& theHeight); + + /// Dump wrapped feature + PRIMITIVESAPI_EXPORT + virtual void dump(ModelHighAPI_Dumper& theDumper) const; +}; + +/// Pointer on primitive Tube object +typedef std::shared_ptr TubePtr; + +/// \ingroup CPPHighAPI +/// \brief Create primitive Tube feature. +PRIMITIVESAPI_EXPORT +TubePtr addTube(const std::shared_ptr& thePart, + const ModelHighAPI_Double& theRMin, + const ModelHighAPI_Double& theRMax, + const ModelHighAPI_Double& theHeight); + +#endif // PRIMITIVESAPI_TUBE_H_ diff --git a/src/PrimitivesAPI/PrimitivesAPI_swig.h b/src/PrimitivesAPI/PrimitivesAPI_swig.h index 21934d3a0..7473a911b 100644 --- a/src/PrimitivesAPI/PrimitivesAPI_swig.h +++ b/src/PrimitivesAPI/PrimitivesAPI_swig.h @@ -28,5 +28,6 @@ #include "PrimitivesAPI_Cylinder.h" #include "PrimitivesAPI_Sphere.h" #include "PrimitivesAPI_Torus.h" + #include "PrimitivesAPI_Tube.h" #endif // PRIMITIVESAPI_SWIG_H_ diff --git a/src/PrimitivesPlugin/CMakeLists.txt b/src/PrimitivesPlugin/CMakeLists.txt index 4504f17ee..9c0272d14 100644 --- a/src/PrimitivesPlugin/CMakeLists.txt +++ b/src/PrimitivesPlugin/CMakeLists.txt @@ -25,6 +25,7 @@ SET(PROJECT_HEADERS PrimitivesPlugin_Cylinder.h PrimitivesPlugin_Sphere.h PrimitivesPlugin_Torus.h + PrimitivesPlugin_Tube.h ) SET(PROJECT_SOURCES @@ -34,6 +35,7 @@ SET(PROJECT_SOURCES PrimitivesPlugin_Cylinder.cpp PrimitivesPlugin_Sphere.cpp PrimitivesPlugin_Torus.cpp + PrimitivesPlugin_Tube.cpp ) SET(XML_RESOURCES @@ -43,6 +45,7 @@ SET(XML_RESOURCES cylinder_widget.xml sphere_widget.xml torus_widget.xml + tube_widget.xml ) SET(TEXT_RESOURCES diff --git a/src/PrimitivesPlugin/PrimitivesPlugin_Plugin.cpp b/src/PrimitivesPlugin/PrimitivesPlugin_Plugin.cpp index 876f4dd9a..5a2481133 100644 --- a/src/PrimitivesPlugin/PrimitivesPlugin_Plugin.cpp +++ b/src/PrimitivesPlugin/PrimitivesPlugin_Plugin.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include @@ -52,6 +53,8 @@ FeaturePtr PrimitivesPlugin_Plugin::createFeature(std::string theFeatureID) return FeaturePtr(new PrimitivesPlugin_Sphere); } else if (theFeatureID == PrimitivesPlugin_Torus::ID()) { return FeaturePtr(new PrimitivesPlugin_Torus); + } else if (theFeatureID == PrimitivesPlugin_Tube::ID()) { + return FeaturePtr(new PrimitivesPlugin_Tube); } // feature of such kind is not found return FeaturePtr(); diff --git a/src/PrimitivesPlugin/PrimitivesPlugin_Sphere.cpp b/src/PrimitivesPlugin/PrimitivesPlugin_Sphere.cpp index 26ed6511d..f6da4b6cb 100644 --- a/src/PrimitivesPlugin/PrimitivesPlugin_Sphere.cpp +++ b/src/PrimitivesPlugin/PrimitivesPlugin_Sphere.cpp @@ -44,7 +44,8 @@ PrimitivesPlugin_Sphere::PrimitivesPlugin_Sphere() //================================================================================================= void PrimitivesPlugin_Sphere::initAttributes() { - data()->addAttribute(PrimitivesPlugin_Sphere::CREATION_METHOD(), ModelAPI_AttributeString::typeId()); + data()->addAttribute(PrimitivesPlugin_Sphere::CREATION_METHOD(), + ModelAPI_AttributeString::typeId()); // data for the first mode : by a point and a radius data()->addAttribute(PrimitivesPlugin_Sphere::CENTER_POINT_ID(), diff --git a/src/PrimitivesPlugin/PrimitivesPlugin_Sphere.h b/src/PrimitivesPlugin/PrimitivesPlugin_Sphere.h index 348c1287c..2e54765cd 100644 --- a/src/PrimitivesPlugin/PrimitivesPlugin_Sphere.h +++ b/src/PrimitivesPlugin/PrimitivesPlugin_Sphere.h @@ -79,42 +79,42 @@ class PrimitivesPlugin_Sphere : public ModelAPI_Feature static const std::string MY_RADIUS_ID("radius"); return MY_RADIUS_ID; } - + /// attribute name of the inner radius inline static const std::string& RMIN_ID() { static const std::string MY_RMIN_ID("rmin"); return MY_RMIN_ID; } - + /// attribute name of the outer radius inline static const std::string& RMAX_ID() { static const std::string MY_RMAX_ID("rmax"); return MY_RMAX_ID; } - + /// attribute name of the lower phi limit inline static const std::string& PHIMIN_ID() { static const std::string MY_PHIMIN_ID("phimin"); return MY_PHIMIN_ID; } - + /// attribute name of the higher phi limit inline static const std::string& PHIMAX_ID() { static const std::string MY_PHIMAX_ID("phimax"); return MY_PHIMAX_ID; } - + /// attribute name of the lower theta limit inline static const std::string& THETAMIN_ID() { static const std::string MY_THETAMIN_ID("thetamin"); return MY_THETAMIN_ID; } - + /// attribute name of the higher theta limit inline static const std::string& THETAMAX_ID() { @@ -142,11 +142,12 @@ class PrimitivesPlugin_Sphere : public ModelAPI_Feature /// Load Naming data structure of the feature to the document void loadNamingDS(std::shared_ptr theSphereAlgo, std::shared_ptr theResultSphere); - + /// Perform the creation of the sphere using a point and a radius void createSphereByPtRadius(); - - /// Perform the creation of the sphere using radii (inner and outer) and angle limits (theta and phi) + + /// Perform the creation of the sphere using radii (inner and outer) and angle limits + /// (theta and phi) void createShereByDimensions(); }; diff --git a/src/PrimitivesPlugin/PrimitivesPlugin_Tube.cpp b/src/PrimitivesPlugin/PrimitivesPlugin_Tube.cpp new file mode 100644 index 000000000..d9a90d9ff --- /dev/null +++ b/src/PrimitivesPlugin/PrimitivesPlugin_Tube.cpp @@ -0,0 +1,78 @@ +// 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 + +#include +#include + +//================================================================================================= +PrimitivesPlugin_Tube::PrimitivesPlugin_Tube() // Nothing to do during instantiation +{ +} + +//================================================================================================= +void PrimitivesPlugin_Tube::initAttributes() +{ + data()->addAttribute(PrimitivesPlugin_Tube::RMIN_ID(), ModelAPI_AttributeDouble::typeId()); + data()->addAttribute(PrimitivesPlugin_Tube::RMAX_ID(), ModelAPI_AttributeDouble::typeId()); + data()->addAttribute(PrimitivesPlugin_Tube::HEIGHT_ID(), ModelAPI_AttributeDouble::typeId()); +} + +//================================================================================================= +void PrimitivesPlugin_Tube::execute() +{ + double aRMin = real(PrimitivesPlugin_Tube::RMIN_ID())->value(); + double aRMax = real(PrimitivesPlugin_Tube::RMAX_ID())->value(); + double aZ = real(PrimitivesPlugin_Tube::HEIGHT_ID())->value(); + + std::shared_ptr aTubeAlgo(new GeomAlgoAPI_Tube(aRMin,aRMax,aZ)); + + // These checks should be made to the GUI for the feature but + // the corresponding validator does not exist yet. + if (!aTubeAlgo->check()) { + setError(aTubeAlgo->getError()); + return; + } + + // Build the tube + aTubeAlgo->build(); + + int aResultIndex = 0; + ResultBodyPtr aResultTube = document()->createBody(data(), aResultIndex); + loadNamingDS(aTubeAlgo, aResultTube); + setResult(aResultTube, aResultIndex); +} + +//================================================================================================= +void PrimitivesPlugin_Tube::loadNamingDS(std::shared_ptr theTubeAlgo, + std::shared_ptr theResultTube) +{ + // Load the result + theResultTube->store(theTubeAlgo->shape()); + + // Prepare the naming + theTubeAlgo->prepareNamingFaces(); + + // Insert to faces + int num = 1; + std::map< std::string, std::shared_ptr > listOfFaces = + theTubeAlgo->getCreatedFaces(); + for (std::map< std::string, std::shared_ptr >::iterator it = listOfFaces.begin(); + it != listOfFaces.end(); + ++it) + { + theResultTube->generated((*it).second, (*it).first); + } +} diff --git a/src/PrimitivesPlugin/PrimitivesPlugin_Tube.h b/src/PrimitivesPlugin/PrimitivesPlugin_Tube.h new file mode 100644 index 000000000..c3af279e1 --- /dev/null +++ b/src/PrimitivesPlugin/PrimitivesPlugin_Tube.h @@ -0,0 +1,88 @@ +// Copyright (C) 2014-2021 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 PrimitivesPlugin_Tube_H_ +#define PrimitivesPlugin_Tube_H_ + +#include +#include +#include + +/**\class PrimitivesPlugin_Tube + * \ingroup Plugins + * \brief Feature for creation of a tube primitive using various methods. + * + * Tube creates a tuboid - Holed cylinder. It can be built via two methods : + * using an inner raidus, an outer radius and a heigth or radii (inner and outer) + * and angles. + */ +class PrimitivesPlugin_Tube : public ModelAPI_Feature +{ + public: + /// Tube kind + inline static const std::string& ID() + { + static const std::string MY_TUBE_ID("Tube"); + return MY_TUBE_ID; + } + + /// Attrinute name of the inner radius + inline static const std::string& RMIN_ID() + { + static const std::string MY_RMIN_ID("rmin"); + return MY_RMIN_ID; + } + + /// Attrinute name of the outer radius + inline static const std::string& RMAX_ID() + { + static const std::string MY_RMAX_ID("rmax"); + return MY_RMAX_ID; + } + + /// Attrinute name of the height + inline static const std::string& HEIGHT_ID() + { + static const std::string MY_HEIGHT_ID("height"); + return MY_HEIGHT_ID; + } + + /// Returns the kind of a feature + PRIMITIVESPLUGIN_EXPORT virtual const std::string& getKind() + { + static std::string MY_KIND = PrimitivesPlugin_Tube::ID(); + return MY_KIND; + } + + /// Performs the algorithm and stores results it in the data structure + PRIMITIVESPLUGIN_EXPORT virtual void execute(); + + /// Request for initialization of data model of the feature: adding all attributes + PRIMITIVESPLUGIN_EXPORT virtual void initAttributes(); + + /// Use plugin manager for features creation. + PrimitivesPlugin_Tube(); + + private: + /// Load naming data structure of the feature to the document + void loadNamingDS(std::shared_ptr theTubeAlgo, + std::shared_ptr theResultBox); +}; + +#endif diff --git a/src/PrimitivesPlugin/PrimitivesPlugin_msg_fr.ts b/src/PrimitivesPlugin/PrimitivesPlugin_msg_fr.ts index 22d0de57f..a046099c6 100644 --- a/src/PrimitivesPlugin/PrimitivesPlugin_msg_fr.ts +++ b/src/PrimitivesPlugin/PrimitivesPlugin_msg_fr.ts @@ -28,6 +28,10 @@ Torus Tore + + Tube + Tube + @@ -51,6 +55,10 @@ By two points Par deux points + + By one point and dimensions + Par un point et des dimensions + Box:FirstPoint @@ -121,6 +129,72 @@ Dimension en Z + + Box:ox + + OX + OX + + + Enter the coordinate X for the center + Entrez la coodonnée en X du centre + + + + Box:oy + + OY + OY + + + Enter the coordinate Y for the center + Entrez la coodonnée en Y du centre + + + + Box:oz + + OZ + OZ + + + Enter the coordinate Z for the center + Entrez la coodonnée en Z du centre + + + + Box:half_dx + + DX + DX + + + Enter the half length in X + Entrez la demi-longueur en X + + + + Box:half_dy + + DY + DY + + + Enter the half length in Y + Entrez la demi-longueur en Y + + + + Box:half_dz + + DZ + DZ + + + Enter the half length in Z + Entrez la demi-longueur en Z + + Cone @@ -313,6 +387,25 @@ Sphere Sphère + + Dimensions + Dimensions + + + Phi/theta range + Intervalles pour Phi/Theta + + + + Sphere:CreationMethod + + By point and radius + Par un centre et un rayon + + + By dimensions + Par dimensions + Sphere:center_point @@ -340,6 +433,72 @@ Rayon + + Sphere:rmin + + Enter the inner radius + Entrez le rayon interne + + + rmin + Rmin + + + + Sphere:rmax + + Enter the outer radius + Entrez le rayon externe + + + rmax + Rmax + + + + Sphere:phimin + + Enter the azimuthal starting angle + Entrez l'angle azimutal de départ + + + phimin + Phi min + + + + Sphere:phimax + + Enter the azimuthal revolution angle + Entrez l'angle azimutal de révolution + + + phimax + Phi max + + + + Sphere:thetamin + + Enter the polar starting angle + Entrez l'angle polaire de départ + + + thetamin + Theta min + + + + Sphere:thetamax + + Enter the polar revolution angle + Entrez l'angle polaire de révolution + + + thetamax + Theta max + + Torus @@ -405,4 +564,46 @@ + + Tube + + Create a Tube + + Créer un tube + + + + Tube:rmin + + Enter the inner radius + Entrez le rayon interne + + + rmin + rmin + + + + Tube:rmax + + Enter the outer radius + Entrez le rayon externe + + + rmax + rmax + + + + Tube:height + + Enter the height + Entrez la hauteur + + + height + height + + + diff --git a/src/PrimitivesPlugin/box_widget.xml b/src/PrimitivesPlugin/box_widget.xml index bcd5ba91a..23ac51326 100644 --- a/src/PrimitivesPlugin/box_widget.xml +++ b/src/PrimitivesPlugin/box_widget.xml @@ -47,21 +47,21 @@ label="OX" step="1." default="0." - tooltip="Enter the coordinate X for the origin"> + tooltip="Enter the coordinate X for the center"> + tooltip="Enter the coordinate Y for the center"> + tooltip="Enter the coordinate Z for the center"> diff --git a/src/PrimitivesPlugin/doc/PrimitivesPlugin.rst b/src/PrimitivesPlugin/doc/PrimitivesPlugin.rst index 364373d00..02e0b8702 100644 --- a/src/PrimitivesPlugin/doc/PrimitivesPlugin.rst +++ b/src/PrimitivesPlugin/doc/PrimitivesPlugin.rst @@ -15,3 +15,4 @@ The Primitives plug-in contains features for creation of geometrical primitives. cylinderFeature.rst sphereFeature.rst torusFeature.rst + tubeFeature.rst diff --git a/src/PrimitivesPlugin/doc/TUI_tubeFeature.rst b/src/PrimitivesPlugin/doc/TUI_tubeFeature.rst new file mode 100644 index 000000000..7b871a1e2 --- /dev/null +++ b/src/PrimitivesPlugin/doc/TUI_tubeFeature.rst @@ -0,0 +1,12 @@ + + .. _tui_create_tube: + +Create / Tube +============== + +.. literalinclude:: examples/tube.py + :linenos: + :language: python + +:download:`Download this script ` + diff --git a/src/PrimitivesPlugin/doc/examples/tube.py b/src/PrimitivesPlugin/doc/examples/tube.py new file mode 100644 index 000000000..99567f94a --- /dev/null +++ b/src/PrimitivesPlugin/doc/examples/tube.py @@ -0,0 +1,9 @@ +from salome.shaper import model + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +Torus_1 = model.addTube(Part_1_doc, 3, 5, 12) +model.do() +model.end() diff --git a/src/PrimitivesPlugin/doc/images/Sphere.png b/src/PrimitivesPlugin/doc/images/Sphere.png deleted file mode 100644 index a507c8afe5d94cce144b545829477dd8ea50ef08..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6430 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 diff --git a/src/PrimitivesPlugin/doc/images/Tube.png b/src/PrimitivesPlugin/doc/images/Tube.png new file mode 100644 index 0000000000000000000000000000000000000000..314d232d9e704a390245a56ccaf9df811571103b GIT binary patch literal 5163 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 literal 0 HcmV?d00001 diff --git a/src/PrimitivesPlugin/doc/images/Tube_button.png b/src/PrimitivesPlugin/doc/images/Tube_button.png new file mode 100755 index 0000000000000000000000000000000000000000..3e274917c286cfa01b0cfcbac596565dba4e1b5e GIT binary patch literal 820 zcmV-41Izr0P)<*y9ZD3&dzb9oHi0HAD@6Ea`~54QPY~W4~q*-Jf9@m)kWE|kO(+5n515>Gx_ob6X{7*Rl#*VR4D;)8+C*b zSSu^Ev}l}6rBGGLgGUdMYtB+i4i6suY-i8&01!d|uvjQy7EM&OIks-_U#tyohzH8I zJN^d&N;nkWbic0aU)7XQduY=JEj}L|k@a7Sbw|H%1=n+_)#^=c=mv`8IGZ-`Ngr*2 zKvO#v2c=|f9NjOeR;v_CrKVmoO_Zs3Q?DD1`ZvbbS+#Af6$^kyqt3gT=@;r8{u}1v zhdvYrLcx%ba^q;&woTD0lgVbh+vE2}pFT_f*i1@f_)K)5H-4_Gvojgl))Dt>dXFN6 y2Eubax9T{~Y(76f^?o7$GMkRw@C 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 literal 0 HcmV?d00001 diff --git a/src/PrimitivesPlugin/doc/images/sphere_32x32.png b/src/PrimitivesPlugin/doc/images/sphere_32x32.png index 484c384e80a7e7c90b2291ee51ddb876213c9fd4..18dc864b2a20480e6caf5a7f5c5edb3464edccd3 100644 GIT binary patch literal 2832 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 delta 1724 zcmV;t21EIf7QGE2iBL{Q4GJ0x0000DNk~Le0000W0000V2nGNE0ESl2jFG+eSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{ z00uWnL_t(Y$HiAmh-6n8{?7Z>ty^`gt9w)sL=ZF~8wHKH41)_7K0w_Dlt4yD95R`n z_c)ocGp{5}j1Hn?C-?vb7Y0Tbe@Y-Lbp%Nwu5=m5bf>$kZr!@)o|lVr>M`kQnHdIh zsZ;mdpYxyp`(Nk(4+;2SAAY|KPaiv_`h%5E3n3oiTqq#G7}Ho|-hScSiCg!(AGucx zoV@(fm-24+TSCaMsw|US2oOpE0Kt10W6(CuuGaeIw4VIz>gi*Dc_;vme{Wp-LecNv zDEj4RI(ZHuB{&zLl!6cv0fYeW9IUlyTa9U5V=@}OURC4oUOTh?uLlNj_QhA$`-8#r zy?!aOP6t9NaL&OP10fNBXy6e_)J*QVL2bKmY`w)f$X*gy7+uI-R+uLI`jn zz&TIv+29G70OK54)&T)P83UIRQc5VLkmWggWvRMF@$>JkpWfdE<;v=}d%g0LYA!qq zW^+L?02ybXoPjZ(e@2>fhAhuvO`E_8a1nuIog784|9CN6{o1|&@^1I3EYBfRz;P~; zKn}`S62w61V!mfkhN4%(SvvRW8eO9JCXKYC*rJ$50 z|3{kO97+l(DIf%&1EY+BG783HYR(kkLO@Cdm1PH?Ilocve*vJf&J#*?qPCoYF}eu2 zr8i>~N(%J4IfjD*!?Hk;cOWIdW39?E_z>;@%{Yh3GNx4L;GSB*ID4GWG$9m(P*6hB zffJ*i5(>^3x_O2V^%S}(3C0=6?J@qgp3I%|f za1!T{2toi#2{cl}Qp?d&?5bEFq5JEg()8P`3z7Y@t;GBnc z0e)#;2S7Uy=Y3p&O3PTe-V5V9+rRvAOsKV97eUqmJMhC zOaW}#fN`y1t%INOAo6i8pqmE42YBz{okQ^M-+O}4TKiXP47_vjb08kx2T&gnsE79i z);iR+hI1Y}BC_k&K(_|Yxg;nc%=wehRI-gR&|1H}2S7cUyxvTw&RWZya|wt~U?_-B z4kSRZe*w-rOq=Ls9|F8f!n{Wai@EnM0t*4g8Z^`CSWl;a-s6IoFP?q3)y-?I*09FF zI*SDmmjtADYCepK!&-}(`{Ei0=RBNqaMpo<#NwniTHXBaM;kxzckKx$Rdu6VR9{h9 zmTEssDVbU?uoMf+8G;m`VWG8iaL&S6n}D`xf3-$kRhU%c8~fIRE2p0QQ#Bs_aXPKh zY7Nu2(Hho7Ev-!(N6nmD{$9MTwUH-vN0X|;w4R_EkA8LS%<;ef->$eCjSfqt{=qr# z&$SG(?+f08dcSW!u&li?7N*tEx4{!h{-R&5e6%wI zG3$!o-uQ&TK!_tJ(XXBj+xDLP|9V09xH_zp`=uKM%4G`Jivd{{tol5{4H@ S){yQ10000!vViySr-*{U_p-IU( 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 Ji}tui{0IC47+?SZ delta 1226 zcmV;*1U37#6Y&XeSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00db{L_t(o!^M|vh*VV= z$N%?r?%TO{-e+gn-I;B3bV(a6&?SjgBXaEp5ki832&7%jG?Dru7WgF)wz8zvH4Qc* zp|%yme_cfz5mBLVW7#qV19u&B+n0I2J9p;J-acgu+3cNJ#s9Z+?>YDRo%5Xg@PDWy z79Of-JY=zUCUJv5zR0s|J44e~LOFpkgY`cdEZ&Kvg~fIfNVX)hrse>s*>?)84gFffzLp`h!~b-ho|=k|HF zz4^<10bmEtE^{l&#s3Tbj|xT+lx4vv6p+hhkjv(J^11A8|Jz$LHDAJsZ@!mZihN?e z-~hm~3|O1y}$>GhjImG|g;C zUwDpnJlP+&eFCz>@i9Z&FAa*SK@>!&ih@uugzzKH@YV(4kYs317u+7to@~#T@7V@m zXew$qczJdf{y^P-QsVRZ5M9y&m(K^He`#>KTpy+nAKhdNplFtl+XYZvZis?#@505h zh(wwYS+p3Es(}!-ck1Awrg;HwCsX})f?EIr{=mHR+%6YlE1rNi5Rhbr9Gw^7!sxBR zqG^uL_hDIe!r^e(Iw?UA(6THBuRpLR)&0fm6#>@2(_tAU^V|7$9|{Jms&=9vf8ep$ zau7{>e{6pjU9k?_NvFS?JJt&Z(z)E-G0|M$IIilNPYA)1WwD5=YOhrUIDd0At{cWU z02ItJ6iEURCFExcumA+B-2GgI!(oKNO7aapFe;=Fo;kv2wqme zvMd&&XiLlLiBCU|R5T=G)2Tj1e{+r#qJpR@h^j$zI^kATBoYba^7)zpJZ=w~mp;C^ zB7m~#`Ab)$;kwHszs3yH+&2qMijoXjRzPGK$*D;s5{U(*BC^_+B{SMq4POp8_wMQa zx*@CUJ86bZ3Ze)?2+X2^o1-^t0#FHQt;!R&@9HT06m)-badO9AJz6RFf8j^`oEGXA_>TPk+Eupv~lE55!s(vi$$ zk8vD_nHn#oEDF+sZ24!W&%RYCmPR;+scAh!)1?IgwD0QBZ%s_>wQ2x^Qt)cDHAf1w2fwD0Pe?LBwCelnSSbvm8yFBFTmeuOnT416|$XFdOUI))Gl_Uyp{r ox|@QZDR=_2Bl0OM9mPY?-@FoL91dZq&;S4c07*qoM6N<$f{5Bf761SM diff --git a/src/PrimitivesPlugin/doc/tubeFeature.rst b/src/PrimitivesPlugin/doc/tubeFeature.rst new file mode 100644 index 000000000..feb2ac468 --- /dev/null +++ b/src/PrimitivesPlugin/doc/tubeFeature.rst @@ -0,0 +1,46 @@ +.. |Tube_button.icon| image:: images/Tube_button.png + +Tube +==== + +Tube feature creates a tube solid. + +To create a Tube in the active part: + +#. select in the Main Menu *Primitives - > Tube* item or +#. click |Tube_button.icon| **Tube** button in the toolbar + +The following property panel appears. + +.. figure:: images/Tube.png + :align: center + + Tube + +Input fields: + +- **rmin** defines the inner radius of the the tube; +- **rmax** defines the outer radius of the the tube; +- **height** defines the height of the the tube; + +**TUI Command**: + +.. py:function:: model.addTube(Part_doc, rmin, rmax, height) + + :param part: The current part object. + :param real: rmin. + :param real: rmax. + :param real: height. + :return: Result object. + +Result +"""""" + +An example is shown below. + +.. figure:: images/Tube_res.png + :align: center + + Tube created + +**See Also** a sample TUI Script of :ref:`tui_create_tube` operation. diff --git a/src/PrimitivesPlugin/icons/sphere.png b/src/PrimitivesPlugin/icons/sphere.png old mode 100644 new mode 100755 index 000d658ab846ac9fdd66be422f6ad446f88c8c52..add03e29a5a0dbd6ee8459e52b14aac430aa87d8 GIT binary patch literal 1831 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4(FKU`)((b`HpPc6ZLt$u9~nNK8(3 z$t*6&NvsSoW?;~mn4FLhOO|GKyppK57poIDp2l!g{@FekYb)G!R z+Q-Of=b*}CASGI}``7`FMf$Is&RD6MZuQ(6ci?)`vJY3g*SpL%xVo5O-IObjQWXBO zcLY!7?(&k5kO*$bdHQJ*lfZ7~6JnZ7R$M3MF()l|z9H@KMup=yM})7(1mg*{%qPM; z&UvuRI{1V6#5GSRA%FKI=eMkkdDG84YMOJztCb;{X`L$blqF$P8Zw^$X*#v&%$FV^ zR`&#rrCJrwRA0Z;kdTy^Wo*!JNM_NmVg(Bw$)o2Kj?8**Y;fb?O%wui|m2PtC zY;4!6|NpNK0|wOmGY3ADANv1)zxdz(|H};nKFhMTF;_B(DyF_OJ$~^wFw84bBRtc5 zeHpZXYz_uiMm7d!Ad8WK2}npWu!7kP3|@@VaCQ)*20~4HCIbspO%#v@ffgWUgwsq5 znBXb|7BC~&Af<**WQFI*v z8Tlpoz>q7-O!mwxNi8ZU0)`^kMworLRiK-Nusk#`v&0T&0GcpVmyJFs$dG~%56)YB>c*j2ykz>$nQ76~67oXj|MwOgQ<(ZzEsi|Q-^Zn5U2vsn!{ZFTUz zop|hfnvSB>bXrv03D|M$N4wh!c!Hb#gnc&vZu&%*UtD+04G^FJ-RW7+tSrNc?e zC9q_DYxKvt(k+|KH(90$FKBf>{OReco-?l_Z_ebrdV5vk=DlqvL)w{|8Mi4)@3HeQ zh!oMakF%5Qb>8uV?b)AgUcJx4exJ3DxqQ!UiexW`>!J#48y4qAM)leK$^DhvFFlmV z=X~`=e$hKm^WLe9UweI@b#=Li>u)t&nPuwmDd}WLU|eJC0U$|f(RLZ(eu z@9piM`8??JF2lDxMQW2Z6$2O77X5O`_Ul|&psZ-X)5vgaZK#B#WZV7!qRV8}mMmS; zl-#mL^7#|Pr5j%`N?&++BgM68-%`nABvf?<_HLUN~|OY8)p z(5D+Y)H5sRo%itboAf5=&9ZAoOQyIi6>3uOSQ;3tcrs*ZkgkNlmkkN5sz;3$)##LV z@Xypp$~x6~Xi?Il=_mjEvWj5c?iO?K)1gZyJD*2r?D=-u=W5ZmEu5+?~}_^ zv-!o?-ROGcN9nb!t?M?+tuF0lzoWePz2~eVF`-5uL#G$7syb?F8MjT??$E0ACb_I8 znzQnRzO!`i&4M2}-wzykbz=$hlAz3%B*QyzGmiiHBcnHO|AxS6ryslgm%i<#Ahy#f zc4_&6-*fB&mw(^AXJ2#VOet3rG1v5TcBP3NdGWg)tzF`_bo9@EQ*r0AvHipE^Ez++ z`t{;rQTU6#j;j9;nRjws{rl(5nxNc1zO7rW1H(7V3dh?$w){B%Q&sHdizilY_!LHe80`Q60bfZ(K~y-)t&>el0#Ou(AFnNQH%x6-0UU(JU?;t1XxB{l1L|0$dbhE<2^^&V={aDZ13)%8%76c#4-o` zbHpN1+=^n;L-RoZ5?d)Y6C1cjU7TKC0GJj;SmIbD%9t#-J6l6)VTNVK6WUB9^SC>~PRm%3cRWGc; z{iRy%Fe)exLh!|9DgE?JUJaDV@YeCz!Xv!E#~@gm0?IoT$9S7~Un0)W))t`2%Y^{^d;$RA76q__x5xwd zzvlpeHJ`$EPTqno7X|>ZOL}Ya0a({T0Kg70vJ;U>w8a~G(J zASRhcg>3nHdeK6dXcd*MLfhlVdosy>zba7~Kaa&bAbjfy{2&Yg-}dH7jki!k7lJQ? z78tVSk2!=i{!aZb@K>Q90^sRe#R5BCux4}Q)pDJVcR>S_Ifj@5NJIcErjEFIO`>HV_BPK4Vc^|AO&g_VjmDoGy z$YghCrHwpB0mJ{yqFz;P&(r+_sCV)<8TS0(3e;)G)Z5i}i*z+~?GZS0Cy9cco3s3@ zS0N&&OP5=VQMxbp;QCR*H;Js5)dK=7%H2NKP}IOccz@0#2Ke`(oPj{@bJx|Y`H09F z^wRa2rEhgZ-2UXXg53+$^%zTqcCIwP_G~evpcWIfu&0_LrsV*1Q2bV=A%e_!`EIew zX6o}dhF*xPoh@o81xxdH&uTG=EWBTJFXeMrkLz_jnG>Gx<02BcFWuKheOl;xgX4ZO zOE}vMUAK9D#d!w~_aJl+& z@@S;jfgn4QF-NUA5GR_~Uht!o55t%Xl9 zbN%Pm?P*g)@2D@*M$;9PiKFS1zM<8R)B}rGpS3%j7AYfLG69`Y#ATX6ja8vRP^9?# zQX2`?OgmzhWxCSkl9H2|8>Sn(;fhhid!diRVB=*G4| zSlcqDVH_M@?ww`XZPN({72=T!qS^o>5?)mc%grCQ!sC?(vKgj5Lcq3H{y0;eK*ZqLE7-BQ7HkM^)r740&#zYb;b+9IB0Bbet?(w$qooM@kpbJW|M}g zWo!PU43$N>_c9R?HxjL&>4A^OHN(5U2r2bybGgY%+9Woj_Mlznup_umSQK6HJ~5-F z^~0Ycs<%A_b)PHXQqn>j_bzl2RVT=&%p=;mQcNqm*u{C*`!O2_S-Vg>pX7#Pxuq>) zb)sDBIK8SXkSni)l@QAKKTL)2iOf=vKJqM>55MBs>178|lmN1Qy4+uWR9%6>)q!zw z4c*7zW?y_08$DI_M^kh_p&gW?Y9J#=iW5T=Uo_q0-8&1ufE3M5qTlcI_Q1aG$m;P^ zxd+pg6o>}~e2kykvv@A62Fn#PDy%VH6iDdrZChF$G3EPA&hJTEYiI}I0iqIfdMB);7EOHb$EB@etn3m zy^+pj8Xa*uZMY4UUYw+tQ~eR9Gx^=-==re4nht!UvTwX zeb56mhJ{EvYE(|HBSCqH7x6`xISRHO=ByyEa=G@E1o2w}-d0!bF@VY`O_WBgmrCPU z_vyF61)RyIk4gFg?H^1v#iI8LJ{7xi`*>L@cqhra^F)vEQ!Ww+a2s_;XP)Hldx1Bw^!HVu(ak|!-7`%d1X*bgZ}0?G^nGLae})XIsN6Y z1VZI#)6tkJ@I;mwJ3(et$EC<@IAWQDHO~~9$qhnggC-tk2YRy)ljTAa)v&i;83r4c z72o_n*({nq)`dTHqh>h0s?SlilTS;s-vN|uF^(K!y;83tbL+No?zWnm@q z)FokyMHyDtCy^RYrQqi|Cf`=?#+RWUTN^E8Z>qdF1Kc&%%wC^TY&sqL}`hqlVt0rZXJQi2k%7X%9%876{%YV_%4JHx22Yw`T$H`K z^{Joo!#=ZTh%sbf;AWhlL$qtJCoqMemqzLVAbmtf=nA@$p4CTw0}3bbA9zoAbZI<< zMPF`}%!!=$%2pdYIm#Ws_bAhQ!8mE?{B*WSx_G4YCc7hRoU}0*P_7CU|Ltq!d&7^X zL>cNdJdU1z_h7@yYr@g?w>Ojf3}BuiVDrS9 zDUkSDKeJYPp?+rk&d7YIU2<-FuE3i&-TokgtRc4L+70EVH-T?EW^Hyu^=04x<}>%I zWh7@$Ns&7gb7paPqmLB#D2#mfVCSJVJFxth0@l556Qbx`&tRUB>``@-t3YgP>a}^T zeHNc|UWHXu7=))MXrAJXRdsQ-7KJpGGYLokT=EA;k<>{y+ef&m&tFJIVJ@O|*0~l& zt5Q zF4(A=9npK{wqHP?dXiEy>pYuf?~^;idDiQvRWvyej|~qoa#eh|m{OGRDLr(lAo1Af z@tH3Rm6eDvhWtc9;|B?Sw`FM4Qt@j4wJ2kxJpiR<--3-F>amZtR$&bh7MLY%psS-B}G_TQcU!0Z43 delta 1724 zcmV;t21EIf7QGE2iBL{Q4GJ0x0000DNk~Le0000W0000V2nGNE0ESl2jFG+eSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{ z00uWnL_t(Y$HiAmh-6n8{?7Z>ty^`gt9w)sL=ZF~8wHKH41)_7K0w_Dlt4yD95R`n z_c)ocGp{5}j1Hn?C-?vb7Y0Tbe@Y-Lbp%Nwu5=m5bf>$kZr!@)o|lVr>M`kQnHdIh zsZ;mdpYxyp`(Nk(4+;2SAAY|KPaiv_`h%5E3n3oiTqq#G7}Ho|-hScSiCg!(AGucx zoV@(fm-24+TSCaMsw|US2oOpE0Kt10W6(CuuGaeIw4VIz>gi*Dc_;vme{Wp-LecNv zDEj4RI(ZHuB{&zLl!6cv0fYeW9IUlyTa9U5V=@}OURC4oUOTh?uLlNj_QhA$`-8#r zy?!aOP6t9NaL&OP10fNBXy6e_)J*QVL2bKmY`w)f$X*gy7+uI-R+uLI`jn zz&TIv+29G70OK54)&T)P83UIRQc5VLkmWggWvRMF@$>JkpWfdE<;v=}d%g0LYA!qq zW^+L?02ybXoPjZ(e@2>fhAhuvO`E_8a1nuIog784|9CN6{o1|&@^1I3EYBfRz;P~; zKn}`S62w61V!mfkhN4%(SvvRW8eO9JCXKYC*rJ$50 z|3{kO97+l(DIf%&1EY+BG783HYR(kkLO@Cdm1PH?Ilocve*vJf&J#*?qPCoYF}eu2 zr8i>~N(%J4IfjD*!?Hk;cOWIdW39?E_z>;@%{Yh3GNx4L;GSB*ID4GWG$9m(P*6hB zffJ*i5(>^3x_O2V^%S}(3C0=6?J@qgp3I%|f za1!T{2toi#2{cl}Qp?d&?5bEFq5JEg()8P`3z7Y@t;GBnc z0e)#;2S7Uy=Y3p&O3PTe-V5V9+rRvAOsKV97eUqmJMhC zOaW}#fN`y1t%INOAo6i8pqmE42YBz{okQ^M-+O}4TKiXP47_vjb08kx2T&gnsE79i z);iR+hI1Y}BC_k&K(_|Yxg;nc%=wehRI-gR&|1H}2S7cUyxvTw&RWZya|wt~U?_-B z4kSRZe*w-rOq=Ls9|F8f!n{Wai@EnM0t*4g8Z^`CSWl;a-s6IoFP?q3)y-?I*09FF zI*SDmmjtADYCepK!&-}(`{Ei0=RBNqaMpo<#NwniTHXBaM;kxzckKx$Rdu6VR9{h9 zmTEssDVbU?uoMf+8G;m`VWG8iaL&S6n}D`xf3-$kRhU%c8~fIRE2p0QQ#Bs_aXPKh zY7Nu2(Hho7Ev-!(N6nmD{$9MTwUH-vN0X|;w4R_EkA8LS%<;ef->$eCjSfqt{=qr# z&$SG(?+f08dcSW!u&li?7N*tEx4{!h{-R&5e6%wI zG3$!o-uQ&TK!_tJ(XXBj+xDLP|9V09xH_zp`=uKM%4G`Jivd{{tol5{4H@ S){yQ10000!vViySr-*{U_p-IU( zQ4Y0o$oUYF;-LddNe+)hc{i1wx6k|DpU-`NzxVaKuIu}|zxO|Pj2+Qpouq;!008R< zmgWwEh!9Q*h+t(NKRzc2Af|)G9-yd0@r_^;=|v`Z+t>gaf?NU+13>_=kOGJZ76m|T zH3tAI(B`$=0i^zu6YT?te&zuXdNV85`jP%F+9C-4(9v5%LO}Q2b#_}iqXYlu^1gajGmshfT7I{3t+j0Y6md4elz*uWA4TDVE6>GeCPoP zp|6`eJ(y*TL<$S7jc@7gTU%h_Tb`0=g z;eQzX0)JN-VT29)M+3jz&MGRn9=xOxX6>r+lCMoDz5oCzA(;P*M20pv`Orv?aQuRH zdCjFFmN%7JahbS%W4^k24g|7aQ!c2uyQ)!cIa^f$Mcp9LtuZRQ%{^yC1iBCQClWyx zrNXm0BIgmV>Pjt$5MFs_M&+T-j5oB)M5&nW4DYG1@hi-_4_BDOwZ*{7EW#1a0WXA>M~7Z`g*C=Z_~4R-UkZm&8oTnJ8{obdQ>(qlr>d&B?A|bYiSt z$BQaat$7*!4OY9DTCK9L#(Mrp`K?I3niya*D4$?ihEhmNeyCyLqI7I1gr=Bzb3X-2 zeybdSj5L^4luGQ!crvWLQ%3-+7^@f))hMLWy)229r_54I-rLf1)|+H1=?jPr?dJ^| zAEb+F1`G-_g%3K?W z*UW>&DNr{n*MdolNv>T5wwSuK*M{p)s}GJIf$MEmb|k%i5moFAA#p1rABc%P(gZI# z*X?bEmR}%pM}t!wjmO<2++0GZK@XUU-io{SrAzn1&r(l5zRASi2|N7dj9EwCSSraL z&W)R)t&F^)k4!+eHyD`p-o@#j*SMK+!TvpS|I}8=e&!19#OF=0+)7beh4}q1P3fx1ch*H?{h7D~S;xIG z^$+5g8*{I12WjLH!3i(*r*G}ty0vU#>TFcT(cUuYR&)g?wQq#Q$bFuhND$f0jtaER z!N}FW4-XkciT}-?xZq@G8B0S2>8r@TD1WjGQ#*|$Z`*jb^kS>F_3-A86}?yjuzS;y ztNIG?+lO!9`|w-Ro)+|EY$;8K8(ut9nQ;&*{jeo+OM&*|%&}L#)>dG5f@f@=vYfKA zf`9sFT1UJ10b;-nUuo<`{aT{9-@&3MdiBXKmWx|16U}Y}DS+@gEcpf7N)@C0!#iX2 zTnRA!t~c`z?d|0UJUlO?Ks9bt-Nxdm@5Ov27>m`ePkPLodnBq76`@;tey1F?GCCdJ z|8n8+IXH-Lk)Vo-gzK3FZpcmT0Nx0v0^op8yio8;@ksp6#D5y2g@(Fg~ z86rAp$0zsPtOsRUXO_~YZ#{+~W}Gz-&hStvFTeKhJn~Wc;f$l^v~r605_GO7d&Yvay|Yx8H4i7EwJGB)h_3e>LuM8Vs2bN6N+9QQQ*G_?>9j zukm?vKd=2GDwhvLAgYL&IErr@PdsA0^Uxy%Hw;qkE5p%9Jz9MNZ8+9ZmpY(zuxj@9 zv;C9f7`f%q>Fg1@+P`J3Xbn2aG2~4<7?)m!?+;q5vXQULj3PH?+ltaU`!;%HuCgNNEFo4ausUU&8AX9jqzZGC)v zTe|$Y#s{;zb^7XtuQCozo<4a%CxZGuzsJMYbZA)&RZV4QeOe@63!W;h)D0DnlQHp~ z?>UmzjCD$b4}6^GXvxcc94NPVH&pE}HZJwN%6}oDV*yXa_-f*=sHqg5xCenvK3#6O zSU-uARGWMWw?L)OLqMH@9AohIDHpbr#N_;){+&J(O$k}v23q;8eCz4{)Kn#t<{`pD|5Bmlex>XfCLHH&PMp6w_kq6X8aUBX=0!&@%*(9r;oR7c z3jJ{Yt1F@%UpUg78hN*1sV1c50@5DdSd*QMzqCP&_iTJY)a6K@r{^u_q>{sBIc?`C z+YBzfG0f?%(>(Q=2cFKgn3_G#^J_NUX}(gY)O7vbbqB|Rb7^U2j;Wm4qNxez93^qs zI(s<(<-EJf8`3d9Sn;KBNY`J(Q!0ifUr>7;k2G3%Kg_e`R`{FLRlpWJI#IhmflrlC z{F{pJLd)N4^q%}X-_HJ|nA><3p2?Z38nT}M(>G@*{OMHe&=Qp&TpB$lJJu1*4*9gL zgJLiTuPq!sjU}Dc7EKqaxi+(HBRu(<@`(r%RzseD%nIH(zQ8{});BV{Snm>MsIrnP zxuPkWb7(rHpz9bsl(1rGQ185TxlP&(SwsB5CJo#PNGmXeOS*SI8XT_Gw&Aqjvv3vF z#oM@)nJ0nYT1UNB;d>X>Pc^+u(yOuWUzqZv$W|^DkH@WB0pC4*+$#vVXexZV5cU$y Ji}tui{0IC47+?SZ delta 1226 zcmV;*1U37#6Y&XeSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00db{L_t(o!^M|vh*VV= z$N%?r?%TO{-e+gn-I;B3bV(a6&?SjgBXaEp5ki832&7%jG?Dru7WgF)wz8zvH4Qc* zp|%yme_cfz5mBLVW7#qV19u&B+n0I2J9p;J-acgu+3cNJ#s9Z+?>YDRo%5Xg@PDWy z79Of-JY=zUCUJv5zR0s|J44e~LOFpkgY`cdEZ&Kvg~fIfNVX)hrse>s*>?)84gFffzLp`h!~b-ho|=k|HF zz4^<10bmEtE^{l&#s3Tbj|xT+lx4vv6p+hhkjv(J^11A8|Jz$LHDAJsZ@!mZihN?e z-~hm~3|O1y}$>GhjImG|g;C zUwDpnJlP+&eFCz>@i9Z&FAa*SK@>!&ih@uugzzKH@YV(4kYs317u+7to@~#T@7V@m zXew$qczJdf{y^P-QsVRZ5M9y&m(K^He`#>KTpy+nAKhdNplFtl+XYZvZis?#@505h zh(wwYS+p3Es(}!-ck1Awrg;HwCsX})f?EIr{=mHR+%6YlE1rNi5Rhbr9Gw^7!sxBR zqG^uL_hDIe!r^e(Iw?UA(6THBuRpLR)&0fm6#>@2(_tAU^V|7$9|{Jms&=9vf8ep$ zau7{>e{6pjU9k?_NvFS?JJt&Z(z)E-G0|M$IIilNPYA)1WwD5=YOhrUIDd0At{cWU z02ItJ6iEURCFExcumA+B-2GgI!(oKNO7aapFe;=Fo;kv2wqme zvMd&&XiLlLiBCU|R5T=G)2Tj1e{+r#qJpR@h^j$zI^kATBoYba^7)zpJZ=w~mp;C^ zB7m~#`Ab)$;kwHszs3yH+&2qMijoXjRzPGK$*D;s5{U(*BC^_+B{SMq4POp8_wMQa zx*@CUJ86bZ3Ze)?2+X2^o1-^t0#FHQt;!R&@9HT06m)-badO9AJz6RFf8j^`oEGXA_>TPk+Eupv~lE55!s(vi$$ zk8vD_nHn#oEDF+sZ24!W&%RYCmPR;+scAh!)1?IgwD0QBZ%s_>wQ2x^Qt)cDHAf1w2fwD0Pe?LBwCelnSSbvm8yFBFTmeuOnT416|$XFdOUI))Gl_Uyp{r ox|@QZDR=_2Bl0OM9mPY?-@FoL91dZq&;S4c07*qoM6N<$f{5Bf761SM diff --git a/src/PrimitivesPlugin/icons/tube.png b/src/PrimitivesPlugin/icons/tube.png new file mode 100755 index 0000000000000000000000000000000000000000..3e274917c286cfa01b0cfcbac596565dba4e1b5e GIT binary patch literal 820 zcmV-41Izr0P)<*y9ZD3&dzb9oHi0HAD@6Ea`~54QPY~W4~q*-Jf9@m)kWE|kO(+5n515>Gx_ob6X{7*Rl#*VR4D;)8+C*b zSSu^Ev}l}6rBGGLgGUdMYtB+i4i6suY-i8&01!d|uvjQy7EM&OIks-_U#tyohzH8I zJN^d&N;nkWbic0aU)7XQduY=JEj}L|k@a7Sbw|H%1=n+_)#^=c=mv`8IGZ-`Ngr*2 zKvO#v2c=|f9NjOeR;v_CrKVmoO_Zs3Q?DD1`ZvbbS+#Af6$^kyqt3gT=@;r8{u}1v zhdvYrLcx%ba^q;&woTD0lgVbh+vE2}pFT_f*i1@f_)K)5H-4_Gvojgl))Dt>dXFN6 y2Eubax9T{~Y(76f^?o7$GMk + + + + + diff --git a/src/PrimitivesPlugin/tube_widget.xml b/src/PrimitivesPlugin/tube_widget.xml new file mode 100644 index 000000000..4fc429339 --- /dev/null +++ b/src/PrimitivesPlugin/tube_widget.xml @@ -0,0 +1,26 @@ + + + + + + + + diff --git a/src/PythonAPI/model/primitives/__init__.py b/src/PythonAPI/model/primitives/__init__.py index 6e2110eca..3c2e74901 100644 --- a/src/PythonAPI/model/primitives/__init__.py +++ b/src/PythonAPI/model/primitives/__init__.py @@ -19,4 +19,4 @@ """Package for Primitives plugin for the Parametric Geometry API of the Modeler. """ -from PrimitivesAPI import addBox, addCone, addCylinder, addSphere, addTorus +from PrimitivesAPI import addBox, addCone, addCylinder, addSphere, addTorus, addTube diff --git a/test.API/SHAPER/Primitives/TestTube.py b/test.API/SHAPER/Primitives/TestTube.py new file mode 100644 index 000000000..b170cc4c0 --- /dev/null +++ b/test.API/SHAPER/Primitives/TestTube.py @@ -0,0 +1,66 @@ +# Copyright (C) 2017-2021 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() + +# Parameters +model.addParameter(Part_1_doc, "rmin", "10") +model.addParameter(Part_1_doc, "rmax", "12") +model.addParameter(Part_1_doc, "h", "20.5") + +# Tests +Tube_1 = model.addTube(Part_1_doc, 3, 5, 12) +Tube_2 = model.addTube(Part_1_doc, "rmin", "rmax", "h") +Tube_3 = model.addTube(Part_1_doc, 5, 3, 12) +Tube_4 = model.addTube(Part_1_doc, -2.5, 5, 12) +Tube_5 = model.addTube(Part_1_doc, 3, 5, -10) + +model.do() +model.end() + +# Checks +from GeomAPI import GeomAPI_Shape + +model.testNbResults(Tube_1, 1) +model.testNbSubResults(Tube_1, [0]) +model.testNbSubShapes(Tube_1, GeomAPI_Shape.SOLID, [1]) +model.testNbSubShapes(Tube_1, GeomAPI_Shape.FACE, [4]) +model.testHaveNamingFaces(Tube_1, model, Part_1_doc) + +model.testNbResults(Tube_2, 1) +model.testNbSubResults(Tube_2, [0]) +model.testNbSubShapes(Tube_2, GeomAPI_Shape.SOLID, [1]) +model.testNbSubShapes(Tube_2, GeomAPI_Shape.FACE, [4]) +model.testHaveNamingFaces(Tube_2, model, Part_1_doc) + +model.testNbResults(Tube_3, 0) +print(Tube_3.feature().error()) +assert(Tube_3.feature().error() == "Tube builder :: rmin is greater then or equal to rmax.") + +model.testNbResults(Tube_4, 0) +print(Tube_4.feature().error()) +assert(Tube_4.feature().error() == "Tube builder :: rmin is negative.") + +model.testNbResults(Tube_5, 0) +print(Tube_5.feature().error()) +assert(Tube_5.feature().error() == "Tube builder :: z is negative or null.") diff --git a/test.API/SHAPER/tests.set b/test.API/SHAPER/tests.set index d3bd600bd..b36fa9d9d 100644 --- a/test.API/SHAPER/tests.set +++ b/test.API/SHAPER/tests.set @@ -23,6 +23,7 @@ SET(TEST_NAMES Primitives/TestCylinder.py Primitives/TestSphere.py Primitives/TestTorus.py + Primitives/TestTube.py Primitives/TestAPI_Box.py Primitives/TestAPI_Cone.py Primitives/TestAPI_Cylinder.py -- 2.39.2