From: lucasjerome Date: Wed, 27 Jan 2021 18:38:10 +0000 (+0100) Subject: First implementation of Loft Feature X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=1148f24edde9cc0dd494e7d7a66cbfe2e4803a3c;p=modules%2Fshaper.git First implementation of Loft Feature --- diff --git a/src/FeaturesAPI/CMakeLists.txt b/src/FeaturesAPI/CMakeLists.txt index 0b8e3055c..3d5dd4d8f 100644 --- a/src/FeaturesAPI/CMakeLists.txt +++ b/src/FeaturesAPI/CMakeLists.txt @@ -36,6 +36,7 @@ SET(PROJECT_HEADERS FeaturesAPI_MultiTranslation.h FeaturesAPI_Partition.h FeaturesAPI_Pipe.h + FeaturesAPI_Loft.h FeaturesAPI_Placement.h FeaturesAPI_Recover.h FeaturesAPI_RemoveResults.h @@ -69,6 +70,7 @@ SET(PROJECT_SOURCES FeaturesAPI_MultiTranslation.cpp FeaturesAPI_Partition.cpp FeaturesAPI_Pipe.cpp + FeaturesAPI_Loft.cpp FeaturesAPI_Placement.cpp FeaturesAPI_Recover.cpp FeaturesAPI_RemoveResults.cpp diff --git a/src/FeaturesAPI/FeaturesAPI.i b/src/FeaturesAPI/FeaturesAPI.i index b76fd2dc4..20007d352 100644 --- a/src/FeaturesAPI/FeaturesAPI.i +++ b/src/FeaturesAPI/FeaturesAPI.i @@ -75,6 +75,7 @@ %shared_ptr(FeaturesAPI_MultiTranslation) %shared_ptr(FeaturesAPI_Partition) %shared_ptr(FeaturesAPI_Pipe) +%shared_ptr(FeaturesAPI_Loft) %shared_ptr(FeaturesAPI_Placement) %shared_ptr(FeaturesAPI_Recover) %shared_ptr(FeaturesAPI_RemoveSubShapes) @@ -215,6 +216,7 @@ %include "FeaturesAPI_MultiTranslation.h" %include "FeaturesAPI_Partition.h" %include "FeaturesAPI_Pipe.h" +%include "FeaturesAPI_Loft.h" %include "FeaturesAPI_Placement.h" %include "FeaturesAPI_Recover.h" %include "FeaturesAPI_RemoveSubShapes.h" diff --git a/src/FeaturesAPI/FeaturesAPI_Loft.cpp b/src/FeaturesAPI/FeaturesAPI_Loft.cpp new file mode 100644 index 000000000..210186c83 --- /dev/null +++ b/src/FeaturesAPI/FeaturesAPI_Loft.cpp @@ -0,0 +1,77 @@ +// Copyright (C) 2014-2020 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..0777fba4d --- /dev/null +++ b/src/FeaturesAPI/FeaturesAPI_Loft.h @@ -0,0 +1,74 @@ +// Copyright (C) 2014-2020 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 17ada7187..4dec708b9 100644 --- a/src/FeaturesAPI/FeaturesAPI_swig.h +++ b/src/FeaturesAPI/FeaturesAPI_swig.h @@ -39,6 +39,7 @@ #include "FeaturesAPI_MultiTranslation.h" #include "FeaturesAPI_Partition.h" #include "FeaturesAPI_Pipe.h" + #include "FeaturesAPI_Loft.h" #include "FeaturesAPI_Placement.h" #include "FeaturesAPI_Recover.h" #include "FeaturesAPI_RemoveSubShapes.h" diff --git a/src/FeaturesPlugin/CMakeLists.txt b/src/FeaturesPlugin/CMakeLists.txt index 1dce791a9..766fde58f 100644 --- a/src/FeaturesPlugin/CMakeLists.txt +++ b/src/FeaturesPlugin/CMakeLists.txt @@ -38,6 +38,7 @@ SET(PROJECT_HEADERS FeaturesPlugin_Intersection.h FeaturesPlugin_Partition.h FeaturesPlugin_Pipe.h + FeaturesPlugin_Loft.h FeaturesPlugin_Placement.h FeaturesPlugin_CompositeBoolean.h FeaturesPlugin_CompositeSketch.h @@ -85,6 +86,7 @@ SET(PROJECT_SOURCES FeaturesPlugin_Intersection.cpp FeaturesPlugin_Partition.cpp FeaturesPlugin_Pipe.cpp + FeaturesPlugin_Loft.cpp FeaturesPlugin_Placement.cpp FeaturesPlugin_CompositeBoolean.cpp FeaturesPlugin_CompositeSketch.cpp @@ -135,6 +137,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 diff --git a/src/FeaturesPlugin/FeaturesPlugin_Loft.cpp b/src/FeaturesPlugin/FeaturesPlugin_Loft.cpp new file mode 100644 index 000000000..0c30c0176 --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_Loft.cpp @@ -0,0 +1,380 @@ +// Copyright (C) 2014-2020 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 +#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(); + + } + // Loft for two edges + if(aFirstShape->isEdge()) { + + std::shared_ptr aFilling( + new GeomAlgoAPI_Filling(2.0, 5.0, 0, 0.0001, 0.0001 )); + + // collect base shapes + GeomEdgePtr aFirstEdge = toEdge(aFirstShape); + if (!aFirstEdge) { + myLastEdgeStartPoint = GeomPointPtr(); + myLastEdgeEndPoint = GeomPointPtr(); + return; + } + aFilling->add(aFirstEdge); + + GeomEdgePtr aSecondEdge = toEdge(aSecondShape); + if (!aSecondEdge) { + myLastEdgeStartPoint = GeomPointPtr(); + myLastEdgeEndPoint = GeomPointPtr(); + return; + } + aFilling->add(aSecondEdge); + myLastEdgeStartPoint = GeomPointPtr(); + myLastEdgeEndPoint = GeomPointPtr(); + + // build result + aFilling->build(); + std::string anError; + if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aFilling, getKind(), anError)) { + setError(anError); + removeResults(0); + return; + } + + /// store result + GeomShapePtr aCreatedFace = aFilling->shape(); + ResultBodyPtr aResultBody = document()->createBody(data()); + aResultBody->store(aCreatedFace); + // store edges + int anEdgeInd = 0; + for(GeomAPI_ShapeExplorer anExp(aCreatedFace, GeomAPI_Shape::EDGE); + anExp.more(); anExp.next()) { + GeomShapePtr anEdge = anExp.current(); + aResultBody->generated(anEdge, "Loft_Edge_" + std::to_string((long long)anEdgeInd)); + } + setResult(aResultBody, 0); + + } else { + + std::shared_ptr aLoftAlgo(new GeomAlgoAPI_Loft(aFirstShape, aSecondShape)); + + std::string anError; + + 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 edges + int anEdgeInd = 0; + for(GeomAPI_ShapeExplorer anExp(aLoftAlgo->shape(), GeomAPI_Shape::EDGE); + anExp.more(); anExp.next()) { + GeomShapePtr anEdge = anExp.current(); + aResultBody->generated(anEdge, "Loft_Edge_" + std::to_string((long long)anEdgeInd)); + } + int anFaceInd = 0; + for(GeomAPI_ShapeExplorer anExp(aLoftAlgo->shape(), GeomAPI_Shape::FACE); + anExp.more(); anExp.next()) { + GeomShapePtr anEdge = anExp.current(); + aResultBody->generated(anEdge, "Loft_Face_" + std::to_string((long long)anFaceInd)); + } + setResult(aResultBody, 0); + } + } +} +/*================================================================================================= +GeomShapePtr FeaturesPlugin_Loft::getShape(const std::string& anID) +{ + AttributeSelectionPtr theSelection = selection(anID); + if (!theSelection.get()) { + setError("Error: One of the selected base objects is empty."); + return; + } + + GeomShapePtr aShape = theSelection->value(); + + if (aShape.get() && !aShape->isNull()) { + std::cout<<"C'est un shape"<(theSelection->context()); + if(!aConstruction.get()) { + setError("Error: One of selected sketches does not have results."); + return; + } + int aFacesNum = aConstruction->facesNum(); + if(aFacesNum == 0) { + // Probably it can be construction. + aShape = aConstruction->shape(); + if(aShape.get() && !aShape->isNull()) { + std::cout<<"C'est un aConstruction"<empty()) { + static const std::string aFeatureError = + "Error: incorrect type of input feature (edges are supported only)."; + setError(aFeatureError); + return anEdge; + } + + // correct edge orientation according to filling method + // check the distance to previous edge boundaries, reverse edge if necessary + GeomPointPtr aStartPnt = anEdge->firstPoint(); + GeomPointPtr aEndPnt = anEdge->lastPoint(); + if (anEdge->orientation() == GeomAPI_Shape::REVERSED) { + aStartPnt = anEdge->lastPoint(); + aEndPnt = anEdge->firstPoint(); + } + bool isReverse = false; + if (myLastEdgeStartPoint) { + double d1 = myLastEdgeStartPoint->distance(aStartPnt) + + myLastEdgeEndPoint->distance(aEndPnt); + double d2 = myLastEdgeStartPoint->distance(aEndPnt) + + myLastEdgeEndPoint->distance(aStartPnt); + if (fabs(d1 - d2) < 1.e-7) { + // undefined case => check distance to start point only + d1 = myLastEdgeStartPoint->distance(aStartPnt); + d2 = myLastEdgeStartPoint->distance(aEndPnt); + } + isReverse = d2 < d1; + } + + if (isReverse) { + anEdge->reverse(); + myLastEdgeStartPoint = aEndPnt; + myLastEdgeEndPoint = aStartPnt; + } else { + myLastEdgeStartPoint = aStartPnt; + myLastEdgeEndPoint = aEndPnt; + } + + return anEdge; +} + +/*================================================================================================== +void FeaturesPlugin_Loft::storeResult(const std::shared_ptr theFirstShape, + const std::shared_ptr theSecondShape, + const std::shared_ptr theLoftAlgo, + const int theResultIndex) +{ + // Create result body. + ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex); + + // Store generated shape. + aResultBody->storeGenerated(theFirstShape, theLoftAlgo->shape()); + aResultBody->storeGenerated(theSecondShape, theLoftAlgo->shape()); + + // Store generated edges/faces. + GeomAPI_Shape::ShapeType aBaseShapeType = theFirstShape->shapeType(); + GeomAPI_Shape::ShapeType aShapeTypeToExplode = GeomAPI_Shape::SHAPE; + + switch(aBaseShapeType) { + case GeomAPI_Shape::VERTEX: { + aShapeTypeToExplode = GeomAPI_Shape::VERTEX; + break; + } + case GeomAPI_Shape::EDGE: + case GeomAPI_Shape::WIRE: { + std::shared_ptr aV1, aV2; + GeomAlgoAPI_ShapeTools::findBounds(theFirstShape, aV1, aV2); + ListOfShape aV1History, aV2History; + theLoftAlgo->generated(aV1, aV1History); + theLoftAlgo->generated(aV2, aV2History); + if(!aV1History.empty()) { + aResultBody->generated(aV1, aV1History.front()); + } + if(!aV2History.empty()) { + aResultBody->generated(aV2, aV2History.front()); + } + GeomAlgoAPI_ShapeTools::findBounds(theSecondShape, aV1, aV2); + theLoftAlgo->generated(aV1, aV1History); + theLoftAlgo->generated(aV2, aV2History); + if(!aV1History.empty()) { + aResultBody->generated(aV1, aV1History.front()); + } + if(!aV2History.empty()) { + aResultBody->generated(aV2, aV2History.front()); + } + } + case GeomAPI_Shape::FACE: + case GeomAPI_Shape::SHELL: { + aShapeTypeToExplode = GeomAPI_Shape::EDGE; + break; + } + case GeomAPI_Shape::COMPOUND: { + aShapeTypeToExplode = GeomAPI_Shape::COMPOUND; + break; + } + default: + return; // unsupported type of shape + } + + if(aShapeTypeToExplode == GeomAPI_Shape::VERTEX || + aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) { + aResultBody->loadGeneratedShapes(theLoftAlgo, theFirstShape, GeomAPI_Shape::VERTEX); + aResultBody->loadGeneratedShapes(theLoftAlgo, theSecondShape, GeomAPI_Shape::VERTEX); + } + if(aShapeTypeToExplode == GeomAPI_Shape::EDGE || + aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) { + aResultBody->loadGeneratedShapes(theLoftAlgo, theFirstShape, GeomAPI_Shape::EDGE); + aResultBody->loadGeneratedShapes(theLoftAlgo, theSecondShape, GeomAPI_Shape::EDGE); + } + + // Store from shapes. + storeShapes(aResultBody, aBaseShapeType, theLoftAlgo->fromShapes(), "From_"); + + // Store to shapes. + storeShapes(aResultBody, aBaseShapeType, theLoftAlgo->toShapes(), "To_"); + + setResult(aResultBody, theResultIndex); +} + +//================================================================================================== +void FeaturesPlugin_Loft::storeShapes(ResultBodyPtr theResultBody, + const GeomAPI_Shape::ShapeType theBaseShapeType, + const ListOfShape& theShapes, + const std::string theName) +{ + GeomAPI_Shape::ShapeType aShapeTypeToExplore = GeomAPI_Shape::FACE; + std::string aShapeTypeStr = "Face"; + switch(theBaseShapeType) { + case GeomAPI_Shape::VERTEX: { + aShapeTypeToExplore = GeomAPI_Shape::VERTEX; + aShapeTypeStr = "Vertex"; + break; + } + case GeomAPI_Shape::EDGE: + case GeomAPI_Shape::WIRE: { + aShapeTypeToExplore = GeomAPI_Shape::EDGE; + aShapeTypeStr = "Edge"; + break; + } + case GeomAPI_Shape::FACE: + case GeomAPI_Shape::SHELL: { + aShapeTypeToExplore = GeomAPI_Shape::FACE; + aShapeTypeStr = "Face"; + break; + } + case GeomAPI_Shape::COMPOUND: { + aShapeTypeToExplore = GeomAPI_Shape::COMPOUND; + break; + } + default: + return; // unsupported type of shape + } + + // Store shapes. + int aShapeIndex = 1; + int aFaceIndex = 1; + for(ListOfShape::const_iterator anIt = theShapes.cbegin(); anIt != theShapes.cend(); ++anIt) { + GeomShapePtr aShape = *anIt; + + if(aShapeTypeToExplore == GeomAPI_Shape::COMPOUND) { + std::string aName = theName + (aShape->shapeType() == GeomAPI_Shape::EDGE ? "Edge" : "Face"); + storeSubShapeTT(theResultBody, aShape, + aShape->shapeType(), + aName, + aShape->shapeType() == GeomAPI_Shape::EDGE ? aShapeIndex : aFaceIndex); + } else { + std::string aName = theName + aShapeTypeStr; + storeSubShapeTT(theResultBody, aShape, aShapeTypeToExplore, aName, aShapeIndex); + } + } +} + +//================================================================================================== +void storeSubShapeTT(ResultBodyPtr theResultBody, + const GeomShapePtr theShape, + const GeomAPI_Shape::ShapeType theType, + const std::string theName, + int& theShapeIndex) +{ + for(GeomAPI_ShapeExplorer anExp(theShape, theType); anExp.more(); anExp.next()) { + GeomShapePtr aSubShape = anExp.current(); + std::ostringstream aStr; + aStr << theName << "_" << theShapeIndex++; + theResultBody->generated(aSubShape, aStr.str()); + } +} +*/ \ No newline at end of file diff --git a/src/FeaturesPlugin/FeaturesPlugin_Loft.h b/src/FeaturesPlugin/FeaturesPlugin_Loft.h new file mode 100644 index 000000000..ef426ffe7 --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_Loft.h @@ -0,0 +1,101 @@ +// Copyright (C) 2014-2020 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:\n +/// Vertex -> Edge\n +/// Edge -> Face\n +/// Wire -> Shell\n +/// 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(); + + private: + + void storeResult(const std::shared_ptr theFirstShape, + const std::shared_ptr theSecondShape, + const std::shared_ptr theLoftAlgo, + const int theResultIndex = 0); + + void storeShapes(ResultBodyPtr theResultBody, + const GeomAPI_Shape::ShapeType theBaseShapeType, + const ListOfShape& theShapes, + const std::string theName); + private: + /// Convert shape to edge + std::shared_ptr toEdge(const std::shared_ptr& theShape); + + private: + std::shared_ptr myLastEdgeStartPoint; + std::shared_ptr myLastEdgeEndPoint; +}; + +#endif diff --git a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp index 0d49dfe08..a59a083c6 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -79,7 +80,9 @@ FeaturesPlugin_Plugin::FeaturesPlugin_Plugin() aFactory->registerValidator("FeaturesPlugin_ValidatorPipeLocations", new FeaturesPlugin_ValidatorPipeLocations); aFactory->registerValidator("FeaturesPlugin_ValidatorPipeLocationsNumber", - new FeaturesPlugin_ValidatorPipeLocationsNumber); + new FeaturesPlugin_ValidatorLoftSameTypeShape); + aFactory->registerValidator("FeaturesPlugin_ValidatorLoftSameTypeShape", + new FeaturesPlugin_ValidatorLoftSameTypeShape); aFactory->registerValidator("FeaturesPlugin_ValidatorExtrusionDir", new FeaturesPlugin_ValidatorExtrusionDir); aFactory->registerValidator("FeaturesPlugin_ValidatorExtrusionBoundary", @@ -155,6 +158,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 55bad81ce..89f21dbc1 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 951d4c52f..5be518132 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/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..e88c48b55 --- /dev/null +++ b/src/FeaturesPlugin/loft_widget.xml @@ -0,0 +1,17 @@ + + + + + + + + + diff --git a/src/FeaturesPlugin/plugin-Features.xml b/src/FeaturesPlugin/plugin-Features.xml index 08c08b775..6c2d309c1 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 = true; + + 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(); + } + + if (aFirstShape.ShapeType() == TopAbs_WIRE) { + aFirstShapeOut = aFirstShape; + aSecondShapeOut = aSecondShape; + anIsSolid = false; + } + + // Initialize and build + BRepOffsetAPI_ThruSections * ThruSections = + new BRepOffsetAPI_ThruSections(anIsSolid, Standard_False, 1.0e-06); + ThruSections->AddWire( TopoDS::Wire( aFirstShapeOut ) ); + ThruSections->AddWire( TopoDS::Wire( aSecondShapeOut) ); + + try + { + ThruSections->Build(); + } + catch (Standard_Failure& aFail) + { + //std::cout << "Error: crash in BRepOffsetAPI_ThruSections" << std::endl; + 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); +} + +//================================================================================================== +void GeomAlgoAPI_Loft::generated(const GeomShapePtr theShape, + ListOfShape& theHistory) +{ + GeomAlgoAPI_MakeShape::generated(theShape, theHistory); +} diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Loft.h b/src/GeomAlgoAPI/GeomAlgoAPI_Loft.h new file mode 100644 index 000000000..7636e038f --- /dev/null +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Loft.h @@ -0,0 +1,57 @@ +// Copyright (C) 2014-2020 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:\n +/// 2 edges -> Face\n +/// 2 Wire -> Shell\n +/// 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); + + /// \return the list of shapes generated from theShape. + /// \param[in] theShape base shape. + /// \param[out] theHistory generated shapes. + GEOMALGOAPI_EXPORT void generated(const GeomShapePtr theShape, + ListOfShape& theHistory); + +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 772dc05c2..7377be5f1 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