From 8b70f46fd6ac8b7cc1823d911c37788b8bca5e65 Mon Sep 17 00:00:00 2001 From: cg246364 Date: Wed, 16 Jun 2021 15:14:48 +0200 Subject: [PATCH] Add a new method to create a box with a center and three half-lengths --- src/GeomAlgoAPI/GeomAlgoAPI_Box.cpp | 54 ++++++++++--- src/GeomAlgoAPI/GeomAlgoAPI_Box.h | 17 ++++ src/PrimitivesAPI/PrimitivesAPI_Box.cpp | 73 +++++++++++++++++- src/PrimitivesAPI/PrimitivesAPI_Box.h | 51 +++++++++++- src/PrimitivesPlugin/PrimitivesPlugin_Box.cpp | 57 ++++++++++++++ src/PrimitivesPlugin/PrimitivesPlugin_Box.h | 55 ++++++++++++- src/PrimitivesPlugin/box_widget.xml | 51 ++++++++++++ src/PrimitivesPlugin/doc/TUI_boxByPtDims.rst | 12 +++ src/PrimitivesPlugin/doc/boxFeature.rst | 48 +++++++++++- src/PrimitivesPlugin/doc/examples/box3.py | 9 +++ src/PrimitivesPlugin/doc/images/Box3.png | Bin 0 -> 4828 bytes .../doc/images/Box_ptAndDims.png | Bin 0 -> 14590 bytes .../doc/images/box_pt_dxyz_32x32.png | Bin 0 -> 1188 bytes .../icons/box_pt_dxyz_32x32.png | Bin 0 -> 1188 bytes 14 files changed, 407 insertions(+), 20 deletions(-) create mode 100644 src/PrimitivesPlugin/doc/TUI_boxByPtDims.rst create mode 100644 src/PrimitivesPlugin/doc/examples/box3.py create mode 100644 src/PrimitivesPlugin/doc/images/Box3.png create mode 100644 src/PrimitivesPlugin/doc/images/Box_ptAndDims.png create mode 100644 src/PrimitivesPlugin/doc/images/box_pt_dxyz_32x32.png create mode 100644 src/PrimitivesPlugin/icons/box_pt_dxyz_32x32.png diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Box.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Box.cpp index 1dcc9fa97..21da9cb04 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_Box.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Box.cpp @@ -34,6 +34,7 @@ GeomAlgoAPI_Box::GeomAlgoAPI_Box(const double theDx, const double theDy, const d myDy = theDy; myDz = theDz; myMethodType = MethodType::BOX_DIM; + headError = "Box builder with dimensions"; } //================================================================================================= @@ -43,33 +44,48 @@ GeomAlgoAPI_Box::GeomAlgoAPI_Box(std::shared_ptr theFirstPoint, myFirstPoint = theFirstPoint; mySecondPoint = theSecondPoint; myMethodType = MethodType::BOX_POINTS; + headError = "Box builder with two points"; +} + +//================================================================================================= +GeomAlgoAPI_Box::GeomAlgoAPI_Box(const double theOx, const double theOy, const double theOz, + const double theDx, const double theDy, const double theDz) +{ + myOx = theOx; + myOy = theOy; + myOz = theOz; + myDx = theDx; + myDy = theDy; + myDz = theDz; + myMethodType = MethodType::BOX_POINT_DIMS; + headError = "Box builder with coordinates and dimensions"; } //================================================================================================= bool GeomAlgoAPI_Box::check() { - if (myMethodType == MethodType::BOX_DIM) { + if (myMethodType == MethodType::BOX_DIM || myMethodType == MethodType::BOX_POINT_DIMS) { if (myDx < Precision::Confusion()) { - myError = "Box builder with dimensions :: Dx is null or negative."; + myError = headError + " :: Dx is null or negative."; return false; } else if (myDy < Precision::Confusion()) { - myError = "Box builder with dimensions :: Dy is null or negative."; + myError = headError + " :: Dy is null or negative."; return false; } else if (myDz < Precision::Confusion()) { - myError = "Box builder with dimensions :: Dz is null or negative."; + myError = headError + " :: Dz is null or negative."; return false; } } else if (myMethodType == MethodType::BOX_POINTS) { if (!myFirstPoint.get()) { - myError = "Box builder with points :: the first point is not valid."; + myError = headError + " :: the first point is not valid."; return false; } if (!mySecondPoint.get()) { - myError = "Box builder with points :: the second point is not valid."; + myError = headError + " :: the second point is not valid."; return false; } if (myFirstPoint->distance(mySecondPoint) < Precision::Confusion()) { - myError = "Box builder with points :: the distance between the two points is null."; + myError = headError + " :: the distance between the two points is null."; return false; } double aDiffX = myFirstPoint->x() - mySecondPoint->x(); @@ -79,7 +95,7 @@ bool GeomAlgoAPI_Box::check() fabs(aDiffY) < Precision::Confusion() || fabs(aDiffZ) < Precision::Confusion()) { myError = - "Box builder with points :: the points belong both to one of the OXY, OYZ or OZX planes."; + headError + " :: the points belong both to one of the OXY, OYZ or OZX planes."; return false; } } else { @@ -96,6 +112,8 @@ void GeomAlgoAPI_Box::build() buildWithDimensions(); } else if (myMethodType == MethodType::BOX_POINTS) { buildWithPoints(); + } else if (myMethodType == MethodType::BOX_POINT_DIMS) { + buildWithPointAndDims(); } else { myError = "Box builder :: Method not implemented."; return; @@ -113,7 +131,7 @@ void GeomAlgoAPI_Box::buildWithDimensions() // Test the algorithm if (!aBoxMaker->IsDone()) { - myError = "Box builder with dimensions :: algorithm failed."; + myError = headError + " :: algorithm failed."; return; } @@ -124,7 +142,7 @@ void GeomAlgoAPI_Box::buildWithDimensions() // Test on the shapes if (!aShape.get() || aShape->isNull()) { - myError = "Box builder with dimensions :: resulting shape is null."; + myError = headError + " :: resulting shape is null."; return; } @@ -147,7 +165,7 @@ void GeomAlgoAPI_Box::buildWithPoints() // Test the algorithm if(!aBoxMaker->IsDone()) { - myError = "Box builder with two points :: algorithm failed."; + myError = headError + " :: algorithm failed."; return; } @@ -159,7 +177,7 @@ void GeomAlgoAPI_Box::buildWithPoints() // Tests on the shape if (!aShape.get() || aShape->isNull()) { - myError = "Box builder with two points :: resulting shape is null."; + myError = headError + " :: resulting shape is null."; return; } @@ -168,6 +186,18 @@ void GeomAlgoAPI_Box::buildWithPoints() setDone(true); } +//================================================================================================= +void GeomAlgoAPI_Box::buildWithPointAndDims() +{ + // Construct points from cordinates and dimensions to use the method with two points + myFirstPoint = + std::shared_ptr(new GeomAPI_Pnt(myOx - myDx, myOy - myDy, myOz - myDz)); + mySecondPoint = + std::shared_ptr(new GeomAPI_Pnt(myOx + myDx, myOy + myDy, myOz + myDz)); + + buildWithPoints(); +} + //================================================================================================= void GeomAlgoAPI_Box::prepareNamingFaces() { diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Box.h b/src/GeomAlgoAPI/GeomAlgoAPI_Box.h index c6f1269f1..44cdd1c69 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_Box.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Box.h @@ -34,6 +34,7 @@ class GeomAlgoAPI_Box : public GeomAlgoAPI_MakeShape enum MethodType { BOX_DIM, ///< Box with dimensions BOX_POINTS, ///< Box with points + BOX_POINT_DIMS, /// theFirstPoint, std::shared_ptr theSecondPoint); + + /// Creates a box using coordinates of a point (the center of gravity) andthe dimensions. + /// \param theOx The X coordinate of the point + /// \param theOy The Y coordinate of the point + /// \param theOz The Z coordinate of the point + /// \param theDx The dimension on X + /// \param theDy The dimension on Y + /// \param theDz The dimension on Z + GEOMALGOAPI_EXPORT GeomAlgoAPI_Box(const double theOx, const double theOy, const double theOz, + const double theDx, const double theDy, const double theDz); /// Checks if data for the box construction is OK. GEOMALGOAPI_EXPORT bool check(); @@ -64,13 +75,19 @@ class GeomAlgoAPI_Box : public GeomAlgoAPI_MakeShape void buildWithDimensions(); /// Builds the box with two points void buildWithPoints(); + /// Buils the box with coordinates of a point and dimensions + void buildWithPointAndDims(); + double myOx; /// X coordinate of the center to create a box. + double myOy; /// Y coordinate of the center to create a box. + double myOz; /// Z coordinate of the center to create a box. double myDx; /// Dimension on X to create a box. double myDy; /// Dimension on Y to create a box. double myDz; /// Dimension Z to create a box. std::shared_ptr myFirstPoint; /// First point to create a box. std::shared_ptr mySecondPoint; /// Second point to create a box. MethodType myMethodType; /// Type of method used. + std::string headError; /// Head of the error message according to the method }; diff --git a/src/PrimitivesAPI/PrimitivesAPI_Box.cpp b/src/PrimitivesAPI/PrimitivesAPI_Box.cpp index 04b73f6ee..67fbe3396 100644 --- a/src/PrimitivesAPI/PrimitivesAPI_Box.cpp +++ b/src/PrimitivesAPI/PrimitivesAPI_Box.cpp @@ -50,6 +50,29 @@ PrimitivesAPI_Box::PrimitivesAPI_Box(const std::shared_ptr& th setPoints(theFirstPoint, theSecondPoint); } +//================================================================================================== +PrimitivesAPI_Box::PrimitivesAPI_Box(const std::shared_ptr& theFeature, + const ModelHighAPI_Double& theOx, + const ModelHighAPI_Double& theOy, + const ModelHighAPI_Double& theOz, + const ModelHighAPI_Double& theHalfX, + const ModelHighAPI_Double& theHalfY, + const ModelHighAPI_Double& theHalfZ) +: ModelHighAPI_Interface(theFeature) +{ + if (initialize()) + { + fillAttribute(PrimitivesPlugin_Box::CREATION_METHOD_BY_ONE_POINT_AND_DIMS(), creationMethod()); + fillAttribute(theOx, ox()); + fillAttribute(theOy, oy()); + fillAttribute(theOz, oz()); + fillAttribute(theHalfX, halfdx()); + fillAttribute(theHalfY, halfdy()); + fillAttribute(theHalfZ, halfdz()); + execute(); + } +} + //================================================================================================== PrimitivesAPI_Box::~PrimitivesAPI_Box() { @@ -80,6 +103,30 @@ void PrimitivesAPI_Box::setPoints(const ModelHighAPI_Selection& theFirstPoint, execute(); } +//================================================================================================== +void PrimitivesAPI_Box::setOrigin(const ModelHighAPI_Double& theOx, + const ModelHighAPI_Double& theOy, + const ModelHighAPI_Double& theOz) +{ + fillAttribute(theOx, ox()); + fillAttribute(theOy, oy()); + fillAttribute(theOz, oz()); + + execute(); +} + +//================================================================================================== +void PrimitivesAPI_Box::setHalfLengths(const ModelHighAPI_Double& theHalfLengthX, + const ModelHighAPI_Double& theHalfLengthY, + const ModelHighAPI_Double& theHalfLengthZ) +{ + fillAttribute(theHalfLengthX, halfdx()); + fillAttribute(theHalfLengthY, halfdy()); + fillAttribute(theHalfLengthZ, halfdz()); + + execute(); +} + //================================================================================================== void PrimitivesAPI_Box::dump(ModelHighAPI_Dumper& theDumper) const { @@ -101,6 +148,16 @@ void PrimitivesAPI_Box::dump(ModelHighAPI_Dumper& theDumper) const AttributeSelectionPtr anAttrSecondPnt = aBase->selection(PrimitivesPlugin_Box::POINT_SECOND_ID()); theDumper << ", " << anAttrFirstPnt << ", " << anAttrSecondPnt; + } else if (aCreationMethod == PrimitivesPlugin_Box::CREATION_METHOD_BY_ONE_POINT_AND_DIMS()) { + AttributeDoublePtr anAttrOx = aBase->real(PrimitivesPlugin_Box::OX_ID()); + AttributeDoublePtr anAttrOy = aBase->real(PrimitivesPlugin_Box::OY_ID()); + AttributeDoublePtr anAttrOz = aBase->real(PrimitivesPlugin_Box::OZ_ID()); + AttributeDoublePtr anAttrHalfLengthX = aBase->real(PrimitivesPlugin_Box::HALF_DX_ID()); + AttributeDoublePtr anAttrHalfLengthY = aBase->real(PrimitivesPlugin_Box::HALF_DY_ID()); + AttributeDoublePtr anAttrHalfLengthZ = aBase->real(PrimitivesPlugin_Box::HALF_DZ_ID()); + theDumper << ", " << anAttrOx << ", " << anAttrOy << ", " << anAttrOz; + theDumper << ", " << anAttrHalfLengthX << ", " << anAttrHalfLengthY; + theDumper << ", " << anAttrHalfLengthZ; } theDumper << ")" << std::endl; @@ -123,4 +180,18 @@ BoxPtr addBox(const std::shared_ptr& thePart, { std::shared_ptr aFeature = thePart->addFeature(PrimitivesAPI_Box::ID()); return BoxPtr(new PrimitivesAPI_Box(aFeature, theFirstPoint, theSecondPoint)); -} \ No newline at end of file +} + +//================================================================================================== +BoxPtr addBox(const std::shared_ptr& thePart, + const ModelHighAPI_Double& theOx, + const ModelHighAPI_Double& theOy, + const ModelHighAPI_Double& theOz, + const ModelHighAPI_Double& theHalfLengthX, + const ModelHighAPI_Double& theHalfLengthY, + const ModelHighAPI_Double& theHalfLengthZ) +{ + std::shared_ptr aFeature = thePart->addFeature(PrimitivesAPI_Box::ID()); + return BoxPtr(new PrimitivesAPI_Box(aFeature, theOx, theOy, theOz, theHalfLengthX, + theHalfLengthY, theHalfLengthZ)); +} diff --git a/src/PrimitivesAPI/PrimitivesAPI_Box.h b/src/PrimitivesAPI/PrimitivesAPI_Box.h index 2fda32494..33b412bea 100644 --- a/src/PrimitivesAPI/PrimitivesAPI_Box.h +++ b/src/PrimitivesAPI/PrimitivesAPI_Box.h @@ -53,11 +53,21 @@ public: const ModelHighAPI_Selection& theFirstPoint, const ModelHighAPI_Selection& theSecondPoint); + /// Constructor with values. + PRIMITIVESAPI_EXPORT + explicit PrimitivesAPI_Box(const std::shared_ptr& theFeature, + const ModelHighAPI_Double& theOx, + const ModelHighAPI_Double& theOy, + const ModelHighAPI_Double& theOz, + const ModelHighAPI_Double& theHalfX, + const ModelHighAPI_Double& theHalfY, + const ModelHighAPI_Double& theHalfZ); + /// Destructor. PRIMITIVESAPI_EXPORT virtual ~PrimitivesAPI_Box(); - INTERFACE_6(PrimitivesPlugin_Box::ID(), + INTERFACE_12(PrimitivesPlugin_Box::ID(), creationMethod, PrimitivesPlugin_Box::CREATION_METHOD(), ModelAPI_AttributeString, /** Creation method */, dx, PrimitivesPlugin_Box::DX_ID(), @@ -69,7 +79,19 @@ public: firstPoint, PrimitivesPlugin_Box::POINT_FIRST_ID(), ModelAPI_AttributeSelection, /** First point */, secondPoint, PrimitivesPlugin_Box::POINT_SECOND_ID(), - ModelAPI_AttributeSelection, /** Second point */) + ModelAPI_AttributeSelection, /** Second point */, + ox, PrimitivesPlugin_Box::OX_ID(), + ModelAPI_AttributeDouble, /** X coordinate for origin*/, + oy, PrimitivesPlugin_Box::OY_ID(), + ModelAPI_AttributeDouble, /** Y coordinate for origin*/, + oz, PrimitivesPlugin_Box::OZ_ID(), + ModelAPI_AttributeDouble, /** Z coordinate for origin*/, + halfdx, PrimitivesPlugin_Box::HALF_DX_ID(), + ModelAPI_AttributeDouble, /** Half length in X*/, + halfdy, PrimitivesPlugin_Box::HALF_DY_ID(), + ModelAPI_AttributeDouble, /** Half length in Y*/, + halfdz, PrimitivesPlugin_Box::HALF_DZ_ID(), + ModelAPI_AttributeDouble, /** Half length in Z*/) /// Set dimensions PRIMITIVESAPI_EXPORT @@ -82,6 +104,18 @@ public: void setPoints(const ModelHighAPI_Selection& theFirstPoint, const ModelHighAPI_Selection& theSecondPoint); + /// Set origin point + PRIMITIVESAPI_EXPORT + void setOrigin(const ModelHighAPI_Double& theOx, + const ModelHighAPI_Double& theOy, + const ModelHighAPI_Double& theOz); + + /// Set half lengths + PRIMITIVESAPI_EXPORT + void setHalfLengths(const ModelHighAPI_Double& theHalfLengthX, + const ModelHighAPI_Double& theHalfLengthY, + const ModelHighAPI_Double& theHalfLengthZ); + /// Dump wrapped feature PRIMITIVESAPI_EXPORT virtual void dump(ModelHighAPI_Dumper& theDumper) const; @@ -105,4 +139,15 @@ BoxPtr addBox(const std::shared_ptr& thePart, const ModelHighAPI_Selection& theFirstPoint, const ModelHighAPI_Selection& theSecondPoint); -#endif // PRIMITIVESAPI_BOX_H_ \ No newline at end of file +/// \ingroup CPPHighAPI +/// \brief Create primitive Box feature. +PRIMITIVESAPI_EXPORT +BoxPtr addBox(const std::shared_ptr& thePart, + const ModelHighAPI_Double& theOx, + const ModelHighAPI_Double& theOy, + const ModelHighAPI_Double& theOz, + const ModelHighAPI_Double& theHalfLengthX, + const ModelHighAPI_Double& theHalfLengthY, + const ModelHighAPI_Double& theHalfLengthZ); + +#endif // PRIMITIVESAPI_BOX_H_ diff --git a/src/PrimitivesPlugin/PrimitivesPlugin_Box.cpp b/src/PrimitivesPlugin/PrimitivesPlugin_Box.cpp index 30caf171d..c9606b717 100644 --- a/src/PrimitivesPlugin/PrimitivesPlugin_Box.cpp +++ b/src/PrimitivesPlugin/PrimitivesPlugin_Box.cpp @@ -40,14 +40,24 @@ void PrimitivesPlugin_Box::initAttributes() { data()->addAttribute(PrimitivesPlugin_Box::CREATION_METHOD(), ModelAPI_AttributeString::typeId()); + // Data for the first mode data()->addAttribute(PrimitivesPlugin_Box::DX_ID(), ModelAPI_AttributeDouble::typeId()); data()->addAttribute(PrimitivesPlugin_Box::DY_ID(), ModelAPI_AttributeDouble::typeId()); data()->addAttribute(PrimitivesPlugin_Box::DZ_ID(), ModelAPI_AttributeDouble::typeId()); + // Data for the second mode data()->addAttribute(PrimitivesPlugin_Box::POINT_FIRST_ID(), ModelAPI_AttributeSelection::typeId()); data()->addAttribute(PrimitivesPlugin_Box::POINT_SECOND_ID(), ModelAPI_AttributeSelection::typeId()); + + // Data for the third mode + data()->addAttribute(PrimitivesPlugin_Box::OX_ID(), ModelAPI_AttributeDouble::typeId()); + data()->addAttribute(PrimitivesPlugin_Box::OY_ID(), ModelAPI_AttributeDouble::typeId()); + data()->addAttribute(PrimitivesPlugin_Box::OZ_ID(), ModelAPI_AttributeDouble::typeId()); + data()->addAttribute(PrimitivesPlugin_Box::HALF_DX_ID(), ModelAPI_AttributeDouble::typeId()); + data()->addAttribute(PrimitivesPlugin_Box::HALF_DY_ID(), ModelAPI_AttributeDouble::typeId()); + data()->addAttribute(PrimitivesPlugin_Box::HALF_DZ_ID(), ModelAPI_AttributeDouble::typeId()); } //================================================================================================= @@ -61,6 +71,9 @@ void PrimitivesPlugin_Box::execute() if (aMethodType == CREATION_METHOD_BY_TWO_POINTS()) createBoxByTwoPoints(); + + if (aMethodType == CREATION_METHOD_BY_ONE_POINT_AND_DIMS()) + createBoxByOnePointAndDims(); } //================================================================================================= @@ -148,6 +161,50 @@ void PrimitivesPlugin_Box::createBoxByTwoPoints() setResult(aResultBox, aResultIndex); } +//================================================================================================= +void PrimitivesPlugin_Box::createBoxByOnePointAndDims() +{ + // Getting dx, dy and dz + double aDx = real(PrimitivesPlugin_Box::HALF_DX_ID())->value(); + double aDy = real(PrimitivesPlugin_Box::HALF_DY_ID())->value(); + double aDz = real(PrimitivesPlugin_Box::HALF_DZ_ID())->value(); + + // Getting point coordinates + double x = real(PrimitivesPlugin_Box::OX_ID())->value(); + double y = real(PrimitivesPlugin_Box::OY_ID())->value(); + double z = real(PrimitivesPlugin_Box::OZ_ID())->value(); + + std::shared_ptr aBoxAlgo; + aBoxAlgo = std::shared_ptr(new GeomAlgoAPI_Box(x,y,z,aDx,aDy,aDz)); + + // These checks should be made to the GUI for the feature but + // the corresponding validator does not exist yet. + if (!aBoxAlgo->check()) { + setError(aBoxAlgo->getError()); + return; + } + + // Build the box + aBoxAlgo->build(); + + // Check if the creation of the box + if(!aBoxAlgo->isDone()) { + // The error is not displayed in a popup window. It must be in the message console. + setError(aBoxAlgo->getError()); + return; + } + if(!aBoxAlgo->checkValid("Box builder with one point and dimensions")) { + // The error is not displayed in a popup window. It must be in the message console. + setError(aBoxAlgo->getError()); + return; + } + + int aResultIndex = 0; + ResultBodyPtr aResultBox = document()->createBody(data(), aResultIndex); + loadNamingDS(aBoxAlgo, aResultBox); + setResult(aResultBox, aResultIndex); +} + //================================================================================================= void PrimitivesPlugin_Box::loadNamingDS(std::shared_ptr theBoxAlgo, std::shared_ptr theResultBox) diff --git a/src/PrimitivesPlugin/PrimitivesPlugin_Box.h b/src/PrimitivesPlugin/PrimitivesPlugin_Box.h index 252cf52f3..0f3bc7f0f 100644 --- a/src/PrimitivesPlugin/PrimitivesPlugin_Box.h +++ b/src/PrimitivesPlugin/PrimitivesPlugin_Box.h @@ -32,7 +32,8 @@ class ModelAPI_ResultBody; * \brief Feature for creation of a box primitive using various methods. * * Box creates a cuboid - Parallelepiped with 6 rectangular faces. It can be built via two - * methods : using two points that define a diagonal, or using 3 lengths that define the + * methods : using two points that define a diagonal, a point that define a center and 3 lengths + * that define the half-lengths on X, Y and Z-axes, or using 3 lengths that define the * rectangular dimensions. */ class PrimitivesPlugin_Box : public ModelAPI_Feature @@ -66,6 +67,13 @@ class PrimitivesPlugin_Box : public ModelAPI_Feature return MY_CREATION_METHOD_ID; } + /// Attribute name for creation method + inline static const std::string& CREATION_METHOD_BY_ONE_POINT_AND_DIMS() + { + static const std::string MY_CREATION_METHOD_ID("BoxByOnePointAndDims"); + return MY_CREATION_METHOD_ID; + } + /// Attribute name of first point inline static const std::string& POINT_FIRST_ID() { @@ -100,6 +108,48 @@ class PrimitivesPlugin_Box : public ModelAPI_Feature static const std::string MY_DZ_ID("dz"); return MY_DZ_ID; } + + /// Attribute name of the first coordinate of the center + inline static const std::string& OX_ID() + { + static const std::string MY_OX_ID("ox"); + return MY_OX_ID; + } + + /// Attribute name of the second coordinate of the center + inline static const std::string& OY_ID() + { + static const std::string MY_OY_ID("oy"); + return MY_OY_ID; + } + + /// Attribute name of the third coordinate of the center + inline static const std::string& OZ_ID() + { + static const std::string MY_OZ_ID("oz"); + return MY_OZ_ID; + } + + /// Attribute name of the half-length on X axis + inline static const std::string& HALF_DX_ID() + { + static const std::string MY_HALF_DX_ID("half_dx"); + return MY_HALF_DX_ID; + } + + /// Attribute name of the half-length on Y axis + inline static const std::string& HALF_DY_ID() + { + static const std::string MY_HALF_DY_ID("half_dy"); + return MY_HALF_DY_ID; + } + + /// Attribute name of the half-length on Z axis + inline static const std::string& HALF_DZ_ID() + { + static const std::string MY_HALF_DZ_ID("half_dz"); + return MY_HALF_DZ_ID; + } /// Returns the kind of a feature PRIMITIVESPLUGIN_EXPORT virtual const std::string& getKind() @@ -128,6 +178,9 @@ class PrimitivesPlugin_Box : public ModelAPI_Feature ///Perform the creation of the box using three cordinates void createBoxByDimensions(); + ///Perform the creation of the box using a center and three half-lenths + void createBoxByOnePointAndDims(); + }; diff --git a/src/PrimitivesPlugin/box_widget.xml b/src/PrimitivesPlugin/box_widget.xml index f968b5154..bcd5ba91a 100644 --- a/src/PrimitivesPlugin/box_widget.xml +++ b/src/PrimitivesPlugin/box_widget.xml @@ -40,5 +40,56 @@ shape_types="vertex"> + + + + + + + + + + + + + + + + + + + + + diff --git a/src/PrimitivesPlugin/doc/TUI_boxByPtDims.rst b/src/PrimitivesPlugin/doc/TUI_boxByPtDims.rst new file mode 100644 index 000000000..2b5aa3142 --- /dev/null +++ b/src/PrimitivesPlugin/doc/TUI_boxByPtDims.rst @@ -0,0 +1,12 @@ + + .. _tui_create_boxptdim: + +Create Box coordinates of a point and dimensions +================================================ + +.. literalinclude:: examples/box3.py + :linenos: + :language: python + +:download:`Download this script ` + diff --git a/src/PrimitivesPlugin/doc/boxFeature.rst b/src/PrimitivesPlugin/doc/boxFeature.rst index 759fc9eb8..1171514af 100644 --- a/src/PrimitivesPlugin/doc/boxFeature.rst +++ b/src/PrimitivesPlugin/doc/boxFeature.rst @@ -12,7 +12,7 @@ To create a Box in the active part: #. select in the Main Menu *Primitives - > Box* item or #. click |box.icon| **Box** button in the toolbar: -There are 2 algorithms for creation of a Box: +There are 3 algorithms for creation of a Box: .. figure:: images/box_dxyz_32x32.png :align: left @@ -26,6 +26,12 @@ There are 2 algorithms for creation of a Box: **By two points** +.. figure:: images/box_pt_dxyz_32x32.png + :align: left + :height: 24px + +**By coordinates of a point and dimensions** + -------------------------------------------------------------------------------- By dimensions @@ -81,8 +87,6 @@ Input fields: :param object: Second vertex of diagonal. :return: Result object. -**Arguments**: Part + 2 selected points (opposite vertices of the box) - Result """""" @@ -94,3 +98,41 @@ A solid box based on two points and with edges parallel to the coordinate axes. Created boxes **See Also** a sample TUI Script of :ref:`tui_create_boxpnt` operation. + +By coordinates of a point and dimensions +---------------------------------------- + +Box is created by dimensions along X, Y, Z axis starting from the point of coordinates (x,y,z). + +.. figure:: images/Box_ptAndDims.png + :align: center + +Input fields: + +- **OX**, **OY**, **OZ** define coordinates of the center of box. +- **DX**, **DY**, **DZ** define dimensions (hafl length) of the box along the corresponding coordinate axes. + +**TUI Command**: + +.. py:function:: model.addBox(Part_doc, OX, OY, OZ, DX, DY, DZ) + + :param part: The current part object. + :param real: X coordinate of the center point + :param real: Y coordinate of the center point + :param real: Z coordinate of the center point + :param real: Half size along X. + :param real: Half size along Y. + :param real: Half size along Z. + :return: Result object. + +Result +"""""" + +A solid box whose point coordinates are the center and the dimensions are half lengths on one side and the other on the axes relative to the center. + +.. figure:: images/Box3.png + :align: center + + Created boxes + +**See Also** a sample TUI Script of :ref:`tui_create_boxptdim` operation. diff --git a/src/PrimitivesPlugin/doc/examples/box3.py b/src/PrimitivesPlugin/doc/examples/box3.py new file mode 100644 index 000000000..493143920 --- /dev/null +++ b/src/PrimitivesPlugin/doc/examples/box3.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() +Box_1 = model.addBox(Part_1_doc, 0, 0, 0, 20, 20, 20) +model.do() +model.end() diff --git a/src/PrimitivesPlugin/doc/images/Box3.png b/src/PrimitivesPlugin/doc/images/Box3.png new file mode 100644 index 0000000000000000000000000000000000000000..a1b5e5fcec174bb54b17897e5c070345534fa0b3 GIT binary patch literal 4828 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 literal 0 HcmV?d00001 diff --git a/src/PrimitivesPlugin/doc/images/Box_ptAndDims.png b/src/PrimitivesPlugin/doc/images/Box_ptAndDims.png new file mode 100644 index 0000000000000000000000000000000000000000..3fedaf7dfda746631209fbfac42f5ad0e772b29b GIT binary patch literal 14590 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 Qb7P{alGc+_Ma#GU3&dj>2LJ#7 literal 0 HcmV?d00001 diff --git a/src/PrimitivesPlugin/doc/images/box_pt_dxyz_32x32.png b/src/PrimitivesPlugin/doc/images/box_pt_dxyz_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..db199ea7b2e76b8ad13b1590a4aca86f25527446 GIT binary patch literal 1188 zcmV;V1Y7%wP);t6w@9EA`FA1tb1w{n%RRlg z@O0rmm-~S5qVM)>=RD{4oX_{1-#NcWph02Lu?a$o(?Echc&!p}Q+R}L*}g{zvH-8S zggcqg1{XqLTCoyuoo?2!8x6lRJUle%o!i;MqT=2bNCmz#Hl7!ri<~t)`%BkR~e?Fb=jy6s3>`S?n{#vfU zcgDuE{E-NC1D@cw8XKs;UPgb z!4(5q;6+!yTw7tnxF`fKr>oi3-Azl|ooV4`bIxm?mZqq z(3=Wi$VS}O*I1YEuFLq|1N$5kduywh^HSeuqW_Np-GG(V`x8Jqu3cbl6%l7XR1cO? zvjI(s(hUxH{E~Gm+aPAC@>Gk{*yx7s1Se=w01b*$U zJn;QDO6=B-7IH>LsLs#jP(vMuPGk@ozQpa^;=!ox5I!9q0zEj2R5nrDkH@91TG2$#Zy(j9?2`;PSoku~m5c_`19=E-&TtuP!1T z2icBfzp8<+vraQ;?x4hK!N+Q0%+HUi%v|n1``=&9?&FJH1>#O66=lwF2_&}_=H<8; z7#p+EXYQb*y_J`MpY(bv)Lxi(erlYHfy1d8vjR?)#cG*oN+4McKFL7y?Z5aqM>XbN-$Jg-G`V2ly8!6U8#6v7%%E0000;t6w@9EA`FA1tb1w{n%RRlg z@O0rmm-~S5qVM)>=RD{4oX_{1-#NcWph02Lu?a$o(?Echc&!p}Q+R}L*}g{zvH-8S zggcqg1{XqLTCoyuoo?2!8x6lRJUle%o!i;MqT=2bNCmz#Hl7!ri<~t)`%BkR~e?Fb=jy6s3>`S?n{#vfU zcgDuE{E-NC1D@cw8XKs;UPgb z!4(5q;6+!yTw7tnxF`fKr>oi3-Azl|ooV4`bIxm?mZqq z(3=Wi$VS}O*I1YEuFLq|1N$5kduywh^HSeuqW_Np-GG(V`x8Jqu3cbl6%l7XR1cO? zvjI(s(hUxH{E~Gm+aPAC@>Gk{*yx7s1Se=w01b*$U zJn;QDO6=B-7IH>LsLs#jP(vMuPGk@ozQpa^;=!ox5I!9q0zEj2R5nrDkH@91TG2$#Zy(j9?2`;PSoku~m5c_`19=E-&TtuP!1T z2icBfzp8<+vraQ;?x4hK!N+Q0%+HUi%v|n1``=&9?&FJH1>#O66=lwF2_&}_=H<8; z7#p+EXYQb*y_J`MpY(bv)Lxi(erlYHfy1d8vjR?)#cG*oN+4McKFL7y?Z5aqM>XbN-$Jg-G`V2ly8!6U8#6v7%%E0000