From 78205c43afb89dee242a940236c22000df5af987 Mon Sep 17 00:00:00 2001 From: dbv Date: Thu, 26 May 2016 16:26:10 +0300 Subject: [PATCH] Issue #1366: Remove Sub-Shapes feature added. --- src/BuildPlugin/BuildPlugin_SubShapes.cpp | 5 +- src/FeaturesPlugin/CMakeLists.txt | 3 + src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp | 7 + .../FeaturesPlugin_RemoveSubShapes.cpp | 113 ++++++++++ .../FeaturesPlugin_RemoveSubShapes.h | 62 ++++++ .../FeaturesPlugin_Validators.cpp | 209 ++++++++++++++---- .../FeaturesPlugin_Validators.h | 36 ++- src/FeaturesPlugin/icons/remove_subshapes.png | Bin 0 -> 608 bytes src/FeaturesPlugin/plugin-Features.xml | 3 + .../remove_subshapes_widget.xml | 20 ++ src/GeomAlgoAPI/GeomAlgoAPI_ShapeBuilder.cpp | 4 +- src/GeomAlgoAPI/GeomAlgoAPI_ShapeBuilder.h | 6 +- src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp | 12 + src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h | 4 + .../GeomValidators_BodyShapes.cpp | 38 ++-- .../GeomValidators_ShapeType.cpp | 25 ++- src/GeomValidators/GeomValidators_ShapeType.h | 1 + src/Model/Model_SelectionNaming.cpp | 61 +++-- src/ModuleBase/ModuleBase_Tools.cpp | 37 ++-- 19 files changed, 527 insertions(+), 119 deletions(-) create mode 100644 src/FeaturesPlugin/FeaturesPlugin_RemoveSubShapes.cpp create mode 100644 src/FeaturesPlugin/FeaturesPlugin_RemoveSubShapes.h create mode 100644 src/FeaturesPlugin/icons/remove_subshapes.png create mode 100644 src/FeaturesPlugin/remove_subshapes_widget.xml diff --git a/src/BuildPlugin/BuildPlugin_SubShapes.cpp b/src/BuildPlugin/BuildPlugin_SubShapes.cpp index 000fb19e3..ebbe753ba 100644 --- a/src/BuildPlugin/BuildPlugin_SubShapes.cpp +++ b/src/BuildPlugin/BuildPlugin_SubShapes.cpp @@ -42,10 +42,11 @@ void BuildPlugin_SubShapes::attributeChanged(const std::string& theID) if(!aShapeAttrSelection.get() || !aSubShapesAttrList.get()) { return; } - ResultPtr aContext = aShapeAttrSelection->context(); aSubShapesAttrList->clear(); + ResultPtr aContext = aShapeAttrSelection->context(); + GeomShapePtr aBaseShape = aShapeAttrSelection->value(); if(!aBaseShape.get()) { return; @@ -103,7 +104,7 @@ void BuildPlugin_SubShapes::execute() // Copy sub-shapes from list to new shape. if(!aShapesToAdd.empty()) { - aBuilder.add(aResultShape, aShapesToAdd); + aBuilder.addInternal(aResultShape, aShapesToAdd); aResultShape = aBuilder.shape(); } diff --git a/src/FeaturesPlugin/CMakeLists.txt b/src/FeaturesPlugin/CMakeLists.txt index a58b83a39..bb7849f33 100644 --- a/src/FeaturesPlugin/CMakeLists.txt +++ b/src/FeaturesPlugin/CMakeLists.txt @@ -26,6 +26,7 @@ SET(PROJECT_HEADERS FeaturesPlugin_RevolutionFuse.h FeaturesPlugin_ValidatorTransform.h FeaturesPlugin_Validators.h + FeaturesPlugin_RemoveSubShapes.h ) SET(PROJECT_SOURCES @@ -50,6 +51,7 @@ SET(PROJECT_SOURCES FeaturesPlugin_RevolutionFuse.cpp FeaturesPlugin_ValidatorTransform.cpp FeaturesPlugin_Validators.cpp + FeaturesPlugin_RemoveSubShapes.cpp ) SET(XML_RESOURCES @@ -68,6 +70,7 @@ SET(XML_RESOURCES placement_widget.xml intersection_widget.xml pipe_widget.xml + remove_subshapes_widget.xml ) INCLUDE_DIRECTORIES( diff --git a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp index 75ee7ff66..d6fa48f3d 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +49,10 @@ FeaturesPlugin_Plugin::FeaturesPlugin_Plugin() new FeaturesPlugin_ValidatorBooleanSelection); aFactory->registerValidator("FeaturesPlugin_ValidatorPartitionSelection", new FeaturesPlugin_ValidatorPartitionSelection); + aFactory->registerValidator("FeaturesPlugin_ValidatorRemoveSubShapesSelection", + new FeaturesPlugin_ValidatorRemoveSubShapesSelection); + aFactory->registerValidator("FeaturesPlugin_ValidatorRemoveSubShapesResult", + new FeaturesPlugin_ValidatorRemoveSubShapesResult); // register this plugin ModelAPI_Session::get()->registerPlugin(this); @@ -83,6 +88,8 @@ FeaturePtr FeaturesPlugin_Plugin::createFeature(string theFeatureID) return FeaturePtr(new FeaturesPlugin_RevolutionCut); } else if (theFeatureID == FeaturesPlugin_RevolutionFuse::ID()) { return FeaturePtr(new FeaturesPlugin_RevolutionFuse); + } else if (theFeatureID == FeaturesPlugin_RemoveSubShapes::ID()) { + return FeaturePtr(new FeaturesPlugin_RemoveSubShapes); } // feature of such kind is not found diff --git a/src/FeaturesPlugin/FeaturesPlugin_RemoveSubShapes.cpp b/src/FeaturesPlugin/FeaturesPlugin_RemoveSubShapes.cpp new file mode 100644 index 000000000..84541fcd1 --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_RemoveSubShapes.cpp @@ -0,0 +1,113 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: FeaturesPlugin_RemoveSubShapes.cpp +// Created: 14 April 2016 +// Author: Dmitry Bobylev + +#include "FeaturesPlugin_RemoveSubShapes.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +//================================================================================================== +FeaturesPlugin_RemoveSubShapes::FeaturesPlugin_RemoveSubShapes() +{ +} + +//================================================================================================== +void FeaturesPlugin_RemoveSubShapes::initAttributes() +{ + data()->addAttribute(BASE_SHAPE_ID(), ModelAPI_AttributeSelection::typeId()); + + data()->addAttribute(SUBSHAPES_ID(), ModelAPI_AttributeSelectionList::typeId()); +} + +void FeaturesPlugin_RemoveSubShapes::attributeChanged(const std::string& theID) +{ + ModelAPI_Feature::attributeChanged(theID); + + if(theID == BASE_SHAPE_ID()) { + AttributeSelectionPtr aShapeAttrSelection = selection(BASE_SHAPE_ID()); + AttributeSelectionListPtr aSubShapesAttrList = selectionList(SUBSHAPES_ID()); + if(!aShapeAttrSelection.get() || !aSubShapesAttrList.get()) { + return; + } + + aSubShapesAttrList->clear(); + + ResultPtr aContext = aShapeAttrSelection->context(); + ResultCompSolidPtr aResultCompSolid = std::dynamic_pointer_cast(aContext); + if(!aResultCompSolid.get()) { + return; + } + + GeomShapePtr aBaseShape = aShapeAttrSelection->value(); + if(!aBaseShape.get()) { + aBaseShape = aContext->shape(); + } + if(!aBaseShape.get()) { + return; + } + GeomAPI_Shape::ShapeType aShapeType = aBaseShape->shapeType(); + if(aShapeType != GeomAPI_Shape::WIRE + && aShapeType != GeomAPI_Shape::SHELL + && aShapeType != GeomAPI_Shape::COMPSOLID + && aShapeType != GeomAPI_Shape::COMPOUND) { + return; + } + for(GeomAPI_ShapeIterator anIt(aBaseShape); anIt.more(); anIt.next()) { + GeomShapePtr aSubShape = anIt.current(); + const int aNumOfSubs = aResultCompSolid->numberOfSubs(); + if(aNumOfSubs == 0) { + aSubShapesAttrList->append(aContext, aSubShape); + } else { + for(int anIndex = 0; anIndex < aResultCompSolid->numberOfSubs(); ++anIndex) { + ResultBodyPtr aSubResult = aResultCompSolid->subResult(anIndex); + if(aSubResult->shape()->isEqual(aSubShape)) { + aSubShapesAttrList->append(aSubResult, aSubShape); + break; + } + } + } + } + } +} + +//================================================================================================== +void FeaturesPlugin_RemoveSubShapes::execute() +{ + // Get base shape and sub-shapes list. + AttributeSelectionPtr aShapeAttrSelection = selection(BASE_SHAPE_ID()); + AttributeSelectionListPtr aSubShapesAttrList = selectionList(SUBSHAPES_ID()); + if(!aShapeAttrSelection.get() || !aSubShapesAttrList.get()) { + return; + } + + // Copy base shape. + GeomShapePtr aBaseShape = aShapeAttrSelection->value(); + if(!aBaseShape.get()) { + return; + } + GeomShapePtr aResultShape = aBaseShape->emptyCopied(); + + // Copy sub-shapes from list to new shape. + for(int anIndex = 0; anIndex < aSubShapesAttrList->size(); ++anIndex) { + AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex); + GeomShapePtr aShapeToAdd = anAttrSelectionInList->value(); + GeomAlgoAPI_ShapeBuilder::add(aResultShape, aShapeToAdd); + } + + // Store result. + ResultBodyPtr aResultBody = document()->createBody(data()); + aResultBody->storeModified(aBaseShape, aResultShape); + setResult(aResultBody); +} diff --git a/src/FeaturesPlugin/FeaturesPlugin_RemoveSubShapes.h b/src/FeaturesPlugin/FeaturesPlugin_RemoveSubShapes.h new file mode 100644 index 000000000..b5e1158a9 --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_RemoveSubShapes.h @@ -0,0 +1,62 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: FeaturesPlugin_RemoveSubShapes.h +// Created: 23 May 2016 +// Author: Dmitry Bobylev + +#ifndef FeaturesPlugin_RemoveSubShapes_H_ +#define FeaturesPlugin_RemoveSubShapes_H_ + +#include "FeaturesPlugin.h" + +#include + +/// \class FeaturesPlugin_RemoveSubShapes +/// \ingroup Plugins +/// \brief Feature for removing sub-shapes from collections(wire, shell, compsolid, compound). +class FeaturesPlugin_RemoveSubShapes: public ModelAPI_Feature +{ +public: + /// Use plugin manager for features creation + FeaturesPlugin_RemoveSubShapes(); + + /// Feature kind. + inline static const std::string& ID() + { + static const std::string MY_ID("Remove_SubShapes"); + return MY_ID; + } + + /// Attribute name of base shape. + inline static const std::string& BASE_SHAPE_ID() + { + static const std::string MY_BASE_SHAPE_ID("base_shape"); + return MY_BASE_SHAPE_ID; + } + + /// Attribute name of sub-shapes. + inline static const std::string& SUBSHAPES_ID() + { + static const std::string MY_SUBSHAPES_ID("subshapes"); + return MY_SUBSHAPES_ID; + } + + /// \return the kind of a feature. + FEATURESPLUGIN_EXPORT virtual const std::string& getKind() + { + static std::string MY_KIND = FeaturesPlugin_RemoveSubShapes::ID(); + return MY_KIND; + } + + /// 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[in] theID identifier of changed attribute. + FEATURESPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID); + + /// Creates a new part document if needed. + FEATURESPLUGIN_EXPORT virtual void execute(); +}; + +#endif diff --git a/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp b/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp index b451667ac..1aee44fa6 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp @@ -23,6 +23,10 @@ #include #include #include +#include + +#include +#include #include //================================================================================================== @@ -35,13 +39,13 @@ bool FeaturesPlugin_ValidatorPipeLocations::isValid(const std::shared_ptrgetKind() != "Pipe") { - theError = "Feature \"" + theFeature->getKind() + "\" does not supported by this validator."; + theError = "Error: Feature \"" + theFeature->getKind() + "\" does not supported by this validator."; return false; } AttributeStringPtr aCreationMethodAttr = theFeature->string(aCreationMethodID); if(!aCreationMethodAttr.get()) { - theError = "Could not get \"" + aCreationMethodID + "\" attribute."; + theError = "Error: Could not get \"" + aCreationMethodID + "\" attribute."; return false; } @@ -51,18 +55,18 @@ bool FeaturesPlugin_ValidatorPipeLocations::isValid(const std::shared_ptrselectionList(aBaseObjectsID); if(!aBaseObjectsSelectionList.get()) { - theError = "Could not get \"" + aBaseObjectsID + "\" attribute."; + theError = "Error: Could not get \"" + aBaseObjectsID + "\" attribute."; return false; } AttributeSelectionListPtr aLocationsSelectionList = theFeature->selectionList(aLocationsID); if(!aLocationsSelectionList.get()) { - theError = "Could not get \"" + aBaseObjectsID + "\" attribute."; + theError = "Error: Could not get \"" + aBaseObjectsID + "\" attribute."; return false; } if(aLocationsSelectionList->size() > 0 && aLocationsSelectionList->size() != aBaseObjectsSelectionList->size()) { - theError = "Number of locations should be the same as base objects."; + theError = "Error: Number of locations should be the same as base objects."; return false; } @@ -81,14 +85,14 @@ bool FeaturesPlugin_ValidatorBaseForGeneration::isValid(const AttributePtr& theA std::string& theError) const { if(theArguments.empty()) { - theError = "Validator parameters is empty."; + theError = "Error: Validator parameters is empty."; return false; } // Checking attribute. if(!isValidAttribute(theAttribute, theArguments, theError)) { if(theError.empty()) { - theError = "Attribute contains unacceptable shape."; + theError = "Error: Attribute contains unacceptable shape."; } return false; } @@ -112,7 +116,7 @@ bool FeaturesPlugin_ValidatorBaseForGeneration::isValid(const AttributePtr& theA if(!aShape.get()) { // Whole sketch selected. if(aSelectedSketchesFromObjects.find(aContext) != aSelectedSketchesFromObjects.cend()) { - theError = "Object from this sketch is already selected. Sketch is not allowed for selection."; + theError = "Error: Object from this sketch is already selected. Sketch is not allowed for selection."; return false; } @@ -120,19 +124,19 @@ bool FeaturesPlugin_ValidatorBaseForGeneration::isValid(const AttributePtr& theA } else { // Object from sketch selected. if(aSelectedSketches.find(aContext) != aSelectedSketches.cend()) { - theError = "Whole sketch with this object is already selected. Don't allow to select this object."; + theError = "Error: Whole sketch with this object is already selected. Don't allow to select this object."; return false; } for(GeomAPI_ShapeExplorer anExp(aShape, GeomAPI_Shape::WIRE); anExp.more(); anExp.next()) { GeomShapePtr aWire = anExp.current(); if(aWire->orientation() != GeomAPI_Shape::FORWARD) { - theError = "Wire with wrong orientation selected."; + theError = "Error: Wire with wrong orientation selected."; return false; } if(aSelectedWiresFromObjects.isBound(aWire)) { - theError = "Objects with such wire already selected. Don't allow to select this object."; + theError = "Error: Objects with such wire already selected. Don't allow to select this object."; return false; } @@ -152,7 +156,7 @@ bool FeaturesPlugin_ValidatorBaseForGeneration::isValidAttribute(const Attribute std::string& theError) const { if(!theAttribute.get()) { - theError = "Empty attribute."; + theError = "Error: Empty attribute."; return false; } @@ -170,7 +174,7 @@ bool FeaturesPlugin_ValidatorBaseForGeneration::isValidAttribute(const Attribute AttributeSelectionPtr anAttr = std::dynamic_pointer_cast(theAttribute); ResultPtr aContext = anAttr->context(); if(!aContext.get()) { - theError = "Attribute have empty context."; + theError = "Error: Attribute have empty context."; return false; } @@ -180,7 +184,7 @@ bool FeaturesPlugin_ValidatorBaseForGeneration::isValidAttribute(const Attribute aShape = aContextShape; } if(!aShape.get()) { - theError = "Empty shape selected"; + theError = "Error: Empty shape selected"; return false; } @@ -188,7 +192,7 @@ bool FeaturesPlugin_ValidatorBaseForGeneration::isValidAttribute(const Attribute if(aConstruction.get()) { // Construciotn selected. Check that is is not infinite. if(aConstruction->isInfinite()) { - theError = "Infinite constructions is not allowed as base."; + theError = "Error: Infinite constructions is not allowed as base."; return false; } @@ -209,14 +213,14 @@ bool FeaturesPlugin_ValidatorBaseForGeneration::isValidAttribute(const Attribute if(!aShape->isEqual(aContextShape)) { // Local selection on body does not allowed. - theError = "Selected shape is in the local selection. Only global selection is allowed."; + theError = "Error: Selected shape is in the local selection. Only global selection is allowed."; return false; } // Check that object is a shape with allowed type. GeomValidators_ShapeType aShapeTypeValidator; if(!aShapeTypeValidator.isValid(anAttr, theArguments, theError)) { - theError = "Selected shape has unacceptable type. Acceptable types are: faces or wires on sketch, " + theError = "Error: Selected shape has unacceptable type. Acceptable types are: faces or wires on sketch, " "whole sketch(if it has at least one face), and whole objects with shape types: "; std::list::const_iterator anIt = theArguments.cbegin(); theError += *anIt; @@ -227,7 +231,7 @@ bool FeaturesPlugin_ValidatorBaseForGeneration::isValidAttribute(const Attribute } } else { - theError = "Following attribute does not supported: " + anAttributeType + "."; + theError = "Error: Attribute \"" + anAttributeType + "\" does not supported by this validator."; return false; } @@ -240,11 +244,11 @@ bool FeaturesPlugin_ValidatorCompositeLauncher::isValid(const AttributePtr& theA std::string& theError) const { if (theAttribute->attributeType() != ModelAPI_AttributeReference::typeId()) { - theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed"; + theError = "Error: The attribute with the " + theAttribute->attributeType() + " type is not processed"; return false; } if (theArguments.size() != 2) { - theError = "Wrong parameters in XML definition for " + theAttribute->attributeType() + " type"; + theError = "Error: Wrong parameters in XML definition for " + theAttribute->attributeType() + " type"; return false; } // first argument is for the base attribute, second - for skipping feature kind @@ -285,7 +289,7 @@ bool FeaturesPlugin_ValidatorCanBeEmpty::isValid(const std::shared_ptrselection(*anArgsIt); if(!aSelAttr.get()) { - theError = "Could not get selection attribute \"" + *anArgsIt + "\"."; + theError = "Error: Could not get selection attribute \"" + *anArgsIt + "\"."; return false; } @@ -308,7 +312,7 @@ bool FeaturesPlugin_ValidatorCanBeEmpty::isValid(const std::shared_ptrcontext(); if(!aContext.get()) { - theError = "Base objects list contains vertex or edge, so attribute \"" + *anArgsIt + theError = "Error: Base objects list contains vertex or edge, so attribute \"" + *anArgsIt + "\" can not be used with default value. Select direction for extrusion."; return false; } @@ -317,7 +321,7 @@ bool FeaturesPlugin_ValidatorCanBeEmpty::isValid(const std::shared_ptr(theAttribute); if(!anAttrSelectionList.get()) { - theError = "Error: this validator can only work with selection list attributes in Boolean feature."; + theError = "Error: This validator can only work with selection list attributes in \"Boolean\" feature."; return false; } FeaturePtr aFeature = std::dynamic_pointer_cast(theAttribute->owner()); @@ -393,12 +397,12 @@ bool FeaturesPlugin_ValidatorBooleanSelection::isValid(const AttributePtr& theAt for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) { AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex); if(!anAttrSelection.get()) { - theError = "Error: empty attribute selection."; + theError = "Error: Empty attribute selection."; return false; } ResultPtr aContext = anAttrSelection->context(); if(!aContext.get()) { - theError = "Error: empty selection context."; + theError = "Error: Empty selection context."; return false; } ResultConstructionPtr aResultConstruction = @@ -412,7 +416,7 @@ bool FeaturesPlugin_ValidatorBooleanSelection::isValid(const AttributePtr& theAt aShape = aContext->shape(); } if(!aShape.get()) { - theError = "Error: empty shape."; + theError = "Error: Empty shape."; return false; } int aShapeType = aShape->shapeType(); @@ -423,14 +427,14 @@ bool FeaturesPlugin_ValidatorBooleanSelection::isValid(const AttributePtr& theAt aShapeType != GeomAPI_Shape::SOLID && aShapeType != GeomAPI_Shape::COMPSOLID && aShapeType != GeomAPI_Shape::COMPOUND) { - theError = "Error: selected shape has the wrong type."; + theError = "Error: Selected shape has the wrong type."; return false; } } else { if(aShapeType != GeomAPI_Shape::SOLID && aShapeType != GeomAPI_Shape::COMPSOLID && aShapeType != GeomAPI_Shape::COMPOUND) { - theError = "Error: selected shape has the wrong type."; + theError = "Error: Selected shape has the wrong type."; return false; } } @@ -444,31 +448,142 @@ bool FeaturesPlugin_ValidatorPartitionSelection::isValid(const AttributePtr& the const std::list& theArguments, std::string& theError) const { - std::string anAttributeType = theAttribute->attributeType(); - if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) { - AttributeSelectionListPtr aSelectionListAttr = - std::dynamic_pointer_cast(theAttribute); + AttributeSelectionListPtr anAttrSelectionList = std::dynamic_pointer_cast(theAttribute); + if(!anAttrSelectionList.get()) { + theError = "Error: This validator can only work with selection list in \"Partition\" feature."; + return false; + } + + for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) { + AttributeSelectionPtr aSelectAttr = anAttrSelectionList->value(anIndex); - for(int anIndex = 0; anIndex < aSelectionListAttr->size(); ++anIndex) { - AttributeSelectionPtr aSelectAttr = aSelectionListAttr->value(anIndex); + //GeomValidators_BodyShapes aBodyValidator; + //if(aBodyValidator.isValid(aSelectAttr, theArguments, theError)) { + // continue; + //} - GeomValidators_BodyShapes aBodyValidator; - if(aBodyValidator.isValid(aSelectAttr, theArguments, theError)) { - continue; - } + GeomValidators_FeatureKind aFeatureKindValidator; + if(aFeatureKindValidator.isValid(aSelectAttr, theArguments, theError)) { + continue; + } - GeomValidators_FeatureKind aFeatureKindValidator; - if(aFeatureKindValidator.isValid(aSelectAttr, theArguments, theError)) { - continue; - } + ResultPtr aContext = aSelectAttr->context(); + ResultConstructionPtr aResultConstruction = std::dynamic_pointer_cast(aContext); + if(aResultConstruction.get()) { + + } - theError = "Only body shapes and construction planes are allowed for selection."; + theError = "Error: Only body shapes and construction planes are allowed for selection."; + return false; + } + + return true; +} + +//================================================================================================== +bool FeaturesPlugin_ValidatorRemoveSubShapesSelection::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + std::string& theError) const +{ + AttributeSelectionListPtr aSubShapesAttrList = std::dynamic_pointer_cast(theAttribute); + if(!aSubShapesAttrList.get()) { + theError = "Error: This validator can only work with selection list in \"Remove Sub-Shapes\" feature."; + return false; + } + + static const std::string aBaseShapeID = "base_shape"; + FeaturePtr aFeature = std::dynamic_pointer_cast(theAttribute->owner()); + AttributeSelectionPtr aShapeAttrSelection = aFeature->selection(aBaseShapeID); + + if(!aShapeAttrSelection.get()) { + theError = "Error: Could not get \"" + aBaseShapeID + "\" attribute."; + return false; + } + + GeomShapePtr aBaseShape = aShapeAttrSelection->value(); + ResultPtr aContext = aShapeAttrSelection->context(); + if(!aContext.get()) { + theError = "Error: Empty context."; + return false; + } + if(!aBaseShape.get()) { + aBaseShape = aContext->shape(); + } + if(!aBaseShape.get()) { + theError = "Error: Empty base shape."; + return false; + } + + for(int anIndex = 0; anIndex < aSubShapesAttrList->size(); ++anIndex) { + bool isSameFound = false; + AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex); + GeomShapePtr aShapeToAdd = anAttrSelectionInList->value(); + for(GeomAPI_ShapeIterator anIt(aBaseShape); anIt.more(); anIt.next()) { + if(anIt.current()->isEqual(aShapeToAdd)) { + isSameFound = true; + break; + } + } + if(!isSameFound) { + theError = "Error: Only sub-shapes of selected shape is allowed for selection."; return false; } - } else { - theError = "This validator supports only " + ModelAPI_AttributeSelectionList::typeId() + " attribute type."; + } + + return true; +} + +//================================================================================================== +bool FeaturesPlugin_ValidatorRemoveSubShapesResult::isValid(const std::shared_ptr& theFeature, + const std::list& theArguments, + std::string& theError) const +{ + static const std::string aBaseShapeID = "base_shape"; + static const std::string aSubShapesID = "subshapes"; + + if(theFeature->getKind() != "Remove_SubShapes") { + theError = "Error: Feature \"" + theFeature->getKind() + "\" does not supported by this validator."; + return false; + } + + AttributeSelectionPtr aShapeAttrSelection = theFeature->selection(aBaseShapeID); + if(!aShapeAttrSelection.get()) { + theError = "Error: Could not get \"" + aBaseShapeID + "\" attribute."; + return false; + } + + AttributeSelectionListPtr aSubShapesAttrList = theFeature->selectionList(aSubShapesID); + if(!aSubShapesAttrList.get()) { + theError = "Error: Could not get \"" + aSubShapesID + "\" attribute."; + return false; + } + + // Copy base shape. + GeomShapePtr aBaseShape = aShapeAttrSelection->value(); + if(!aBaseShape.get()) { + return false; + } + GeomShapePtr aResultShape = aBaseShape->emptyCopied(); + + // Copy sub-shapes from list to new shape. + for(int anIndex = 0; anIndex < aSubShapesAttrList->size(); ++anIndex) { + AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex); + GeomShapePtr aShapeToAdd = anAttrSelectionInList->value(); + GeomAlgoAPI_ShapeBuilder::add(aResultShape, aShapeToAdd); + } + + // Check new shape. + if(!GeomAlgoAPI_ShapeTools::isShapeValid(aResultShape)) { + theError = "Error: Resulting shape is not valid."; return false; } return true; } + +//================================================================================================== +bool FeaturesPlugin_ValidatorRemoveSubShapesResult::isNotObligatory(std::string theFeature, + std::string theAttribute) +{ + return false; +} diff --git a/src/FeaturesPlugin/FeaturesPlugin_Validators.h b/src/FeaturesPlugin/FeaturesPlugin_Validators.h index 905eec5c6..fb05c2ab3 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Validators.h +++ b/src/FeaturesPlugin/FeaturesPlugin_Validators.h @@ -110,7 +110,23 @@ class FeaturesPlugin_ValidatorPartitionSelection: public ModelAPI_AttributeValid { public: /// \return True if the attribute is valid. It checks whether the selection - /// is acceptable for boolean operation. + /// is acceptable for 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, + std::string& theError) const; +}; + +/// \class FeaturesPlugin_ValidatorRemoveSubShapesSelection +/// \ingroup Validators +/// \brief Validates selection for "Remove Sub-Shapes" feature. +class FeaturesPlugin_ValidatorRemoveSubShapesSelection: public ModelAPI_AttributeValidator +{ +public: + /// \return True if the attribute is valid. It checks whether the selection + /// is acceptable for operation. /// \param[in] theAttribute an attribute to check. /// \param[in] theArguments a filter parameters. /// \param[out] theError error message. @@ -119,4 +135,22 @@ public: std::string& theError) const; }; +/// \class FeaturesPlugin_ValidatorRemoveSubShapesResult +/// \ingroup Validators +/// \brief Validator for the Remove Sub-Shapes feature. +class FeaturesPlugin_ValidatorRemoveSubShapesResult: public ModelAPI_FeatureValidator +{ + public: + //! \return true if result is valid shape. + //! \param theFeature the checked feature + //! \param theArguments arguments of the feature (not used) + //! \param theError error message + virtual bool isValid(const std::shared_ptr& theFeature, + const std::list& theArguments, + std::string& theError) const; + + /// Returns true if the attribute in feature is not obligatory for the feature execution + virtual bool isNotObligatory(std::string theFeature, std::string theAttribute); +}; + #endif diff --git a/src/FeaturesPlugin/icons/remove_subshapes.png b/src/FeaturesPlugin/icons/remove_subshapes.png new file mode 100644 index 0000000000000000000000000000000000000000..98d7a8ce8fdf0d2e1fdbf27fef66e3c72d52e233 GIT binary patch literal 608 zcmV-m0-ybfP)+2=4`l3*5c%DU?IH|du8efYL_4nXNH8>nHS$i-i@m`oef@iKn{&R^ z*QORjFSXWkq+_DLXGgX(vn+T;0?}B`aU5?2R*6QGZuO)X?VV9SY{lVtmlN`Tk*k9r zuC3G3X6fz$HFsm&k z9^7Z*`7@fVX)Z?Zl3J)^N{uj?d__;&C6>Nl;D!V%Kk&HR_!@l7r$6i2xjC(}Z}fad zF)+FwvuPu(+fH&PIf$<=PrX^F{J`t=a(Q?JKmfGXj6J-~C+kr;(-J<%*yBzXiiy8> zAR;sb+AI9V=CweLCH@f*h<4`<)AYDZms2fNvTaqcEW_n?l?2fMj-$o4i-xHkPFO|T uZ58dR6s@UOB3-ssdI36LrvIwxKkFy2|D + + + diff --git a/src/FeaturesPlugin/remove_subshapes_widget.xml b/src/FeaturesPlugin/remove_subshapes_widget.xml new file mode 100644 index 000000000..c5e213ff4 --- /dev/null +++ b/src/FeaturesPlugin/remove_subshapes_widget.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeBuilder.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeBuilder.cpp index c8a63bf91..d710493b9 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeBuilder.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeBuilder.cpp @@ -105,8 +105,8 @@ void GeomAlgoAPI_ShapeBuilder::removeInternal(const std::shared_ptr theShape, - const ListOfShape& theShapesToAdd) +void GeomAlgoAPI_ShapeBuilder::addInternal(const std::shared_ptr theShape, + const ListOfShape& theShapesToAdd) { // Get base shape. if(!theShape.get()) { diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeBuilder.h b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeBuilder.h index 55ecaa3c5..cd64980f4 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeBuilder.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeBuilder.h @@ -37,11 +37,11 @@ class GeomAlgoAPI_ShapeBuilder: public GeomAlgoAPI_MakeShapeList /// \param[in] theShape base shape. GEOMALGOAPI_EXPORT void removeInternal(const std::shared_ptr theShape); - /// \brief Store new shape as result of adding theShapesToAdd to theShape. + /// \brief Store new shape as result of adding theShapesToAdd to theShape as internal shapes. /// \param[in] theShape base shape. /// \param[in] theShapesToAdd shapes which will be added. - GEOMALGOAPI_EXPORT void add(const std::shared_ptr theShape, - const ListOfShape& theShapesToAdd); + GEOMALGOAPI_EXPORT void addInternal(const std::shared_ptr theShape, + const ListOfShape& theShapesToAdd); }; #endif diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp index 7f407d677..69da42608 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -599,3 +600,14 @@ bool GeomAlgoAPI_ShapeTools::isSubShapeInsideShape(const std::shared_ptr theShape) +{ + if(!theShape.get()) { + return false; + } + + BRepCheck_Analyzer aChecker(theShape->impl()); + return (aChecker.IsValid() == Standard_True); +} \ No newline at end of file diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h index 3d62588f7..8df74080a 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h @@ -90,6 +90,10 @@ public: /// \return true if edge inside the face. GEOMALGOAPI_EXPORT static bool isSubShapeInsideShape(const std::shared_ptr theSubShape, const std::shared_ptr theBaseShape); + + /// \return true if theShape is valid. + GEOMALGOAPI_EXPORT static bool isShapeValid(const std::shared_ptr theShape); + }; #endif diff --git a/src/GeomValidators/GeomValidators_BodyShapes.cpp b/src/GeomValidators/GeomValidators_BodyShapes.cpp index 13e95ace0..18bd9918a 100644 --- a/src/GeomValidators/GeomValidators_BodyShapes.cpp +++ b/src/GeomValidators/GeomValidators_BodyShapes.cpp @@ -15,24 +15,34 @@ bool GeomValidators_BodyShapes::isValid(const AttributePtr& theAttribute, std::string& theError) const { std::string anAttributeType = theAttribute->attributeType(); - if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) { - AttributeSelectionListPtr aSelectionListAttr = - std::dynamic_pointer_cast(theAttribute); - // all context objects should not be sketch entities - for(int anIndex = 0, aSize = aSelectionListAttr->size(); anIndex < aSize; ++anIndex) { - AttributeSelectionPtr aSelectAttr = aSelectionListAttr->value(anIndex); - ResultPtr aContext = aSelectAttr->context(); - if(!aContext.get()) { - theError = "Error: Context is empty."; - return false; - } + if(anAttributeType == ModelAPI_AttributeSelection::typeId()) { + AttributeSelectionPtr anAttrSelection = + std::dynamic_pointer_cast(theAttribute); + ResultPtr aContext = anAttrSelection->context(); + if(!aContext.get()) { + theError = "Error: Context is empty."; + return false; + } + + ResultConstructionPtr aResultConstruction = std::dynamic_pointer_cast(aContext); + if(aResultConstruction.get()) { + theError = "Error: Result construction selected."; + return false; + } + } else if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) { + AttributeSelectionListPtr anAttrSelectionList = + std::dynamic_pointer_cast(theAttribute); - ResultConstructionPtr aResultConstruction = std::dynamic_pointer_cast(aContext); - if(aResultConstruction.get()) { - theError = "Error: Result construction selected."; + // All objects should not be result constructions. + for(int anIndex = 0, aSize = anAttrSelectionList->size(); anIndex < aSize; ++anIndex) { + AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex); + if(!isValid(anAttrSelection, theArguments, theError)) { return false; } } + } else { + theError = "Error: Attribute \"" + anAttributeType + "\" does not supported by this validator."; + return false; } return true; diff --git a/src/GeomValidators/GeomValidators_ShapeType.cpp b/src/GeomValidators/GeomValidators_ShapeType.cpp index 141839ed1..f9a4e517d 100755 --- a/src/GeomValidators/GeomValidators_ShapeType.cpp +++ b/src/GeomValidators/GeomValidators_ShapeType.cpp @@ -25,16 +25,18 @@ static EdgeTypes MyShapeTypes; GeomValidators_ShapeType::TypeOfShape GeomValidators_ShapeType::shapeType(const std::string& theType) { if (MyShapeTypes.size() == 0) { - MyShapeTypes["empty"] = Empty; - MyShapeTypes["vertex"] = Vertex; - MyShapeTypes["edge"] = Edge; - MyShapeTypes["line"] = Line; - MyShapeTypes["circle"] = Circle; - MyShapeTypes["wire"] = Wire; - MyShapeTypes["face"] = Face; - MyShapeTypes["plane"] = Plane; - MyShapeTypes["shell"] = Shell; - MyShapeTypes["solid"] = Solid; + MyShapeTypes["empty"] = Empty; + MyShapeTypes["vertex"] = Vertex; + MyShapeTypes["edge"] = Edge; + MyShapeTypes["line"] = Line; + MyShapeTypes["circle"] = Circle; + MyShapeTypes["wire"] = Wire; + MyShapeTypes["face"] = Face; + MyShapeTypes["plane"] = Plane; + MyShapeTypes["shell"] = Shell; + MyShapeTypes["solid"] = Solid; + MyShapeTypes["compsolid"] = CompSolid; + MyShapeTypes["compound"] = Compound; } std::string aType = std::string(theType.c_str()); if (MyShapeTypes.find(aType) != MyShapeTypes.end()) @@ -224,6 +226,9 @@ bool GeomValidators_ShapeType::isValidShape(const GeomShapePtr theShape, aValid = theShape->isSolid() || theShape->isCompSolid() || theShape->isCompoundOfSolids(); break; + case CompSolid: + aValid = theShape->shapeType() == GeomAPI_Shape::COMPSOLID; + break; case Compound: aValid = theShape->isCompound(); break; diff --git a/src/GeomValidators/GeomValidators_ShapeType.h b/src/GeomValidators/GeomValidators_ShapeType.h index 297b3fb25..3d2c60e65 100644 --- a/src/GeomValidators/GeomValidators_ShapeType.h +++ b/src/GeomValidators/GeomValidators_ShapeType.h @@ -36,6 +36,7 @@ class GeomValidators_ShapeType : public ModelAPI_AttributeValidator Plane, Shell, Solid, + CompSolid, Compound, AnyShape }; diff --git a/src/Model/Model_SelectionNaming.cpp b/src/Model/Model_SelectionNaming.cpp index 167d3b935..7db813549 100644 --- a/src/Model/Model_SelectionNaming.cpp +++ b/src/Model/Model_SelectionNaming.cpp @@ -261,31 +261,44 @@ std::string Model_SelectionNaming::namingName(ResultPtr& theContext, TopAbs_ShapeEnum translateType (const std::string& theType) { // map from the textual shape types to OCCT enumeration - static std::map MyShapeTypes; - if (MyShapeTypes.size() == 0) { - MyShapeTypes["face"] = TopAbs_FACE; - MyShapeTypes["faces"] = TopAbs_FACE; - MyShapeTypes["vertex"] = TopAbs_VERTEX; - MyShapeTypes["vertices"] = TopAbs_VERTEX; - MyShapeTypes["wire"] = TopAbs_WIRE; - MyShapeTypes["edge"] = TopAbs_EDGE; - MyShapeTypes["edges"] = TopAbs_EDGE; - MyShapeTypes["shell"] = TopAbs_SHELL; - MyShapeTypes["solid"] = TopAbs_SOLID; - MyShapeTypes["solids"] = TopAbs_SOLID; - MyShapeTypes["FACE"] = TopAbs_FACE; - MyShapeTypes["FACES"] = TopAbs_FACE; - MyShapeTypes["VERTEX"] = TopAbs_VERTEX; - MyShapeTypes["VERTICES"] = TopAbs_VERTEX; - MyShapeTypes["WIRE"] = TopAbs_WIRE; - MyShapeTypes["EDGE"] = TopAbs_EDGE; - MyShapeTypes["EDGES"] = TopAbs_EDGE; - MyShapeTypes["SHELL"] = TopAbs_SHELL; - MyShapeTypes["SOLID"] = TopAbs_SOLID; - MyShapeTypes["SOLIDS"] = TopAbs_SOLID; + static std::map aShapeTypes; + + if(aShapeTypes.size() == 0) { + aShapeTypes["compound"] = TopAbs_COMPOUND; + aShapeTypes["compounds"] = TopAbs_COMPOUND; + aShapeTypes["compsolid"] = TopAbs_COMPSOLID; + aShapeTypes["compsolids"] = TopAbs_COMPSOLID; + aShapeTypes["solid"] = TopAbs_SOLID; + aShapeTypes["solids"] = TopAbs_SOLID; + aShapeTypes["shell"] = TopAbs_SHELL; + aShapeTypes["shells"] = TopAbs_SHELL; + aShapeTypes["face"] = TopAbs_FACE; + aShapeTypes["faces"] = TopAbs_FACE; + aShapeTypes["wire"] = TopAbs_WIRE; + aShapeTypes["wires"] = TopAbs_WIRE; + aShapeTypes["edge"] = TopAbs_EDGE; + aShapeTypes["edges"] = TopAbs_EDGE; + aShapeTypes["vertex"] = TopAbs_VERTEX; + aShapeTypes["vertices"] = TopAbs_VERTEX; + aShapeTypes["COMPOUND"] = TopAbs_COMPOUND; + aShapeTypes["COMPOUNDS"] = TopAbs_COMPOUND; + aShapeTypes["COMPSOLID"] = TopAbs_COMPSOLID; + aShapeTypes["COMPSOLIDS"] = TopAbs_COMPSOLID; + aShapeTypes["SOLID"] = TopAbs_SOLID; + aShapeTypes["SOLIDS"] = TopAbs_SOLID; + aShapeTypes["SHELL"] = TopAbs_SHELL; + aShapeTypes["SHELLS"] = TopAbs_SHELL; + aShapeTypes["FACE"] = TopAbs_FACE; + aShapeTypes["FACES"] = TopAbs_FACE; + aShapeTypes["WIRE"] = TopAbs_WIRE; + aShapeTypes["WIRES"] = TopAbs_WIRE; + aShapeTypes["EDGE"] = TopAbs_EDGE; + aShapeTypes["EDGES"] = TopAbs_EDGE; + aShapeTypes["VERTEX"] = TopAbs_VERTEX; + aShapeTypes["VERTICES"] = TopAbs_VERTEX; } - if (MyShapeTypes.find(theType) != MyShapeTypes.end()) - return MyShapeTypes[theType]; + if (aShapeTypes.find(theType) != aShapeTypes.end()) + return aShapeTypes[theType]; Events_Error::send("Shape type defined in XML is not implemented!"); return TopAbs_SHAPE; } diff --git a/src/ModuleBase/ModuleBase_Tools.cpp b/src/ModuleBase/ModuleBase_Tools.cpp index 37e6500b4..da9486b70 100755 --- a/src/ModuleBase/ModuleBase_Tools.cpp +++ b/src/ModuleBase/ModuleBase_Tools.cpp @@ -302,27 +302,32 @@ QString objectInfo(const ObjectPtr& theObj, const bool isUseAttributesInfo) } typedef QMap ShapeTypes; -static ShapeTypes MyShapeTypes; +static ShapeTypes myShapeTypes; TopAbs_ShapeEnum shapeType(const QString& theType) { - if (MyShapeTypes.count() == 0) { - MyShapeTypes["face"] = TopAbs_FACE; - MyShapeTypes["faces"] = TopAbs_FACE; - MyShapeTypes["vertex"] = TopAbs_VERTEX; - MyShapeTypes["vertices"] = TopAbs_VERTEX; - MyShapeTypes["wire"] = TopAbs_WIRE; - MyShapeTypes["wires"] = TopAbs_WIRE; - MyShapeTypes["edge"] = TopAbs_EDGE; - MyShapeTypes["edges"] = TopAbs_EDGE; - MyShapeTypes["shell"] = TopAbs_SHELL; - MyShapeTypes["solid"] = TopAbs_SOLID; - MyShapeTypes["solids"] = TopAbs_SOLID; - MyShapeTypes["objects"] = TopAbs_SHAPE; + if (myShapeTypes.count() == 0) { + myShapeTypes["compound"] = TopAbs_COMPOUND; + myShapeTypes["compounds"] = TopAbs_COMPOUND; + myShapeTypes["compsolid"] = TopAbs_COMPSOLID; + myShapeTypes["compsolids"] = TopAbs_COMPSOLID; + myShapeTypes["solid"] = TopAbs_SOLID; + myShapeTypes["solids"] = TopAbs_SOLID; + myShapeTypes["shell"] = TopAbs_SHELL; + myShapeTypes["shells"] = TopAbs_SHELL; + myShapeTypes["face"] = TopAbs_FACE; + myShapeTypes["faces"] = TopAbs_FACE; + myShapeTypes["wire"] = TopAbs_WIRE; + myShapeTypes["wires"] = TopAbs_WIRE; + myShapeTypes["edge"] = TopAbs_EDGE; + myShapeTypes["edges"] = TopAbs_EDGE; + myShapeTypes["vertex"] = TopAbs_VERTEX; + myShapeTypes["vertices"] = TopAbs_VERTEX; + myShapeTypes["objects"] = TopAbs_SHAPE; } QString aType = theType.toLower(); - if (MyShapeTypes.contains(aType)) - return MyShapeTypes[aType]; + if(myShapeTypes.contains(aType)) + return myShapeTypes[aType]; Events_Error::send("Shape type defined in XML is not implemented!"); return TopAbs_SHAPE; } -- 2.30.2