From f9905f6001261b6b1956c3589164dee3dcb04f51 Mon Sep 17 00:00:00 2001 From: mpv Date: Thu, 18 Oct 2018 17:29:21 +0300 Subject: [PATCH] Support of all types of selection in python names import --- src/Model/Model_AttributeSelection.cpp | 21 ++++- src/Model/Model_AttributeSelection.h | 4 + src/Selector/Selector_NameGenerator.h | 3 + src/Selector/Selector_Selector.cpp | 115 ++++++++++++++++++++++--- src/Selector/Selector_Selector.h | 3 +- 5 files changed, 131 insertions(+), 15 deletions(-) diff --git a/src/Model/Model_AttributeSelection.cpp b/src/Model/Model_AttributeSelection.cpp index 148dbb9b6..b1e9281c8 100644 --- a/src/Model/Model_AttributeSelection.cpp +++ b/src/Model/Model_AttributeSelection.cpp @@ -342,8 +342,8 @@ std::shared_ptr Model_AttributeSelection::internalValue(CenterTyp if (myRef.isInitialized()) { if (aSelLab.IsAttribute(kSIMPLE_REF_ID)) { // it is just reference to shape, not sub-shape ResultPtr aContext = context(); - if (!aContext.get()) - return aResult; // empty result + if (!aContext.get() || aContext->groupName() == ModelAPI_ResultConstruction::group()) + return aResult; // empty result, for whole construction selection also return aContext->shape(); } if (aSelLab.IsAttribute(kPART_REF_ID)) { @@ -955,6 +955,7 @@ void Model_AttributeSelection::selectSubShape( CenterType aCenterType = theType[0] == 'v' || theType[0] == 'V' ? // only for vertex-type centerTypeByName(aSubShapeName) : NOT_CENTER; std::string aType = aCenterType == NOT_CENTER ? theType : "EDGE"; // search for edge now + TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(GeomAPI_Shape::shapeTypeByStr(theType)); static const GeomShapePtr anEmptyShape; // first iteration is selection by name without center prefix, second - in case of problem, @@ -1010,7 +1011,7 @@ void Model_AttributeSelection::selectSubShape( Selector_Selector aSelector(aDoc->generalLabel()); myRestoreDocument = aDoc; - TDF_Label aContextLabel = aSelector.restoreByName(aSubShapeName, this); + TDF_Label aContextLabel = aSelector.restoreByName(aSubShapeName, aShapeType, this); myRestoreDocument.reset(); if (!aContextLabel.IsNull()) { ResultPtr aContext = aDoc->resultByLab(aContextLabel); // any label for document access @@ -1767,3 +1768,17 @@ bool Model_AttributeSelection::restoreContext(std::string theName, } return true; } + +bool Model_AttributeSelection::isLater( + const TDF_Label theResult1, const TDF_Label theResult2) const +{ + std::shared_ptr aDoc = myRestoreDocument.get() ? myRestoreDocument : + std::dynamic_pointer_cast(owner()->document()); + FeaturePtr aFeat1 = aDoc->featureByLab(theResult1); + if (!aFeat1.get()) + return false; + FeaturePtr aFeat2 = aDoc->featureByLab(theResult2); + if (!aFeat2.get()) + return false; + return aDoc->isLater(aFeat1, aFeat2); +} diff --git a/src/Model/Model_AttributeSelection.h b/src/Model/Model_AttributeSelection.h index 187115e51..aaf506295 100644 --- a/src/Model/Model_AttributeSelection.h +++ b/src/Model/Model_AttributeSelection.h @@ -141,6 +141,10 @@ public: MODEL_EXPORT virtual bool restoreContext(std::string theName, TDF_Label& theContext, TDF_Label& theValue) override; + /// Returns true if the first result is newer than the second one in the tree of features + MODEL_EXPORT virtual bool isLater(const TDF_Label theResult1, const TDF_Label theResult2) + const override; + protected: /// Objects are created for features automatically MODEL_EXPORT Model_AttributeSelection(TDF_Label& theLabel); diff --git a/src/Selector/Selector_NameGenerator.h b/src/Selector/Selector_NameGenerator.h index 079316afa..4a06abc07 100644 --- a/src/Selector/Selector_NameGenerator.h +++ b/src/Selector/Selector_NameGenerator.h @@ -44,6 +44,9 @@ public: /// sub-label where the value is. Returns true if it is valid. virtual bool restoreContext(std::string theName, TDF_Label& theContext, TDF_Label& theValue) = 0; + + /// Returns true if the first result is older than the second one in the tree of features + virtual bool isLater(const TDF_Label theResult1, const TDF_Label theResult2) const = 0; }; #endif diff --git a/src/Selector/Selector_Selector.cpp b/src/Selector/Selector_Selector.cpp index 22238b816..c1c86cda3 100644 --- a/src/Selector/Selector_Selector.cpp +++ b/src/Selector/Selector_Selector.cpp @@ -734,12 +734,12 @@ std::string Selector_Selector::name(Selector_NameGenerator* theNameGenerator) { case SELTYPE_CONTAINER: case SELTYPE_INTERSECT: { std::string aResult; - // add names of sub-components one by one separated by "&" + // add names of sub-components one by one in "[]" std::list::iterator aSubSel = mySubSelList.begin(); for(; aSubSel != mySubSelList.end(); aSubSel++) { - if (aSubSel != mySubSelList.begin()) - aResult += "&"; + aResult += '['; aResult += aSubSel->name(theNameGenerator); + aResult += ']'; } return aResult; } @@ -751,13 +751,13 @@ std::string Selector_Selector::name(Selector_NameGenerator* theNameGenerator) { std::string(TCollection_AsciiString(aName->Get()).ToCString()); } case SELTYPE_MODIFICATION: { - // final&/base1&base2 + // final&base1&base2 std::string aResult; Handle(TDataStd_Name) aName; if (!myFinal.FindAttribute(TDataStd_Name::GetID(), aName)) return ""; aResult += theNameGenerator->contextName(myFinal) + "/" + - std::string(TCollection_AsciiString(aName->Get()).ToCString()) + "&/"; + std::string(TCollection_AsciiString(aName->Get()).ToCString()) + "&"; for(TDF_LabelList::iterator aBase = myBases.begin(); aBase != myBases.end(); aBase++) { if (aBase != myBases.begin()) aResult += "&"; @@ -774,13 +774,11 @@ std::string Selector_Selector::name(Selector_NameGenerator* theNameGenerator) { return aResult; } case SELTYPE_FILTER_BY_NEIGHBOR: { - // (nb1)level_if_more_than_1&(nb2)level_if_more_than_1&(nb3)level_if_more_than_1 + // (nb1)level_if_more_than_1(nb2)level_if_more_than_1(nb3)level_if_more_than_1 std::string aResult; std::list::iterator aLevel = myNBLevel.begin(); std::list::iterator aSubSel = mySubSelList.begin(); for(; aSubSel != mySubSelList.end(); aSubSel++, aLevel++) { - if (aSubSel != mySubSelList.begin()) - aResult += "&"; aResult += "(" + aSubSel->name(theNameGenerator) + ")"; if (*aLevel > 1) aResult += *aLevel; @@ -793,17 +791,112 @@ std::string Selector_Selector::name(Selector_NameGenerator* theNameGenerator) { return ""; } -TDF_Label Selector_Selector::restoreByName(std::string theName, +TDF_Label Selector_Selector::restoreByName( + std::string theName, const TopAbs_ShapeEnum theShapeType, Selector_NameGenerator* theNameGenerator) { - if (theName.find('&') == std::string::npos) { // wihtout '&' it can be only primitive + if (theName[0] == '[') { // intersection or container + switch(theShapeType) { + case TopAbs_COMPOUND: + case TopAbs_COMPSOLID: + case TopAbs_SHELL: + case TopAbs_WIRE: + myType = SELTYPE_CONTAINER; + break; + case TopAbs_EDGE: + case TopAbs_FACE: + myType = SELTYPE_INTERSECT; + break; + default: + return TDF_Label(); // unknown case + } + myShapeType = theShapeType; + TDF_Label aContext; + for(size_t aStart = 0; aStart != std::string::npos; + aStart = theName.find('[', aStart + 1)) { + size_t anEndPos = theName.find(']', aStart + 1); + if (anEndPos != std::string::npos) { + std::string aSubStr = theName.substr(aStart + 1, anEndPos - aStart - 1); + mySubSelList.push_back(Selector_Selector(myLab.FindChild(int(mySubSelList.size()) + 1))); + TDF_Label aSubContext = + mySubSelList.back().restoreByName(aSubStr, theShapeType, theNameGenerator); + if (aSubContext.IsNull()) + return aSubContext; // invalid sub-selection parsing + if (!aContext.IsNull() && !aContext.IsEqual(aSubContext)) { + if (theNameGenerator->isLater(aSubContext, aContext)) + aContext = aSubContext; + } else { + aContext = aSubContext; + } + } else + return TDF_Label(); // invalid parentheses + } + return aContext; + } else if (theName[0] == '(') { // filter by neighbours + myType = SELTYPE_FILTER_BY_NEIGHBOR; + TDF_Label aContext; + for(size_t aStart = 0; aStart != std::string::npos; + aStart = theName.find('(', aStart + 1)) { + size_t anEndPos = theName.find(')', aStart + 1); + if (anEndPos != std::string::npos) { + std::string aSubStr = theName.substr(aStart + 1, anEndPos - aStart - 1); + mySubSelList.push_back(Selector_Selector(myLab.FindChild(int(mySubSelList.size()) + 1))); + TDF_Label aSubContext = + mySubSelList.back().restoreByName(aSubStr, theShapeType, theNameGenerator); + if (aSubContext.IsNull()) + return aSubContext; // invalid sub-selection parsing + if (!aContext.IsNull() && !aContext.IsEqual(aSubContext)) { + if (theNameGenerator->isLater(aSubContext, aContext)) + aContext = aSubContext; + } else { + aContext = aSubContext; + } + // searching for the level index + std::string aLevel; + for(anEndPos++; anEndPos != std::string::npos && + theName[anEndPos] != '(' && theName[anEndPos] != 0; + anEndPos++) { + aLevel += theName[anEndPos]; + } + if (aLevel.empty()) + myNBLevel.push_back(1); // by default it is 1 + else { + int aNum = atoi(aLevel.c_str()); + if (aNum > 0) + myNBLevel.push_back(aNum); + else + return TDF_Label(); // invalid number + } + } else + return TDF_Label(); // invalid parentheses + } + return aContext; + } else if (theName.find('&') == std::string::npos) { // wihtout '&' it can be only primitive myType = SELTYPE_PRIMITIVE; TDF_Label aContext; if (theNameGenerator->restoreContext(theName, aContext, myFinal)) { if (!myFinal.IsNull()) return aContext; } - } else { + } else { // modification + myType = SELTYPE_MODIFICATION; + TDF_Label aContext; + for(size_t anEnd, aStart = 0; aStart != std::string::npos; aStart = anEnd) { + anEnd = theName.find('&', aStart + 1); + std::string aSubStr = theName.substr(aStart == 0 ? 0 : aStart + 1, + anEnd == std::string::npos ? anEnd : anEnd - aStart); + TDF_Label aSubContext, aValue; + if (!theNameGenerator->restoreContext(aSubStr, aSubContext, aValue)) + return TDF_Label(); // can not restore + if(aSubContext.IsNull() || aValue.IsNull()) + return TDF_Label(); // can not restore + if (myFinal.IsNull()) { + myFinal = aValue; + aContext = aSubContext; + } else + myBases.Append(aValue); + } + return aContext; } return TDF_Label(); } diff --git a/src/Selector/Selector_Selector.h b/src/Selector/Selector_Selector.h index 5836c2874..a91816c36 100644 --- a/src/Selector/Selector_Selector.h +++ b/src/Selector/Selector_Selector.h @@ -78,7 +78,8 @@ class Selector_Selector /// Restores the selected shape by the topological name string. /// Returns not empty label of the context. - SELECTOR_EXPORT TDF_Label restoreByName(std::string theName, + SELECTOR_EXPORT TDF_Label restoreByName( + std::string theName, const TopAbs_ShapeEnum theShapeType, Selector_NameGenerator* theNameGenerator); /// Updates the current shape by the stored topological name -- 2.39.2