From: azv Date: Thu, 30 Nov 2017 10:04:31 +0000 (+0300) Subject: Implementation of 3D Fillet operation X-Git-Tag: V_2.10.0RC~116 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=f6db3a394a95373c94a9680ac5f963b2928e1c48;p=modules%2Fshaper.git Implementation of 3D Fillet operation --- diff --git a/src/FeaturesAPI/CMakeLists.txt b/src/FeaturesAPI/CMakeLists.txt index 791859eed..1c5492242 100644 --- a/src/FeaturesAPI/CMakeLists.txt +++ b/src/FeaturesAPI/CMakeLists.txt @@ -25,6 +25,7 @@ SET(PROJECT_HEADERS FeaturesAPI_Boolean.h FeaturesAPI_Extrusion.h FeaturesAPI_ExtrusionBoolean.h + FeaturesAPI_Fillet.h FeaturesAPI_Intersection.h FeaturesAPI_MultiRotation.h FeaturesAPI_MultiTranslation.h @@ -46,6 +47,7 @@ SET(PROJECT_SOURCES FeaturesAPI_Boolean.cpp FeaturesAPI_Extrusion.cpp FeaturesAPI_ExtrusionBoolean.cpp + FeaturesAPI_Fillet.cpp FeaturesAPI_Intersection.cpp FeaturesAPI_MultiRotation.cpp FeaturesAPI_MultiTranslation.cpp diff --git a/src/FeaturesAPI/FeaturesAPI.i b/src/FeaturesAPI/FeaturesAPI.i index e77373949..62afc3e48 100644 --- a/src/FeaturesAPI/FeaturesAPI.i +++ b/src/FeaturesAPI/FeaturesAPI.i @@ -44,6 +44,7 @@ %shared_ptr(FeaturesAPI_ExtrusionBoolean) %shared_ptr(FeaturesAPI_ExtrusionCut) %shared_ptr(FeaturesAPI_ExtrusionFuse) +%shared_ptr(FeaturesAPI_Fillet) %shared_ptr(FeaturesAPI_Intersection) %shared_ptr(FeaturesAPI_MultiRotation) %shared_ptr(FeaturesAPI_MultiTranslation) @@ -66,6 +67,7 @@ %include "FeaturesAPI_Boolean.h" %include "FeaturesAPI_Extrusion.h" %include "FeaturesAPI_ExtrusionBoolean.h" +%include "FeaturesAPI_Fillet.h" %include "FeaturesAPI_Intersection.h" %include "FeaturesAPI_MultiRotation.h" %include "FeaturesAPI_MultiTranslation.h" diff --git a/src/FeaturesAPI/FeaturesAPI_Fillet.cpp b/src/FeaturesAPI/FeaturesAPI_Fillet.cpp new file mode 100644 index 000000000..17878f0cf --- /dev/null +++ b/src/FeaturesAPI/FeaturesAPI_Fillet.cpp @@ -0,0 +1,139 @@ +// Copyright (C) 2017 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_Fillet.h" + +#include +#include +////#include +#include + +FeaturesAPI_Fillet::FeaturesAPI_Fillet(const std::shared_ptr& theFeature) + : ModelHighAPI_Interface(theFeature) +{ + initialize(); +} + +FeaturesAPI_Fillet::FeaturesAPI_Fillet(const std::shared_ptr& theFeature, + const std::list& theBaseObjects, + const ModelHighAPI_Double& theRadius) + : ModelHighAPI_Interface(theFeature) +{ + if (initialize()) { + fillAttribute(FeaturesPlugin_Fillet::CREATION_METHOD_SINGLE_RADIUS(), mycreationMethod); + fillAttribute(theBaseObjects, mybaseObjects); + fillAttribute(theRadius, myradius); + } +} + +FeaturesAPI_Fillet::FeaturesAPI_Fillet(const std::shared_ptr& theFeature, + const std::list& theBaseObjects, + const ModelHighAPI_Double& theRadius1, + const ModelHighAPI_Double& theRadius2) + : ModelHighAPI_Interface(theFeature) +{ + if (initialize()) { + fillAttribute(FeaturesPlugin_Fillet::CREATION_METHOD_VARYING_RADIUS(), mycreationMethod); + fillAttribute(theBaseObjects, mybaseObjects); + fillAttribute(theRadius1, mystartRadius); + fillAttribute(theRadius2, myendRadius); + } +} + +FeaturesAPI_Fillet::~FeaturesAPI_Fillet() +{ +} + +//================================================================================================== +void FeaturesAPI_Fillet::setBase(const std::list& theBaseObjects) +{ + mybaseObjects->clear(); + fillAttribute(theBaseObjects, mybaseObjects); + + execIfBaseNotEmpty(); +} + +void FeaturesAPI_Fillet::setRadius(const ModelHighAPI_Double& theRadius) +{ + fillAttribute(FeaturesPlugin_Fillet::CREATION_METHOD_SINGLE_RADIUS(), mycreationMethod); + fillAttribute(theRadius, myradius); + + execIfBaseNotEmpty(); +} + +void FeaturesAPI_Fillet::setRadius(const ModelHighAPI_Double& theRadius1, + const ModelHighAPI_Double& theRadius2) +{ + fillAttribute(FeaturesPlugin_Fillet::CREATION_METHOD_VARYING_RADIUS(), mycreationMethod); + fillAttribute(theRadius1, mystartRadius); + fillAttribute(theRadius2, myendRadius); + + execIfBaseNotEmpty(); +} + +void FeaturesAPI_Fillet::dump(ModelHighAPI_Dumper& theDumper) const +{ + FeaturePtr aBase = feature(); + const std::string& aDocName = theDumper.name(aBase->document()); + + AttributeSelectionListPtr anAttrObjects = + aBase->selectionList(FeaturesPlugin_Fillet::OBJECT_LIST_ID()); + + theDumper << aBase << " = model.addFillet(" << aDocName << ", " << anAttrObjects; + + std::string aCreationMethod = aBase->string(FeaturesPlugin_Fillet::CREATION_METHOD())->value(); + + if(aCreationMethod == FeaturesPlugin_Fillet::CREATION_METHOD_SINGLE_RADIUS()) { + AttributeDoublePtr anAttrRadius = aBase->real(FeaturesPlugin_Fillet::RADIUS_ID()); + theDumper << ", " << anAttrRadius; + } else if(aCreationMethod == FeaturesPlugin_Fillet::CREATION_METHOD_VARYING_RADIUS()) { + AttributeDoublePtr anAttrRadius1 = aBase->real(FeaturesPlugin_Fillet::START_RADIUS_ID()); + AttributeDoublePtr anAttrRadius2 = aBase->real(FeaturesPlugin_Fillet::END_RADIUS_ID()); + theDumper << ", " << anAttrRadius1 << ", " << anAttrRadius2; + } + + theDumper << ")" << std::endl; +} + +void FeaturesAPI_Fillet::execIfBaseNotEmpty() +{ + if (mybaseObjects->size() > 0) + execute(); +} + + +//================================================================================================== + +FilletPtr addFillet(const std::shared_ptr& thePart, + const std::list& theBaseObjects, + const ModelHighAPI_Double& theRadius) +{ + std::shared_ptr aFeature = thePart->addFeature(FeaturesAPI_Fillet::ID()); + return FilletPtr(new FeaturesAPI_Fillet(aFeature, theBaseObjects, theRadius)); +} + +FilletPtr addFillet(const std::shared_ptr& thePart, + const std::list& theBaseObjects, + const ModelHighAPI_Double& theRadius1, + const ModelHighAPI_Double& theRadius2) +{ + std::shared_ptr aFeature = thePart->addFeature(FeaturesAPI_Fillet::ID()); + return FilletPtr(new FeaturesAPI_Fillet(aFeature, theBaseObjects, theRadius1, theRadius2)); +} diff --git a/src/FeaturesAPI/FeaturesAPI_Fillet.h b/src/FeaturesAPI/FeaturesAPI_Fillet.h new file mode 100644 index 000000000..e62240823 --- /dev/null +++ b/src/FeaturesAPI/FeaturesAPI_Fillet.h @@ -0,0 +1,116 @@ +// Copyright (C) 2017 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_Fillet_H_ +#define FeaturesAPI_Fillet_H_ + +#include "FeaturesAPI.h" + +#include + +#include +#include + +class ModelHighAPI_Double; +class ModelHighAPI_Selection; + +/// \class FeaturesAPI_Fillet +/// \ingroup CPPHighAPI +/// \brief Interface for Fillet feature. +class FeaturesAPI_Fillet: public ModelHighAPI_Interface +{ +public: + /// Constructor without values. + FEATURESAPI_EXPORT + explicit FeaturesAPI_Fillet(const std::shared_ptr& theFeature); + + /// Constructor with values. + FEATURESAPI_EXPORT + explicit FeaturesAPI_Fillet(const std::shared_ptr& theFeature, + const std::list& theBaseObjects, + const ModelHighAPI_Double& theRadius); + + /// Constructor with values. + FEATURESAPI_EXPORT + explicit FeaturesAPI_Fillet(const std::shared_ptr& theFeature, + const std::list& theBaseObjects, + const ModelHighAPI_Double& theRadius1, + const ModelHighAPI_Double& theRadius2); + + /// Destructor. + FEATURESAPI_EXPORT + virtual ~FeaturesAPI_Fillet(); + + INTERFACE_5(FeaturesPlugin_Fillet::ID(), + creationMethod, FeaturesPlugin_Fillet::CREATION_METHOD(), + ModelAPI_AttributeString, + /** Creation method */, + baseObjects, FeaturesPlugin_Fillet::OBJECT_LIST_ID(), + ModelAPI_AttributeSelectionList, + /** Base objects */, + radius, FeaturesPlugin_Fillet::RADIUS_ID(), + ModelAPI_AttributeDouble, + /** Value of the fixed radius fillet */, + startRadius, FeaturesPlugin_Fillet::START_RADIUS_ID(), + ModelAPI_AttributeDouble, + /** Start radius of the varying radius fillet */, + endRadius, FeaturesPlugin_Fillet::END_RADIUS_ID(), + ModelAPI_AttributeDouble, + /** End radius of the varying radius fillet */) + + /// Modify base objects of the fillet. + FEATURESAPI_EXPORT + void setBase(const std::list& theBaseObjects); + + /// Modify fillet to have fixed radius + FEATURESAPI_EXPORT + void setRadius(const ModelHighAPI_Double& theRadius); + + /// Modify fillet to have varying radius + FEATURESAPI_EXPORT + void setRadius(const ModelHighAPI_Double& theRadius1, const ModelHighAPI_Double& theRadius2); + + /// Dump wrapped feature + FEATURESAPI_EXPORT + virtual void dump(ModelHighAPI_Dumper& theDumper) const; + +private: + void execIfBaseNotEmpty(); +}; + +/// Pointer on Fillet object. +typedef std::shared_ptr FilletPtr; + +/// \ingroup CPPHighAPI +/// \brief Create Fillet feature. +FEATURESAPI_EXPORT +FilletPtr addFillet(const std::shared_ptr& thePart, + const std::list& theBaseObjects, + const ModelHighAPI_Double& theRadius); + +/// \ingroup CPPHighAPI +/// \brief Create Fillet feature. +FEATURESAPI_EXPORT +FilletPtr addFillet(const std::shared_ptr& thePart, + const std::list& theBaseObjects, + const ModelHighAPI_Double& theRadius1, + const ModelHighAPI_Double& theRadius2); + +#endif // FeaturesAPI_Fillet_H_ diff --git a/src/FeaturesAPI/FeaturesAPI_swig.h b/src/FeaturesAPI/FeaturesAPI_swig.h index 9a6637c03..8b6ce0005 100644 --- a/src/FeaturesAPI/FeaturesAPI_swig.h +++ b/src/FeaturesAPI/FeaturesAPI_swig.h @@ -27,6 +27,7 @@ #include "FeaturesAPI_Boolean.h" #include "FeaturesAPI_Extrusion.h" #include "FeaturesAPI_ExtrusionBoolean.h" + #include "FeaturesAPI_Fillet.h" #include "FeaturesAPI_Intersection.h" #include "FeaturesAPI_MultiRotation.h" #include "FeaturesAPI_MultiTranslation.h" diff --git a/src/FeaturesPlugin/CMakeLists.txt b/src/FeaturesPlugin/CMakeLists.txt index d527286bb..3b9197381 100644 --- a/src/FeaturesPlugin/CMakeLists.txt +++ b/src/FeaturesPlugin/CMakeLists.txt @@ -51,6 +51,7 @@ SET(PROJECT_HEADERS FeaturesPlugin_Scale.h FeaturesPlugin_MultiTranslation.h FeaturesPlugin_MultiRotation.h + FeaturesPlugin_Fillet.h ) SET(PROJECT_SOURCES @@ -82,6 +83,7 @@ SET(PROJECT_SOURCES FeaturesPlugin_Scale.cpp FeaturesPlugin_MultiTranslation.cpp FeaturesPlugin_MultiRotation.cpp + FeaturesPlugin_Fillet.cpp ) SET(XML_RESOURCES @@ -106,6 +108,7 @@ SET(XML_RESOURCES scale_widget.xml multitranslation_widget.xml multirotation_widget.xml + fillet_widget.xml ) SET(TEXT_RESOURCES diff --git a/src/FeaturesPlugin/FeaturesPlugin_Fillet.cpp b/src/FeaturesPlugin/FeaturesPlugin_Fillet.cpp new file mode 100644 index 000000000..958336bcf --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_Fillet.cpp @@ -0,0 +1,231 @@ +// Copyright (C) 2017 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_Fillet.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + + +// Obtain all sub-shapes from the shape and append them to the list +static void collectSubs(const GeomShapePtr& theShape, + ListOfShape& theSubs, + const GeomAPI_Shape::ShapeType theShapeType) +{ + GeomAPI_ShapeExplorer anExp(theShape, theShapeType); + for (; anExp.more(); anExp.next()) { + GeomShapePtr aShape = anExp.current(); + // Store all shapes with FORWARD orientation to avoid duplication of shared edges/vertices + aShape->setOrientation(GeomAPI_Shape::FORWARD); + theSubs.push_back(aShape); + } +} + +// Extract edges from the list +static ListOfShape selectEdges(const ListOfShape& theShapes) +{ + ListOfShape anEdges; + for (ListOfShape::const_iterator anIt = theShapes.begin(); anIt != theShapes.end(); ++anIt) + if ((*anIt)->isEdge()) + anEdges.push_back(*anIt); + return anEdges; +} + +// If theShape is a compound of single shape, return it +static GeomShapePtr unwrapCompound(const GeomShapePtr& theShape) +{ + GeomShapePtr aShape = theShape; + if(aShape->shapeType() == GeomAPI_Shape::COMPOUND) { + int aSubResultsNb = 0; + GeomAPI_ShapeIterator anIt(aShape); + for(; anIt.more(); anIt.next()) + ++aSubResultsNb; + + if(aSubResultsNb == 1) { + anIt.init(aShape); + aShape = anIt.current(); + } + } + return aShape; +} + + +FeaturesPlugin_Fillet::FeaturesPlugin_Fillet() +{ +} + +void FeaturesPlugin_Fillet::initAttributes() +{ + data()->addAttribute(CREATION_METHOD(), ModelAPI_AttributeString::typeId()); + data()->addAttribute(OBJECT_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()); + data()->addAttribute(START_RADIUS_ID(), ModelAPI_AttributeDouble::typeId()); + data()->addAttribute(END_RADIUS_ID(), ModelAPI_AttributeDouble::typeId()); + + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), END_RADIUS_ID()); +} + + +void FeaturesPlugin_Fillet::execute() +{ + AttributeStringPtr aCreationMethod = string(CREATION_METHOD()); + if (!aCreationMethod) + return; + + GeomAPI_DataMapOfShapeMapOfShapes aSolidsAndSubs; + + // getting objects and sort them accroding to parent solids + AttributeSelectionListPtr anObjectsSelList = selectionList(OBJECT_LIST_ID()); + for (int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); ++anObjectsIndex) { + AttributeSelectionPtr anObjectAttr = anObjectsSelList->value(anObjectsIndex); + GeomShapePtr anObject = anObjectAttr->value(); + if (!anObject) + return; + + ResultPtr aContext = anObjectAttr->context(); + ResultCompSolidPtr aCtxOwner = ModelAPI_Tools::compSolidOwner(aContext); + GeomShapePtr aParent = aCtxOwner ? aCtxOwner->shape() : aContext->shape(); + if (!aParent) + return; + + ListOfShape anEdgesAndVertices; + collectSubs(anObject, anEdgesAndVertices, GeomAPI_Shape::EDGE); + collectSubs(anObject, anEdgesAndVertices, GeomAPI_Shape::VERTEX); + for (ListOfShape::iterator aEIt = anEdgesAndVertices.begin(); + aEIt != anEdgesAndVertices.end(); ++aEIt) + aSolidsAndSubs.add(aParent, *aEIt); + } + + bool isFixedRadius = true; + double aRadius1 = 0.0, aRadius2 = 0.0; + if (aCreationMethod->value() == CREATION_METHOD_SINGLE_RADIUS()) + aRadius1 = real(RADIUS_ID())->value(); + else { + aRadius1 = real(START_RADIUS_ID())->value(); + aRadius2 = real(END_RADIUS_ID())->value(); + isFixedRadius = false; + } + + // Perform fillet operation + GeomAlgoAPI_MakeShapeList aMakeShapeList; + std::shared_ptr aFilletBuilder; + int aResultIndex = 0; + + GeomAPI_DataMapOfShapeMapOfShapes::iterator anIt = aSolidsAndSubs.begin(); + for (; anIt != aSolidsAndSubs.end(); ++anIt) { + GeomShapePtr aSolid = anIt.first(); + ListOfShape aFilletEdgesAndVertices = anIt.second(); + + ListOfShape aFilletEdges = selectEdges(aFilletEdgesAndVertices); + if (isFixedRadius) + aFilletBuilder.reset(new GeomAlgoAPI_Fillet(aSolid, aFilletEdges, aRadius1)); + else + aFilletBuilder.reset(new GeomAlgoAPI_Fillet(aSolid, aFilletEdges, aRadius1, aRadius2)); + if (isFailed(aFilletBuilder)) + return; + + GeomShapePtr aResult = unwrapCompound(aFilletBuilder->shape()); + std::shared_ptr aResultBody = + document()->createBody(data(), aResultIndex); + + loadNamingDS(aResultBody, aSolid, aFilletEdgesAndVertices, aResult, aFilletBuilder); + setResult(aResultBody, aResultIndex); + aResultIndex++; + } + removeResults(aResultIndex); +} + +bool FeaturesPlugin_Fillet::isFailed( + const std::shared_ptr& theAlgorithm) +{ + if (!theAlgorithm->isDone()) { + static const std::string aFeatureError = "Error: fillet algorithm failed."; + setError(aFeatureError); + return true; + } + if (theAlgorithm->shape()->isNull()) { + static const std::string aShapeError = "Error: Resulting shape of fillet is Null."; + setError(aShapeError); + return true; + } + if (!theAlgorithm->isValid()) { + std::string aFeatureError = "Error: Resulting shape of fillet is not valid."; + setError(aFeatureError); + return true; + } + return false; +} + +void FeaturesPlugin_Fillet::loadNamingDS( + std::shared_ptr theResultBody, + const std::shared_ptr theBaseShape, + const ListOfShape& theFilletShapes, + const std::shared_ptr theResultShape, + const std::shared_ptr& theMakeShape) +{ + //load result + if(theBaseShape->isEqual(theResultShape)) { + theResultBody->store(theResultShape, false); + return; + } + + std::shared_ptr aMapOfShapes = theMakeShape->mapOfSubShapes(); + + const int aDeletedTag = 1; + const int aModifyTag = 2; + const int aGeneratedTag = 3; + /// sub solids will be placed at labels 4, 5, etc. if result is compound of solids + const int aSubsolidsTag = 4; + + theResultBody->storeModified(theBaseShape, theResultShape, aSubsolidsTag); + theResultBody->storeGenerated(theBaseShape, theResultShape); + + const std::string aModFaceName = "Modified_Face"; + const std::string aFilletFaceName = "Fillet_Face"; + + // Store modified faces + theResultBody->loadAndOrientModifiedShapes(theMakeShape.get(), theBaseShape, GeomAPI_Shape::FACE, + aModifyTag, aModFaceName, *aMapOfShapes); + + // Store new faces generated from edges and vertices + theResultBody->loadAndOrientGeneratedShapes(theMakeShape.get(), theBaseShape, GeomAPI_Shape::EDGE, + aGeneratedTag, aFilletFaceName, *aMapOfShapes); + theResultBody->loadAndOrientGeneratedShapes(theMakeShape.get(), theBaseShape, GeomAPI_Shape::VERTEX, + aGeneratedTag, aFilletFaceName, *aMapOfShapes); + + // Deleted shapes + theResultBody->loadDeletedShapes(theMakeShape.get(), theBaseShape, + GeomAPI_Shape::EDGE, aDeletedTag); + theResultBody->loadDeletedShapes(theMakeShape.get(), theBaseShape, + GeomAPI_Shape::FACE, aDeletedTag); +} diff --git a/src/FeaturesPlugin/FeaturesPlugin_Fillet.h b/src/FeaturesPlugin/FeaturesPlugin_Fillet.h new file mode 100644 index 000000000..d0aa71255 --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_Fillet.h @@ -0,0 +1,120 @@ +// Copyright (C) 2017 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_Fillet_H_ +#define FeaturesPlugin_Fillet_H_ + +#include "FeaturesPlugin.h" + +#include + +#include + +class GeomAlgoAPI_MakeShape; +class GeomAPI_DataMapOfShapeMapOfShapes; + +/// \class FeaturesPlugin_Fillet +/// \ingroup Plugins +/// \brief Feature for applying the Fillet operations on Solids. +/// Supports fixed radius fillet and varying 2-radius fillet. +class FeaturesPlugin_Fillet : public ModelAPI_Feature +{ +public: + /// Feature kind. + inline static const std::string& ID() + { + static const std::string MY_ID("Fillet"); + return MY_ID; + } + + /// \return the kind of a feature. + FEATURESPLUGIN_EXPORT virtual const std::string& getKind() + { + static std::string MY_KIND = FeaturesPlugin_Fillet::ID(); + return MY_KIND; + } + + inline static const std::string& CREATION_METHOD() + { + static std::string MY_CREATION_METHOD("creation_method"); + return MY_CREATION_METHOD; + } + + inline static const std::string CREATION_METHOD_SINGLE_RADIUS() + { + static std::string MY_SINGLE_RADIUS("fixed_radius"); + return MY_SINGLE_RADIUS; + } + + inline static const std::string CREATION_METHOD_VARYING_RADIUS() + { + static std::string MY_VARYING_RADIUS("variable_radius"); + return MY_VARYING_RADIUS; + } + + /// Attribute name of main objects. + inline static const std::string& OBJECT_LIST_ID() + { + static const std::string MY_OBJECT_LIST_ID("main_objects"); + return MY_OBJECT_LIST_ID; + } + + /// Attribute name of start radius. + inline static const std::string& START_RADIUS_ID() + { + static const std::string MY_START_RADIUS_ID("radius1"); + return MY_START_RADIUS_ID; + } + + /// Attribute name of end radius. + inline static const std::string& END_RADIUS_ID() + { + static const std::string MY_END_RADIUS_ID("radius2"); + return MY_END_RADIUS_ID; + } + + /// Attribute name of a radius for fillet with fixed radius. + inline static const std::string& RADIUS_ID() + { + return START_RADIUS_ID(); + } + + /// Creates a new part document if needed. + 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_Fillet(); + +private: + /// Check algorithm is finished correctly and store error otherwise + bool isFailed(const std::shared_ptr& theAlgorithm); + + /// Load Naming data structure of the feature to the document + void loadNamingDS(std::shared_ptr theResultBody, + const std::shared_ptr theBaseShape, + const ListOfShape& theFilletShapes, + const std::shared_ptr theResultShape, + const std::shared_ptr& theMakeShape); +}; + +#endif diff --git a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp index 954a0fb3c..b9760dc07 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -84,6 +85,8 @@ FeaturesPlugin_Plugin::FeaturesPlugin_Plugin() new FeaturesPlugin_ValidatorUnionArguments); aFactory->registerValidator("FeaturesPlugin_ValidatorConcealedResult", new FeaturesPlugin_ValidatorConcealedResult); + aFactory->registerValidator("FeaturesPlugin_ValidatorFilletSelection", + new FeaturesPlugin_ValidatorFilletSelection); // register this plugin ModelAPI_Session::get()->registerPlugin(this); @@ -131,6 +134,8 @@ FeaturePtr FeaturesPlugin_Plugin::createFeature(std::string theFeatureID) return FeaturePtr(new FeaturesPlugin_MultiTranslation); } else if (theFeatureID == FeaturesPlugin_MultiRotation::ID()) { return FeaturePtr(new FeaturesPlugin_MultiRotation); + } else if (theFeatureID == FeaturesPlugin_Fillet::ID()) { + return FeaturePtr(new FeaturesPlugin_Fillet); } // feature of such kind is not found diff --git a/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp b/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp index 5ec81daa0..4c53bcbb2 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp @@ -663,6 +663,47 @@ bool FeaturesPlugin_ValidatorBooleanSelection::isValid(const AttributePtr& theAt return true; } +//================================================================================================== +bool FeaturesPlugin_ValidatorFilletSelection::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + AttributeSelectionListPtr anAttrSelectionList = + std::dynamic_pointer_cast(theAttribute); + if(!anAttrSelectionList.get()) { + theError = + "Error: This validator can only work with selection list attributes in \"Fillet\" feature."; + return false; + } + + FeaturePtr aFeature = std::dynamic_pointer_cast(theAttribute->owner()); + // Check all selected entities are sub-shapes of single solid + GeomShapePtr aBaseSolid; + for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) { + AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex); + if(!anAttrSelection.get()) { + theError = "Error: Empty attribute selection."; + return false; + } + ResultPtr aContext = anAttrSelection->context(); + if(!aContext.get()) { + theError = "Error: Empty selection context."; + return false; + } + + ResultCompSolidPtr aContextOwner = ModelAPI_Tools::compSolidOwner(aContext); + GeomShapePtr anOwner = aContextOwner.get() ? aContextOwner->shape() : aContext->shape(); + if (!aBaseSolid) + aBaseSolid = anOwner; + else if (!aBaseSolid->isEqual(anOwner)) { + theError = "Error: Sub-shapes of different solids have been selected."; + return false; + } + } + + return true; +} + //================================================================================================== bool FeaturesPlugin_ValidatorPartitionSelection::isValid(const AttributePtr& theAttribute, const std::list& theArguments, diff --git a/src/FeaturesPlugin/FeaturesPlugin_Validators.h b/src/FeaturesPlugin/FeaturesPlugin_Validators.h index d8c0a091e..62edcb2bf 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Validators.h +++ b/src/FeaturesPlugin/FeaturesPlugin_Validators.h @@ -152,6 +152,22 @@ public: Events_InfoMessage& theError) const; }; +/// \class FeaturesPlugin_ValidatorFilletSelection +/// \ingroup Validators +/// \brief Validates selection for fillet operation. +class FeaturesPlugin_ValidatorFilletSelection: public ModelAPI_AttributeValidator +{ +public: + /// \return True if the attribute is valid. It checks whether the selection + /// is acceptable for boolean operation. + /// \param[in] theAttribute an attribute to check. + /// \param[in] theArguments a filter parameters. + /// \param[out] theError error message. + virtual bool isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const; +}; + /// \class FeaturesPlugin_ValidatorPartitionSelection /// \ingroup Validators /// \brief Validates selection for partition. diff --git a/src/FeaturesPlugin/Test/TestFillet.py b/src/FeaturesPlugin/Test/TestFillet.py new file mode 100644 index 000000000..49831b3f5 --- /dev/null +++ b/src/FeaturesPlugin/Test/TestFillet.py @@ -0,0 +1,134 @@ +## Copyright (C) 2017 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 +## + +""" + TestFillet.py + Unit test of FeaturesPlugin_Fillet class +""" + +from ModelAPI import * + +__updated__ = "2017-11-30" + +#========================================================================= +# Initialization of the test +#========================================================================= +aSession = ModelAPI_Session.get() +aDocument = aSession.moduleDocument() +# Create a part for extrusion +aSession.startOperation() +aPartFeature = aDocument.addFeature("Part") +aSession.finishOperation() +aPart = aSession.activeDocument() + +# Create a box and a cylinder for filleting +aSession.startOperation() +aBox = aPart.addFeature("Box") +aBox.string("CreationMethod").setValue("BoxByDimensions") +aBox.real("dx").setValue(10) +aBox.real("dy").setValue(10) +aBox.real("dz").setValue(10) +aSession.finishOperation() + +# a point to anchor a cylinder +aSession.startOperation() +aPoint = aPart.addFeature("Point") +aPoint.string("creation_method").setValue("by_xyz") +aPoint.real("x").setValue(20) +aPoint.real("y").setValue(5) +aPoint.real("z").setValue(0) +aSession.finishOperation() + +aSession.startOperation() +aCylinder = aPart.addFeature("Cylinder") +aCylinder.string("CreationMethod").setValue("Cylinder") +aCylinder.selection("base_point").selectSubShape("vertex", "Point_1") +aCylinder.selection("axis").selectSubShape("edge", "PartSet/OZ") +aCylinder.real("radius").setValue(5) +aCylinder.real("height").setValue(10) +aSession.finishOperation() + +#========================================================================= +# Test 1. Create fillet with fixed radius +#========================================================================= +aSession.startOperation() +aFillet1 = aPart.addFeature("Fillet") +aFillet1.string("creation_method").setValue("fixed_radius") +anObjects = aFillet1.selectionList("main_objects") +anObjects.append("Box_1_1/Left&Box_1_1/Top", "edge") +aFillet1.real("radius1").setValue(3) +aSession.finishOperation() +assert(aFillet1.error() == ""), "FAILED: Fillet reports error \"{}\"".format(aFillet1.error()) + +#========================================================================= +# Test 2. Change fillet type +#========================================================================= +aSession.startOperation() +aFillet1.string("creation_method").setValue("variable_radius") +aFillet1.real("radius1").setValue(5) +aFillet1.real("radius2").setValue(1) +aSession.finishOperation() +assert(aFillet1.error() == ""), "FAILED: Fillet reports error \"{}\"".format(aFillet1.error()) + +#========================================================================= +# Test 3. Check fillet reports error if selected entities from different solids +#========================================================================= +aSession.startOperation() +aFillet2 = aPart.addFeature("Fillet") +aFillet2.string("creation_method").setValue("fixed_radius") +anObjects = aFillet2.selectionList("main_objects") +anObjects.append("Cylinder_1_1/Face_2", "face") +anObjects.append("_Box_1_1/Right", "face") +aFillet2.real("radius1").setValue(2) +aSession.finishOperation() +assert(aFillet2.error() != ""), "FAILED: Fillet does not report error" + +#========================================================================= +# Test 4. Fix the error +#========================================================================= +aSession.startOperation() +anObjects.removeLast() +aSession.finishOperation() +assert(aFillet2.error() == ""), "FAILED: Fillet reports error \"{}\"".format(aFillet1.error()) + +#========================================================================= +# Test 5. Check fillet reports error on smoothly connected edges +#========================================================================= +aSession.startOperation() +aFillet3 = aPart.addFeature("Fillet") +aFillet3.string("creation_method").setValue("fixed_radius") +aFillet3.selectionList("main_objects").append("Cylinder_1_1/Modified_Face_1", "face") +aFillet3.real("radius1").setValue(3) +aSession.finishOperation() +assert(aFillet3.lastResult() is None), "FAILED: Fillet should not produce a result" + +#========================================================================= +# Test 6. Remove last fillet feature +#========================================================================= +aSession.startOperation() +aPart.removeFeature(aFillet3) +aSession.finishOperation() + +#========================================================================= +# End of test +#========================================================================= + +from salome.shaper import model +assert(model.checkPythonDump()) diff --git a/src/FeaturesPlugin/fillet_widget.xml b/src/FeaturesPlugin/fillet_widget.xml new file mode 100644 index 000000000..1ccb5bc55 --- /dev/null +++ b/src/FeaturesPlugin/fillet_widget.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/FeaturesPlugin/icons/fillet.png b/src/FeaturesPlugin/icons/fillet.png new file mode 100644 index 000000000..3b5a98289 Binary files /dev/null and b/src/FeaturesPlugin/icons/fillet.png differ diff --git a/src/FeaturesPlugin/icons/fillet_fixed_radius.png b/src/FeaturesPlugin/icons/fillet_fixed_radius.png new file mode 100644 index 000000000..0897bdeb8 Binary files /dev/null and b/src/FeaturesPlugin/icons/fillet_fixed_radius.png differ diff --git a/src/FeaturesPlugin/icons/fillet_var_radius.png b/src/FeaturesPlugin/icons/fillet_var_radius.png new file mode 100644 index 000000000..56e4a78f3 Binary files /dev/null and b/src/FeaturesPlugin/icons/fillet_var_radius.png differ diff --git a/src/FeaturesPlugin/plugin-Features.xml b/src/FeaturesPlugin/plugin-Features.xml index 298723427..171d8acb8 100644 --- a/src/FeaturesPlugin/plugin-Features.xml +++ b/src/FeaturesPlugin/plugin-Features.xml @@ -80,6 +80,11 @@ email : webmaster.salome@opencascade.com + + + + + diff --git a/src/GeomAPI/GeomAPI_DataMapOfShapeMapOfShapes.cpp b/src/GeomAPI/GeomAPI_DataMapOfShapeMapOfShapes.cpp index d5132057c..a7497c0dc 100644 --- a/src/GeomAPI/GeomAPI_DataMapOfShapeMapOfShapes.cpp +++ b/src/GeomAPI/GeomAPI_DataMapOfShapeMapOfShapes.cpp @@ -24,7 +24,8 @@ #include #include -#define MY_MAP implPtr > >() +typedef NCollection_DataMap > MAP; +#define MY_MAP implPtr() //================================================================================================= GeomAPI_DataMapOfShapeMapOfShapes::GeomAPI_DataMapOfShapeMapOfShapes() @@ -113,3 +114,158 @@ int GeomAPI_DataMapOfShapeMapOfShapes::size() const { return MY_MAP->Size(); } + + +//================================================================================================= +// iterator implementation +//================================================================================================= + +class IteratorImpl : public GeomAPI_DataMapOfShapeMapOfShapes::iterator +{ +public: + IteratorImpl() {} + + IteratorImpl(const MAP::Iterator& theIterator) + : myIterator(theIterator) + {} + + IteratorImpl(const std::shared_ptr& theIterator) + { + mySelf = theIterator; + } + + bool operator==(const std::shared_ptr& theOther) const + { + if (theOther) + return theOther->myIterator.IsEqual(myIterator); + + // theOther is end iterator => check the current iterator is not at the end + return !myIterator.More(); + } + + virtual iterator& operator++() + { + myIterator.Next(); + return *this; + } + virtual iterator operator++(int) + { + std::shared_ptr aSelf = std::dynamic_pointer_cast(mySelf); + std::shared_ptr aCopy(new IteratorImpl(aSelf->myIterator)); + myIterator.Next(); + return IteratorImpl(aCopy); + } + + virtual key_type first() const + { + if (mySelf) + return iterator::first(); + + GeomShapePtr aShape(new GeomAPI_Shape); + aShape->setImpl(new TopoDS_Shape(myIterator.Key())); + return aShape; + } + + virtual mapped_type second() const + { + if (mySelf) + return iterator::second(); + + ListOfShape anItems; + const NCollection_Map& aMap = myIterator.Value(); + for(NCollection_Map::Iterator anIt(aMap); anIt.More(); anIt.Next()) { + std::shared_ptr aShape(new GeomAPI_Shape); + aShape->setImpl(new TopoDS_Shape(anIt.Value())); + anItems.push_back(aShape); + } + return anItems; + } + +private: + MAP::Iterator myIterator; +}; + + +GeomAPI_DataMapOfShapeMapOfShapes::iterator::iterator() +{ +} + +GeomAPI_DataMapOfShapeMapOfShapes::iterator::iterator( + const GeomAPI_DataMapOfShapeMapOfShapes::iterator& theOther) + : mySelf(theOther.mySelf) +{ +} + +const GeomAPI_DataMapOfShapeMapOfShapes::iterator& + GeomAPI_DataMapOfShapeMapOfShapes::iterator::operator=( + const GeomAPI_DataMapOfShapeMapOfShapes::iterator& theOther) +{ + mySelf = theOther.mySelf; + return *this; +} + +bool GeomAPI_DataMapOfShapeMapOfShapes::iterator::operator==(const iterator& theOther) const +{ + std::shared_ptr aSelf = std::dynamic_pointer_cast(mySelf); + std::shared_ptr aSelfOther = + std::dynamic_pointer_cast(theOther.mySelf); + + return aSelf ? aSelf->operator==(aSelfOther) + : (aSelfOther ? aSelfOther->operator==(aSelf) : true); +} + +bool GeomAPI_DataMapOfShapeMapOfShapes::iterator::operator!=(const iterator& theOther) const +{ + return !operator==(theOther); +} + +GeomAPI_DataMapOfShapeMapOfShapes::iterator& + GeomAPI_DataMapOfShapeMapOfShapes::iterator::operator++() +{ + mySelf->operator++(); + return *this; +} + +GeomAPI_DataMapOfShapeMapOfShapes::iterator + GeomAPI_DataMapOfShapeMapOfShapes::iterator::operator++(int) +{ + return ++(*mySelf); +} + +GeomAPI_DataMapOfShapeMapOfShapes::iterator::key_type + GeomAPI_DataMapOfShapeMapOfShapes::iterator::first() const +{ + return mySelf->first(); +} + +GeomAPI_DataMapOfShapeMapOfShapes::iterator::mapped_type + GeomAPI_DataMapOfShapeMapOfShapes::iterator::second() const +{ + return mySelf->second(); +} + + + +GeomAPI_DataMapOfShapeMapOfShapes::iterator GeomAPI_DataMapOfShapeMapOfShapes::begin() +{ + MAP::Iterator anIt(*MY_MAP); + std::shared_ptr anIter(new IteratorImpl(anIt)); + return IteratorImpl(anIter); +} + +GeomAPI_DataMapOfShapeMapOfShapes::const_iterator GeomAPI_DataMapOfShapeMapOfShapes::begin() const +{ + MAP::Iterator anIt(*MY_MAP); + std::shared_ptr anIter(new IteratorImpl(anIt)); + return IteratorImpl(anIter); +} + +GeomAPI_DataMapOfShapeMapOfShapes::iterator GeomAPI_DataMapOfShapeMapOfShapes::end() +{ + return IteratorImpl(std::shared_ptr()); +} + +GeomAPI_DataMapOfShapeMapOfShapes::const_iterator GeomAPI_DataMapOfShapeMapOfShapes::end() const +{ + return IteratorImpl(std::shared_ptr()); +} diff --git a/src/GeomAPI/GeomAPI_DataMapOfShapeMapOfShapes.h b/src/GeomAPI/GeomAPI_DataMapOfShapeMapOfShapes.h index 9e631c861..395abae34 100644 --- a/src/GeomAPI/GeomAPI_DataMapOfShapeMapOfShapes.h +++ b/src/GeomAPI/GeomAPI_DataMapOfShapeMapOfShapes.h @@ -64,6 +64,40 @@ public: /// \return size of map. GEOMAPI_EXPORT int size() const; + +public: + class iterator + { + public: + typedef GeomShapePtr key_type; + typedef ListOfShape mapped_type; + typedef std::pair value_type; + + public: + GEOMAPI_EXPORT iterator(); + GEOMAPI_EXPORT iterator(const iterator&); + GEOMAPI_EXPORT const iterator& operator=(const iterator&); + + GEOMAPI_EXPORT bool operator==(const iterator&) const; + GEOMAPI_EXPORT bool operator!=(const iterator&) const; + + GEOMAPI_EXPORT virtual iterator& operator++(); + GEOMAPI_EXPORT virtual iterator operator++(int); + + GEOMAPI_EXPORT virtual key_type first() const; + GEOMAPI_EXPORT virtual mapped_type second() const; + + protected: + std::shared_ptr mySelf; + }; + + typedef iterator const_iterator; + + GEOMAPI_EXPORT iterator begin(); + GEOMAPI_EXPORT const_iterator begin() const; + + GEOMAPI_EXPORT iterator end(); + GEOMAPI_EXPORT const_iterator end() const; }; #endif diff --git a/src/GeomAlgoAPI/CMakeLists.txt b/src/GeomAlgoAPI/CMakeLists.txt index aa563452b..f2b4f4330 100644 --- a/src/GeomAlgoAPI/CMakeLists.txt +++ b/src/GeomAlgoAPI/CMakeLists.txt @@ -74,6 +74,7 @@ SET(PROJECT_HEADERS GeomAlgoAPI_Scale.h GeomAlgoAPI_Circ2dBuilder.h GeomAlgoAPI_UnifySameDomain.h + GeomAlgoAPI_Fillet.h ) SET(PROJECT_SOURCES @@ -126,6 +127,7 @@ SET(PROJECT_SOURCES GeomAlgoAPI_Scale.cpp GeomAlgoAPI_Circ2dBuilder.cpp GeomAlgoAPI_UnifySameDomain.cpp + GeomAlgoAPI_Fillet.cpp ) SET(PROJECT_LIBRARIES @@ -140,6 +142,7 @@ SET(PROJECT_LIBRARIES ${CAS_TKBRep} ${CAS_TKCAF} ${CAS_TKCAF} + ${CAS_TKFillet} ${CAS_TKLCAF} ${CAS_TKPrim} ${CAS_TKSTEP} diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Fillet.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Fillet.cpp new file mode 100644 index 000000000..b3d510cfb --- /dev/null +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Fillet.cpp @@ -0,0 +1,86 @@ +// Copyright (C) 2017 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 "GeomAlgoAPI_Fillet.h" + +#include + +//================================================================================================= +GeomAlgoAPI_Fillet::GeomAlgoAPI_Fillet(const GeomShapePtr& theBaseSolid, + const ListOfShape& theFilletEdges, + const double theFilletRadius) +{ + build(theBaseSolid, theFilletEdges, theFilletRadius); +} + +//================================================================================================= +GeomAlgoAPI_Fillet::GeomAlgoAPI_Fillet(const GeomShapePtr& theBaseSolid, + const ListOfShape& theFilletEdges, + const double theStartRadius, + const double theEndRadius) +{ + if (theEndRadius < 0.) + return; + build(theBaseSolid, theFilletEdges, theStartRadius, theEndRadius); +} + +//================================================================================================= +void GeomAlgoAPI_Fillet::build(const GeomShapePtr& theBaseSolid, + const ListOfShape& theFilletEdges, + const double theStartRadius, + const double theEndRadius) +{ + if (!theBaseSolid || theFilletEdges.empty() || theStartRadius < 0.) + return; + + // create fillet builder + BRepFilletAPI_MakeFillet* aFilletBuilder = + new BRepFilletAPI_MakeFillet(theBaseSolid->impl()); + setImpl(aFilletBuilder); + setBuilderType(OCCT_BRepBuilderAPI_MakeShape); + + // assign filleting edges + for (ListOfShape::const_iterator anIt = theFilletEdges.begin(); + anIt != theFilletEdges.end(); ++anIt) { + if ((*anIt)->isEdge()) + aFilletBuilder->Add( (*anIt)->impl() ); + } + + // assign fillet radii for each contour of filleting edges + bool isFixedRadius = theEndRadius < 0.; + int aNbContours = aFilletBuilder->NbContours(); + for (int ind = 1; ind <= aNbContours; ++ind) { + if (isFixedRadius) + aFilletBuilder->SetRadius(theStartRadius, ind, 1); + else + aFilletBuilder->SetRadius(theStartRadius, theEndRadius, ind, 1); + } + + // build and get result + aFilletBuilder->Build(); + if (!aFilletBuilder->IsDone()) + return; + const TopoDS_Shape& aResult = aFilletBuilder->Shape(); + + std::shared_ptr aShape(new GeomAPI_Shape()); + aShape->setImpl(new TopoDS_Shape(aResult)); + setShape(aShape); + setDone(true); +} diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Fillet.h b/src/GeomAlgoAPI/GeomAlgoAPI_Fillet.h new file mode 100644 index 000000000..56648cdec --- /dev/null +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Fillet.h @@ -0,0 +1,66 @@ +// Copyright (C) 2017 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_Fillet_H_ +#define GeomAlgoAPI_Fillet_H_ + +#include +#include + +#include + +/// \class GeomAlgoAPI_Fillet +/// \ingroup DataAlgo +/// \brief Perform fillet +class GeomAlgoAPI_Fillet : public GeomAlgoAPI_MakeShape +{ +public: + /// Run fillet operation with fixed radius. + /// \param theBaseSolid a changing solid + /// \param theFilletEdges list of edges the fillet is performed on + /// \param theFilletRadius radius of the fillet + GEOMALGOAPI_EXPORT GeomAlgoAPI_Fillet(const GeomShapePtr& theBaseSolid, + const ListOfShape& theFilletEdges, + const double theFilletRadius); + + /// Run fillet operation with variable radius. + /// \param theBaseSolid a changing solid + /// \param theFilletEdges list of edges the fillet is performed on + /// \param theStartRadius start radius of the fillet + /// \param theEndRadius end radius of the fillet + GEOMALGOAPI_EXPORT GeomAlgoAPI_Fillet(const GeomShapePtr& theBaseSolid, + const ListOfShape& theFilletEdges, + const double theStartRadius, + const double theEndRadius); + +private: + /// Perform fillet operation. + /// If theEndRadius is less than 0., the fixed radius fillet will be built. + /// \param theBaseSolid a changing solid + /// \param theFilletEdges list of edges the fillet is performed on + /// \param theStartRadius start radius of the fillet + /// \param theEndRadius end radius of the fillet + void build(const GeomShapePtr& theBaseSolid, + const ListOfShape& theFilletEdges, + const double theStartRadius, + const double theEndRadius = -1.0); +}; + +#endif diff --git a/src/Model/Model_BodyBuilder.cpp b/src/Model/Model_BodyBuilder.cpp index 24acebc17..f582556ff 100755 --- a/src/Model/Model_BodyBuilder.cpp +++ b/src/Model/Model_BodyBuilder.cpp @@ -446,8 +446,8 @@ void Model_BodyBuilder::loadAndOrientGeneratedShapes ( for (; aShapeExplorer.More(); aShapeExplorer.Next ()) { const TopoDS_Shape& aRoot = aShapeExplorer.Current (); if (!aView.Add(aRoot)) continue; - if (TNaming_Tool::NamedShape(aRoot, builder(theTag)->NamedShape()->Label()).IsNull()) - continue; // there is no sence to write history is old shape does not persented in document + //if (TNaming_Tool::NamedShape(aRoot, builder(theTag)->NamedShape()->Label()).IsNull()) + // continue; // there is no sence to write history is old shape does not persented in document ListOfShape aList; std::shared_ptr aRShape(new GeomAPI_Shape()); aRShape->setImpl((new TopoDS_Shape(aRoot))); diff --git a/src/PythonAPI/model/features/__init__.py b/src/PythonAPI/model/features/__init__.py index a69fea2d0..0347b26b2 100644 --- a/src/PythonAPI/model/features/__init__.py +++ b/src/PythonAPI/model/features/__init__.py @@ -9,3 +9,4 @@ from FeaturesAPI import addPipe from FeaturesAPI import addCut, addFuse, addCommon, addSmash, addFill from FeaturesAPI import addIntersection, addPartition, addUnion, addRemoveSubShapes from FeaturesAPI import addRecover +from FeaturesAPI import addFillet