From: Alexey Kondratyev Date: Fri, 8 Oct 2021 13:54:33 +0000 (+0300) Subject: [bos #26448] : [EDF] (2021) SHAPER: construction elements: create extra planes X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=3198d52565f952c83b7af8e9abe232c4bf47486c;p=modules%2Fshaper.git [bos #26448] : [EDF] (2021) SHAPER: construction elements: create extra planes Add attribute "number of copies" for creating plane by rotating and by distance from other plane. Added a corresponding field in the creation window. Change documentation to reference about copies when creating a planes. Change "dump to script" to set number of copies(or without it). Add Python test. Add translate to French. --- diff --git a/src/ConstructionAPI/ConstructionAPI_Plane.cpp b/src/ConstructionAPI/ConstructionAPI_Plane.cpp index cd0bbb424..3933b1623 100644 --- a/src/ConstructionAPI/ConstructionAPI_Plane.cpp +++ b/src/ConstructionAPI/ConstructionAPI_Plane.cpp @@ -33,11 +33,12 @@ ConstructionAPI_Plane::ConstructionAPI_Plane(const std::shared_ptr& theFeature, const ModelHighAPI_Selection& theFace, const ModelHighAPI_Double& theDistance, - const bool theIsReverse) + const bool theIsReverse, + const ModelHighAPI_Integer& theNbCopy) : ModelHighAPI_Interface(theFeature) { if(initialize()) { - setByFaceAndDistance(theFace, theDistance, theIsReverse); + setByFaceAndDistance(theFace, theDistance, theIsReverse, theNbCopy); } } @@ -99,11 +100,12 @@ ConstructionAPI_Plane::ConstructionAPI_Plane(const std::shared_ptr& theFeature, const ModelHighAPI_Selection& thePlane, const ModelHighAPI_Selection& theAxis, - const ModelHighAPI_Double& theAngle) + const ModelHighAPI_Double& theAngle, + const ModelHighAPI_Integer& theNbCopy) : ModelHighAPI_Interface(theFeature) { if(initialize()) { - setByRotation(thePlane, theAxis, theAngle); + setByRotation(thePlane, theAxis, theAngle, theNbCopy); } } @@ -115,7 +117,8 @@ ConstructionAPI_Plane::~ConstructionAPI_Plane() //================================================================================================== void ConstructionAPI_Plane::setByFaceAndDistance(const ModelHighAPI_Selection& theFace, const ModelHighAPI_Double& theDistance, - const bool theIsReverse) + const bool theIsReverse, + const ModelHighAPI_Integer& theNbCopy) { fillAttribute(ConstructionPlugin_Plane::CREATION_METHOD_BY_OTHER_PLANE(), mycreationMethod); fillAttribute(theFace, myplane); @@ -123,6 +126,7 @@ void ConstructionAPI_Plane::setByFaceAndDistance(const ModelHighAPI_Selection& t mycreationMethodByOtherPlane); fillAttribute(theDistance, mydistance); fillAttribute(theIsReverse, myreverse); + fillAttribute(theNbCopy, mynbcopy); execute(); } @@ -196,7 +200,8 @@ void ConstructionAPI_Plane::setByCoincidentToPoint(const ModelHighAPI_Selection& //================================================================================================== void ConstructionAPI_Plane::setByRotation(const ModelHighAPI_Selection& thePlane, const ModelHighAPI_Selection& theAxis, - const ModelHighAPI_Double& theAngle) + const ModelHighAPI_Double& theAngle, + const ModelHighAPI_Integer& theNbCopy) { fillAttribute(ConstructionPlugin_Plane::CREATION_METHOD_BY_OTHER_PLANE(), mycreationMethod); fillAttribute(thePlane, myplane); @@ -204,6 +209,7 @@ void ConstructionAPI_Plane::setByRotation(const ModelHighAPI_Selection& thePlane mycreationMethodByOtherPlane); fillAttribute(theAxis, myaxis); fillAttribute(theAngle, myangle); + fillAttribute(theNbCopy, mynbcopy); execute(); } @@ -248,8 +254,11 @@ void ConstructionAPI_Plane::dump(ModelHighAPI_Dumper& theDumper) const ConstructionPlugin_Plane::CREATION_METHOD_BY_DISTANCE_FROM_OTHER()) { AttributeDoublePtr anAttrDistance = aBase->real(ConstructionPlugin_Plane::DISTANCE()); AttributeBooleanPtr anAttrReverse = aBase->boolean(ConstructionPlugin_Plane::REVERSE()); + AttributeIntegerPtr anAttrNbCopy = aBase->integer(ConstructionPlugin_Plane::NB_COPIES()); theDumper << ", " << anAttrPlane << ", " << anAttrDistance << ", " << anAttrReverse; + if(anAttrNbCopy.get() && anAttrNbCopy->value() > 1) + theDumper << ", " << anAttrNbCopy; } else if(aCreationMethodOption == ConstructionPlugin_Plane::CREATION_METHOD_BY_COINCIDENT_TO_POINT()) { AttributeSelectionPtr anAttrPoint = @@ -259,8 +268,11 @@ void ConstructionAPI_Plane::dump(ModelHighAPI_Dumper& theDumper) const } else if(aCreationMethodOption == ConstructionPlugin_Plane::CREATION_METHOD_BY_ROTATION()) { AttributeSelectionPtr anAttrAxis = aBase->selection(ConstructionPlugin_Plane::AXIS()); AttributeDoublePtr anAttrAngle = aBase->real(ConstructionPlugin_Plane::ANGLE()); + AttributeIntegerPtr anAttrNbCopy = aBase->integer(ConstructionPlugin_Plane::NB_COPIES()); theDumper << ", " << anAttrPlane << ", " << anAttrAxis << ", " << anAttrAngle; + if (anAttrNbCopy.get() && anAttrNbCopy->value() > 1) + theDumper << ", " << anAttrNbCopy; } } else if(aCreationMethod == ConstructionPlugin_Plane::CREATION_METHOD_BY_TWO_PARALLEL_PLANES()) { @@ -277,11 +289,12 @@ void ConstructionAPI_Plane::dump(ModelHighAPI_Dumper& theDumper) const PlanePtr addPlane(const std::shared_ptr& thePart, const ModelHighAPI_Selection& theFace, const ModelHighAPI_Double& theDistance, - const bool theIsReverse) + const bool theIsReverse, + const ModelHighAPI_Integer& theNbCopies) { // TODO(spo): check that thePart is not empty std::shared_ptr aFeature = thePart->addFeature(ConstructionAPI_Plane::ID()); - return PlanePtr(new ConstructionAPI_Plane(aFeature, theFace, theDistance, theIsReverse)); + return PlanePtr(new ConstructionAPI_Plane(aFeature, theFace, theDistance, theIsReverse, theNbCopies)); } //================================================================================================== @@ -332,9 +345,10 @@ PlanePtr addPlane(const std::shared_ptr& thePart, PlanePtr addPlane(const std::shared_ptr& thePart, const ModelHighAPI_Selection& thePlane, const ModelHighAPI_Selection& theAxis, - const ModelHighAPI_Double& theAngle) + const ModelHighAPI_Double& theAngle, + const ModelHighAPI_Integer& theNbCopies) { // TODO(spo): check that thePart is not empty std::shared_ptr aFeature = thePart->addFeature(ConstructionAPI_Plane::ID()); - return PlanePtr(new ConstructionAPI_Plane(aFeature, thePlane, theAxis, theAngle)); + return PlanePtr(new ConstructionAPI_Plane(aFeature, thePlane, theAxis, theAngle, theNbCopies)); } diff --git a/src/ConstructionAPI/ConstructionAPI_Plane.h b/src/ConstructionAPI/ConstructionAPI_Plane.h index b8b28d3f4..b99940b09 100644 --- a/src/ConstructionAPI/ConstructionAPI_Plane.h +++ b/src/ConstructionAPI/ConstructionAPI_Plane.h @@ -26,6 +26,7 @@ #include #include +#include class ModelHighAPI_Double; class ModelHighAPI_Selection; @@ -45,7 +46,8 @@ public: ConstructionAPI_Plane(const std::shared_ptr& theFeature, const ModelHighAPI_Selection& theFace, const ModelHighAPI_Double& theDistance, - const bool theIsReverse); + const bool theIsReverse, + const ModelHighAPI_Integer& theNbCopy = ModelHighAPI_Integer(1)); /// Constructor with values CONSTRUCTIONAPI_EXPORT @@ -80,13 +82,14 @@ public: ConstructionAPI_Plane(const std::shared_ptr& theFeature, const ModelHighAPI_Selection& thePlane, const ModelHighAPI_Selection& theAxis, - const ModelHighAPI_Double& theAngle); + const ModelHighAPI_Double& theAngle, + const ModelHighAPI_Integer& theNbCopy = ModelHighAPI_Integer(1)); /// Destructor CONSTRUCTIONAPI_EXPORT virtual ~ConstructionAPI_Plane(); - INTERFACE_20(ConstructionPlugin_Plane::ID(), + INTERFACE_21(ConstructionPlugin_Plane::ID(), creationMethod, ConstructionPlugin_Plane::CREATION_METHOD(), ModelAPI_AttributeString, /** Creation method */, A, ConstructionPlugin_Plane::A(), @@ -127,13 +130,16 @@ public: plane1, ConstructionPlugin_Plane::PLANE1(), ModelAPI_AttributeSelection, /** Plane 1 */, plane2, ConstructionPlugin_Plane::PLANE2(), - ModelAPI_AttributeSelection, /** Plane 2 */) + ModelAPI_AttributeSelection, /** Plane 2 */, + nbcopy, ConstructionPlugin_Plane::NB_COPIES(), + ModelAPI_AttributeInteger, /** Number of copies */) /// Set face and distance CONSTRUCTIONAPI_EXPORT void setByFaceAndDistance(const ModelHighAPI_Selection& theFace, const ModelHighAPI_Double& theDistance, - const bool theIsReverse); + const bool theIsReverse, + const ModelHighAPI_Integer& theNbCopy = ModelHighAPI_Integer(1)); /// Set GeneralEquation parameters of the feature CONSTRUCTIONAPI_EXPORT @@ -168,7 +174,8 @@ public: CONSTRUCTIONAPI_EXPORT void setByRotation(const ModelHighAPI_Selection& thePlane, const ModelHighAPI_Selection& theAxis, - const ModelHighAPI_Double& theAngle); + const ModelHighAPI_Double& theAngle, + const ModelHighAPI_Integer& theNbCopy = ModelHighAPI_Integer(1)); /// Dump wrapped feature CONSTRUCTIONAPI_EXPORT @@ -184,7 +191,8 @@ CONSTRUCTIONAPI_EXPORT PlanePtr addPlane(const std::shared_ptr& thePart, const ModelHighAPI_Selection& theFace, const ModelHighAPI_Double& theDistance, - const bool theIsReverse); + const bool theIsReverse, + const ModelHighAPI_Integer& theNbCopy = ModelHighAPI_Integer(1)); /// \ingroup CPPHighAPI /// \brief Create Plane feature @@ -224,6 +232,7 @@ CONSTRUCTIONAPI_EXPORT PlanePtr addPlane(const std::shared_ptr& thePart, const ModelHighAPI_Selection& thePlane, const ModelHighAPI_Selection& theAxis, - const ModelHighAPI_Double& theAngle); + const ModelHighAPI_Double& theAngle, + const ModelHighAPI_Integer& theNbCopy = ModelHighAPI_Integer(1)); #endif /* SRC_CONSTRUCTIONAPI_CONSTRUCTIONAPI_PLANE_H_ */ diff --git a/src/ConstructionPlugin/ConstructionPlugin_Plane.cpp b/src/ConstructionPlugin/ConstructionPlugin_Plane.cpp index c4c384ba5..6a6d7fc6b 100644 --- a/src/ConstructionPlugin/ConstructionPlugin_Plane.cpp +++ b/src/ConstructionPlugin/ConstructionPlugin_Plane.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -99,46 +100,63 @@ void ConstructionPlugin_Plane::initAttributes() // By two parallel planes. data()->addAttribute(PLANE1(), ModelAPI_AttributeSelection::typeId()); data()->addAttribute(PLANE2(), ModelAPI_AttributeSelection::typeId()); + + // By other plane. + AttributeIntegerPtr aNbCopies = std::dynamic_pointer_cast( + data()->addAttribute(NB_COPIES(), ModelAPI_AttributeInteger::typeId())); + + if (!aNbCopies->isInitialized()) + aNbCopies->setValue(1); } //================================================================================================== void ConstructionPlugin_Plane::execute() { - GeomShapePtr aShape; + ListOfShape aShapes; std::string aCreationMethod = string(CREATION_METHOD())->value(); if(aCreationMethod == CREATION_METHOD_BY_GENERAL_EQUATION() || aCreationMethod == "PlaneByGeneralEquation") { - aShape = createByGeneralEquation(); + aShapes.push_back(createByGeneralEquation()); } else if(aCreationMethod == CREATION_METHOD_BY_THREE_POINTS()) { - aShape = createByThreePoints(); + aShapes.push_back(createByThreePoints()); } else if(aCreationMethod == CREATION_METHOD_BY_LINE_AND_POINT()) { - aShape = createByLineAndPoint(); + aShapes.push_back(createByLineAndPoint()); } else if(aCreationMethod == CREATION_METHOD_BY_OTHER_PLANE()) { std::string aCreationMethodOption = string(CREATION_METHOD_BY_OTHER_PLANE_OPTION())->value(); if(aCreationMethodOption == CREATION_METHOD_BY_DISTANCE_FROM_OTHER()) { - aShape = createByDistanceFromOther(); + createByDistanceFromOther(aShapes); } else if(aCreationMethodOption == CREATION_METHOD_BY_COINCIDENT_TO_POINT()) { - aShape = createByCoincidentPoint(); + aShapes.push_back(createByCoincidentPoint()); } else if(aCreationMethodOption == CREATION_METHOD_BY_ROTATION()) { - aShape = createByRotation(); + createByRotation(aShapes); } } else if(aCreationMethod == CREATION_METHOD_BY_TWO_PARALLEL_PLANES()) { - aShape = createByTwoParallelPlanes(); + aShapes.push_back(createByTwoParallelPlanes()); } else { setError("Error: Plane creation method \"" + aCreationMethod + "\" not supported."); return; } - if(!aShape.get()) { + if(aShapes.size() == 0) { setError("Error: Could not create a plane."); return; } - ResultConstructionPtr aConstr = document()->createConstruction(data()); - aConstr->setInfinite(true); - aConstr->setShape(aShape); - setResult(aConstr); + int anIndex = 0; + for (auto aShapeIter = aShapes.begin(); aShapeIter != aShapes.end(); ++aShapeIter, ++anIndex) + { + if (!aShapeIter->get()) + { + setError("Error: Could not create a plane."); + continue; + } + ResultConstructionPtr aConstr = document()->createConstruction(data(), anIndex); + aConstr->setInfinite(true); + aConstr->setShape(*aShapeIter); + setResult(aConstr, anIndex); + } + removeResults(anIndex); } //================================================================================================== @@ -191,7 +209,6 @@ std::shared_ptr ConstructionPlugin_Plane::createByGeneralEquation } return aPlaneFace; } - //================================================================================================== std::shared_ptr ConstructionPlugin_Plane::createByThreePoints() { @@ -275,17 +292,18 @@ std::shared_ptr ConstructionPlugin_Plane::createByLineAndPoint() } //================================================================================================== -std::shared_ptr ConstructionPlugin_Plane::createByDistanceFromOther() +void ConstructionPlugin_Plane::createByDistanceFromOther(ListOfShape& theShapes) { AttributeSelectionPtr aFaceAttr = data()->selection(ConstructionPlugin_Plane::PLANE()); AttributeDoublePtr aDistAttr = data()->real(ConstructionPlugin_Plane::DISTANCE()); - std::shared_ptr aPlane; + AttributeIntegerPtr aNbCopyAttr = data()->integer(ConstructionPlugin_Plane::NB_COPIES()); if ((aFaceAttr.get() != NULL) && - (aDistAttr.get() != NULL) && + (aDistAttr.get() != NULL) && (aNbCopyAttr.get() != NULL) && aFaceAttr->isInitialized() && aDistAttr->isInitialized()) { double aDist = aDistAttr->value(); bool anIsReverse = boolean(REVERSE())->value(); + int aNumOfCopies = aNbCopyAttr->value(); if(anIsReverse) aDist = -aDist; GeomShapePtr aShape = aFaceAttr->value(); if (!aShape.get() && aFaceAttr->context()) { @@ -293,7 +311,7 @@ std::shared_ptr ConstructionPlugin_Plane::createByDistanceFromOth } if(!aShape.get()) { - return aPlane; + return; } std::shared_ptr aFace; @@ -305,18 +323,22 @@ std::shared_ptr ConstructionPlugin_Plane::createByDistanceFromOth aFace = anIt.current()->face(); } if (!aFace) - return GeomShapePtr(); + return; std::shared_ptr aPln = aFace->getPlane(); std::shared_ptr aOrig = aPln->location(); std::shared_ptr aDir = aPln->direction(); - aOrig->translate(aDir, aDist); - std::shared_ptr aNewPln(new GeomAPI_Pln(aOrig, aDir)); + for (int aNbCopy = 0; aNbCopy < aNumOfCopies; ++aNbCopy) + { + std::shared_ptr aPlane; + aOrig->translate(aDir, aDist); + std::shared_ptr aNewPln(new GeomAPI_Pln(aOrig, aDir)); - aPlane = makeRectangularFace(aFace, aNewPln); + aPlane = makeRectangularFace(aFace, aNewPln); + theShapes.push_back(aPlane); + } } - return aPlane; } //================================================================================================== @@ -357,7 +379,7 @@ std::shared_ptr ConstructionPlugin_Plane::createByCoincidentPoint } //================================================================================================== -std::shared_ptr ConstructionPlugin_Plane::createByRotation() +void ConstructionPlugin_Plane::createByRotation(ListOfShape& theShapes) { // Get face. AttributeSelectionPtr aFaceSelection = selection(PLANE()); @@ -374,7 +396,7 @@ std::shared_ptr ConstructionPlugin_Plane::createByRotation() aFace = anIt.current()->face(); } if (!aFace) - return GeomShapePtr(); + return; aFace = makeRectangularFace(aFace, aFace->getPlane()); // Get axis. @@ -392,7 +414,14 @@ std::shared_ptr ConstructionPlugin_Plane::createByRotation() anEdge = anIt.current()->edge(); } if (!anEdge) - return GeomShapePtr(); + return; + + AttributeIntegerPtr aNbCopyAttr = data()->integer(ConstructionPlugin_Plane::NB_COPIES()); + int aNBCopy; + if (!aNbCopyAttr.get()) + return; + + aNBCopy = aNbCopyAttr->value(); std::shared_ptr anAxis = std::shared_ptr(new GeomAPI_Ax1(anEdge->line()->location(), @@ -401,17 +430,20 @@ std::shared_ptr ConstructionPlugin_Plane::createByRotation() // Getting angle. double anAngle = real(ANGLE())->value(); - std::shared_ptr aRotationAlgo( - new GeomAlgoAPI_Rotation(aFace, anAxis, anAngle)); - // Checking that the algorithm worked properly. - std::string anError; - if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aRotationAlgo, getKind(), anError)) { - setError("Error: Failed to rotate plane"); - return GeomShapePtr(); - } + for (int anIndex = 1; anIndex <= aNBCopy; ++anIndex) + { + std::shared_ptr aRotationAlgo( + new GeomAlgoAPI_Rotation(aFace, anAxis, anAngle * anIndex)); + // Checking that the algorithm worked properly. + std::string anError; + if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aRotationAlgo, getKind(), anError)) { + setError("Error: Failed to rotate plane"); + return; + } - std::shared_ptr aRes(new GeomAPI_Face(aRotationAlgo->shape())); - return aRes; + std::shared_ptr aRes(new GeomAPI_Face(aRotationAlgo->shape())); + theShapes.push_back(aRes); + } } //================================================================================================== diff --git a/src/ConstructionPlugin/ConstructionPlugin_Plane.h b/src/ConstructionPlugin/ConstructionPlugin_Plane.h index 214f4e6db..ff6b14adf 100644 --- a/src/ConstructionPlugin/ConstructionPlugin_Plane.h +++ b/src/ConstructionPlugin/ConstructionPlugin_Plane.h @@ -25,6 +25,7 @@ #include #include #include +#include /// \class ConstructionPlugin_Plane /// \ingroup Plugins @@ -226,6 +227,11 @@ public: return ATTR_ID; } + inline static const std::string& NB_COPIES() + { + static const std::string ATTR_ID("nb_copies"); + return ATTR_ID; + } /// Attribute name for a parameter for the general equation of a plane (ax+by+cz+d=0) inline static const std::string& A() @@ -270,11 +276,11 @@ protected: std::shared_ptr createByThreePoints(); std::shared_ptr createByLineAndPoint(); std::shared_ptr createByCoincidentPoint(); - std::shared_ptr createByRotation(); + void createByRotation(ListOfShape& theShapes); std::shared_ptr createByTwoParallelPlanes(); /// Creates a new plane by copy of face plane with translation along the normal /// to the specified distance. - std::shared_ptr createByDistanceFromOther(); + void createByDistanceFromOther(ListOfShape& theShapes); }; #endif diff --git a/src/ConstructionPlugin/ConstructionPlugin_msg_en.ts b/src/ConstructionPlugin/ConstructionPlugin_msg_en.ts index ecb0de35d..2de6c5fea 100644 --- a/src/ConstructionPlugin/ConstructionPlugin_msg_en.ts +++ b/src/ConstructionPlugin/ConstructionPlugin_msg_en.ts @@ -300,6 +300,13 @@ Select the third point. + + Plane:nb_copies + + Attribute "%1" is not initialized. + Select the number of copies. + + Point:edge diff --git a/src/ConstructionPlugin/ConstructionPlugin_msg_fr.ts b/src/ConstructionPlugin/ConstructionPlugin_msg_fr.ts index 21fa8315f..24550d296 100644 --- a/src/ConstructionPlugin/ConstructionPlugin_msg_fr.ts +++ b/src/ConstructionPlugin/ConstructionPlugin_msg_fr.ts @@ -759,7 +759,21 @@ Sens inverse - + + Plane:nb_copies + + Nb copies + Nb de exemplaires + + + Number of copies of the plane + Nombre des exemplaires de la avion + + + Attribute "%1" is not initialized. + Sélectionnez le nombre de exemplaires. + + Point diff --git a/src/ConstructionPlugin/Test/TestPlane_Copies.py b/src/ConstructionPlugin/Test/TestPlane_Copies.py new file mode 100644 index 000000000..ddc46213d --- /dev/null +++ b/src/ConstructionPlugin/Test/TestPlane_Copies.py @@ -0,0 +1,65 @@ +# 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 +# + +""" +Test case for Construction Plane feature. Written on High API. +""" +from ModelAPI import * +from GeomAPI import * + +from salome.shaper import model + +# Get session +aSession = ModelAPI_Session.get() + +# Create a part +aDocument = aSession.activeDocument() +aSession.startOperation() +model.addPart(aDocument) +aDocument = aSession.activeDocument() +aSession.finishOperation() + +# Test a plane by general equation +aSession.startOperation() +aPlane = model.addPlane(aDocument, 1, 1, 1, 0) +aSession.finishOperation() +assert (len(aPlane.results()) > 0) + +# Create an axis +aSession.startOperation() +anAxis = model.addAxis(aDocument, 100, 0, 0) +aSession.finishOperation() + +# Test a plane by rotation +aSession.startOperation() +aRotatedPlane = model.addPlane(aDocument, aPlane.result(), anAxis.result(), 45) +aRotatedPlanes = model.addPlane(aDocument, aPlane.result(), anAxis.result(), 45, 5) +aSession.finishOperation() +assert (len(aRotatedPlane.results()) > 0) +assert (len(aRotatedPlanes.results()) == 5) + +# Test a plane by distance from other +aSession.startOperation() +anOnlyPlane = model.addPlane(aDocument, aPlane.result(), 50, False) +assert (len(anOnlyPlane.results()) > 0) +aPlane = model.addPlane(aDocument, aPlane.result(), 50, False, 10) +aSession.finishOperation() +assert (len(aPlane.results()) == 10) + +assert(model.checkPythonDump()) diff --git a/src/ConstructionPlugin/doc/images/Plane3.png b/src/ConstructionPlugin/doc/images/Plane3.png index be4eddd0d..a0512dd0a 100644 Binary files a/src/ConstructionPlugin/doc/images/Plane3.png and b/src/ConstructionPlugin/doc/images/Plane3.png differ diff --git a/src/ConstructionPlugin/doc/planeFeature.rst b/src/ConstructionPlugin/doc/planeFeature.rst index 90c7134e0..a0b2d71fb 100644 --- a/src/ConstructionPlugin/doc/planeFeature.rst +++ b/src/ConstructionPlugin/doc/planeFeature.rst @@ -28,7 +28,7 @@ There are 4 algorithms for creation of a Plane: :align: left :height: 24px -**By other plane** creates a plane parallel to another plane. +**By other plane** creates a plane or planes(if the number of copies is more than one) parallel to another plane. .. figure:: images/plane_by_two_parallel_planes_32x32.png :align: left @@ -134,18 +134,19 @@ By rotation around an edge by a specified angle. **TUI Commands**: -.. py:function:: model.addPlane(Part_doc, model.selection("FACE", "Box_1_1/Front"), 10, False) +.. py:function:: model.addPlane(Part_doc, model.selection("FACE", "Box_1_1/Front"), 10, False, 1) :param part: The current part object. :param object: A plane. :param real: An offset. :param boolean: Is reverse. + :param integer: Number of copies :return: Result object. Result """""" -The Result of the operation will be a plane parallel to already existing one: +The Result of the operation will be a plane (or planes at equal distance from each other, if the number of copies is more than one) parallel to already existing one: .. figure:: images/CreatedPlane3.png :align: center diff --git a/src/ConstructionPlugin/plane_widget.xml b/src/ConstructionPlugin/plane_widget.xml index b9e777555..0c487b5ac 100644 --- a/src/ConstructionPlugin/plane_widget.xml +++ b/src/ConstructionPlugin/plane_widget.xml @@ -75,6 +75,12 @@ min="0" default="10"> + + + + diff --git a/src/ConstructionPlugin/tests.set b/src/ConstructionPlugin/tests.set index 09e2211bc..1bfdfa7fd 100644 --- a/src/ConstructionPlugin/tests.set +++ b/src/ConstructionPlugin/tests.set @@ -37,6 +37,7 @@ SET(TEST_NAMES TestPlane.py TestPlane_ErrorMsg.py TestPlane_FaceValidator.py + TestPlane_Copies.py Test19207.py Test19471.py ) diff --git a/src/Model/Model_Objects.cpp b/src/Model/Model_Objects.cpp index ebb3d6be9..1265360d6 100644 --- a/src/Model/Model_Objects.cpp +++ b/src/Model/Model_Objects.cpp @@ -1905,10 +1905,12 @@ void Model_Objects::updateResults(FeaturePtr theFeature, std::set& t } } else if (aGroup->Get() == ModelAPI_ResultConstruction::group().c_str()) { ResultConstructionPtr aConstr = createConstruction(theFeature->data(), aResIndex); - if (!aConstr->updateShape()) - theFeature->execute(); // not stored shape in the data structure, execute to have it - else - theFeature->setResult(aConstr, aResIndex); // result is ready without execution + if (!aConstr->data()->isDeleted()) { + if (!aConstr->updateShape()) + theFeature->execute(); // not stored shape in the data structure, execute to have it + else + theFeature->setResult(aConstr, aResIndex); // result is ready without execution + } } else if (aGroup->Get() == ModelAPI_ResultGroup::group().c_str()) { aNewBody = createGroup(theFeature->data(), aResIndex); } else if (aGroup->Get() == ModelAPI_ResultField::group().c_str()) { diff --git a/src/Model/Model_Update.cpp b/src/Model/Model_Update.cpp index 25c0cd978..dc5da8ad1 100644 --- a/src/Model/Model_Update.cpp +++ b/src/Model/Model_Update.cpp @@ -905,8 +905,7 @@ void Model_Update::updateArguments(FeaturePtr theFeature) { bool isObligatory = aFactory->isCase(theFeature, theFeature->data()->id(aSel)); if (isObligatory) aState = ModelAPI_StateInvalidArgument; - } else if (theFeature->getKind() == "Sketch" && aSel->id() == "External" && - aSel->isInitialized()) { + } else if (aSel->isInitialized()) { // #19703 : if sketch plane was selected, but after context disappears, it must become invalid aSel->update(); if (aSel->isInvalid()) {