X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSelector%2FSelector_FilterByNeighbors.cpp;h=49992956baf17b69272e20cdb32a5b6e949e68c5;hb=380f01e1fce1a012267d604a1190d04bf4659447;hp=41049e877f606a0b20a7b3c28255381056c64a68;hpb=6ec24b345160a20a44a0079be4ae87b7936fc276;p=modules%2Fshaper.git diff --git a/src/Selector/Selector_FilterByNeighbors.cpp b/src/Selector/Selector_FilterByNeighbors.cpp index 41049e877..49992956b 100644 --- a/src/Selector/Selector_FilterByNeighbors.cpp +++ b/src/Selector/Selector_FilterByNeighbors.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2017 CEA/DEN, EDF R&D +// Copyright (C) 2014-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 @@ -12,10 +12,9 @@ // // 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 +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -// See http://www.salome-platform.org/ or -// email : webmaster.salome@opencascade.com +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // #include @@ -42,19 +41,32 @@ static void findNeighbors(const TopoDS_Shape theContext, const TopoDS_Shape theV const int theLevel, TopTools_MapOfShape& theResult) { TopAbs_ShapeEnum aConnectorType = TopAbs_VERTEX; // type of the connector sub-shapes - if (theValue.ShapeType() == TopAbs_FACE) + TopAbs_ShapeEnum aValueType = theValue.ShapeType(); + if (aValueType == TopAbs_FACE) aConnectorType = TopAbs_EDGE; + else if (aValueType == TopAbs_COMPOUND) { // for geometrical naming: compound of faces + TopExp_Explorer anExp(theValue, TopAbs_FACE); + if (anExp.More()) { + aConnectorType = TopAbs_EDGE; + aValueType = TopAbs_FACE; + } else { + aValueType = TopAbs_EDGE; + } + } TopTools_MapOfShape aNBConnectors; // connector shapes that already belong to neighbors - for(TopExp_Explorer aValExp(theValue, aConnectorType); aValExp.More(); aValExp.Next()) { + for(TopExp_Explorer aValExp(theValue, aConnectorType); aValExp.More(); aValExp.Next()) aNBConnectors.Add(aValExp.Current()); - } TopTools_MapOfShape alreadyProcessed; - alreadyProcessed.Add(theValue); + if (aValueType == theValue.ShapeType()) + alreadyProcessed.Add(theValue); + else + for(TopExp_Explorer aValExp(theValue, aValueType); aValExp.More(); aValExp.Next()) + alreadyProcessed.Add(aValExp.Current()); for(int aLevel = 1; aLevel <= theLevel; aLevel++) { TopoDS_ListOfShape aGoodCandidates; - TopExp_Explorer aCandidate(theContext, theValue.ShapeType()); + TopExp_Explorer aCandidate(theContext, aValueType); for(; aCandidate.More(); aCandidate.Next()) { if (alreadyProcessed.Contains(aCandidate.Current())) continue; @@ -102,18 +114,16 @@ static const TopoDS_Shape findNeighbor(const TopoDS_Shape theContext, if (aNBIter->second == aMinLevel) { TopTools_MapOfShape aThisNBs; findNeighbors(theContext, aNBIter->first, aMinLevel, aThisNBs); - // aMatches must contain common part of all NBs lists - for(TopTools_MapOfShape::Iterator aThisNB(aThisNBs); aThisNB.More(); aThisNB.Next()) { - if (aFirst) { + if (aFirst) { // aMatches must contain common part of all NBs lists + for(TopTools_MapOfShape::Iterator aThisNB(aThisNBs); aThisNB.More(); aThisNB.Next()) { aMatches.Append(aThisNB.Value()); - } else { - // remove all in aMatches which are not in this NBs - for(TopoDS_ListOfShape::Iterator aMatch(aMatches); aMatch.More(); ) { - if (aThisNBs.Contains(aMatch.Value())) { - aMatch.Next(); - } else { - aMatches.Remove(aMatch); - } + } + } else { // remove all in aMatches which are not in this NBs + for(TopoDS_ListOfShape::Iterator aMatch(aMatches); aMatch.More(); ) { + if (aThisNBs.Contains(aMatch.Value())) { + aMatch.Next(); + } else { + aMatches.Remove(aMatch); } } } @@ -155,6 +165,7 @@ static const TopoDS_Shape findNeighbor(const TopoDS_Shape theContext, } else return TopoDS_Shape(); } + break; // no more NBs with higher levels } if (!aLevelNBs.IsEmpty()) { TopTools_MapOfShape aNBsOfCandidate; @@ -176,12 +187,16 @@ static const TopoDS_Shape findNeighbor(const TopoDS_Shape theContext, return aGoodCandidate; } -bool Selector_FilterByNeighbors::select(const TopoDS_Shape theContext, const TopoDS_Shape theValue) +bool Selector_FilterByNeighbors::select( + const TDF_Label theContextLab, const TopoDS_Shape theContext, const TopoDS_Shape theValue) { myShapeType = theValue.ShapeType(); + myContext = theContextLab; // searching by neighbors std::list > aNBs; /// neighbor sub-shape -> level of neighborhood - for(int aLevel = 1; true; aLevel++) { + // # 19071 : moving through all levels may be too long, in practice there are no more than 2 or 3 + // levels real cases, so, make it "5" as maximum possible + for(int aLevel = 1; aLevel < 5; aLevel++) { TopTools_MapOfShape aNewNB; findNeighbors(theContext, theValue, aLevel, aNewNB); if (aNewNB.Extent() == 0) { // there are no neighbors of the given level, stop iteration @@ -230,13 +245,18 @@ void Selector_FilterByNeighbors::store() TDataStd_IntegerArray::Set(label(), kLEVELS_ARRAY, 0, int(myNBLevel.size()) - 1); std::list::iterator aLevel = myNBLevel.begin(); for(int anIndex = 0; aLevel != myNBLevel.end(); aLevel++, anIndex++) { - anArray->SetValue(anIndex, *aLevel); + anArray->SetValue(anIndex, Abs(*aLevel)); } // store all sub-selectors std::list::const_iterator aSubSel = list().cbegin(); for(; aSubSel != list().cend(); aSubSel++) { (*aSubSel)->store(); } + // store context reference if exists + if (!myContext.IsNull()) { + static const TDF_LabelList anEmptyRefList; + storeBaseArray(anEmptyRefList, myContext); + } } bool Selector_FilterByNeighbors::restore() @@ -253,30 +273,43 @@ bool Selector_FilterByNeighbors::restore() myNBLevel.push_back(anArray->Value(anIndex)); } // restore sub-selectors - bool aSubResult = true; for(TDF_ChildIterator aSub(label(), false); aSub.More(); aSub.Next()) { Selector_Algo* aSubSel = restoreByLab(aSub.Value(), baseDocument()); if (!append(aSubSel, false)) { - break; // some empty label left in the end + if (!aSub.Value().HasAttribute()) + break; // some empty label left in the end + // some selector fails, try to use rest selectors, myNBLevel becomes negative: unused + if (myNBLevel.size() > list().size()) { + std::list::iterator aListIter = myNBLevel.begin(); + for(size_t a = 0; a < list().size(); a++) + aListIter++; + *aListIter = -*aListIter; + list().push_back(NULL); + } } } - return true; + // restore context reference if exists + static TDF_LabelList anEmptyRefList; + restoreBaseArray(anEmptyRefList, myContext); + + return myNBLevel.size() == list().size() && !myNBLevel.empty(); } -TDF_Label Selector_FilterByNeighbors::restoreByName(std::string theName, +TDF_Label Selector_FilterByNeighbors::restoreByName(std::wstring theName, const TopAbs_ShapeEnum theShapeType, Selector_NameGenerator* theNameGenerator) { 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); + std::wstring aLastLevel; // last level string (after '(' ) to check the context name in the end + for (size_t aStart = 0; aStart != std::wstring::npos; + aStart = theName.find(L'(', aStart + 1)) { + size_t anEndPos = theName.find(L')', aStart + 1); + if (anEndPos != std::wstring::npos) { + std::wstring aSubStr = theName.substr(aStart + 1, anEndPos - aStart - 1); TDF_Label aSubContext; Selector_Algo* aSubSel = - Selector_Algo::restoreByName( - newSubLabel(), baseDocument(), aSubStr, myShapeType, theNameGenerator, aSubContext); + Selector_Algo::restoreByName(newSubLabel(), baseDocument(), aSubStr, myShapeType, + geometricalNaming(), theNameGenerator, aSubContext); if (!append(aSubSel)) return TDF_Label(); @@ -291,20 +324,21 @@ TDF_Label Selector_FilterByNeighbors::restoreByName(std::string theName, } else { aContext = aSubContext; } - if (!aContext.IsNull()) // for filters by neighbor the latest context shape is vital - aContext = theNameGenerator->newestContext(aContext); + //if (!aContext.IsNull()) // for filters by neighbor the latest context shape is vital + // aContext = theNameGenerator->newestContext(aContext); // searching for the level index - std::string aLevel; - for (anEndPos++; anEndPos != std::string::npos && - theName[anEndPos] != '(' && theName[anEndPos] != 0; + std::wstring aLevel; + for (anEndPos++; anEndPos != std::wstring::npos && + theName[anEndPos] != L'(' && theName[anEndPos] != 0; anEndPos++) { aLevel += theName[anEndPos]; } - if (aLevel.empty()) + aLastLevel = aLevel; + if (aLevel.empty() || aLevel[0] == L'_') myNBLevel.push_back(1); // by default it is 1 else { - int aNum = atoi(aLevel.c_str()); + int aNum = std::stoi(aLevel.c_str()); if (aNum > 0) myNBLevel.push_back(aNum); else @@ -313,6 +347,20 @@ TDF_Label Selector_FilterByNeighbors::restoreByName(std::string theName, } else return TDF_Label(); // invalid parentheses } + if (!aLastLevel.empty()) { // get the context + size_t aLinePos = aLastLevel.find(L"_"); + if (aLinePos != std::wstring::npos) { + std::wstring aContextName = aLastLevel.substr(aLinePos + 1); + if (!aContextName.empty()) { + TDF_Label aThisContext, aValue; + if (theNameGenerator->restoreContext(aContextName, aThisContext, aValue)) { + if (!aThisContext.IsNull()) + aContext = aThisContext; + } + } + } + } + myContext = aContext; return aContext; } @@ -324,32 +372,49 @@ bool Selector_FilterByNeighbors::solve(const TopoDS_Shape& theContext) std::list::iterator aLevel = myNBLevel.begin(); std::list::const_iterator aSubSel = list().cbegin(); for(; aSubSel != list().cend(); aSubSel++, aLevel++) { - if (!(*aSubSel)->solve(theContext)) { - return false; + if (*aLevel < 0) + continue; // skip because sub-selector is not good + if ((*aSubSel)->solve(theContext)) { + aNBs.push_back(std::pair((*aSubSel)->value(), *aLevel)); } - aNBs.push_back(std::pair((*aSubSel)->value(), *aLevel)); } - aResult = findNeighbor(theContext, aNBs, geometricalNaming()); - if (!aResult.IsNull()) { - Selector_Algo::store(aResult); - return true; + if (!aNBs.empty()) { + aResult = findNeighbor(theContext, aNBs, geometricalNaming()); + if (!aResult.IsNull()) { + Selector_Algo::store(aResult); + return true; + } } return false; } -std::string Selector_FilterByNeighbors::name(Selector_NameGenerator* theNameGenerator) +std::wstring Selector_FilterByNeighbors::name(Selector_NameGenerator* theNameGenerator) { // (nb1)level_if_more_than_1(nb2)level_if_more_than_1(nb3)level_if_more_than_1 - std::string aResult; + bool aThisContextNameNeeded = !myContext.IsNull(); + std::wstring aContextName; + if (aThisContextNameNeeded) + aContextName = theNameGenerator->contextName(myContext); + std::wstring aResult; std::list::iterator aLevel = myNBLevel.begin(); std::list::const_iterator aSubSel = list().cbegin(); for(; aSubSel != list().cend(); aSubSel++, aLevel++) { - aResult += "(" + (*aSubSel)->name(theNameGenerator) + ")"; + if (!*aSubSel) + continue; + std::wstring aSubName = (*aSubSel)->name(theNameGenerator); + aResult += L"(" + aSubName + L")"; if (*aLevel > 1) { - std::ostringstream aLevelStr; + std::wostringstream aLevelStr; aLevelStr<<*aLevel; aResult += aLevelStr.str(); } + // sub-name already contains the needed context name, so, here it is not needed + if (aThisContextNameNeeded && ( + aSubName.find(aContextName) == 0 || aSubName.substr(1).find(aContextName) == 0)) + aThisContextNameNeeded = false; + } + if (aThisContextNameNeeded) { + aResult = aResult + L"_" + aContextName; } return aResult; }