From a64b863474378ac749958bd734179c957cb12339 Mon Sep 17 00:00:00 2001 From: mpv Date: Mon, 12 Nov 2018 17:21:52 +0300 Subject: [PATCH] Initial implementation of work of "To add all elements that share the same topology" flag in Group feature --- doc/gui/Introduction.rst | 2 +- src/CollectionAPI/CollectionAPI_Group.cpp | 10 ++- src/CollectionAPI/CollectionAPI_Group.h | 3 +- src/Model/Model_AttributeSelection.cpp | 46 ++++++++++ src/Model/Model_AttributeSelection.h | 3 + src/Model/Model_AttributeSelectionList.cpp | 88 ++++++++++++++++--- src/Model/Model_AttributeSelectionList.h | 12 +-- src/Model/Model_ResultPart.cpp | 18 ++++ src/Model/Model_ResultPart.h | 2 + src/ModelAPI/ModelAPI_AttributeSelection.h | 2 + src/ModelAPI/ModelAPI_ResultPart.h | 3 + .../ModuleBase_WidgetMultiSelector.cpp | 7 +- src/Selector/Selector_Selector.cpp | 81 ++++++++++++++++- src/Selector/Selector_Selector.h | 4 + 14 files changed, 250 insertions(+), 31 deletions(-) diff --git a/doc/gui/Introduction.rst b/doc/gui/Introduction.rst index 613bd11aa..ae5c997e9 100644 --- a/doc/gui/Introduction.rst +++ b/doc/gui/Introduction.rst @@ -241,7 +241,7 @@ Each feature, result, construction, group, field, parameter can be renamed using .. centered:: Construction pop-up menu -The order of features can be changed using *Move to the end* pop-up menu command. The selected feature will be moved to the end of feature list. +The order of features can be changed using *Move to the end* pop-up menu command. It works only for Group features. The selected group will be moved to the end of features list. Folders can be used to arrange long Tree View for features. diff --git a/src/CollectionAPI/CollectionAPI_Group.cpp b/src/CollectionAPI/CollectionAPI_Group.cpp index e6660beec..19fd1a44e 100644 --- a/src/CollectionAPI/CollectionAPI_Group.cpp +++ b/src/CollectionAPI/CollectionAPI_Group.cpp @@ -64,13 +64,19 @@ void CollectionAPI_Group::dump(ModelHighAPI_Dumper& theDumper) const AttributeSelectionListPtr anAttrList = aBase->selectionList(CollectionPlugin_Group::LIST_ID()); - theDumper << aBase << " = model.addGroup(" << aDocName << ", " << anAttrList << ")" << std::endl; + theDumper << aBase << " = model.addGroup(" << aDocName << ", " << anAttrList; + if (anAttrList->isGeometricalSelection()) + theDumper <<", True"; + theDumper << ")" << std::endl; } //================================================================================================== GroupPtr addGroup(const std::shared_ptr& thePart, - const std::list& theGroupList) + const std::list& theGroupList, + const bool theShareSameTopology) { std::shared_ptr aFeature = thePart->addFeature(CollectionAPI_Group::ID()); + if (theShareSameTopology) + aFeature->selectionList(CollectionPlugin_Group::LIST_ID())->setGeometricalSelection(true); return GroupPtr(new CollectionAPI_Group(aFeature, theGroupList)); } diff --git a/src/CollectionAPI/CollectionAPI_Group.h b/src/CollectionAPI/CollectionAPI_Group.h index bb92ff1b8..fe28fc2f4 100644 --- a/src/CollectionAPI/CollectionAPI_Group.h +++ b/src/CollectionAPI/CollectionAPI_Group.h @@ -70,6 +70,7 @@ typedef std::shared_ptr GroupPtr; /// \brief Create Group feature. COLLECTIONAPI_EXPORT GroupPtr addGroup(const std::shared_ptr& thePart, - const std::list& theGroupList); + const std::list& theGroupList, + const bool theShareSameTopology = false); #endif // CollectionAPI_Group_H_ diff --git a/src/Model/Model_AttributeSelection.cpp b/src/Model/Model_AttributeSelection.cpp index a59e90a0d..7ca2ca089 100644 --- a/src/Model/Model_AttributeSelection.cpp +++ b/src/Model/Model_AttributeSelection.cpp @@ -1770,3 +1770,49 @@ ResultPtr Model_AttributeSelection::newestContext( aResult = theCurrent; return aResult; } + +void Model_AttributeSelection::combineGeometrical() +{ + if (myTmpContext.get() || myTmpSubShape.get()) + return; + TDF_Label aSelLab = selectionLabel(); + if (aSelLab.IsAttribute(kINVALID_SELECTION) || !myRef.isInitialized()) + return; + + if (aSelLab.IsAttribute(kCIRCLE_CENTER) || aSelLab.IsAttribute(kELLIPSE_CENTER1) || + aSelLab.IsAttribute(kELLIPSE_CENTER2) || aSelLab.IsAttribute(kSIMPLE_REF_ID)) + return; + + if (aSelLab.IsAttribute(kPART_REF_ID)) { + ResultPartPtr aPart = std::dynamic_pointer_cast(context()); + if (!aPart.get() || !aPart->isActivated()) + return; // postponed naming needed + Handle(TDataStd_Integer) anIndex; + if (aSelLab.FindAttribute(TDataStd_Integer::GetID(), anIndex)) { + if (anIndex->Get()) { // special selection attribute was created, use it + std::string aNewName; + aPart->combineGeometrical(anIndex->Get(), aNewName); + TDataStd_Name::Set(aSelLab, aNewName.c_str()); + } + } + return; + } + + std::shared_ptr aConstr = + std::dynamic_pointer_cast(context()); + if (aConstr.get()) + return; + FeaturePtr aFeature = contextFeature(); + if (aFeature.get()) + return; + + Selector_Selector aSelector(aSelLab); + if (ModelAPI_Session::get()->moduleDocument() != owner()->document()) { + aSelector.setBaseDocument(std::dynamic_pointer_cast + (ModelAPI_Session::get()->moduleDocument())->extConstructionsLabel()); + } + if (aSelector.restore()) { + TopoDS_Shape aContextShape = context()->shape()->impl(); + aSelector.combineGeometrical(aContextShape); + } +} diff --git a/src/Model/Model_AttributeSelection.h b/src/Model/Model_AttributeSelection.h index 0e98757fb..a624e5cf0 100644 --- a/src/Model/Model_AttributeSelection.h +++ b/src/Model/Model_AttributeSelection.h @@ -150,6 +150,9 @@ public: /// Returns the name by context. Adds the part name if the context is located in other document MODEL_EXPORT virtual std::string contextName(const ResultPtr& theContext) const; + /// Makes the current local selection becomes all sub-shapes with same base geometry. + MODEL_EXPORT virtual void combineGeometrical(); + protected: /// Objects are created for features automatically MODEL_EXPORT Model_AttributeSelection(TDF_Label& theLabel); diff --git a/src/Model/Model_AttributeSelectionList.cpp b/src/Model/Model_AttributeSelectionList.cpp index f32fbcf63..617007a5e 100644 --- a/src/Model/Model_AttributeSelectionList.cpp +++ b/src/Model/Model_AttributeSelectionList.cpp @@ -26,11 +26,13 @@ #include #include +#include #include #include #include #include +#include #include #include #include @@ -41,6 +43,10 @@ #include #include +/// GUID for UAttribute that indicates the list has "To add all elements that share the same +/// topology" flag enabled +static const Standard_GUID kIS_GEOMETRICAL_SELECTION("f16987b6-e6c8-435c-99fa-03a7e0b06e83"); + void Model_AttributeSelectionList::append( const ObjectPtr& theContext, const std::shared_ptr& theSubShape, const bool theTemporarily) @@ -231,7 +237,7 @@ void Model_AttributeSelectionList::remove(const std::set& theIndices) { int anOldSize = mySize->Get(); int aRemoved = 0; - // iterate one by one and shifting the removed indicies + // iterate one by one and shifting the removed indices for(int aCurrent = 0; aCurrent < anOldSize; aCurrent++) { if (theIndices.find(aCurrent) == theIndices.end()) { // not removed if (aRemoved) { // but must be shifted to the removed position @@ -263,6 +269,19 @@ int Model_AttributeSelectionList::size() return mySize->Get(); } +// returns true if theShape is same with theInList or is contained in it (a compound) +static bool isIn(GeomShapePtr theInList, GeomShapePtr theShape) { + if (theShape->isSame(theInList)) + return true; + if (theInList.get() && theInList->shapeType() == GeomAPI_Shape::COMPOUND) { + for(GeomAPI_ShapeIterator anIter(theInList); anIter.more(); anIter.next()) { + if (!anIter.current()->isNull() && anIter.current()->isSame(theShape)) + return true; + } + } + return false; +} + bool Model_AttributeSelectionList::isInList(const ObjectPtr& theContext, const std::shared_ptr& theSubShape, const bool theTemporarily) @@ -281,7 +300,7 @@ bool Model_AttributeSelectionList::isInList(const ObjectPtr& theContext, return true; } else { // we need to call here isSame instead of isEqual to do not check shapes orientation - if (theSubShape->isSame(*aShapes)) + if (isIn(*aShapes, theSubShape)) return true; } } @@ -301,7 +320,7 @@ bool Model_AttributeSelectionList::isInList(const ObjectPtr& theContext, } } else { // we need to call here isSame instead of isEqual to do not check shapes orientation - if (theSubShape->isSame(aValue)) // shapes are equal + if (isIn(aValue, theSubShape)) // shapes are equal return true; } } @@ -328,8 +347,8 @@ std::shared_ptr } TDF_Label aLabel = mySize->Label().FindChild(theIndex + 1); // create a new attribute each time, by demand - // supporting of old attributes is too slow (synch each time) and buggy on redo - // (if attribute is deleted and created, the abort updates attriute and makes the Attr invalid) + // supporting of old attributes is too slow (sync each time) and buggy on redo + // (if attribute is deleted and created, the abort updates attribute and makes the Attr invalid) std::shared_ptr aNewAttr = std::shared_ptr(new Model_AttributeSelection(aLabel)); if (owner()) { @@ -371,8 +390,7 @@ bool Model_AttributeSelectionList::isInitialized() } Model_AttributeSelectionList::Model_AttributeSelectionList(TDF_Label& theLabel) -: myLab(theLabel), - myIsGeometricalSelection(false) +: myLab(theLabel) { reinit(); } @@ -404,10 +422,58 @@ void Model_AttributeSelectionList::cashValues(const bool theEnabled) } } +bool Model_AttributeSelectionList::isGeometricalSelection() const +{ + return myLab.IsAttribute(kIS_GEOMETRICAL_SELECTION); +} + void Model_AttributeSelectionList::setGeometricalSelection(const bool theIsGeometricalSelection) { - myIsGeometricalSelection = theIsGeometricalSelection; - // TODO: update list accodring to the flag: - // false - all objects with same geometry must be splited in separate. - // true - all objets with same geometry must be combined into single. + if (isGeometricalSelection() == theIsGeometricalSelection) + return; // nothing to do + if (theIsGeometricalSelection) // store the state + TDataStd_UAttribute::Set(myLab, kIS_GEOMETRICAL_SELECTION); + else + myLab.ForgetAttribute(kIS_GEOMETRICAL_SELECTION); + std::set anIndiciesToRemove; // Update list according to the flag + if (theIsGeometricalSelection) { // all objects with same geometry must be combined into single + std::list anAttributes; // collect attributes with geometrical compounds + for(int anIndex = 0; anIndex < size(); anIndex++) { + AttributeSelectionPtr anAttr = value(anIndex); + if (!anAttr.get() || !anAttr->context().get()) + continue; + anAttr->combineGeometrical(); + if (!anAttr->value().get() || anAttr->value()->shapeType() != GeomAPI_Shape::COMPOUND) + continue; + // check it is equal to some other attribute already presented in the list + std::list::iterator anAttrIter = anAttributes.begin(); + for(; anAttrIter != anAttributes.end(); anAttrIter++) { + if (anAttr->context() == (*anAttrIter)->context() && + anAttr->namingName() == (*anAttrIter)->namingName()) { + anIndiciesToRemove.insert(anIndex); + break; + } + } + if (anAttrIter == anAttributes.end()) // not removed, so, add to the compare-list + anAttributes.push_back(anAttr); + } + } else { // all objects with same geometry must be divided into separated sub-attributes + int anInitialSize = size(); + for(int anIndex = 0; anIndex < anInitialSize; anIndex++) { + AttributeSelectionPtr anAttr = value(anIndex); + if (!anAttr.get() || !anAttr->context().get()) + continue; + GeomShapePtr aValue = anAttr->value(); + if (!aValue.get() || aValue->shapeType() != GeomAPI_Shape::COMPOUND) + continue; + for(GeomAPI_ShapeIterator anIter(aValue); anIter.more(); anIter.next()) { + append(anAttr->context(), anIter.current()); + } + anIndiciesToRemove.insert(anIndex); + } + } + remove(anIndiciesToRemove); + myIsCashed = false; + myCash.clear(); // empty list as indicator that cash is not used + owner()->data()->sendAttributeUpdated(this); } diff --git a/src/Model/Model_AttributeSelectionList.h b/src/Model/Model_AttributeSelectionList.h index 1870d95d4..d84ca1ff4 100644 --- a/src/Model/Model_AttributeSelectionList.h +++ b/src/Model/Model_AttributeSelectionList.h @@ -45,14 +45,12 @@ class Model_AttributeSelectionList : public ModelAPI_AttributeSelectionList /// the cashed shapes to optimize isInList method: from context to set of shapes in this context std::map > > myCash; bool myIsCashed; ///< true if cashing is performed - /// If true attribute selects geometry instead of shape. - bool myIsGeometricalSelection; public: /// Adds the new reference to the end of the list /// \param theContext object where the sub-shape was selected /// \param theSubShape selected sub-shape (if null, the whole context is selected) /// \param theTemporarily if it is true, do not store and name the added in the data framework - /// (used to remove immideately, without the following updates) + /// (used to remove immediately, without the following updates) MODEL_EXPORT virtual void append( const ObjectPtr& theContext, const std::shared_ptr& theSubShape, const bool theTemporarily = false); @@ -79,14 +77,14 @@ public: /// \param theIndices a list of indices of elements to be removed MODEL_EXPORT virtual void remove(const std::set& theIndices); - /// Returns the number ofselection attributes in the list + /// Returns the number of selection attributes in the list MODEL_EXPORT virtual int size(); /// Returns true if the object with the shape are in list /// \param theContext object where the sub-shape was selected /// \param theSubShape selected sub-shape (if null, the whole context is selected) /// \param theTemporarily if it is true, it checks also the temporary added item - /// \returns true if the pair is found in the attirbute + /// \returns true if the pair is found in the attribute MODEL_EXPORT virtual bool isInList( const ObjectPtr& theContext, const std::shared_ptr& theSubShape, const bool theTemporarily = false); @@ -116,9 +114,7 @@ public: MODEL_EXPORT virtual void setGeometricalSelection(const bool theIsGeometricalSelection) override; /// Returns true if is geometrical selection. - MODEL_EXPORT virtual bool isGeometricalSelection() const override { - return myIsGeometricalSelection; - }; + MODEL_EXPORT virtual bool isGeometricalSelection() const override; protected: /// Objects are created for features automatically diff --git a/src/Model/Model_ResultPart.cpp b/src/Model/Model_ResultPart.cpp index c4f6f309e..dbad51c7b 100644 --- a/src/Model/Model_ResultPart.cpp +++ b/src/Model/Model_ResultPart.cpp @@ -323,6 +323,24 @@ gp_Trsf Model_ResultPart::sumTrsf() { return aResult; } +bool Model_ResultPart::combineGeometrical(const int theIndex, std::string& theNewName) +{ + std::shared_ptr aDoc = std::dynamic_pointer_cast(partDoc()); + if (aDoc.get()) { + AttributeSelectionListPtr aSelAttr = aDoc->selectionInPartFeature(); + AttributeSelectionPtr aThisAttr = aSelAttr->value(theIndex - 1); + if (aThisAttr.get()) { + aThisAttr->combineGeometrical(); + if (aThisAttr->value().get()) { + int anIndex; + theNewName = nameInPart(aThisAttr->value(), anIndex); + return true; + } + } + } + return false; // something is wrong +} + std::shared_ptr Model_ResultPart::shapeInPart( const std::string& theName, const std::string& theType, int& theIndex) { diff --git a/src/Model/Model_ResultPart.h b/src/Model/Model_ResultPart.h index b6a130511..d632ae187 100644 --- a/src/Model/Model_ResultPart.h +++ b/src/Model/Model_ResultPart.h @@ -79,6 +79,8 @@ class Model_ResultPart : public ModelAPI_ResultPart /// Returns the shape by the name in the part MODEL_EXPORT virtual std::shared_ptr shapeInPart( const std::string& theName, const std::string& theType, int& theIndex); + /// Updates the selection inside of the part as a geometrical selection + MODEL_EXPORT virtual bool combineGeometrical(const int theIndex, std::string& theNewName); /// Updates the shape-result of the part (called on Part feature execution) MODEL_EXPORT virtual void updateShape(); /// Applies the additional transformation of the part diff --git a/src/ModelAPI/ModelAPI_AttributeSelection.h b/src/ModelAPI/ModelAPI_AttributeSelection.h index 93ad948d5..d2dec5bc4 100644 --- a/src/ModelAPI/ModelAPI_AttributeSelection.h +++ b/src/ModelAPI/ModelAPI_AttributeSelection.h @@ -124,6 +124,8 @@ class ModelAPI_AttributeSelection : public ModelAPI_Attribute /// Returns the name by context. Adds the part name if the context is located in other document MODELAPI_EXPORT virtual std::string contextName(const ResultPtr& theContext) const = 0; + /// Makes the current local selection becomes all sub-shapes with same base geometry. + MODELAPI_EXPORT virtual void combineGeometrical() = 0; protected: /// Objects are created for features automatically diff --git a/src/ModelAPI/ModelAPI_ResultPart.h b/src/ModelAPI/ModelAPI_ResultPart.h index 418e2d9d9..db0baf99c 100644 --- a/src/ModelAPI/ModelAPI_ResultPart.h +++ b/src/ModelAPI/ModelAPI_ResultPart.h @@ -87,6 +87,9 @@ class ModelAPI_ResultPart : public ModelAPI_Result virtual std::shared_ptr shapeInPart( const std::string& theName, const std::string& theType, int& theIndex) = 0; + /// Updates the selection inside of the part as a geometrical selection + virtual bool combineGeometrical(const int theIndex, std::string& theNewName) = 0; + /// Returns the shape selected in the selection index virtual std::shared_ptr selectionValue(const int theIndex) = 0; diff --git a/src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp b/src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp index 9a2007cd9..b17d97413 100755 --- a/src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp +++ b/src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp @@ -160,9 +160,6 @@ ModuleBase_WidgetMultiSelector::ModuleBase_WidgetMultiSelector(QWidget* theParen aMainLay->addWidget(myListView->getControl(), 2, 0, 1, -1); aMainLay->setRowStretch(2, 1); - //aMainLay->addWidget(new QLabel(this)); //FIXME(sbh)??? - //aMainLay->setRowMinimumHeight(3, 20); - //this->setLayout(aMainLay); connect(myTypeCtrl, SIGNAL(valueChanged(int)), this, SLOT(onSelectionTypeChanged())); bool aSameTop = theData->getBooleanAttribute("same_topology", false); @@ -250,9 +247,9 @@ bool ModuleBase_WidgetMultiSelector::restoreValueCustom() return false; AttributePtr anAttribute = myFeature->data()->attribute(attributeID()); + AttributeSelectionListPtr aSelectionListAttr = myFeature->data()->selectionList(attributeID()); std::string aType = anAttribute->attributeType(); if (aType == ModelAPI_AttributeSelectionList::typeId()) { - AttributeSelectionListPtr aSelectionListAttr = myFeature->data()->selectionList(attributeID()); // Restore shape type std::string aSelectionType = aSelectionListAttr->selectionType().c_str(); if (!aSelectionType.empty()) { @@ -261,6 +258,7 @@ bool ModuleBase_WidgetMultiSelector::restoreValueCustom() myIsFirst = false; } } + myGeomCheck->setChecked(aSelectionListAttr->isGeometricalSelection()); updateSelectionList(); return true; } @@ -1058,7 +1056,6 @@ void ModuleBase_WidgetMultiSelector::onSameTopology(bool theOn) std::string aType = anAttribute->attributeType(); if (aType == ModelAPI_AttributeSelectionList::typeId()) { AttributeSelectionListPtr aSelectionListAttr = myFeature->data()->selectionList(attributeID()); - //TODO: set same topology flag aSelectionListAttr->setGeometricalSelection(theOn); updateObject(myFeature); } diff --git a/src/Selector/Selector_Selector.cpp b/src/Selector/Selector_Selector.cpp index 4f5f62f2e..140294004 100644 --- a/src/Selector/Selector_Selector.cpp +++ b/src/Selector/Selector_Selector.cpp @@ -75,6 +75,7 @@ static const std::string kPUREWEAK_NAME_IDENTIFIER = "_weak_name_"; Selector_Selector::Selector_Selector(TDF_Label theLab) : myLab(theLab) { myWeakIndex = -1; + myAlwaysGeometricalNaming = false; } TDF_Label Selector_Selector::label() @@ -362,7 +363,7 @@ bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape { // iterate all sub-shapes and select them on sublabels for(TopoDS_Iterator aSubIter(theValue); aSubIter.More(); aSubIter.Next()) { if (!selectBySubSelector(theContext, aSubIter.Value(), - theGeometricalNaming, theUseNeighbors, theUseIntersections)) { + false, theUseNeighbors, theUseIntersections)) {//for subs no geometrical naming allowed return false; // if some selector is failed, everything is failed } } @@ -461,8 +462,20 @@ bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape } } - // weak naming to distinguish commons coming from intersection if (aLastCommon.Extent() > 1) { + if (myAlwaysGeometricalNaming) { + TopoDS_ListOfShape::Iterator aCommonIter(aLastCommon); + TopoDS_Shape aFirst = aCommonIter.Value(); + for(aCommonIter.Next(); aCommonIter.More(); aCommonIter.Next()) { + if (!sameGeometry(aFirst, aCommonIter.Value())) + break; + } + if (!aCommonIter.More()) { // all geometry is same, result is a compound + myType = SELTYPE_INTERSECT; + return true; + } + } + // weak naming to distinguish commons coming from intersection Selector_NExplode aNexp(aLastCommon); myWeakIndex = aNexp.index(theValue); if (myWeakIndex != -1) { @@ -580,6 +593,18 @@ bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape findModificationResult(aCommon); // trying to search by neighbors if (aCommon.Extent() > 1) { // more complicated selection + if (myAlwaysGeometricalNaming) { + TopoDS_ListOfShape::Iterator aCommonIter(aCommon); + TopoDS_Shape aFirst = aCommonIter.Value(); + for(aCommonIter.Next(); aCommonIter.More(); aCommonIter.Next()) { + if (!sameGeometry(aFirst, aCommonIter.Value())) + break; + } + if (!aCommonIter.More()) { // all geometry is same, result is a compound + myType = SELTYPE_MODIFICATION; + return true; + } + } if (!theUseNeighbors) return false; @@ -622,7 +647,20 @@ bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape } } // filter by neighbors did not help - if (aCommon.Extent() > 1) { // weak naming between the common results + if (aCommon.Extent() > 1) { + if (myAlwaysGeometricalNaming) { + TopoDS_ListOfShape::Iterator aCommonIter(aCommon); + TopoDS_Shape aFirst = aCommonIter.Value(); + for(aCommonIter.Next(); aCommonIter.More(); aCommonIter.Next()) { + if (!sameGeometry(aFirst, aCommonIter.Value())) + break; + } + if (!aCommonIter.More()) { // all geometry is same, result is a compound + myType = SELTYPE_FILTER_BY_NEIGHBOR; + return true; + } + } + // weak naming between the common results Selector_NExplode aNexp(aCommon); myWeakIndex = aNexp.index(theValue); if (myWeakIndex == -1) @@ -1361,3 +1399,40 @@ bool Selector_Selector::selectBySubSelector(const TopoDS_Shape theContext, } return true; } + +void Selector_Selector::combineGeometrical(const TopoDS_Shape theContext) +{ + TopoDS_Shape aValue = value(); + if (aValue.IsNull() || aValue.ShapeType() == TopAbs_COMPOUND) + return; + myAlwaysGeometricalNaming = true; + mySubSelList.clear(); + myBases.Clear(); + myWeakIndex = -1; + if (select(theContext, aValue, true)) { + store(); + solve(theContext); + return; + } + // if can not select, select the compound in a custom way + TopTools_MapOfShape aMap; + TopoDS_ListOfShape aList; + for(TopExp_Explorer anExp(theContext, aValue.ShapeType()); anExp.More(); anExp.Next()) { + if (aMap.Add(anExp.Current())) { + if (sameGeometry(aValue, anExp.Current())) + aList.Append(anExp.Current()); + } + } + if (aList.Size() > 1) { + TopoDS_Builder aBuilder; + TopoDS_Compound aCompound; + aBuilder.MakeCompound(aCompound); + for(TopoDS_ListIteratorOfListOfShape aListIter(aList); aListIter.More(); aListIter.Next()) { + aBuilder.Add(aCompound, aListIter.Value()); + } + if (select(theContext, aCompound, true)) { + store(); + solve(theContext); + } + } +} diff --git a/src/Selector/Selector_Selector.h b/src/Selector/Selector_Selector.h index fa069c4aa..46f2db6e5 100644 --- a/src/Selector/Selector_Selector.h +++ b/src/Selector/Selector_Selector.h @@ -62,6 +62,7 @@ class Selector_Selector TDF_Label myBaseDocumentLab; ///< an access-label to the document that may contain initial shapes bool myGeometricalNaming; ///< flag that indicates that geometrical naming selection is enabled + bool myAlwaysGeometricalNaming; /// to enable geometrical naming from beginning, at select public: /// Initializes selector on the label @@ -105,6 +106,9 @@ public: /// Returns the naming name of the selection SELECTOR_EXPORT std::string name(Selector_NameGenerator* theNameGenerator); + /// Makes the current local selection becomes all sub-shapes with same base geometry. + SELECTOR_EXPORT void combineGeometrical(const TopoDS_Shape theContext); + private: /// Create and keep in the list the sub-selector that select the given value. -- 2.39.2