From: mbs Date: Wed, 30 Nov 2022 15:41:31 +0000 (+0000) Subject: added new Sewing feature X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=d41f99973bde57a33c7ef8f6921aed7adfebdab3;p=modules%2Fshaper.git added new Sewing feature --- diff --git a/src/FeaturesAPI/CMakeLists.txt b/src/FeaturesAPI/CMakeLists.txt index 554d5ddaa..1d929468d 100644 --- a/src/FeaturesAPI/CMakeLists.txt +++ b/src/FeaturesAPI/CMakeLists.txt @@ -47,6 +47,7 @@ SET(PROJECT_HEADERS FeaturesAPI_RevolutionBoolean.h FeaturesAPI_Rotation.h FeaturesAPI_Scale.h + FeaturesAPI_Sewing.h FeaturesAPI_Symmetry.h FeaturesAPI_Translation.h FeaturesAPI_Union.h @@ -86,6 +87,7 @@ SET(PROJECT_SOURCES FeaturesAPI_RevolutionBoolean.cpp FeaturesAPI_Rotation.cpp FeaturesAPI_Scale.cpp + FeaturesAPI_Sewing.cpp FeaturesAPI_Symmetry.cpp FeaturesAPI_Translation.cpp FeaturesAPI_Union.cpp diff --git a/src/FeaturesAPI/FeaturesAPI.i b/src/FeaturesAPI/FeaturesAPI.i index 2cc08c164..4a4db824a 100644 --- a/src/FeaturesAPI/FeaturesAPI.i +++ b/src/FeaturesAPI/FeaturesAPI.i @@ -50,6 +50,7 @@ %feature("kwargs") addPlacement; %feature("kwargs") addRotation; %feature("kwargs") addScale; +%feature("kwargs") addSewing; %feature("kwargs") addSplit; %feature("kwargs") addSmash; %feature("kwargs") addSymmetry; @@ -87,6 +88,7 @@ %shared_ptr(FeaturesAPI_RevolutionFuse) %shared_ptr(FeaturesAPI_Rotation) %shared_ptr(FeaturesAPI_Scale) +%shared_ptr(FeaturesAPI_Sewing) %shared_ptr(FeaturesAPI_Symmetry) %shared_ptr(FeaturesAPI_Translation) %shared_ptr(FeaturesAPI_Union) @@ -229,6 +231,7 @@ %include "FeaturesAPI_RevolutionBoolean.h" %include "FeaturesAPI_Rotation.h" %include "FeaturesAPI_Scale.h" +%include "FeaturesAPI_Sewing.h" %include "FeaturesAPI_Symmetry.h" %include "FeaturesAPI_Translation.h" %include "FeaturesAPI_Union.h" diff --git a/src/FeaturesAPI/FeaturesAPI_Sewing.cpp b/src/FeaturesAPI/FeaturesAPI_Sewing.cpp new file mode 100644 index 000000000..65aa60826 --- /dev/null +++ b/src/FeaturesAPI/FeaturesAPI_Sewing.cpp @@ -0,0 +1,115 @@ +// 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_Sewing.h" + +#include +#include +#include + +//================================================================================================== +FeaturesAPI_Sewing::FeaturesAPI_Sewing(const std::shared_ptr& theFeature) +: ModelHighAPI_Interface(theFeature) +{ + initialize(); +} + +//================================================================================================== +FeaturesAPI_Sewing::FeaturesAPI_Sewing(const std::shared_ptr& theFeature, + const std::list& theMainObjects, + const ModelHighAPI_Double& theTolerance, + bool theIsAllowNonManifold/*=false*/, + bool theIsAlwaysCreateResult/*=true*/) +: ModelHighAPI_Interface(theFeature) +{ + if (initialize()) { + fillAttribute(theMainObjects, mainObjects()); + setTolerance(theTolerance); + setIsAllowNonManifold(theIsAllowNonManifold); + setIsAlwaysCreateResult(theIsAlwaysCreateResult); + } +} + +//================================================================================================== +FeaturesAPI_Sewing::~FeaturesAPI_Sewing() +{ +} + +//================================================================================================== +void FeaturesAPI_Sewing::setMainObjects(const std::list& theMainObjects) +{ + fillAttribute(theMainObjects, mainObjects()); + execute(); +} + +//================================================================================================== +void FeaturesAPI_Sewing::setTolerance(const ModelHighAPI_Double& theTolerance) +{ + fillAttribute(theTolerance, tolerance()); + execute(); +} + +//================================================================================================== +void FeaturesAPI_Sewing::setIsAllowNonManifold(bool theFlag) +{ + fillAttribute(theFlag, isAllowNonManifold()); + execute(); +} + +//================================================================================================== +void FeaturesAPI_Sewing::setIsAlwaysCreateResult(bool theFlag) +{ + fillAttribute(theFlag, isAlwaysCreateResult()); + execute(); +} + +//================================================================================================== +void FeaturesAPI_Sewing::dump(ModelHighAPI_Dumper& theDumper) const +{ + FeaturePtr aBase = feature(); + const std::string& aDocName = theDumper.name(aBase->document()); + + AttributeSelectionListPtr anAttrObjects = + aBase->selectionList(FeaturesPlugin_Sewing::OBJECTS_LIST_ID()); + theDumper << aBase << " = model.addSewing(" << aDocName << ", " << anAttrObjects; + + AttributeDoublePtr anAttrTolerance = aBase->real(FeaturesPlugin_Sewing::TOLERANCE_ID()); + theDumper << ", " << anAttrTolerance; + + AttributeBooleanPtr anAttrAllowNonMFold = aBase->boolean(FeaturesPlugin_Sewing::ALLOW_NON_MANIFOLD_ID()); + theDumper << ", " << anAttrAllowNonMFold; + + AttributeBooleanPtr anAttrAlwaysResult = aBase->boolean(FeaturesPlugin_Sewing::ALWAYS_CREATE_RESULT_ID()); + theDumper << ", " << anAttrAlwaysResult; + + theDumper << ")" << std::endl; +} + +//================================================================================================== +SewingPtr addSewing(const std::shared_ptr& thePart, + const std::list& theMainObjects, + const ModelHighAPI_Double& theTolerance, + const bool theIsAllowNonManifold, + const bool theIsAlwaysCreateResult) +{ + std::shared_ptr aFeature = thePart->addFeature(FeaturesAPI_Sewing::ID()); + SewingPtr aSewing; + aSewing.reset(new FeaturesAPI_Sewing(aFeature, theMainObjects, theTolerance, theIsAllowNonManifold, theIsAlwaysCreateResult)); + return aSewing; +} diff --git a/src/FeaturesAPI/FeaturesAPI_Sewing.h b/src/FeaturesAPI/FeaturesAPI_Sewing.h new file mode 100644 index 000000000..049294bdd --- /dev/null +++ b/src/FeaturesAPI/FeaturesAPI_Sewing.h @@ -0,0 +1,99 @@ +// 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_SEWING_H_ +#define FEATURESAPI_SEWING_H_ + +#include "FeaturesAPI.h" + +#include + +#include +#include + +class ModelHighAPI_Double; +class ModelHighAPI_Dumper; +class ModelHighAPI_Selection; + +/// \class FeaturesAPI_Sewing +/// \ingroup CPPHighAPI +/// \brief Interface for Sewing feature. +class FeaturesAPI_Sewing: public ModelHighAPI_Interface +{ +public: + /// Constructor without values. + FEATURESAPI_EXPORT + explicit FeaturesAPI_Sewing(const std::shared_ptr& theFeature); + + /// Constructor with values. + FEATURESAPI_EXPORT + explicit FeaturesAPI_Sewing(const std::shared_ptr& theFeature, + const std::list& theMainObjects, + const ModelHighAPI_Double& theTolerance, + bool theIsAllowNonManifold = false, + bool theIsAlwaysCreateResult = true); + + /// Destructor. + FEATURESAPI_EXPORT + virtual ~FeaturesAPI_Sewing(); + + INTERFACE_4(FeaturesPlugin_Sewing::ID(), + mainObjects, FeaturesPlugin_Sewing::OBJECTS_LIST_ID(), + ModelAPI_AttributeSelectionList, /** Main objects */, + tolerance, FeaturesPlugin_Sewing::TOLERANCE_ID(), + ModelAPI_AttributeDouble, /** Tolerance */, + isAllowNonManifold, FeaturesPlugin_Sewing::ALLOW_NON_MANIFOLD_ID(), + ModelAPI_AttributeBoolean, /** Allow Non-Manifold Shapes */, + isAlwaysCreateResult, FeaturesPlugin_Sewing::ALWAYS_CREATE_RESULT_ID(), + ModelAPI_AttributeBoolean, /** Always Create Result */) + + /// Set main objects. + FEATURESAPI_EXPORT + void setMainObjects(const std::list& theMainObjects); + + /// Set the tolerance. + FEATURESAPI_EXPORT + void setTolerance(const ModelHighAPI_Double& theTolerance); + + /// Set flag whether to allow non-manifold results. + FEATURESAPI_EXPORT + void setIsAllowNonManifold(bool theFlag); + + /// Set flag whether to always create a result. + FEATURESAPI_EXPORT + void setIsAlwaysCreateResult(bool theFlag); + + /// Dump wrapped feature + FEATURESAPI_EXPORT + virtual void dump(ModelHighAPI_Dumper& theDumper) const; +}; + +/// Pointer on Sewing object. +typedef std::shared_ptr SewingPtr; + +/// \ingroup CPPHighAPI +/// \brief Create Sewing feature. +FEATURESAPI_EXPORT +SewingPtr addSewing(const std::shared_ptr& thePart, + const std::list& theMainObjects, + const ModelHighAPI_Double& theTolerance, + const bool theIsAllowNonManifold, + const bool theIsAlwaysCreateResult); + +#endif // FEATURESAPI_SEWING_H_ diff --git a/src/FeaturesAPI/FeaturesAPI_swig.h b/src/FeaturesAPI/FeaturesAPI_swig.h index f03aad755..d46a5c084 100644 --- a/src/FeaturesAPI/FeaturesAPI_swig.h +++ b/src/FeaturesAPI/FeaturesAPI_swig.h @@ -49,6 +49,7 @@ #include "FeaturesAPI_RevolutionBoolean.h" #include "FeaturesAPI_Rotation.h" #include "FeaturesAPI_Scale.h" + #include "FeaturesAPI_Sewing.h" #include "FeaturesAPI_Symmetry.h" #include "FeaturesAPI_Translation.h" #include "FeaturesAPI_Union.h" diff --git a/src/FeaturesPlugin/CMakeLists.txt b/src/FeaturesPlugin/CMakeLists.txt index 9cc750314..3f9fb4e53 100644 --- a/src/FeaturesPlugin/CMakeLists.txt +++ b/src/FeaturesPlugin/CMakeLists.txt @@ -57,6 +57,7 @@ SET(PROJECT_HEADERS FeaturesPlugin_Tools.h FeaturesPlugin_Symmetry.h FeaturesPlugin_Scale.h + FeaturesPlugin_Sewing.h FeaturesPlugin_MultiTranslation.h FeaturesPlugin_MultiRotation.h FeaturesPlugin_Fillet.h @@ -113,6 +114,7 @@ SET(PROJECT_SOURCES FeaturesPlugin_Tools.cpp FeaturesPlugin_Symmetry.cpp FeaturesPlugin_Scale.cpp + FeaturesPlugin_Sewing.cpp FeaturesPlugin_MultiTranslation.cpp FeaturesPlugin_MultiRotation.cpp FeaturesPlugin_Fillet.cpp @@ -159,6 +161,7 @@ SET(XML_RESOURCES union_widget.xml symmetry_widget.xml scale_widget.xml + sewing_widget.xml multitranslation_widget.xml multirotation_widget.xml fillet_widget.xml diff --git a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp index ca33e7adc..56f86af9c 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp @@ -53,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -134,6 +135,8 @@ FeaturesPlugin_Plugin::FeaturesPlugin_Plugin() new FeaturesPlugin_ValidatorImportResults); aFactory->registerValidator("FeaturesPlugin_ValidatorDefeaturingSelection", new FeaturesPlugin_ValidatorDefeaturingSelection); + aFactory->registerValidator("FeaturesPlugin_ValidatorSewingSelection", + new FeaturesPlugin_ValidatorSewingSelection); // register this plugin ModelAPI_Session::get()->registerPlugin(this); @@ -189,6 +192,8 @@ FeaturePtr FeaturesPlugin_Plugin::createFeature(std::string theFeatureID) return FeaturePtr(new FeaturesPlugin_Symmetry); } else if (theFeatureID == FeaturesPlugin_Scale::ID()) { return FeaturePtr(new FeaturesPlugin_Scale); + } else if (theFeatureID == FeaturesPlugin_Sewing::ID()) { + return FeaturePtr(new FeaturesPlugin_Sewing); } else if (theFeatureID == FeaturesPlugin_MultiTranslation::ID()) { return FeaturePtr(new FeaturesPlugin_MultiTranslation); } else if (theFeatureID == FeaturesPlugin_MultiRotation::ID()) { diff --git a/src/FeaturesPlugin/FeaturesPlugin_Sewing.cpp b/src/FeaturesPlugin/FeaturesPlugin_Sewing.cpp new file mode 100644 index 000000000..8282f66c1 --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_Sewing.cpp @@ -0,0 +1,188 @@ +// 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 + +//#include +#include +#include + +//#include +#include +//#include +//#include + +#include +#include +#include +#include +//#include + +//--------------------------------------------------------- +// #define USE_DEBUG +// #define DEBUG +// static const char *dbg_class = "FeaturesPlugin_Sewing"; +// #include "MBDebug.h" +// #include "MBModel.h" +// #include "MBGeom.h" +//--------------------------------------------------------- + + + +//================================================================================================= +FeaturesPlugin_Sewing::FeaturesPlugin_Sewing() +{ +// DBG_FUN(); +} + +//================================================================================================= +void FeaturesPlugin_Sewing::initAttributes() +{ +// DBG_FUN(); + + data()->addAttribute(OBJECTS_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()); + data()->addAttribute(ALLOW_NON_MANIFOLD_ID(), ModelAPI_AttributeBoolean::typeId()); + data()->addAttribute(TOLERANCE_ID(), ModelAPI_AttributeDouble::typeId()); + data()->addAttribute(ALWAYS_CREATE_RESULT_ID(), ModelAPI_AttributeBoolean::typeId()); +} + +//================================================================================================= +void FeaturesPlugin_Sewing::execute() +{ +// DBG_FUN(); + + // Collect all base shapes + ListOfShape aShapes; + getOriginalShapes(OBJECTS_LIST_ID(), aShapes); +// SHOW(aShapes); + + // Get all other feature arguments + bool isAllowNonManifold = boolean(FeaturesPlugin_Sewing::ALLOW_NON_MANIFOLD_ID())->value(); + bool isAlwaysCreateResult = boolean(FeaturesPlugin_Sewing::ALWAYS_CREATE_RESULT_ID())->value(); + double aTolerance = real(FeaturesPlugin_Sewing::TOLERANCE_ID())->value(); + // SHOW(isAllowNonManifold); + // SHOW(isAlwaysCreateResult); + // SHOW(aTolerance); + + std::shared_ptr aSewingAlgo(new GeomAlgoAPI_Sewing(aShapes, isAllowNonManifold, aTolerance)); + + std::string anError; + if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aSewingAlgo, getKind(), anError)) + { + // SHOW(anError); + setError(anError); + return; + } + + // Store result. + GeomShapePtr aResult = aSewingAlgo->shape(); + // SHOW(aResult); + + int anIndex = 0; + ResultBodyPtr aResultBody = document()->createBody(data(), anIndex); + // SHOW(aResultBody); + aResultBody->storeModified(aShapes, aResult, aSewingAlgo); + // SHOW(aResultBody); + + if (!isSewn(aShapes, aResult) && !isAlwaysCreateResult) + { + static const std::string anError = "Error: No faces were sewn."; + setError(anError); + return; + } + + setResult(aResultBody, anIndex); +} + +//================================================================================================= +void FeaturesPlugin_Sewing::getOriginalShapes(const std::string& theAttributeName, + ListOfShape& theShapes) +{ + // DBG_FUN(); + // ARG(theAttributeName); + + // Collect all selections into a single list of shapes + AttributeSelectionListPtr aSelectionList = selectionList(theAttributeName); + for (int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) + { + AttributeSelectionPtr aSelection = aSelectionList->value(anIndex); + GeomShapePtr aShape = aSelection->value(); + GeomShapePtr aContext = aSelection->context()->shape(); + if (!aShape.get()) + { + aShape = aContext; + } + theShapes.push_back(aShape); + } +} + +//================================================================================================= +bool FeaturesPlugin_Sewing::isSewn(const ListOfShape& theInputs, + const GeomShapePtr theResult) +{ + // DBG_FUN(); + // ARG(theInputs); + // ARG(theResult); + + // Consider the list of input shapes the same as the result, if + // * both arguments have the same number of shells + // * the total number of faces in these shells did NOT change. + int nbInputShells = 0, nbInputFaces = 0; + for (ListOfShape::const_iterator anIt = theInputs.cbegin(); + anIt != theInputs.cend(); + ++anIt) + { + GeomShapePtr aShape = *anIt; + if (aShape.get() && aShape->isShell()) + { + nbInputShells++; + nbInputFaces += aShape->subShapes(GeomAPI_Shape::FACE, true).size(); + } + } + // SHOW(nbInputShells); + // SHOW(nbInputFaces); + + int nbResultShells = 0, nbResultFaces = 0; + if (theResult->isCompound()) + { + // MSGEL("...result is COMPOUND"); + ListOfShape shells = theResult->subShapes(GeomAPI_Shape::SHELL, true); + nbResultShells = shells.size(); + for (ListOfShape::const_iterator anIt = shells.cbegin(); + anIt != shells.cend(); + ++anIt) + { + GeomShapePtr aShape = *anIt; + if (aShape.get() && aShape->isShell()) + { + nbInputFaces += aShape->subShapes(GeomAPI_Shape::FACE, true).size(); + } + } + } + else if (theResult->isShell()) + { + // MSGEL("...result is single SHELL"); + nbResultShells = 1; + nbResultFaces = theResult->subShapes(GeomAPI_Shape::FACE, true).size(); + } + // SHOW(nbResultShells); + // SHOW(nbResultFaces); + + return (nbResultShells >= nbInputShells && nbResultFaces > nbInputFaces); +} diff --git a/src/FeaturesPlugin/FeaturesPlugin_Sewing.h b/src/FeaturesPlugin/FeaturesPlugin_Sewing.h new file mode 100644 index 000000000..815ad1aac --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_Sewing.h @@ -0,0 +1,99 @@ +// 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_SEWING_H_ +#define FEATURESPLUGIN_SEWING_H_ + +#include + +#include +//#include +#include + + +/** \class FeaturesPlugin_Sewing + * \ingroup Plugins + * \brief Feature to perform sewing operation on objects. + */ +class FeaturesPlugin_Sewing : public ModelAPI_Feature +{ + public: + /// Sewing kind. + inline static const std::string& ID() + { + static const std::string MY_SEWING_ID("Sewing"); + return MY_SEWING_ID; + } + + /// \return the kind of a feature. + FEATURESPLUGIN_EXPORT virtual const std::string& getKind() + { + static std::string MY_KIND = FeaturesPlugin_Sewing::ID(); + return MY_KIND; + } + + /// Attribute name of referenced objects. + inline static const std::string& OBJECTS_LIST_ID() + { + static const std::string MY_OBJECTS_LIST_ID("main_objects"); + return MY_OBJECTS_LIST_ID; + } + + /// Attribute name for non-manifold state. + inline static const std::string& ALLOW_NON_MANIFOLD_ID() + { + static const std::string MY_ALLOW_NON_MANIFOLD_ID("allow_non_manifold"); + return MY_ALLOW_NON_MANIFOLD_ID; + } + + /// Attribute name for tolerance. + inline static const std::string& TOLERANCE_ID() + { + static const std::string MY_TOLERANCE_ID("tolerance"); + return MY_TOLERANCE_ID; + } + + /// Attribute name for result creation state. + inline static const std::string& ALWAYS_CREATE_RESULT_ID() + { + static const std::string MY_ALWAYS_CREATE_RESULT_ID("always_create_result"); + return MY_ALWAYS_CREATE_RESULT_ID; + } + + /// Request for initialization of data model of the feature: adding all attributes. + FEATURESPLUGIN_EXPORT virtual void initAttributes(); + + /// Performs the algorithm and stores results in the data structure. + FEATURESPLUGIN_EXPORT virtual void execute(); + +public: + /// Use plugin manager for features creation. + FeaturesPlugin_Sewing(); + +private: + /// Retrieve all shapes from the selection list + void getOriginalShapes(const std::string& theAttributeName, + ListOfShape& theShapes); + + /// Check, whether the result is sewn or not + bool isSewn(const ListOfShape& theInputs, + const GeomShapePtr theResult); +}; + +#endif // FEATURESPLUGIN_SEWING_H_ diff --git a/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp b/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp index 68fcb043f..95b5b2be7 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp @@ -2097,3 +2097,69 @@ bool FeaturesPlugin_ValidatorDefeaturingSelection::isValid( return true; } + + +//--------------------------------------------------------- +// #define USE_DEBUG +// #define DEBUG +// static const char *dbg_class = "FeaturesPlugin_ValidatorSewingSelection"; +// #include "MBDebug.h" +// #include "MBModel.h" +// #include "MBGeom.h" +//--------------------------------------------------------- + +//================================================================================================== +bool FeaturesPlugin_ValidatorSewingSelection::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + // DBG_FUN(); + // ARG(theAttribute); + + AttributeSelectionListPtr anAttrSelectionList = + std::dynamic_pointer_cast(theAttribute); + if (!anAttrSelectionList.get()) { + theError = "Error: This validator can only work with selection list attributes."; + return false; + } + + // Check selected entities are of valid types + 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; + } + if (aContext->groupName() != ModelAPI_ResultBody::group()) { + theError = "Error: Not a result body."; + return false; + } + + GeomShapePtr aContextShape = aContext->shape(); + if (!aContextShape.get()) { + theError = "Error: Empty shape."; + return false; + } + + GeomAPI_Shape::ShapeType aShapeType = aContextShape->shapeType(); + std::set anAllowedTypes; + anAllowedTypes.insert(GeomAPI_Shape::FACE); + anAllowedTypes.insert(GeomAPI_Shape::SHELL); + anAllowedTypes.insert(GeomAPI_Shape::SOLID); + anAllowedTypes.insert(GeomAPI_Shape::COMPSOLID); + anAllowedTypes.insert(GeomAPI_Shape::COMPOUND); + if (anAllowedTypes.find(aShapeType) == anAllowedTypes.end()) { + theError = "Error: Selected shape has the wrong type."; + return false; + } + + } + + // MSGEL("...selection is VALID."); + return true; +} diff --git a/src/FeaturesPlugin/FeaturesPlugin_Validators.h b/src/FeaturesPlugin/FeaturesPlugin_Validators.h index adfb0cd3f..4814dc2df 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Validators.h +++ b/src/FeaturesPlugin/FeaturesPlugin_Validators.h @@ -466,4 +466,20 @@ public: Events_InfoMessage& theError) const; }; +/// \class FeaturesPlugin_ValidatorSewingSelection +/// \ingroup Validators +/// \brief Validates selection for sewing operation. +class FeaturesPlugin_ValidatorSewingSelection : public ModelAPI_AttributeValidator +{ +public: + /// \return True if the attribute is valid. It checks whether the selection + /// is acceptable for sewing 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; +}; + #endif diff --git a/src/FeaturesPlugin/FeaturesPlugin_msg_fr.ts b/src/FeaturesPlugin/FeaturesPlugin_msg_fr.ts index 653d085b8..92431eeb7 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_msg_fr.ts +++ b/src/FeaturesPlugin/FeaturesPlugin_msg_fr.ts @@ -85,6 +85,10 @@ Remove Sub-Shapes Supprimer les sous-formes + + Sewing + Couture + Revolution Révolution @@ -2177,6 +2181,63 @@ + + + Sewing + + Perform sewing operation on shapes + Effectuer une opération de couture sur des formes + + + Sewing + Coudre les faces + + + Error: No faces were sewn. + Erreur: Aucun face n'a été cousu. + + + + Sewing:main_objects + + Objects + Objets + + + Select shapes to sew. + Sélectionnez les formes à coudre. + + + + Sewing:tolerance + + Tolerance + Tolérance + + + + Sewing:allow_non_manifold + + Allow Non-Manifold + Autoriser non multiple + + + Allow the creation of non-manifold results + Autoriser la création de résultats non multiples + + + + Sewing:always_create_result + + Always create a result + Créez toujours un résultat + + + Always create a result, even if nothing is sewed + Créez toujours un résultat, même si rien n'est cousu + + + Smash @@ -5246,5 +5307,10 @@ Le résultat est vide + + + + + diff --git a/src/FeaturesPlugin/FeaturesPlugin_msg_ru.ts b/src/FeaturesPlugin/FeaturesPlugin_msg_ru.ts index e27770699..1b328d613 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_msg_ru.ts +++ b/src/FeaturesPlugin/FeaturesPlugin_msg_ru.ts @@ -293,4 +293,61 @@ + + + Sewing + + Perform sewing operation on shapes + Выполнение операции шитья на фигурах + + + Sewing + Шитье лица + + + Error: No faces were sewn. + Ошибка: лица не были сшиты. + + + + Sewing:main_objects + + Objects + Объекты + + + Select shapes to sew. + Выберите фигуры для шитья. + + + + Sewing:tolerance + + Tolerance + Толерантность + + + + Sewing:allow_non_manifold + + Allow Non-Manifold + Разрешить не многообразие + + + Allow the creation of non-manifold results + Разрешить создание однократных результатов + + + + Sewing:always_create_result + + Always create a result + Всегда создавайте результат + + + Always create a result, even if nothing is sewn + Всегда создавайте результат, даже если ничего не шьется + + + diff --git a/src/FeaturesPlugin/icons/sewing.png b/src/FeaturesPlugin/icons/sewing.png new file mode 100644 index 000000000..f9d9ca78d Binary files /dev/null and b/src/FeaturesPlugin/icons/sewing.png differ diff --git a/src/FeaturesPlugin/plugin-Features.xml b/src/FeaturesPlugin/plugin-Features.xml index ccaa0c036..1b603dfd4 100644 --- a/src/FeaturesPlugin/plugin-Features.xml +++ b/src/FeaturesPlugin/plugin-Features.xml @@ -146,6 +146,13 @@ + + + + + diff --git a/src/FeaturesPlugin/sewing_widget.xml b/src/FeaturesPlugin/sewing_widget.xml new file mode 100644 index 000000000..231e43b06 --- /dev/null +++ b/src/FeaturesPlugin/sewing_widget.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Sewing.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Sewing.cpp index 3d9630ecf..18236bd52 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_Sewing.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Sewing.cpp @@ -32,7 +32,12 @@ GeomAlgoAPI_Sewing::GeomAlgoAPI_Sewing(const ListOfShape& theShapes) build(theShapes); } -void GeomAlgoAPI_Sewing::build(const ListOfShape& theShapes) +GeomAlgoAPI_Sewing::GeomAlgoAPI_Sewing(const ListOfShape& theShapes, const bool theAllowNonManifold, const double theTolerance) +{ + build(theShapes, theAllowNonManifold, theTolerance); +} + +void GeomAlgoAPI_Sewing::build(const ListOfShape& theShapes, const bool theAllowNonManifold, const double theTolerance) { if(theShapes.empty()) { return; @@ -41,6 +46,11 @@ void GeomAlgoAPI_Sewing::build(const ListOfShape& theShapes) BRepBuilderAPI_Sewing* aSewingBuilder = new BRepBuilderAPI_Sewing(); this->setImpl(aSewingBuilder); + aSewingBuilder->SetTolerance(theTolerance); + aSewingBuilder->SetFaceMode(Standard_True); + aSewingBuilder->SetFloatingEdgesMode(Standard_False); + aSewingBuilder->SetNonManifoldMode(theAllowNonManifold); + for(ListOfShape::const_iterator anIt = theShapes.cbegin(); anIt != theShapes.cend(); ++anIt) { const TopoDS_Shape& aShape = (*anIt)->impl(); aSewingBuilder->Add(aShape); @@ -49,28 +59,6 @@ void GeomAlgoAPI_Sewing::build(const ListOfShape& theShapes) aSewingBuilder->Perform(); TopoDS_Shape aResult = aSewingBuilder->SewedShape(); - BRep_Builder aBuilder; - if(aResult.ShapeType() == TopAbs_COMPOUND) { - TopoDS_Compound aResultCompound; - aBuilder.MakeCompound(aResultCompound); - for(TopoDS_Iterator anIt(aResult); anIt.More(); anIt.Next()) { - const TopoDS_Shape aSubShape = anIt.Value(); - if(aSubShape.ShapeType() == TopAbs_SHELL) { - aBuilder.Add(aResultCompound, aSubShape); - } else if (aSubShape.ShapeType() == TopAbs_FACE) { - TopoDS_Shell aShell; - aBuilder.MakeShell(aShell); - aBuilder.Add(aShell, aSubShape); - aBuilder.Add(aResultCompound, aShell); - } - } - aResult = aResultCompound; - } else if(aResult.ShapeType() == TopAbs_FACE) { - TopoDS_Shell aShell; - aBuilder.MakeShell(aShell); - aBuilder.Add(aShell, aResult); - aResult = aShell; - } std::shared_ptr aShape(new GeomAPI_Shape()); aShape->setImpl(new TopoDS_Shape(aResult)); diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Sewing.h b/src/GeomAlgoAPI/GeomAlgoAPI_Sewing.h index 4d03762a2..811b6e449 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_Sewing.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Sewing.h @@ -35,6 +35,9 @@ public: /// Constructor. GEOMALGOAPI_EXPORT GeomAlgoAPI_Sewing(const ListOfShape& theShapes); + /// Constructor with additional arguments + GEOMALGOAPI_EXPORT GeomAlgoAPI_Sewing(const ListOfShape& theShapes, const bool theAllowNonManifold, const double theTolerance); + /// \return the list of shapes modified from the shape \a theShape. /// \param[in] theShape base shape. /// \param[out] theHistory modified shapes. @@ -43,7 +46,7 @@ public: private: /// Builds resulting shape. - void build(const ListOfShape& theShapes); + void build(const ListOfShape& theShapes, const bool theAllowNonManifold = false, const double theTolerance = 1.e-6); }; #endif