-// 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
//
// 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<mailto:webmaster.salome@opencascade.com>
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
#include <Selector_FilterByNeighbors.h>
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;
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);
}
}
}
} else
return TopoDS_Shape();
}
+ break; // no more NBs with higher levels
}
if (!aLevelNBs.IsEmpty()) {
TopTools_MapOfShape aNBsOfCandidate;
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<std::pair<TopoDS_Shape, int> > 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
TDataStd_IntegerArray::Set(label(), kLEVELS_ARRAY, 0, int(myNBLevel.size()) - 1);
std::list<int>::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<Selector_Algo*>::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()
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<int>::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();
} 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
} 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;
}
std::list<int>::iterator aLevel = myNBLevel.begin();
std::list<Selector_Algo*>::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<TopoDS_Shape, int>((*aSubSel)->value(), *aLevel));
}
- aNBs.push_back(std::pair<TopoDS_Shape, int>((*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<int>::iterator aLevel = myNBLevel.begin();
std::list<Selector_Algo*>::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;
}