From 44df74980936150d9db90c15aa6be98264baa3ba Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me?= Date: Wed, 9 Dec 2020 17:10:17 +0100 Subject: [PATCH] #20442 Viusalization of faces found and add tolerance --- .../FeaturesAPI_DuplicatedFaces.cpp | 30 +-- src/FeaturesAPI/FeaturesAPI_DuplicatedFaces.h | 23 ++- src/FeaturesPlugin/CMakeLists.txt | 10 +- .../FeaturesPlugin_CommonDuplicatedFaces.cpp | 136 ++++++++++++++ .../FeaturesPlugin_CommonDuplicatedFaces.h | 66 +++++++ .../FeaturesPlugin_DuplicatedFaces.cpp | 171 ++++++++---------- .../FeaturesPlugin_DuplicatedFaces.h | 47 +++-- .../FeaturesPlugin_GroupDuplicatedFaces.cpp | 135 ++++++++++++++ .../FeaturesPlugin_GroupDuplicatedFaces.h | 115 ++++++++++++ src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp | 3 + ...edFaces.py => TestCheckDuplicatedFaces.py} | 2 +- .../doc/checkDuplicatedFaceFeature.rst | 6 +- .../doc/examples/checkDuplicatedFaces.py | 2 +- .../checkduplicatedFacesPropertyPanel.png | Bin 25209 -> 27797 bytes ....xml => duplicated_faces_macro_widget.xml} | 12 +- .../duplicated_faces_widget.xml | 37 ++++ src/FeaturesPlugin/plugin-Features.xml | 10 +- src/ModelHighAPI/CMakeLists.txt | 3 + 18 files changed, 667 insertions(+), 141 deletions(-) create mode 100644 src/FeaturesPlugin/FeaturesPlugin_CommonDuplicatedFaces.cpp create mode 100644 src/FeaturesPlugin/FeaturesPlugin_CommonDuplicatedFaces.h create mode 100644 src/FeaturesPlugin/FeaturesPlugin_GroupDuplicatedFaces.cpp create mode 100644 src/FeaturesPlugin/FeaturesPlugin_GroupDuplicatedFaces.h rename src/FeaturesPlugin/Test/{TestCheckDuplictedFaces.py => TestCheckDuplicatedFaces.py} (98%) rename src/FeaturesPlugin/{duplicatedFaces_widget.xml => duplicated_faces_macro_widget.xml} (75%) create mode 100644 src/FeaturesPlugin/duplicated_faces_widget.xml diff --git a/src/FeaturesAPI/FeaturesAPI_DuplicatedFaces.cpp b/src/FeaturesAPI/FeaturesAPI_DuplicatedFaces.cpp index 5b86cb56e..4e26e4695 100644 --- a/src/FeaturesAPI/FeaturesAPI_DuplicatedFaces.cpp +++ b/src/FeaturesAPI/FeaturesAPI_DuplicatedFaces.cpp @@ -19,8 +19,8 @@ #include "FeaturesAPI_DuplicatedFaces.h" -#include -#include +#include + #include #include @@ -45,17 +45,17 @@ FeaturesAPI_DuplicatedFaces::~FeaturesAPI_DuplicatedFaces() FeaturesAPI_DuplicatedFaces::FeaturesAPI_DuplicatedFaces( const std::shared_ptr& theFeature, const ModelHighAPI_Selection& theObject, - const double theTransparency, + const ModelHighAPI_Integer& theTransparency, + const ModelHighAPI_Double& theTolerance, const std::string & theNameGroup) :ModelHighAPI_Interface(theFeature) { if (initialize()) { fillAttribute(theObject, myobjectselected); fillAttribute(theTransparency, mytransparency); - if (theNameGroup != "") { - fillAttribute(true,feature()->boolean(FeaturesPlugin_DuplicatedFaces::CREATE_GROUP_ID())); - fillAttribute(theNameGroup, mygroupname); - } + fillAttribute(theTolerance, mytolerance); + fillAttribute(theNameGroup, mygroupname); + execute(); } } @@ -67,31 +67,31 @@ void FeaturesAPI_DuplicatedFaces::dump(ModelHighAPI_Dumper& theDumper) const const std::string& aDocName = theDumper.name(aBase->document()); AttributeSelectionPtr anAttrObject; - anAttrObject = aBase->selection(FeaturesPlugin_DuplicatedFaces::OBJECT_ID()); + anAttrObject = aBase->selection(FeaturesPlugin_GroupDuplicatedFaces::OBJECT_ID()); theDumper << aBase << " = model.getDuplicatedFaces(" << aDocName << ", " << anAttrObject; - theDumper << ", " << aBase->integer(FeaturesPlugin_DuplicatedFaces::TRANSPARENCY_ID()); - - if(aBase->boolean(FeaturesPlugin_DuplicatedFaces::CREATE_GROUP_ID())->value() ) - theDumper << ", " << aBase->string(FeaturesPlugin_DuplicatedFaces::GROUP_NAME_ID()); - + theDumper << ", " << aBase->integer(FeaturesPlugin_GroupDuplicatedFaces::TRANSPARENCY_ID()); + theDumper << ", " << aBase->real(FeaturesPlugin_GroupDuplicatedFaces::TOLERANCE_ID()); + theDumper << ", " << aBase->string(FeaturesPlugin_GroupDuplicatedFaces::GROUP_NAME_ID()); theDumper << ")" << std::endl; } //================================================================================================= DuplicatedFacesPtr getDuplicatedFaces(const std::shared_ptr& thePart, const ModelHighAPI_Selection& theObject, - const double theTransparency, + const ModelHighAPI_Integer& theTransparency, + const ModelHighAPI_Double& theTolerance, const std::string & theNameGroup) { - FeaturePtr aFeature = thePart->addFeature(FeaturesPlugin_DuplicatedFaces::ID()); + FeaturePtr aFeature = thePart->addFeature(FeaturesPlugin_GroupDuplicatedFaces::ID()); DuplicatedFacesPtr aDuplicatedFaces; aDuplicatedFaces.reset(new FeaturesAPI_DuplicatedFaces(aFeature, theObject, theTransparency, + theTolerance, theNameGroup)); return aDuplicatedFaces; diff --git a/src/FeaturesAPI/FeaturesAPI_DuplicatedFaces.h b/src/FeaturesAPI/FeaturesAPI_DuplicatedFaces.h index 4924a0597..12705dbe4 100644 --- a/src/FeaturesAPI/FeaturesAPI_DuplicatedFaces.h +++ b/src/FeaturesAPI/FeaturesAPI_DuplicatedFaces.h @@ -22,9 +22,11 @@ #include "FeaturesAPI.h" -#include "FeaturesPlugin_DuplicatedFaces.h" +#include "FeaturesPlugin_GroupDuplicatedFaces.h" #include +#include +#include #include #include @@ -45,21 +47,25 @@ public: FEATURESAPI_EXPORT explicit FeaturesAPI_DuplicatedFaces(const std::shared_ptr& theFeature, const ModelHighAPI_Selection& theobject, - const double theTransparency, + const ModelHighAPI_Integer& theTransparency, + const ModelHighAPI_Double& theTolerance, const std::string & theNameGroup); /// Destructor. FEATURESAPI_EXPORT virtual ~FeaturesAPI_DuplicatedFaces(); - INTERFACE_3(FeaturesPlugin_DuplicatedFaces::ID(), - objectselected, FeaturesPlugin_DuplicatedFaces::OBJECT_ID(), + INTERFACE_4(FeaturesPlugin_GroupDuplicatedFaces::ID(), + objectselected, FeaturesPlugin_GroupDuplicatedFaces::OBJECT_ID(), ModelAPI_AttributeSelection, /** object selected*/, - transparency, FeaturesPlugin_DuplicatedFaces::TRANSPARENCY_ID(), + transparency, FeaturesPlugin_GroupDuplicatedFaces::TRANSPARENCY_ID(), ModelAPI_AttributeInteger, /** transparency*/, - groupname, FeaturesPlugin_DuplicatedFaces::GROUP_NAME_ID(), + tolerance, FeaturesPlugin_GroupDuplicatedFaces::TOLERANCE_ID(), + ModelAPI_AttributeDouble, + /** tolerance*/, + groupname, FeaturesPlugin_GroupDuplicatedFaces::GROUP_NAME_ID(), ModelAPI_AttributeString, /** group name*/) @@ -79,7 +85,8 @@ typedef std::shared_ptr DuplicatedFacesPtr; FEATURESAPI_EXPORT DuplicatedFacesPtr getDuplicatedFaces(const std::shared_ptr& thePart, const ModelHighAPI_Selection& theObject, - const double theTransparency = 0.0, - const std::string & theNameGroup = ""); + const ModelHighAPI_Integer& theTransparency, + const ModelHighAPI_Double& theTolerance, + const std::string & theNameGroup); #endif // FeaturesAPI_DuplicatedFaces_H_ diff --git a/src/FeaturesPlugin/CMakeLists.txt b/src/FeaturesPlugin/CMakeLists.txt index 39470e1f5..0cf4cabcc 100644 --- a/src/FeaturesPlugin/CMakeLists.txt +++ b/src/FeaturesPlugin/CMakeLists.txt @@ -24,7 +24,6 @@ INCLUDE(UseQtExt) # additional include directories INCLUDE_DIRECTORIES( ${PROJECT_SOURCE_DIR}/src/GeomDataAPI ${PROJECT_SOURCE_DIR}/src/Locale - ${PROJECT_SOURCE_DIR}/src/PrimitivesPlugin ${QT_INCLUDES}) # additional preprocessor / compiler flags @@ -71,6 +70,8 @@ SET(PROJECT_HEADERS FeaturesPlugin_Fillet1D.h FeaturesPlugin_Measurement.h FeaturesPlugin_DuplicatedFaces.h + FeaturesPlugin_CommonDuplicatedFaces.h + FeaturesPlugin_GroupDuplicatedFaces.h FeaturesPlugin_FusionFaces.h FeaturesPlugin_RemoveResults.h FeaturesPlugin_Chamfer.h @@ -119,6 +120,8 @@ SET(PROJECT_SOURCES FeaturesPlugin_Fillet1D.cpp FeaturesPlugin_Measurement.cpp FeaturesPlugin_DuplicatedFaces.cpp + FeaturesPlugin_CommonDuplicatedFaces.cpp + FeaturesPlugin_GroupDuplicatedFaces.cpp FeaturesPlugin_FusionFaces.cpp FeaturesPlugin_RemoveResults.cpp FeaturesPlugin_Chamfer.cpp @@ -157,7 +160,8 @@ SET(XML_RESOURCES fillet_widget.xml fillet1d_widget.xml measurement_widget.xml - duplicatedFaces_widget.xml + duplicated_faces_widget.xml + duplicated_faces_macro_widget.xml fusion_faces_widget.xml chamfer_widget.xml copy_widget.xml @@ -708,5 +712,5 @@ ADD_UNIT_TESTS(TestExtrusion.py TestFillet1D_Wire_3.py TestFillet1D_Wire_4.py TestFillet1D_Wire_5.py - TestCheckDuplictedFaces.py + TestCheckDuplicatedFaces.py ) diff --git a/src/FeaturesPlugin/FeaturesPlugin_CommonDuplicatedFaces.cpp b/src/FeaturesPlugin/FeaturesPlugin_CommonDuplicatedFaces.cpp new file mode 100644 index 000000000..93e7f4a66 --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_CommonDuplicatedFaces.cpp @@ -0,0 +1,136 @@ +// Copyright (C) 2018-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_CommonDuplicatedFaces.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +//================================================================================================= +void explode(const GeomShapePtr& theCompound, ListOfShape& theSubs) +{ + if (theCompound->isCompound() || theCompound->isCompSolid()) { + GeomAPI_ShapeIterator anIt(theCompound); + for (; anIt.more(); anIt.next()) + explode(anIt.current(), theSubs); + } else + theSubs.push_back(theCompound); +} + +//================================================================================================= +void FeaturesPlugin_CommonDuplicatedFaces::updateFaces() +{ + AttributeSelectionPtr ancompSolidAttr = + std::dynamic_pointer_cast(attributObject()); + + AttributeSelectionListPtr aFacesListAttr = + std::dynamic_pointer_cast + (attributListFaces()); + + if (aFacesListAttr->isInitialized()) + aFacesListAttr->clear(); + + AttributeDoublePtr aToleranceAttr = + std::dynamic_pointer_cast + (attributTolerance()); + + GeomShapePtr aShape = ancompSolidAttr->value(); + if (aShape.get() && ancompSolidAttr->context().get() && aToleranceAttr.get()) { + + aShape = ancompSolidAttr->context()->shape(); + if (aShape) { + std::string anError; + ListOfShape aFaces; + ListOfShape theSubs; + explode(aShape, theSubs); + + if (!GetDuplicatedFaces(theSubs, + aToleranceAttr->value(), + aFaces, + anError)) + setError("Error in duplicated faces calculation :" + anError); + + aFacesListAttr->setSelectionType("face"); + + ListOfShape::const_iterator anIt = aFaces.cbegin(); + for (; anIt != aFaces.cend(); ++anIt) { + + GeomShapePtr aFacePtr = *anIt; + + if (!aFacePtr.get()) { + setError("GetDuplicatedFaces : An invalid face found " + anError); + } + aFacesListAttr->append(ancompSolidAttr->context(), aFacePtr); + } + std::stringstream alabel; + alabel << "Number of duplicated faces : " << aFacesListAttr->size(); + AttributeStringPtr aNumberFacesAttr = + std::dynamic_pointer_cast + (attributNumberFaces()); + aNumberFacesAttr->setValue(alabel.str()); + } + } +} + +//================================================================================================= +void FeaturesPlugin_CommonDuplicatedFaces::setFacesGroup(const std::wstring& theName) +{ + std::vector aColor; + ResultGroupPtr aGroup = document()->createGroup(data()); + // clean the result of the operation + aGroup->data()->setName(theName); + aGroup->store(GeomShapePtr()); + + // shapes containing in group + ListOfShape aFaces; + AttributeSelectionListPtr aFacesListAttr = + std::dynamic_pointer_cast + (attributListFaces()); + + for (int anI =0; anI< aFacesListAttr->size(); anI++) { + AttributeSelectionPtr aAtt = aFacesListAttr->value(anI); + aFaces.push_back(aAtt->value()); + } + GeomShapePtr aCompound = GeomAlgoAPI_CompoundBuilder::compound(aFaces); + + aGroup->store(aCompound); + aColor = {255,0,0}; + setResult(aGroup); + ModelAPI_Tools::setColor(lastResult(),aColor); +} + diff --git a/src/FeaturesPlugin/FeaturesPlugin_CommonDuplicatedFaces.h b/src/FeaturesPlugin/FeaturesPlugin_CommonDuplicatedFaces.h new file mode 100644 index 000000000..4333f34c4 --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_CommonDuplicatedFaces.h @@ -0,0 +1,66 @@ +// Copyright (C) 2018-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_CommonDuplicatedFaces_H_ +#define FeaturesPlugin_CommonDuplicatedFaces_H_ + +#include "FeaturesPlugin.h" +#include +#include +#include + +#include +#include + + +/// \class FeaturesPlugin_CommonDuplicatedFaces +/// \ingroup Plugins +/// \brief Feature to check the duplicated faces of solid + +class FeaturesPlugin_CommonDuplicatedFaces : public ModelAPI_Feature +{ +public: + + /// Performs the algorithm and stores results it in the data structure. + FEATURESPLUGIN_EXPORT virtual void execute(){}; + + /// Return Attribut values of result. + virtual AttributePtr attributObject() = 0; + + /// Return Attribut values of result. + virtual AttributePtr attributListFaces() = 0; + + /// Return Attribut values of result. + virtual AttributePtr attributNumberFaces() = 0; + + /// Return Attribut values of tolerance. + virtual AttributePtr attributTolerance() = 0; + + protected: + FeaturesPlugin_CommonDuplicatedFaces() {} + + //Set group of faces + void setFacesGroup(const std::wstring& theName); + + // Update the list of faces + void updateFaces(); + +}; + +#endif diff --git a/src/FeaturesPlugin/FeaturesPlugin_DuplicatedFaces.cpp b/src/FeaturesPlugin/FeaturesPlugin_DuplicatedFaces.cpp index 9442b5553..6a409fee6 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_DuplicatedFaces.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_DuplicatedFaces.cpp @@ -19,10 +19,11 @@ #include "FeaturesPlugin_DuplicatedFaces.h" +#include #include -#include #include #include +#include #include #include #include @@ -36,14 +37,10 @@ #include #include -#include #include -#include -#include #include #include #include -#include //================================================================================================= FeaturesPlugin_DuplicatedFaces::FeaturesPlugin_DuplicatedFaces() @@ -59,48 +56,73 @@ void FeaturesPlugin_DuplicatedFaces::initAttributes() data()->addAttribute(NUMBER_FACES_ID(), ModelAPI_AttributeString::typeId()); data()->addAttribute(TRANSPARENCY_ID(), ModelAPI_AttributeInteger::typeId()); + data()->addAttribute(TOLERANCE_ID(), ModelAPI_AttributeDouble::typeId()); data()->addAttribute(CREATE_GROUP_ID(), ModelAPI_AttributeBoolean::typeId()); data()->addAttribute(GROUP_NAME_ID(), ModelAPI_AttributeString::typeId()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), GROUP_NAME_ID()); - boolean(CREATE_GROUP_ID())->setValue(false); } + //================================================================================================= -void explode(const GeomShapePtr& theCompound, ListOfShape& theSubs) +AttributePtr FeaturesPlugin_DuplicatedFaces::attributObject() { - if (theCompound->isCompound() || theCompound->isCompSolid()) { - GeomAPI_ShapeIterator anIt(theCompound); - for (; anIt.more(); anIt.next()) - explode(anIt.current(), theSubs); - } - else - theSubs.push_back(theCompound); + return attribute(OBJECT_ID()); +} + +//================================================================================================= +AttributePtr FeaturesPlugin_DuplicatedFaces::attributListFaces() +{ + return attribute(LIST_FACES_ID()); +} + +//================================================================================================= +AttributePtr FeaturesPlugin_DuplicatedFaces::attributNumberFaces() +{ + return attribute(NUMBER_FACES_ID()); } +//================================================================================================= +AttributePtr FeaturesPlugin_DuplicatedFaces::attributTolerance() +{ + return attribute(TOLERANCE_ID()); +} + + //================================================================================================= void FeaturesPlugin_DuplicatedFaces::execute() { - if(boolean(CREATE_GROUP_ID())->value() - && selectionList(LIST_FACES_ID())->isInitialized() - && string(GROUP_NAME_ID())->value() != "" ){ + if (boolean(CREATE_GROUP_ID())->value()) { - AttributeStringPtr aNameAtt = string(GROUP_NAME_ID()); - std::wstring aNameFace = aNameAtt->isUValue() ? - Locale::Convert::toWString(aNameAtt->valueU()) : - Locale::Convert::toWString(aNameAtt->value()); + if (string(GROUP_NAME_ID())->value() != "" + && selectionList(LIST_FACES_ID())->isInitialized()) { - if (myGroup.get()) - eraseResults(); - setFacesGroup(aNameFace); + if (lastResult().get()) { + eraseResultFromList(lastResult()); + } - } else { - if (myGroup.get()) { - eraseResults(); - myGroup.reset(); + if (!myCreateGroupFeature.get()) + createGroup(); + updateGroup(); } + } else { + if (selectionList(LIST_FACES_ID())->isInitialized()) { + + if (myCreateGroupFeature.get()) { + myCreateGroupFeature->eraseResults(); + SessionPtr aSession = ModelAPI_Session::get(); + DocumentPtr aDoc = aSession->activeDocument(); + aDoc->removeFeature(myCreateGroupFeature); + myCreateGroupFeature.reset(); + } + + if (lastResult().get()) + eraseResultFromList(lastResult()); + setFacesGroup(L"Group_DuplicatedFaces"); + } } + if (selection(OBJECT_ID())->isInitialized()) { AttributeSelectionPtr ancompSolidAttr = selection(OBJECT_ID()); ResultPtr aResult = ancompSolidAttr->context(); @@ -113,7 +135,7 @@ void FeaturesPlugin_DuplicatedFaces::execute() ModelAPI_Tools::allSubs(aResultBody, allRes); std::list::iterator aRes; for (aRes = allRes.begin(); aRes != allRes.end(); aRes++) { - ModelAPI_Tools::setTransparency(*aRes, aTranparency); + ModelAPI_Tools::setTransparency(*aRes, aTranparency); } } } @@ -121,77 +143,42 @@ void FeaturesPlugin_DuplicatedFaces::execute() //================================================================================================= void FeaturesPlugin_DuplicatedFaces::attributeChanged(const std::string& theID) { - if (theID == OBJECT_ID()) { - AttributeSelectionPtr ancompSolidAttr = selection(OBJECT_ID()); - - GeomShapePtr aShape = ancompSolidAttr->value(); - if (aShape.get() && ancompSolidAttr->context().get()) { - - aShape = ancompSolidAttr->context()->shape(); - if (aShape) { - std::string anError; - ListOfShape aFaces; - ListOfShape theSubs; - explode(aShape, theSubs); + if (theID == OBJECT_ID() + || theID == TOLERANCE_ID()) { - if (!GetDuplicatedFaces(theSubs, - 0.001, - aFaces, - anError)) - setError("Error in duplicated faces calculation :" + anError); - - - AttributeSelectionListPtr aFacesListAttr = - std::dynamic_pointer_cast - (attribute(LIST_FACES_ID())); - - if (aFacesListAttr->isInitialized()) - aFacesListAttr->clear(); - - aFacesListAttr->setSelectionType("face"); + updateFaces(); + if (myCreateGroupFeature.get()) + updateGroup(); + } +} - ListOfShape::const_iterator anIt = aFaces.cbegin(); - for(; anIt != aFaces.cend(); ++anIt) { +//================================================================================================= +void FeaturesPlugin_DuplicatedFaces::createGroup() +{ + SessionPtr aSession = ModelAPI_Session::get(); - GeomShapePtr aFacePtr = *anIt; + DocumentPtr aDoc = aSession->activeDocument(); - if (!aFacePtr.get()) { - setError("GetDuplicatedFaces : An invalid face found " + anError); - } - aFacesListAttr->append( ancompSolidAttr->context(), aFacePtr); - } - std::stringstream alabel; - alabel << "Number of duplicated faces : " << aFacesListAttr->size(); - string(NUMBER_FACES_ID() )->setValue( alabel.str() ); - } - } + if (aDoc.get()) { + myCreateGroupFeature = aDoc->addFeature(FeaturesPlugin_GroupDuplicatedFaces::ID()); } } //================================================================================================= -void FeaturesPlugin_DuplicatedFaces::setFacesGroup(const std::wstring& theName ) +void FeaturesPlugin_DuplicatedFaces::updateGroup() { - std::vector aColor; - myGroup = document()->createGroup(data()); - // clean the result of the operation - myGroup->data()->setName(theName); - myGroup->store(GeomShapePtr()); - - // shapes containing in each group - ListOfShape aFaces; - AttributeSelectionListPtr aFacesListAttr = - std::dynamic_pointer_cast - (attribute(LIST_FACES_ID())); - - for (int anI =0; anI< aFacesListAttr->size(); anI++) { - AttributeSelectionPtr aAtt = aFacesListAttr->value(anI); - aFaces.push_back( aAtt->value() ); - } + myCreateGroupFeature->string(FeaturesPlugin_GroupDuplicatedFaces::GROUP_NAME_ID()) + ->setValue(string(GROUP_NAME_ID())->value()); - GeomShapePtr aCompound = GeomAlgoAPI_CompoundBuilder::compound(aFaces); - myGroup->store(aCompound); - aColor = {255,0,0}; - setResult(myGroup); - ModelAPI_Tools::setColor( lastResult(),aColor); -} + myCreateGroupFeature->selection(FeaturesPlugin_GroupDuplicatedFaces::OBJECT_ID()) + ->setValue(selection(OBJECT_ID())->context() , + selection(OBJECT_ID())->value()); + + myCreateGroupFeature->integer(FeaturesPlugin_GroupDuplicatedFaces::TRANSPARENCY_ID()) + ->setValue(integer(TRANSPARENCY_ID())->value()); + + myCreateGroupFeature->real(FeaturesPlugin_GroupDuplicatedFaces::TOLERANCE_ID()) + ->setValue(real(TOLERANCE_ID())->value()); + myCreateGroupFeature->execute(); +} \ No newline at end of file diff --git a/src/FeaturesPlugin/FeaturesPlugin_DuplicatedFaces.h b/src/FeaturesPlugin/FeaturesPlugin_DuplicatedFaces.h index 490208992..61c753058 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_DuplicatedFaces.h +++ b/src/FeaturesPlugin/FeaturesPlugin_DuplicatedFaces.h @@ -20,24 +20,18 @@ #ifndef FeaturesPlugin_DuplicatedFaces_H_ #define FeaturesPlugin_DuplicatedFaces_H_ -#include "FeaturesPlugin.h" -#include -#include - -#include -#include -#include +#include /// \class FeaturesPlugin_DuplicatedFaces /// \ingroup Plugins /// \brief Feature to check the duplicated faces of solid -class FeaturesPlugin_DuplicatedFaces : public ModelAPI_Feature +class FeaturesPlugin_DuplicatedFaces : public FeaturesPlugin_CommonDuplicatedFaces { public: inline static const std::string& ID() { - static const std::string MY_ID("Duplicated_faces"); + static const std::string MY_ID("Duplicated_faces_macro"); return MY_ID; } @@ -68,13 +62,20 @@ public: return MY_LIST_FACES_ID; } - /// Attribute name for transparency. + /// Attribute name for transparency. inline static const std::string& TRANSPARENCY_ID() { static const std::string MY_TRANSPARENCY_ID("transparency"); return MY_TRANSPARENCY_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 checkbox create group. inline static const std::string& CREATE_GROUP_ID() { @@ -99,14 +100,34 @@ public: /// \param theID identifier of changed attribute FEATURESPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID); + /// Reimplemented from ModelAPI_Feature::isMacro(). Returns true. + FEATURESPLUGIN_EXPORT virtual bool isMacro() const { return true; } + /// Use plugin manager for features creation FeaturesPlugin_DuplicatedFaces(); private: - //Set group of faces - void setFacesGroup(const std::wstring& theName ); - ResultGroupPtr myGroup; + /// Return Attribut values of object. + virtual AttributePtr attributObject(); + + /// Return Attribut values of list of faces. + virtual AttributePtr attributListFaces(); + + /// Return Attribut values of number of faces. + virtual AttributePtr attributNumberFaces(); + + /// Return Attribut values of tolerance. + virtual AttributePtr attributTolerance(); + + /// Create group + void createGroup(); + + /// Update group + void updateGroup(); + + /// Feature to create group + FeaturePtr myCreateGroupFeature; }; #endif diff --git a/src/FeaturesPlugin/FeaturesPlugin_GroupDuplicatedFaces.cpp b/src/FeaturesPlugin/FeaturesPlugin_GroupDuplicatedFaces.cpp new file mode 100644 index 000000000..147ab3abf --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_GroupDuplicatedFaces.cpp @@ -0,0 +1,135 @@ +// Copyright (C) 2018-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_GroupDuplicatedFaces.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +//================================================================================================= +FeaturesPlugin_GroupDuplicatedFaces::FeaturesPlugin_GroupDuplicatedFaces() +{ +} + +//================================================================================================= +void FeaturesPlugin_GroupDuplicatedFaces::initAttributes() +{ + // attribute for object selected + data()->addAttribute(OBJECT_ID(), ModelAPI_AttributeSelection::typeId()); + AttributeSelectionListPtr aList = std::dynamic_pointer_cast( + data()->addAttribute(LIST_FACES_ID(), ModelAPI_AttributeSelectionList::typeId())); + + data()->addAttribute(NUMBER_FACES_ID(), ModelAPI_AttributeString::typeId()); + data()->addAttribute(TRANSPARENCY_ID(), ModelAPI_AttributeInteger::typeId()); + data()->addAttribute(TOLERANCE_ID(), ModelAPI_AttributeDouble::typeId()); + data()->addAttribute(GROUP_NAME_ID(), ModelAPI_AttributeString::typeId()); + +} + + +//================================================================================================= +AttributePtr FeaturesPlugin_GroupDuplicatedFaces::attributObject() +{ + return attribute(OBJECT_ID()); +} + +//================================================================================================= +AttributePtr FeaturesPlugin_GroupDuplicatedFaces::attributListFaces() +{ + return attribute(LIST_FACES_ID()); +} + +//================================================================================================= +AttributePtr FeaturesPlugin_GroupDuplicatedFaces::attributNumberFaces() +{ + return attribute(NUMBER_FACES_ID()); +} + +//================================================================================================= +AttributePtr FeaturesPlugin_GroupDuplicatedFaces::attributTolerance() +{ + return attribute(TOLERANCE_ID()); +} + +//================================================================================================= +void FeaturesPlugin_GroupDuplicatedFaces::execute() +{ + if (selectionList(LIST_FACES_ID())->isInitialized() + && string(GROUP_NAME_ID())->value() != "") { + AttributeStringPtr aNameAtt = string(GROUP_NAME_ID()) ; + std::wstring aNameFace = aNameAtt->isUValue() ? + Locale::Convert::toWString(aNameAtt->valueU()) : + Locale::Convert::toWString(aNameAtt->value()); + + if (lastResult().get()) + eraseResultFromList(lastResult()); + setFacesGroup(aNameFace); + + } else { + if (lastResult().get()) { + eraseResultFromList(lastResult()); + } + + } + if (selection(OBJECT_ID())->isInitialized()) { + AttributeSelectionPtr ancompSolidAttr = selection(OBJECT_ID()); + ResultPtr aResult = ancompSolidAttr->context(); + + double aTranparency = integer(TRANSPARENCY_ID())->value()/100.0; + ModelAPI_Tools::setTransparency(aResult, aTranparency); + + ResultBodyPtr aResultBody = std::dynamic_pointer_cast(aResult); + std::list allRes; + ModelAPI_Tools::allSubs(aResultBody, allRes); + std::list::iterator aRes; + for(aRes = allRes.begin(); aRes != allRes.end(); aRes++) { + ModelAPI_Tools::setTransparency(*aRes, aTranparency); + } + } +} + +//================================================================================================= +void FeaturesPlugin_GroupDuplicatedFaces::attributeChanged(const std::string& theID) +{ + if (theID == OBJECT_ID() + || theID == TOLERANCE_ID()) { + updateFaces(); + } +} \ No newline at end of file diff --git a/src/FeaturesPlugin/FeaturesPlugin_GroupDuplicatedFaces.h b/src/FeaturesPlugin/FeaturesPlugin_GroupDuplicatedFaces.h new file mode 100644 index 000000000..583b770ec --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_GroupDuplicatedFaces.h @@ -0,0 +1,115 @@ +// Copyright (C) 2018-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_GroupDuplicatedFaces_H_ +#define FeaturesPlugin_GroupDuplicatedFaces_H_ + +#include + +/// \class FeaturesPlugin_GroupDuplicatedFaces +/// \ingroup Plugins +/// \brief Feature to check the duplicated faces of solid + +class FeaturesPlugin_GroupDuplicatedFaces : public FeaturesPlugin_CommonDuplicatedFaces +{ +public: + inline static const std::string& ID() + { + static const std::string MY_ID("Duplicated_faces"); + return MY_ID; + } + + /// \return the kind of a feature. + virtual const std::string& getKind() + { + return ID(); + } + + /// Attribute name for object selected. + inline static const std::string& OBJECT_ID() + { + static const std::string MY_OBJECT_ID("main_object"); + return MY_OBJECT_ID; + } + + /// Attribute name for number of faces. + inline static const std::string& NUMBER_FACES_ID() + { + static const std::string MY_NUMBER_FACES_ID("number_duplicated_faces"); + return MY_NUMBER_FACES_ID; + } + + /// Attribute name for z coodinate. + inline static const std::string& LIST_FACES_ID() + { + static const std::string MY_LIST_FACES_ID("faces"); + return MY_LIST_FACES_ID; + } + + /// Attribute name for transparency. + inline static const std::string& TRANSPARENCY_ID() + { + static const std::string MY_TRANSPARENCY_ID("transparency"); + return MY_TRANSPARENCY_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 group name. + inline static const std::string& GROUP_NAME_ID() + { + static const std::string MY_GROUP_NAME_ID("group_name"); + return MY_GROUP_NAME_ID; + } + + /// 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(); + + /// Called on change of any argument-attribute of this object + /// \param theID identifier of changed attribute + FEATURESPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID); + + /// Use plugin manager for features creation + FeaturesPlugin_GroupDuplicatedFaces(); + + private: + + /// Return Attribut values of object. + virtual AttributePtr attributObject(); + + /// Return Attribut values of list of faces. + virtual AttributePtr attributListFaces(); + + /// Return Attribut values of number of faces. + virtual AttributePtr attributNumberFaces(); + + /// Return Attribut values of tolerance. + virtual AttributePtr attributTolerance(); + +}; + +#endif diff --git a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp index 5914a064c..02914017e 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -190,6 +191,8 @@ FeaturePtr FeaturesPlugin_Plugin::createFeature(std::string theFeatureID) return FeaturePtr(new FeaturesPlugin_Measurement); } else if (theFeatureID == FeaturesPlugin_DuplicatedFaces::ID()) { return FeaturePtr(new FeaturesPlugin_DuplicatedFaces); + } else if (theFeatureID == FeaturesPlugin_GroupDuplicatedFaces::ID()) { + return FeaturePtr(new FeaturesPlugin_GroupDuplicatedFaces); } else if (theFeatureID == FeaturesPlugin_RemoveResults::ID()) { return FeaturePtr(new FeaturesPlugin_RemoveResults); } else if (theFeatureID == FeaturesPlugin_Chamfer::ID()) { diff --git a/src/FeaturesPlugin/Test/TestCheckDuplictedFaces.py b/src/FeaturesPlugin/Test/TestCheckDuplicatedFaces.py similarity index 98% rename from src/FeaturesPlugin/Test/TestCheckDuplictedFaces.py rename to src/FeaturesPlugin/Test/TestCheckDuplicatedFaces.py index 50b8e44f4..6c08bcb45 100644 --- a/src/FeaturesPlugin/Test/TestCheckDuplictedFaces.py +++ b/src/FeaturesPlugin/Test/TestCheckDuplicatedFaces.py @@ -60,7 +60,7 @@ if __name__ == '__main__': model.selection("SOLID", "Box_3_1")] Compound_1 = model.addCompound(Part_1_doc, Compound_1_objects) ### Create Duplicated_faces - Duplicated_faces_1 = model.getDuplicatedFaces(Part_1_doc, model.selection("COMPOUND", "Compound_1_1"), 50, "mygroup") + Duplicated_faces_1 = model.getDuplicatedFaces(Part_1_doc, model.selection("COMPOUND", "Compound_1_1"), 50, 0.001, "mygroup") model.do() # Check results diff --git a/src/FeaturesPlugin/doc/checkDuplicatedFaceFeature.rst b/src/FeaturesPlugin/doc/checkDuplicatedFaceFeature.rst index aba107ea5..181b1682f 100644 --- a/src/FeaturesPlugin/doc/checkDuplicatedFaceFeature.rst +++ b/src/FeaturesPlugin/doc/checkDuplicatedFaceFeature.rst @@ -26,17 +26,19 @@ Input fields: - **Number of duplicated faces** indicate the number of found faces. - **List of faces** the list of found faces. - **Transparency** set the transparency of selected object. +- **Tolerance** set the tolerance for the algotithme. - **Create group** check-box allow the creation of the group of found faces. - **Group name** specified the name of the group created. **TUI Command**: -.. py:function:: model.getDuplicatedFaces(Part_doc, shape, transparency, nameGroup) +.. py:function:: model.getDuplicatedFaces(Part_doc, shape, transparency, tolerance, nameGroup) :param part: The current part object. :param object: A composolid or compound in format *model.selection("Type", shape)*. - :param number: value for the transparency. + :param number: value of the transparency. + :param number: value of the tolerance. :param string: name of group created. :return: Created group. diff --git a/src/FeaturesPlugin/doc/examples/checkDuplicatedFaces.py b/src/FeaturesPlugin/doc/examples/checkDuplicatedFaces.py index 1ccb4cb88..40be3117c 100644 --- a/src/FeaturesPlugin/doc/examples/checkDuplicatedFaces.py +++ b/src/FeaturesPlugin/doc/examples/checkDuplicatedFaces.py @@ -23,7 +23,7 @@ Compound_1_objects = [model.selection("SOLID", "Box_1_1"), model.selection("SOLID", "Box_3_1")] Compound_1 = model.addCompound(Part_1_doc, Compound_1_objects) ### Create Duplicated_faces -Duplicated_faces_1 = model.getDuplicatedFaces(Part_1_doc, model.selection("COMPOUND", "Compound_1_1"), 50, "mygroup") +Duplicated_faces_1 = model.getDuplicatedFaces(Part_1_doc, model.selection("COMPOUND", "Compound_1_1"), 50, 0.001, "mygroup") model.do() model.end() diff --git a/src/FeaturesPlugin/doc/images/checkduplicatedFacesPropertyPanel.png b/src/FeaturesPlugin/doc/images/checkduplicatedFacesPropertyPanel.png index 48700f68abf4a83800a308532faafd938527a39f..439d7508943ca8905214eb31b90592f4d93ae295 100644 GIT binary patch literal 27797 zcmbq)bC4%Z*Jby#ZQHipJ=3;r+qP}n=Cs|vY1{U+ZF~E9zkN5pjc*YfTM-qRmAF}d zWYxX*oRbmqvSM)1*w8>gKyVV`!iqpZz#!juEhPANOR|#D+jjx#^ix6^^850JG!FlM z#&Q->cUH19b#^mwGyyWRwX-pyb24%?F|l5dujF3n{y2pKrQ(PcDD` zxmm`;;_!m`NtzJ6G7#M@snGaXDN~_Q#9o8WW~mfeSTdw`f!%DTe1S*|Ni6E>_|y#$ zAZ1F_=716?I(l*6pOw5ky5q`ox;pZi=E|GqvXhWB%tjJI{Jh)8Za&pX6G9Ar^1s)? z5d1EKAi)C(frv371LH+=pL9qaDu3ySa;%N@*n-uMyuky{2-6pC9i^pvnKPlCJGRs? zxeDYheMB%keMu;_b`9{5)I(^>JE;xzafUrmbZJ$o){ql3Gp_^QUY=*Vy;?b1bhz&V z0~AE|r@*{B&0)l9H%JtAqvb+gov~RHdzx(~)&_?K54AITi=cOnQo?d5`=3j7?VJU! zj6@@((;Rb82)-tRA0&rxJNk}Zwgsy(KJ{ueo3ZNx!DMus-kvVZ7AqGSy2)GDyGNqy zWatzC52dr$AZ;!m5g$i&PH*q@=za?6*AHgli`~8m1TYmkOqwlKabX9Y^b(KG5=f*P zuSkC>fAoe?5;G^h!kwDEdwunMMCWl*?U{X77VP8&lwb&bI#Gt>SbTSj(>~dKcS&V& z1#%Bu89Z$m8OgIvZlmu&Wwb`!E@*Zyss(qH;~ixnSo|bVc<1?@Iw&AsYIPt*x}y}U zcOcof=1VVx|W~3Gxb`RV=21b7sxwp6a>=hi>r7kx~8A>?Fo~9^u~dPW7mQ z6LG9w5w&d)aW2bQFcjay0i{hv*?vHu2U$$+A2!M-a&nmXjTiIKto(>#uXTw(JC#Z= zB`+=WT*NGs?WQ**x?id-P<~P`myK`8?>=bYl3TJhkGmZ>&o%m46+YeSw7!DApq0oA zGCn|j_WHoZd∾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 T7yvsv;*Fe?l4Pa0aqxcw-#8>2 diff --git a/src/FeaturesPlugin/duplicatedFaces_widget.xml b/src/FeaturesPlugin/duplicated_faces_macro_widget.xml similarity index 75% rename from src/FeaturesPlugin/duplicatedFaces_widget.xml rename to src/FeaturesPlugin/duplicated_faces_macro_widget.xml index c3a8c5bde..4b94b1109 100644 --- a/src/FeaturesPlugin/duplicatedFaces_widget.xml +++ b/src/FeaturesPlugin/duplicated_faces_macro_widget.xml @@ -11,13 +11,13 @@ + +