From: lucasjerome Date: Wed, 27 Jan 2021 18:38:10 +0000 (+0100) Subject: CEA - Lot3 : Add LOFT Feature X-Git-Tag: V9_10_0a1~2^2 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=371adab6b0fad916f5f9f35dd64ae23f74b5c489;p=modules%2Fshaper.git CEA - Lot3 : Add LOFT Feature --- diff --git a/src/FeaturesAPI/CMakeLists.txt b/src/FeaturesAPI/CMakeLists.txt index 5ced6f8c9..554d5ddaa 100644 --- a/src/FeaturesAPI/CMakeLists.txt +++ b/src/FeaturesAPI/CMakeLists.txt @@ -37,6 +37,7 @@ SET(PROJECT_HEADERS FeaturesAPI_MultiTranslation.h FeaturesAPI_Partition.h FeaturesAPI_Pipe.h + FeaturesAPI_Loft.h FeaturesAPI_Placement.h FeaturesAPI_PointCloudOnFace.h FeaturesAPI_Recover.h @@ -75,6 +76,7 @@ SET(PROJECT_SOURCES FeaturesAPI_MultiTranslation.cpp FeaturesAPI_Partition.cpp FeaturesAPI_Pipe.cpp + FeaturesAPI_Loft.cpp FeaturesAPI_Placement.cpp FeaturesAPI_PointCloudOnFace.cpp FeaturesAPI_Recover.cpp diff --git a/src/FeaturesAPI/FeaturesAPI.i b/src/FeaturesAPI/FeaturesAPI.i index d9d5367b8..2cc08c164 100644 --- a/src/FeaturesAPI/FeaturesAPI.i +++ b/src/FeaturesAPI/FeaturesAPI.i @@ -76,6 +76,7 @@ %shared_ptr(FeaturesAPI_MultiTranslation) %shared_ptr(FeaturesAPI_Partition) %shared_ptr(FeaturesAPI_Pipe) +%shared_ptr(FeaturesAPI_Loft) %shared_ptr(FeaturesAPI_Placement) %shared_ptr(FeaturesAPI_PointCloudOnFace) %shared_ptr(FeaturesAPI_Recover) @@ -219,6 +220,7 @@ %include "FeaturesAPI_MultiTranslation.h" %include "FeaturesAPI_Partition.h" %include "FeaturesAPI_Pipe.h" +%include "FeaturesAPI_Loft.h" %include "FeaturesAPI_Placement.h" %include "FeaturesAPI_PointCloudOnFace.h" %include "FeaturesAPI_Recover.h" diff --git a/src/FeaturesAPI/FeaturesAPI_Loft.cpp b/src/FeaturesAPI/FeaturesAPI_Loft.cpp new file mode 100644 index 000000000..ad21aa52d --- /dev/null +++ b/src/FeaturesAPI/FeaturesAPI_Loft.cpp @@ -0,0 +1,77 @@ +// Copyright (C) 2014-2022 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 "FeaturesAPI_Loft.h" + +#include +#include + +//================================================================================================== +FeaturesAPI_Loft::FeaturesAPI_Loft(const std::shared_ptr& theFeature) +: ModelHighAPI_Interface(theFeature) +{ + initialize(); +} + +//================================================================================================== +FeaturesAPI_Loft::FeaturesAPI_Loft(const std::shared_ptr& theFeature, + const ModelHighAPI_Selection& theFirstObject, + const ModelHighAPI_Selection& theSecondObject) +: ModelHighAPI_Interface(theFeature) +{ + if(initialize()) { + fillAttribute(theFirstObject, myfisrstObject); + fillAttribute(theSecondObject, mysecondObject); + execute(); + } +} + +//================================================================================================== +FeaturesAPI_Loft::~FeaturesAPI_Loft() +{ + +} + +//================================================================================================== +void FeaturesAPI_Loft::dump(ModelHighAPI_Dumper& theDumper) const +{ + FeaturePtr aBase = feature(); + const std::string& aDocName = theDumper.name(aBase->document()); + + AttributeSelectionPtr anAttrFirstObject = + aBase->selection(FeaturesPlugin_Loft::FIRST_OBJECT_ID()); + AttributeSelectionPtr anAttrSecondObject = + aBase->selection(FeaturesPlugin_Loft::SECOND_OBJECT_ID()); + + theDumper << aBase << " = model.addLoft(" << aDocName << ", " + << anAttrFirstObject << ", " << anAttrSecondObject; + + theDumper << ")" << std::endl; +} + +//================================================================================================== +LoftPtr addLoft(const std::shared_ptr& thePart, + const ModelHighAPI_Selection& theFirstObject, + const ModelHighAPI_Selection& theSecondObject) +{ + std::shared_ptr aFeature = thePart->addFeature(FeaturesAPI_Loft::ID()); + + return LoftPtr(new FeaturesAPI_Loft(aFeature, theFirstObject, theSecondObject)); +} + diff --git a/src/FeaturesAPI/FeaturesAPI_Loft.h b/src/FeaturesAPI/FeaturesAPI_Loft.h new file mode 100644 index 000000000..aabe0dc41 --- /dev/null +++ b/src/FeaturesAPI/FeaturesAPI_Loft.h @@ -0,0 +1,74 @@ +// Copyright (C) 2014-2022 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 FeaturesAPI_Loft_H_ +#define FeaturesAPI_Loft_H_ + +#include "FeaturesAPI.h" + +#include + +#include +#include + +class ModelHighAPI_Dumper; +class ModelHighAPI_Selection; + +/// \class FeaturesAPI_Loft +/// \ingroup CPPHighAPI +/// \brief Interface for Loft feature. +class FeaturesAPI_Loft: public ModelHighAPI_Interface +{ +public: + /// Constructor without values. + FEATURESAPI_EXPORT + explicit FeaturesAPI_Loft(const std::shared_ptr& theFeature); + + /// Constructor with values. + FEATURESAPI_EXPORT + explicit FeaturesAPI_Loft(const std::shared_ptr& theFeature, + const ModelHighAPI_Selection& theFirstObject, + const ModelHighAPI_Selection& theSecondObject); + + /// Destructor. + FEATURESAPI_EXPORT + virtual ~FeaturesAPI_Loft(); + + INTERFACE_2(FeaturesPlugin_Loft::ID(), + fisrstObject, FeaturesPlugin_Loft::FIRST_OBJECT_ID(), + ModelAPI_AttributeSelection, /** First object */, + secondObject, FeaturesPlugin_Loft::SECOND_OBJECT_ID(), + ModelAPI_AttributeSelection, /** second objexct */) + + /// Dump wrapped feature + FEATURESAPI_EXPORT + virtual void dump(ModelHighAPI_Dumper& theDumper) const; +}; + +/// Pointer on Loft object. +typedef std::shared_ptr LoftPtr; + +/// \ingroup CPPHighAPI +/// \brief Create Loft feature. +FEATURESAPI_EXPORT +LoftPtr addLoft(const std::shared_ptr& thePart, + const ModelHighAPI_Selection& theFirstObject, + const ModelHighAPI_Selection& theSecondObject); + +#endif // FeaturesAPI_Loft_H_ diff --git a/src/FeaturesAPI/FeaturesAPI_swig.h b/src/FeaturesAPI/FeaturesAPI_swig.h index a761ff93a..f03aad755 100644 --- a/src/FeaturesAPI/FeaturesAPI_swig.h +++ b/src/FeaturesAPI/FeaturesAPI_swig.h @@ -40,6 +40,7 @@ #include "FeaturesAPI_MultiTranslation.h" #include "FeaturesAPI_Partition.h" #include "FeaturesAPI_Pipe.h" + #include "FeaturesAPI_Loft.h" #include "FeaturesAPI_Placement.h" #include "FeaturesAPI_PointCloudOnFace.h" #include "FeaturesAPI_Recover.h" diff --git a/src/FeaturesPlugin/CMakeLists.txt b/src/FeaturesPlugin/CMakeLists.txt index 4f2148191..9cc750314 100644 --- a/src/FeaturesPlugin/CMakeLists.txt +++ b/src/FeaturesPlugin/CMakeLists.txt @@ -39,6 +39,7 @@ SET(PROJECT_HEADERS FeaturesPlugin_Intersection.h FeaturesPlugin_Partition.h FeaturesPlugin_Pipe.h + FeaturesPlugin_Loft.h FeaturesPlugin_Placement.h FeaturesPlugin_PointCloudOnFace.h FeaturesPlugin_CompositeBoolean.h @@ -94,6 +95,7 @@ SET(PROJECT_SOURCES FeaturesPlugin_Intersection.cpp FeaturesPlugin_Partition.cpp FeaturesPlugin_Pipe.cpp + FeaturesPlugin_Loft.cpp FeaturesPlugin_Placement.cpp FeaturesPlugin_PointCloudOnFace.cpp FeaturesPlugin_CompositeBoolean.cpp @@ -152,6 +154,7 @@ SET(XML_RESOURCES placement_widget.xml intersection_widget.xml pipe_widget.xml + loft_widget.xml remove_subshapes_widget.xml union_widget.xml symmetry_widget.xml @@ -223,16 +226,16 @@ ADD_UNIT_TESTS( IF(${HAVE_SALOME}) enable_testing() set(TEST_INSTALL_DIRECTORY "${SALOME_SHAPER_INSTALL_TESTS}/FeaturesPlugin") - + install(FILES CTestTestfileInstall.cmake DESTINATION ${TEST_INSTALL_DIRECTORY} RENAME CTestTestfile.cmake) install(FILES tests.set DESTINATION ${TEST_INSTALL_DIRECTORY}) - + set(TMP_TESTS_NAMES) foreach(tfile ${TEST_NAMES}) list(APPEND TMP_TESTS_NAMES "Test/${tfile}") endforeach(tfile ${TEST_NAMES}) - + install(FILES ${TMP_TESTS_NAMES} DESTINATION ${TEST_INSTALL_DIRECTORY}) ENDIF(${HAVE_SALOME}) diff --git a/src/FeaturesPlugin/FeaturesPlugin_Loft.cpp b/src/FeaturesPlugin/FeaturesPlugin_Loft.cpp new file mode 100644 index 000000000..223e41e6f --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_Loft.cpp @@ -0,0 +1,89 @@ +// Copyright (C) 2014-2022 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 "FeaturesPlugin_Loft.h" +#include "FeaturesPlugin_Tools.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include + +//================================================================================================== +FeaturesPlugin_Loft::FeaturesPlugin_Loft() +{ +} + +//================================================================================================== +void FeaturesPlugin_Loft::initAttributes() +{ + data()->addAttribute(FIRST_OBJECT_ID(), ModelAPI_AttributeSelection::typeId()); + data()->addAttribute(SECOND_OBJECT_ID(), ModelAPI_AttributeSelection::typeId()); +} + +//================================================================================================== +void FeaturesPlugin_Loft::execute() +{ + AttributeSelectionPtr aFirstSelection = selection(FIRST_OBJECT_ID()); + AttributeSelectionPtr aSecondelection = selection(SECOND_OBJECT_ID()); + + if (aFirstSelection->isInitialized() && aSecondelection->isInitialized()) { + + GeomShapePtr aFirstShape, aSecondShape; + + if (aFirstSelection && aSecondelection) { + aFirstShape = aFirstSelection->value(); + if (!aFirstShape && aFirstSelection->context()) + aFirstShape = aFirstSelection->context()->shape(); + + aSecondShape = aSecondelection->value(); + if (!aSecondShape && aSecondelection->context()) + aSecondShape = aSecondelection->context()->shape(); + } + + std::string anError; + std::shared_ptr aLoftAlgo(new GeomAlgoAPI_Loft(aFirstShape, aSecondShape)); + + if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aLoftAlgo, getKind(), anError)) { + setError(anError); + return; + } + ListOfShape theBoundaryShapes; + theBoundaryShapes.push_back(aFirstShape); + theBoundaryShapes.push_back(aSecondShape); + + // Create result body. + ResultBodyPtr aResultBody = document()->createBody(data()); + + aResultBody->store(aLoftAlgo->shape()); + // store Faces + for(GeomAPI_ShapeExplorer anExp(aLoftAlgo->shape(), GeomAPI_Shape::FACE); + anExp.more(); anExp.next()) { + GeomShapePtr anEdge = anExp.current(); + aResultBody->generated(anEdge, "Loft_Face"); + } + setResult(aResultBody, 0); + } +} diff --git a/src/FeaturesPlugin/FeaturesPlugin_Loft.h b/src/FeaturesPlugin/FeaturesPlugin_Loft.h new file mode 100644 index 000000000..aa83785bd --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_Loft.h @@ -0,0 +1,82 @@ +// Copyright (C) 2014-2022 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 FeaturesPlugin_Loft_H_ +#define FeaturesPlugin_Loft_H_ + +#include "FeaturesPlugin.h" + +#include + +#include +#include + +class GeomAPI_Pnt; + +/// \class FeaturesPlugin_Loft +/// \ingroup Plugins +/// \brief Feature for creation of extrusion along a path. +/// Pipe creates extrusion of objects along a path. +/// It produces the following results from objects: +/// Vertex -> Edge +/// Edge -> Face +/// Wire -> Shell +/// Face -> Solid +class FeaturesPlugin_Loft : public ModelAPI_Feature +{ +public: + /// Feature kind. + inline static const std::string& ID() + { + static const std::string MY_FEATURE_ID("Loft"); + return MY_FEATURE_ID; + } + + /// Attribute name for first object selected. + inline static const std::string& FIRST_OBJECT_ID() + { + static const std::string MY_FIRST_OBJECT("first_object"); + return MY_FIRST_OBJECT; + } + + /// Attribute name for second object selected. + inline static const std::string& SECOND_OBJECT_ID() + { + static const std::string MY_SECOND_OBJECT("second_object"); + return MY_SECOND_OBJECT; + } + + /// \return the kind of a feature. + FEATURESPLUGIN_EXPORT virtual const std::string& getKind() + { + static std::string MY_KIND = FeaturesPlugin_Loft::ID(); + return MY_KIND; + } + + /// Performs the algorithm and stores results it in the data structure. + FEATURESPLUGIN_EXPORT virtual void execute(); + + /// Request for initialization of data model of the feature: adding all attributes + FEATURESPLUGIN_EXPORT virtual void initAttributes(); + + /// Use plugin manager for features creation + FeaturesPlugin_Loft(); +}; + +#endif diff --git a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp index 24442767f..ca33e7adc 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -87,6 +88,8 @@ FeaturesPlugin_Plugin::FeaturesPlugin_Plugin() new FeaturesPlugin_ValidatorPipeLocations); aFactory->registerValidator("FeaturesPlugin_ValidatorPipeLocationsNumber", new FeaturesPlugin_ValidatorPipeLocationsNumber); + aFactory->registerValidator("FeaturesPlugin_ValidatorLoftSameTypeShape", + new FeaturesPlugin_ValidatorLoftSameTypeShape); aFactory->registerValidator("FeaturesPlugin_ValidatorExtrusionDir", new FeaturesPlugin_ValidatorExtrusionDir); aFactory->registerValidator("FeaturesPlugin_ValidatorExtrusionBoundary", @@ -162,6 +165,8 @@ FeaturePtr FeaturesPlugin_Plugin::createFeature(std::string theFeatureID) return FeaturePtr(new FeaturesPlugin_Partition); } else if (theFeatureID == FeaturesPlugin_Pipe::ID()) { return FeaturePtr(new FeaturesPlugin_Pipe); + } else if (theFeatureID == FeaturesPlugin_Loft::ID()) { + return FeaturePtr(new FeaturesPlugin_Loft); } else if (theFeatureID == FeaturesPlugin_Placement::ID()) { return FeaturePtr(new FeaturesPlugin_Placement); } else if (theFeatureID == FeaturesPlugin_Recover::ID()) { diff --git a/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp b/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp index 3181fc925..68fcb043f 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp @@ -228,6 +228,57 @@ bool FeaturesPlugin_ValidatorPipeLocationsNumber::isValid( } // LCOV_EXCL_STOP +//================================================================================================== +bool FeaturesPlugin_ValidatorLoftSameTypeShape::isValid( + const std::shared_ptr& theFeature, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + static const std::string aFirstObjetcID = "first_object"; + static const std::string aSecondObjetcID = "second_object"; + + if (theFeature->getKind() != "Loft") { + theError = "Error: Feature \"%1\" does not supported by this validator."; + theError.arg(theFeature->getKind()); + return false; + } + + AttributeSelectionPtr aFirstObjectsSelection = theFeature->selection(aFirstObjetcID); + if ( !aFirstObjectsSelection->isInitialized()) { + theError = "Error: Could not get \"%1\" attribute."; + theError.arg(aFirstObjetcID); + return false; + } + + AttributeSelectionPtr aSecondObjectsSelection = theFeature->selection(aSecondObjetcID); + if (!aSecondObjectsSelection->isInitialized()) { + theError = "Error: Could not get \"%1\" attribute."; + theError.arg(aSecondObjetcID); + return false; + } + + GeomShapePtr aFirstShape = aFirstObjectsSelection->value(); + if (!aFirstShape.get()) { + aFirstShape = aFirstObjectsSelection->context()->shape(); + } + GeomShapePtr aSecondShape = aSecondObjectsSelection->value(); + if (!aSecondShape.get()) { + aSecondShape = aSecondObjectsSelection->context()->shape(); + } + + if (aFirstShape->isEqual(aSecondShape)) { + theError = "Error: the shapes are equal"; + return false; + } + + if (aFirstShape->shapeType()!=aSecondShape->shapeType()) { + theError = "Error: the shapes have different type"; + return false; + } + + return true; +} + //================================================================================================== bool FeaturesPlugin_ValidatorBaseForGeneration::isValid(const AttributePtr& theAttribute, const std::list& theArguments, diff --git a/src/FeaturesPlugin/FeaturesPlugin_Validators.h b/src/FeaturesPlugin/FeaturesPlugin_Validators.h index b868e23b8..adfb0cd3f 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Validators.h +++ b/src/FeaturesPlugin/FeaturesPlugin_Validators.h @@ -68,6 +68,21 @@ class FeaturesPlugin_ValidatorPipeLocationsNumber: public ModelAPI_FeatureValida Events_InfoMessage& theError) const; }; +/// \class FeaturesPlugin_ValidatorLoftSameTypeShape +/// \ingroup Validators +/// \brief Validator for the same type of shape. +class FeaturesPlugin_ValidatorLoftSameTypeShape: public ModelAPI_FeatureValidator +{ + public: + //! \return true if the type of selected are the same + //! \param theFeature the checked feature + //! \param theArguments arguments of the feature (not used) + //! \param theError error message + virtual bool isValid(const std::shared_ptr& theFeature, + const std::list& theArguments, + Events_InfoMessage& theError) const; +}; + /// \class FeaturesPlugin_ValidatorBaseForGeneration /// \ingroup Validators /// \brief A validator for selection base for generation. Allows to select faces on sketch, diff --git a/src/FeaturesPlugin/FeaturesPlugin_msg_fr.ts b/src/FeaturesPlugin/FeaturesPlugin_msg_fr.ts index 878c1f4d5..653d085b8 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_msg_fr.ts +++ b/src/FeaturesPlugin/FeaturesPlugin_msg_fr.ts @@ -65,6 +65,10 @@ Pipe Tuyau + + Loft + Lissage + Recover Récupérer @@ -1384,6 +1388,28 @@ + + + Loft + + Loft + Lissage + + + + Loft:first_object + + First object: + Premier objet: + + + + Loft:second_object + + Second object: + Deuxième objet: + + Recover diff --git a/src/FeaturesPlugin/Test/TestLoft.py b/src/FeaturesPlugin/Test/TestLoft.py new file mode 100644 index 000000000..2744522b2 --- /dev/null +++ b/src/FeaturesPlugin/Test/TestLoft.py @@ -0,0 +1,198 @@ +# Copyright (C) 2018-2022 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() + +### Create Part +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() + +### Create Sketch +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) + +### Create SketchLine +SketchLine_1 = Sketch_1.addLine(65.56914119359536, 34.84279475982533, -62.33478893740904, 34.84279475982533) + +### Create SketchLine +SketchLine_2 = Sketch_1.addLine(-62.33478893740904, 34.84279475982533, -62.33478893740904, -28.08005822416302) + +### Create SketchLine +SketchLine_3 = Sketch_1.addLine(-62.33478893740904, -28.08005822416302, 65.56914119359536, -28.08005822416302) + +### Create SketchLine +SketchLine_4 = Sketch_1.addLine(65.56914119359536, -28.08005822416302, 65.56914119359536, 34.84279475982533) +Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint()) +Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) +Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint()) +Sketch_1.setHorizontal(SketchLine_1.result()) +Sketch_1.setVertical(SketchLine_2.result()) +Sketch_1.setHorizontal(SketchLine_3.result()) +Sketch_1.setVertical(SketchLine_4.result()) +model.do() + +### Create Plane +Plane_4 = model.addPlane(Part_1_doc, model.selection("EDGE", "Sketch_1/SketchLine_4"), model.selection("VERTEX", "Sketch_1/SketchLine_3_StartVertex"), False) + +### Create Plane +Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f-SketchLine_4f"), 100, False) + +### Create Sketch +Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("YOZ")) + +### Create SketchCircle +SketchCircle_1 = Sketch_2.addCircle(60.9581866489876, 39.76685108527785, 26.86156014153439) +model.do() + +### Create Plane +Plane_6 = model.addPlane(Part_1_doc, model.selection("FACE", "Sketch_2/Face-SketchCircle_1_2r"), 100, False) + +### Create Box +Box_1 = model.addBox(Part_1_doc, 10, 10, 10) + +### Create Box +Box_2 = model.addBox(Part_1_doc, 10, 10, 10) + +### Create Translation +Translation_1 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "all-in-Box_2")], axis = model.selection("EDGE", "PartSet/OY"), distance = 100, keepSubResults = True) + +### Create Wire +Wire_1_objects = [model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Right]"), + model.selection("EDGE", "[Box_1_1/Right][Box_1_1/Top]"), + model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Right]"), + model.selection("EDGE", "[Box_1_1/Right][Box_1_1/Bottom]")] +Wire_1 = model.addWire(Part_1_doc, Wire_1_objects, False) + +### Create Wire +Wire_2_objects = [model.selection("EDGE", "[Translation_1_1_1/MF:Translated&Box_2_1/Left][Translation_1_1_1/MF:Translated&Box_2_1/Top]"), + model.selection("EDGE", "[Translation_1_1_1/MF:Translated&Box_2_1/Front][Translation_1_1_1/MF:Translated&Box_2_1/Left]"), + model.selection("EDGE", "[Translation_1_1_1/MF:Translated&Box_2_1/Left][Translation_1_1_1/MF:Translated&Box_2_1/Bottom]"), + model.selection("EDGE", "[Translation_1_1_1/MF:Translated&Box_2_1/Back][Translation_1_1_1/MF:Translated&Box_2_1/Left]")] +Wire_2 = model.addWire(Part_1_doc, Wire_2_objects, False) + +### Create Box +Box_3 = model.addBox(Part_1_doc, 10, 10, 10) + +### Create Wire +Wire_3 = model.addWire(Part_1_doc, [model.selection("EDGE", "[Box_3_1/Left][Box_3_1/Top]"), model.selection("EDGE", "[Box_3_1/Front][Box_3_1/Left]")], False) + +### Create Box +Box_4 = model.addBox(Part_1_doc, 10, 10, 10) + +### Create Translation +Translation_2 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "all-in-Box_4")], axis = model.selection("EDGE", "PartSet/OY"), distance = 40, keepSubResults = True) + +### Create Wire +Wire_4 = model.addWire(Part_1_doc, [model.selection("EDGE", "[Translation_2_1_1/MF:Translated&Box_4_1/Left][Translation_2_1_1/MF:Translated&Box_4_1/Top]"), model.selection("EDGE", "[Translation_2_1_1/MF:Translated&Box_4_1/Front][Translation_2_1_1/MF:Translated&Box_4_1/Left]")], False) + +### Create Loft +Loft_1 = model.addLoft(Part_1_doc, model.selection("FACE", "Plane_2"), model.selection("FACE", "Plane_1")) + +### Create Loft +Loft_2 = model.addLoft(Part_1_doc, model.selection("WIRE", "Wire_2_1"), model.selection("WIRE", "Wire_1_1")) + +### Create Loft +Loft_3 = model.addLoft(Part_1_doc, model.selection("WIRE", "Wire_3_1"), model.selection("WIRE", "Wire_4_1")) + +### Create Loft +Loft_4 = model.addLoft(Part_1_doc, model.selection("EDGE", "Sketch_1/SketchLine_2"), model.selection("EDGE", "Sketch_1/SketchLine_4")) + +# # Errors tests +# Wire and Edge +Box_5 = model.addBox(Part_1_doc, 10, 10, 10) +Wire_5_objects = [model.selection("EDGE", "[Box_5_1/Back][Box_5_1/Left]"), + model.selection("EDGE", "[Box_5_1/Left][Box_5_1/Top]"), + model.selection("EDGE", "[Box_5_1/Front][Box_5_1/Left]"), + model.selection("EDGE", "[Box_5_1/Left][Box_5_1/Bottom]")] +Wire_5 = model.addWire(Part_1_doc, Wire_5_objects, False) +Box_6 = model.addBox(Part_1_doc, 10, 10, 10) +Loft_5 = model.addLoft(Part_1_doc, model.selection("WIRE", "Wire_5_1"), model.selection("EDGE", "[Box_6_1/Right][Box_6_1/Top]")) +assert(Loft_5.feature().error() == "Error: the shapes have different type") + +# Wire and Face +Wire_6_objects = [model.selection("EDGE", "[Loft_1_1/Loft_Face_1][Loft_1_1/Loft_Face_5]"), + model.selection("EDGE", "[Loft_1_1/Loft_Face_1][Loft_1_1/Loft_Face_4]"), + model.selection("EDGE", "[Loft_1_1/Loft_Face_1][Loft_1_1/Loft_Face_2]"), + model.selection("EDGE", "[Loft_1_1/Loft_Face_1][Loft_1_1/Loft_Face_6]")] +Wire_6 = model.addWire(Part_1_doc, Wire_6_objects, False) +Loft_6 = model.addLoft(Part_1_doc, model.selection("WIRE", "Wire_6_1"), model.selection("EDGE", "Plane_3")) +assert(Loft_6.feature().error() == "Error: the shapes have different type") + +# Only one element +Box_7 = model.addBox(Part_1_doc, 10, 10, 10) +Loft_7 = model.addLoft(Part_1_doc, model.selection("SOLID", "Box_7_1"), model.selection()) +assert(Loft_7.feature().error() == 'Error: Could not get "second_object" attribute.') + +# Two faces with different number of edges +Cone_1 = model.addCone(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 10, 5, 10) +Loft_8 = model.addLoft(Part_1_doc, model.selection("FACE", "Cone_1_1/Face_2"), model.selection("EDGE", "Plane_3")) + +model.end() + +from GeomAPI import GeomAPI_Shape + +#test loft with two face +model.testNbResults(Loft_1, 1) +model.testNbSubResults(Loft_1, [0]) +model.testNbSubShapes(Loft_1, GeomAPI_Shape.SOLID, [1]) +model.testNbSubShapes(Loft_1, GeomAPI_Shape.FACE, [6]) +model.testNbSubShapes(Loft_1, GeomAPI_Shape.EDGE, [24]) +model.testNbSubShapes(Loft_1, GeomAPI_Shape.VERTEX, [48]) +model.testResultsVolumes(Loft_1, [996988.58940]) + +#test loft with two wire +model.testNbResults(Loft_2, 1) +model.testNbSubResults(Loft_2, [0]) +model.testNbSubShapes(Loft_2, GeomAPI_Shape.SHELL, [1]) +model.testNbSubShapes(Loft_2, GeomAPI_Shape.FACE, [4]) +model.testNbSubShapes(Loft_2, GeomAPI_Shape.EDGE, [16]) +model.testNbSubShapes(Loft_2, GeomAPI_Shape.VERTEX, [32]) +model.testResultsVolumes(Loft_2, [0.0]) + +#test loft with two wire +model.testNbResults(Loft_3, 1) +model.testNbSubResults(Loft_3, [0]) +model.testNbSubShapes(Loft_3, GeomAPI_Shape.SHELL, [1]) +model.testNbSubShapes(Loft_3, GeomAPI_Shape.FACE, [2]) +model.testNbSubShapes(Loft_3, GeomAPI_Shape.EDGE, [8]) +model.testNbSubShapes(Loft_3, GeomAPI_Shape.VERTEX, [16]) +model.testResultsVolumes(Loft_3, [0.0]) + +#test loft with two edge +model.testNbResults(Loft_4, 1) +model.testNbSubResults(Loft_4, [0]) +model.testNbSubShapes(Loft_4, GeomAPI_Shape.FACE, [1]) +model.testNbSubShapes(Loft_4, GeomAPI_Shape.EDGE, [4]) +model.testNbSubShapes(Loft_4, GeomAPI_Shape.VERTEX, [8]) +model.testResultsVolumes(Loft_4, [0.0]) + +#test loft with faces with different number of edges +model.testNbResults(Loft_8, 1) +model.testNbSubResults(Loft_8, [0]) +model.testNbSubShapes(Loft_8, GeomAPI_Shape.FACE, [7]) +model.testNbSubShapes(Loft_8, GeomAPI_Shape.EDGE, [30]) +model.testNbSubShapes(Loft_8, GeomAPI_Shape.VERTEX, [60]) +model.testResultsVolumes(Loft_8, [151868.70541]) + + + + diff --git a/src/FeaturesPlugin/doc/FeaturesPlugin.rst b/src/FeaturesPlugin/doc/FeaturesPlugin.rst index 6fc8177bd..ac4a0fd5b 100644 --- a/src/FeaturesPlugin/doc/FeaturesPlugin.rst +++ b/src/FeaturesPlugin/doc/FeaturesPlugin.rst @@ -25,6 +25,7 @@ Features plug-in provides a set of common topological operations. It implements geometryCalculationFeature.rst importResultFeature.rst linearCopyFeature.rst + loftFeature.rst measurementFeature.rst normalToFaceFeature.rst pipeFeature.rst diff --git a/src/FeaturesPlugin/doc/TUI_loftFeature.rst b/src/FeaturesPlugin/doc/TUI_loftFeature.rst new file mode 100644 index 000000000..c97cf3fc9 --- /dev/null +++ b/src/FeaturesPlugin/doc/TUI_loftFeature.rst @@ -0,0 +1,11 @@ + + .. _tui_loft: + +loft +==== + +.. literalinclude:: examples/loft.py + :linenos: + :language: python + +:download:`Download this script ` diff --git a/src/FeaturesPlugin/doc/examples/loft.py b/src/FeaturesPlugin/doc/examples/loft.py new file mode 100644 index 000000000..f3f9dfebe --- /dev/null +++ b/src/FeaturesPlugin/doc/examples/loft.py @@ -0,0 +1,45 @@ +from SketchAPI import * + +from salome.shaper import model + +model.begin() +partSet = model.moduleDocument() + +### Create Part +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() + +### Create Sketch +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) + +### Create SketchLine +SketchLine_1 = Sketch_1.addLine(65.56914119359536, 34.84279475982533, -62.33478893740904, 34.84279475982533) + +### Create SketchLine +SketchLine_2 = Sketch_1.addLine(-62.33478893740904, 34.84279475982533, -62.33478893740904, -28.08005822416302) + +### Create SketchLine +SketchLine_3 = Sketch_1.addLine(-62.33478893740904, -28.08005822416302, 65.56914119359536, -28.08005822416302) + +### Create SketchLine +SketchLine_4 = Sketch_1.addLine(65.56914119359536, -28.08005822416302, 65.56914119359536, 34.84279475982533) +Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint()) +Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) +Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint()) +Sketch_1.setHorizontal(SketchLine_1.result()) +Sketch_1.setVertical(SketchLine_2.result()) +Sketch_1.setHorizontal(SketchLine_3.result()) +Sketch_1.setVertical(SketchLine_4.result()) +model.do() + +### Create Plane +Plane_1 = model.addPlane(Part_1_doc, model.selection("EDGE", "Sketch_1/SketchLine_4"), model.selection("VERTEX", "Sketch_1/SketchLine_3_StartVertex"), False) + +### Create Plane +Plane_2 = model.addPlane(Part_1_doc, model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f-SketchLine_4f"), 100, False) + +### Create Loft +Loft_1 = model.addLoft(Part_1_doc, model.selection("FACE", "Plane_1"), model.selection("FACE", "Plane_2")) + +model.end() diff --git a/src/FeaturesPlugin/doc/images/loft.png b/src/FeaturesPlugin/doc/images/loft.png new file mode 100644 index 000000000..892ead927 Binary files /dev/null and b/src/FeaturesPlugin/doc/images/loft.png differ diff --git a/src/FeaturesPlugin/doc/images/loftPropertyPanel.png b/src/FeaturesPlugin/doc/images/loftPropertyPanel.png new file mode 100644 index 000000000..760244331 Binary files /dev/null and b/src/FeaturesPlugin/doc/images/loftPropertyPanel.png differ diff --git a/src/FeaturesPlugin/doc/images/resultLoft.png b/src/FeaturesPlugin/doc/images/resultLoft.png new file mode 100644 index 000000000..acf0013cd Binary files /dev/null and b/src/FeaturesPlugin/doc/images/resultLoft.png differ diff --git a/src/FeaturesPlugin/doc/loftFeature.rst b/src/FeaturesPlugin/doc/loftFeature.rst new file mode 100644 index 000000000..d053bba68 --- /dev/null +++ b/src/FeaturesPlugin/doc/loftFeature.rst @@ -0,0 +1,45 @@ +.. |loft.icon| image:: images/loft.png + +Loft +==== + +**Loft** feature is used to create a face, shell or a solid shape from two or more objects. +The two objects can be edges, wires or faces but must be of the same type + +To create a Loft in the active part: + +#. select in the Main Menu *Features - > Loft* item or +#. click |loft.icon| **Loft** button in the toolbar + +The following property panel appears. + +.. figure:: images/loftPropertyPanel.png + :align: center + + Loft property panel + +Input fields: + +- **First object** defines the first shape (edge, wire, face) selected in 3D OCC viewer or object browser; +- **Second object** defines the second shape (edge, wire, face) selected in 3D OCC viewer or object browser; + +**TUI Command**: + +.. py:function:: model.addLoft(Part_doc, [shape], [shape]) + + :param part: The current part object. + :param object: A shape in format *model.selection(TYPE, shape)*. + :param object: A shape in format *model.selection(TYPE, shape)*. + :return: Created object. + +Result +"""""" + +Result of loft between two faces. + +.. figure:: images/resultLoft.png + :align: center + + Loft between two faces + +**See Also** a sample TUI Script of :ref:`tui_loft` operation. diff --git a/src/FeaturesPlugin/icons/loft.png b/src/FeaturesPlugin/icons/loft.png new file mode 100644 index 000000000..892ead927 Binary files /dev/null and b/src/FeaturesPlugin/icons/loft.png differ diff --git a/src/FeaturesPlugin/loft_widget.xml b/src/FeaturesPlugin/loft_widget.xml new file mode 100644 index 000000000..21dc390d6 --- /dev/null +++ b/src/FeaturesPlugin/loft_widget.xml @@ -0,0 +1,19 @@ + + + + + + + + + diff --git a/src/FeaturesPlugin/plugin-Features.xml b/src/FeaturesPlugin/plugin-Features.xml index 0292c038c..ccaa0c036 100644 --- a/src/FeaturesPlugin/plugin-Features.xml +++ b/src/FeaturesPlugin/plugin-Features.xml @@ -39,6 +39,10 @@ icon="icons/Features/pipe.png" helpfile="pipeFeature.html"> + + + +#include +#include +#include + +//================================================================================================== +GeomAlgoAPI_Loft::GeomAlgoAPI_Loft(const GeomShapePtr theFirstShape, const GeomShapePtr theSecondShape) +{ + build(theFirstShape, theSecondShape); +} + +//================================================================================================== +void GeomAlgoAPI_Loft::build(const GeomShapePtr theFirstShape, + const GeomShapePtr theSecondShape) +{ + // Getting base shape. + if(!theFirstShape.get() || !theSecondShape.get()) { + return; + } + TopoDS_Shape aFirstShape = theFirstShape->impl(); + if(aFirstShape.IsNull()) { + return; + } + TopoDS_Shape aSecondShape= theSecondShape->impl(); + if(aSecondShape.IsNull()) { + return; + } + + bool anIsSolid = false; + + TopoDS_Shape aFirstShapeOut; + TopoDS_Shape aSecondShapeOut; + if (aFirstShape.ShapeType() == TopAbs_FACE) { + TopExp_Explorer anExp(aFirstShape, TopAbs_WIRE); + aFirstShapeOut = anExp.Current(); + TopExp_Explorer anExp2(aSecondShape, TopAbs_WIRE); + aSecondShapeOut = anExp2.Current(); + anIsSolid = true; + } + + if (aFirstShape.ShapeType() == TopAbs_WIRE) { + aFirstShapeOut = aFirstShape; + aSecondShapeOut = aSecondShape; + } + + if (aFirstShape.ShapeType() == TopAbs_EDGE) + { + GeomShapePtr aFirstWire, aSecondWire; + ListOfShape aFirstEdge, aSecondEdge; + + // Convert first edge to wire + aFirstEdge.push_back(theFirstShape); + aFirstWire = GeomAlgoAPI_WireBuilder::wire(aFirstEdge); + TopoDS_Shape aFirstShape = aFirstWire->impl(); + + // Convert first edge to wire + aSecondEdge.push_back(theSecondShape); + aSecondWire = GeomAlgoAPI_WireBuilder::wire(aSecondEdge); + TopoDS_Shape aSecondShape = aSecondWire->impl(); + + aFirstShapeOut = aFirstShape; + aSecondShapeOut = aSecondShape; + } + + // Initialize and build + BRepOffsetAPI_ThruSections * ThruSections = + new BRepOffsetAPI_ThruSections(anIsSolid); + ThruSections->AddWire( TopoDS::Wire( aFirstShapeOut ) ); + ThruSections->AddWire( TopoDS::Wire( aSecondShapeOut) ); + + try + { + ThruSections->Build(); + } + catch (Standard_Failure& aFail) + { + delete ThruSections; + return; + } + // Checking result. + if(!ThruSections->IsDone() || ThruSections->Shape().IsNull()) { + delete ThruSections; + return; + } + + this->initialize(ThruSections); + + // Setting result. + TopoDS_Shape aResult = ThruSections->Shape(); + aResult = GeomAlgoAPI_DFLoader::refineResult(aResult); + GeomShapePtr aGeomSh(new GeomAPI_Shape()); + aGeomSh->setImpl(new TopoDS_Shape(aResult)); + this->setShape(aGeomSh); + this->setDone(true); +} diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Loft.h b/src/GeomAlgoAPI/GeomAlgoAPI_Loft.h new file mode 100644 index 000000000..da5da2caf --- /dev/null +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Loft.h @@ -0,0 +1,51 @@ +// Copyright (C) 2014-2022 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_Loft_H_ +#define GeomAlgoAPI_Loft_H_ + +#include "GeomAlgoAPI.h" + +#include "GeomAlgoAPI_MakeShape.h" + +#include + +/// \class GeomAlgoAPI_Loft +/// \ingroup DataAlgo +/// \brief Allows to create loft of two objects with same type. +/// It produces the following results from objects: +/// 2 edges -> Face +/// 2 Wire -> Shell +/// 2 Face -> Solid +class GeomAlgoAPI_Loft : public GeomAlgoAPI_MakeShape +{ + public: + /// \brief Creates loft for two given shape with same type. + /// \param[in] theFirstShape the first shape. + /// \param[in] theSecondShape the second shape. + GEOMALGOAPI_EXPORT GeomAlgoAPI_Loft(const GeomShapePtr theFirstShape, + const GeomShapePtr theSecondShape); + + private: + void build(const GeomShapePtr theFirstShape, + const GeomShapePtr theSecondShape); + +}; + +#endif diff --git a/src/PythonAPI/model/features/__init__.py b/src/PythonAPI/model/features/__init__.py index c0faaacf6..043f9c726 100644 --- a/src/PythonAPI/model/features/__init__.py +++ b/src/PythonAPI/model/features/__init__.py @@ -23,7 +23,7 @@ from FeaturesAPI import addPlacement, addRotation, addScale, addSymmetry, addTra from FeaturesAPI import addMultiTranslation, addMultiRotation from FeaturesAPI import addExtrusion, addExtrusionCut, addExtrusionFuse from FeaturesAPI import addRevolution, addRevolutionCut, addRevolutionFuse -from FeaturesAPI import addPipe +from FeaturesAPI import addPipe, addLoft from FeaturesAPI import addCut, addFuse, addCommon, addSmash, addSplit from FeaturesAPI import addIntersection, addPartition, addUnion, addRemoveSubShapes from FeaturesAPI import addRecover