1 // Copyright (C) 2014-2017 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
21 #include <Selector_Selector.h>
23 #include <Selector_NameGenerator.h>
25 #include <TDF_ChildIDIterator.hxx>
26 #include <TopoDS_Iterator.hxx>
27 #include <TopoDS_Builder.hxx>
28 #include <TopExp_Explorer.hxx>
29 #include <TNaming_Tool.hxx>
30 #include <TNaming_NewShapeIterator.hxx>
31 #include <TNaming_OldShapeIterator.hxx>
32 #include <TNaming_SameShapeIterator.hxx>
33 #include <TNaming_Iterator.hxx>
34 #include <TNaming_Builder.hxx>
35 #include <TopTools_MapOfShape.hxx>
37 #include <TDataStd_Integer.hxx>
38 #include <TDataStd_ReferenceArray.hxx>
39 #include <TDataStd_IntegerArray.hxx>
40 #include <TDataStd_Name.hxx>
44 /// type of the selection, integerm keeps the Selector_Type value
45 static const Standard_GUID kSEL_TYPE("db174d59-c2e3-4a90-955e-55544df090d6");
46 /// type of the shape, stored in case it is intersection or container
47 static const Standard_GUID kSHAPE_TYPE("864b3267-cb9d-4107-bf58-c3ce1775b171");
48 // reference attribute that contains the reference to labels where the "from" or "base" shapes
49 // of selection are located
50 static const Standard_GUID kBASE_ARRAY("7c515b1a-9549-493d-9946-a4933a22f45f");
51 // array of the neighbor levels
52 static const Standard_GUID kLEVELS_ARRAY("ee4c4b45-e859-4e86-aa4f-6eac68e0ca1f");
54 Selector_Selector::Selector_Selector(TDF_Label theLab) : myLab(theLab)
58 TDF_Label Selector_Selector::label()
63 // adds to theResult all labels that contain initial shapes for theValue located in theFinal
64 static void findBases(Handle(TNaming_NamedShape) theFinal, const TopoDS_Shape& theValue,
65 bool aMustBeAtFinal, TDF_LabelList& theResult)
67 TNaming_SameShapeIterator aLabIter(theValue, theFinal->Label());
68 for(; aLabIter.More(); aLabIter.Next()) {
69 Handle(TNaming_NamedShape) aNS;
70 aLabIter.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS);
71 if (aMustBeAtFinal && aNS != theFinal)
72 continue; // looking for old at the same final label only
73 TNaming_Evolution anEvolution = aNS->Evolution();
74 if (anEvolution == TNaming_PRIMITIVE) {
75 // check that this is not in the results already
76 const TDF_Label aResult = aNS->Label();
77 TDF_LabelList::Iterator aResIter(theResult);
78 for(; aResIter.More(); aResIter.Next()) {
79 if (aResIter.Value().IsEqual(aResult))
82 if (!aResIter.More()) // not found, so add this new
83 theResult.Append(aResult);
85 if (anEvolution == TNaming_GENERATED || anEvolution == TNaming_MODIFY) {
86 for(TNaming_Iterator aThisIter(aNS); aThisIter.More(); aThisIter.Next()) {
87 if (aThisIter.NewShape().IsSame(theValue)) {
88 // continue recursively, null NS means that any NS are ok
89 findBases(theFinal, aThisIter.OldShape(), false, theResult);
96 // returns the sub-shapes of theSubType which belong to all theShapes (so, common or intersection)
97 static void commonShapes(const TopoDS_ListOfShape& theShapes, TopAbs_ShapeEnum theSubType,
98 TopoDS_ListOfShape& theResults)
100 TopoDS_ListOfShape::iterator aSubSel = theShapes.begin();
101 for(; aSubSel != theShapes.end(); aSubSel++) {
102 TopTools_MapOfShape aCurrentMap;
103 for(TopExp_Explorer anExp(*aSubSel, theSubType); anExp.More(); anExp.Next()) {
104 if (aCurrentMap.Add(anExp.Current()) && aSubSel == theShapes.begin())
105 theResults.Append(anExp.Current());
107 if (aSubSel != theShapes.begin()) { // remove from common shapes not in aCurrentMap
108 for(TopoDS_ListOfShape::Iterator aComIter(theResults); aComIter.More(); ) {
109 if (aCurrentMap.Contains(aComIter.Value()))
112 theResults.Remove(aComIter);
118 /// Searches neighbor of theLevel of neighborhood to theValue in theContex
119 static void findNeighbors(const TopoDS_Shape theContext, const TopoDS_Shape theValue,
120 const int theLevel, TopTools_MapOfShape& theResult)
122 TopAbs_ShapeEnum aConnectorType = TopAbs_VERTEX; // type of the connector sub-shapes
123 if (theValue.ShapeType() == TopAbs_FACE)
124 aConnectorType = TopAbs_EDGE;
125 TopTools_MapOfShape aNBConnectors; // connector shapes that already belong to neighbors
126 for(TopExp_Explorer aValExp(theValue, aConnectorType); aValExp.More(); aValExp.Next()) {
127 aNBConnectors.Add(aValExp.Current());
130 for(int aLevel = 1; aLevel <= theLevel; aLevel++) {
131 TopoDS_ListOfShape aGoodCandidates;
132 TopExp_Explorer aCandidate(theContext, theValue.ShapeType());
133 for(; aCandidate.More(); aCandidate.Next()) {
134 TopExp_Explorer aCandConnector(aCandidate.Current(), aConnectorType);
135 for(; aCandConnector.More(); aCandConnector.Next()) {
136 if (aNBConnectors.Contains(aCandConnector.Current())) // candidate is neighbor
139 if (aCandConnector.More()) {
140 if (aLevel == theLevel) { // add a NB into result: it is connected to other neighbors
141 theResult.Add(aCandidate.Current());
142 } else { // add to the NB of the current level
143 aGoodCandidates.Append(aCandidate.Current());
147 if (aLevel != theLevel) { // good candidates are added to neighbor of this level by connectors
148 for(TopoDS_ListOfShape::Iterator aGood(aGoodCandidates); aGood.More(); aGood.Next()) {
149 TopExp_Explorer aGoodConnector(aGood.Value(), aConnectorType);
150 for(; aGoodConnector.More(); aGoodConnector.Next()) {
151 aNBConnectors.Add(aGoodConnector.Current());
158 /// Searches the neighbor shape by neighbors defined in theNB in theContext shape
159 static const TopoDS_Shape findNeighbor(const TopoDS_Shape theContext,
160 const std::list<std::pair<TopoDS_Shape, int> >& theNB)
162 // searching for neighbors with minimum level
164 std::list<std::pair<TopoDS_Shape, int> >::const_iterator aNBIter = theNB.cbegin();
165 for(; aNBIter != theNB.cend(); aNBIter++) {
166 if (aMinLevel == 0 || aNBIter->second < aMinLevel) {
167 aMinLevel = aNBIter->second;
170 // collect all neighbors which are neighbors of sub-shapes with minimum level
172 TopoDS_ListOfShape aMatches;
173 for(aNBIter = theNB.cbegin(); aNBIter != theNB.cend(); aNBIter++) {
174 if (aNBIter->second == aMinLevel) {
175 TopTools_MapOfShape aThisNBs;
176 findNeighbors(theContext, aNBIter->first, aMinLevel, aThisNBs);
177 // aMatches must contain common part of all NBs lists
178 for(TopTools_MapOfShape::Iterator aThisNB(aThisNBs); aThisNB.More(); aThisNB.Next()) {
180 aMatches.Append(aThisNB.Value());
182 // remove all in aMatches which are not in this NBs
183 for(TopoDS_ListOfShape::Iterator aMatch(aMatches); aMatch.More(); ) {
184 if (aThisNBs.Contains(aMatch.Value())) {
187 aMatches.Remove(aMatch);
194 if (aMatches.IsEmpty())
195 return TopoDS_Shape(); // not found any candidate
196 if (aMatches.Extent() == 1)
197 return aMatches.First(); // already found good candidate
198 // iterate all matches to find by other (higher level) neighbors the best candidate
199 TopoDS_Shape aGoodCandidate;
200 for(TopoDS_ListOfShape::Iterator aCandidate(aMatches); aCandidate.More(); aCandidate.Next()) {
201 bool aValidCadidate = true;
202 for(int aLevel = aMinLevel + 1; true; aLevel++) {
203 bool aFooundHigherLevel = false;
204 TopoDS_ListOfShape aLevelNBs;
205 for(aNBIter = theNB.cbegin(); aNBIter != theNB.cend(); aNBIter++) {
206 if (aNBIter->second == aLevel)
207 aLevelNBs.Append(aNBIter->first);
208 else if (aNBIter->second >= aLevel)
209 aFooundHigherLevel = true;
211 if (!aFooundHigherLevel && aLevelNBs.IsEmpty()) { // iterated all, so, good candidate
212 if (aGoodCandidate.IsNull()) {
213 aGoodCandidate = aCandidate.Value();
214 } else { // too many good candidates
215 return TopoDS_Shape();
218 if (!aLevelNBs.IsEmpty()) {
219 TopTools_MapOfShape aNBsOfCandidate;
220 findNeighbors(theContext, aCandidate.Value(), aLevel, aNBsOfCandidate);
221 // check all stored neighbors are in the map of real neighbors
222 for(TopoDS_ListOfShape::Iterator aLevIter(aLevelNBs); aLevIter.More(); aLevIter.Next()) {
223 if (!aNBsOfCandidate.Contains(aLevIter.Value())) {
224 aValidCadidate = false;
229 if (!aValidCadidate) // candidate is not valid, break the checking
233 return aGoodCandidate;
236 bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape theValue,
237 const bool theUseNeighbors)
239 if (theValue.IsNull() || theContext.IsNull())
241 // check the value shape can be named as it is, or it is needed to construct it from the
242 // higher level shapes (like a box vertex by faces that form this vertex)
243 if (!TNaming_Tool::HasLabel(myLab, theValue)) {
244 TopAbs_ShapeEnum aSelectionType = theValue.ShapeType();
245 myShapeType = aSelectionType;
246 if (aSelectionType == TopAbs_COMPOUND || aSelectionType == TopAbs_COMPSOLID ||
247 aSelectionType == TopAbs_SHELL || aSelectionType == TopAbs_WIRE)
248 { // iterate all sub-shapes and select them on sublabels
249 for(TopoDS_Iterator aSubIter(theValue); aSubIter.More(); aSubIter.Next()) {
250 if (!selectBySubSelector(theContext, aSubIter.Value())) {
251 return false; // if some selector is failed, everything is failed
254 myType = SELTYPE_CONTAINER;
258 // try to find the shape of the higher level type in the context shape
259 bool aFacesTried = false; // for identification of vertices, faces are tried, then edges
260 while(aSelectionType != TopAbs_FACE || !aFacesTried) {
261 if (aSelectionType == TopAbs_FACE && theValue.ShapeType() == TopAbs_VERTEX) {
263 aSelectionType = TopAbs_EDGE;
265 aSelectionType = TopAbs_FACE;
266 TopTools_MapOfShape anIntersectors; // shapes of aSelectionType that contain theValue
267 TopoDS_ListOfShape anIntList; // same as anIntersectors
268 for(TopExp_Explorer aSelExp(theContext, aSelectionType); aSelExp.More(); aSelExp.Next()) {
269 TopExp_Explorer aSubExp(aSelExp.Current(), theValue.ShapeType());
270 for(; aSubExp.More(); aSubExp.Next()) {
271 if (aSubExp.Current().IsSame(theValue)) {
272 if (anIntersectors.Add(aSelExp.Current()))
273 anIntList.Append(aSelExp.Current());
278 // check that solution is only one
279 TopoDS_ListOfShape aCommon;
280 commonShapes(anIntList, theValue.ShapeType(), aCommon);
281 if (aCommon.Extent() == 1 && aCommon.First().IsSame(theValue)) {
282 // name the intersectors
283 std::list<Selector_Selector> aSubSelList;
284 TopTools_MapOfShape::Iterator anInt(anIntersectors);
285 for (; anInt.More(); anInt.Next()) {
286 if (!selectBySubSelector(theContext, anInt.Value())) {
287 break; // if some selector is failed, stop and search another solution
290 if (!anInt.More()) { // all intersectors were correctly named
291 myType = SELTYPE_INTERSECT;
297 if (!theUseNeighbors)
300 // searching by neighbours
301 std::list<std::pair<TopoDS_Shape, int> > aNBs; /// neighbor sub-shape -> level of neighborhood
302 for(int aLevel = 1; true; aLevel++) {
303 TopTools_MapOfShape aNewNB;
304 findNeighbors(theContext, theValue, aLevel, aNewNB);
305 if (aNewNB.Extent() == 0) { // there are no neighbors of the given level, stop iteration
308 // check which can be named correctly, without by neighbors type
309 for(TopTools_MapOfShape::Iterator aNBIter(aNewNB); aNBIter.More(); ) {
310 Selector_Selector aSelector(myLab.FindChild(1));
311 if (aSelector.select(theContext, aNBIter.Value(), false)) { // add to the list of good NBs
312 aNBs.push_back(std::pair<TopoDS_Shape, int>(aNBIter.Value(), aLevel));
314 aNewNB.Remove(aNBIter.Key());
315 aNBIter.Initialize(aNewNB);
317 TopoDS_Shape aResult = findNeighbor(theContext, aNBs);
318 if (!aResult.IsNull() && aResult.IsSame(theValue)) {
319 std::list<std::pair<TopoDS_Shape, int> >::iterator aNBIter = aNBs.begin();
320 for(; aNBIter != aNBs.end(); aNBIter++) {
321 if (!selectBySubSelector(theContext, aNBIter->first)) {
322 return false; // something is wrong because before this selection was ok
324 myNBLevel.push_back(aNBIter->second);
327 myType = SELTYPE_FILTER_BY_NEIGHBOR;
333 // searching for the base shapes of the value
334 Handle(TNaming_NamedShape) aPrimitiveNS;
335 NCollection_List<Handle(TNaming_NamedShape)> aModifList;
336 for(TNaming_SameShapeIterator aShapes(theValue, myLab); aShapes.More(); aShapes.Next())
338 Handle(TNaming_NamedShape) aNS;
339 if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
340 TNaming_Evolution anEvolution = aNS->Evolution();
341 if (anEvolution == TNaming_PRIMITIVE) { // the value shape is declared as PRIMITIVE
344 } else if (anEvolution == TNaming_GENERATED || anEvolution == TNaming_MODIFY) {
345 // check this is a new shape
346 TNaming_Iterator aNSIter(aNS);
347 for(; aNSIter.More(); aNSIter.Next())
348 if (aNSIter.NewShape().IsSame(theValue))
350 if (aNSIter.More()) // new was found
351 aModifList.Append(aNS);
356 if (!aPrimitiveNS.IsNull()) {
357 myType = SELTYPE_PRIMITIVE;
358 myFinal = aPrimitiveNS->Label();
362 if (aModifList.Extent() > 1) { // searching for the best modification result: by context
363 Handle(TNaming_NamedShape) aCandidate;
364 NCollection_List<Handle(TNaming_NamedShape)>::Iterator aModIter(aModifList);
365 for(; !aModifList.IsEmpty() && aModIter.More(); aModIter.Next()) {
366 aCandidate = aModIter.Value();
367 TDF_Label aFatherLab = aCandidate->Label().Father();
368 Handle(TNaming_NamedShape) aFatherNS;
369 if (aFatherLab.FindAttribute(TNaming_NamedShape::GetID(), aFatherNS)) {
370 for(TNaming_Iterator anIter(aFatherNS); anIter.More(); anIter.Next()) {
371 if (theContext.IsSame(anIter.NewShape())) { // found the best modification
378 // take the best candidate, or the last in the iteration
380 aModifList.Append(aCandidate);
383 if (!aModifList.IsEmpty()) {
384 // searching for all the base shapes of this modification
385 findBases(aModifList.First(), theValue, true, myBases);
386 if (!myBases.IsEmpty()) {
387 myFinal = aModifList.First()->Label();
388 myType = SELTYPE_MODIFICATION;
389 return !myBases.IsEmpty();
393 // not found a good result
397 void Selector_Selector::store()
399 myLab.ForgetAllAttributes(true); // remove old naming data
400 TDataStd_Integer::Set(myLab, kSEL_TYPE, (int)myType);
402 case SELTYPE_CONTAINER:
403 case SELTYPE_INTERSECT: {
404 TDataStd_Integer::Set(myLab, kSHAPE_TYPE, (int)myShapeType);
405 // store also all sub-selectors
406 std::list<Selector_Selector>::iterator aSubSel = mySubSelList.begin();
407 for(; aSubSel != mySubSelList.end(); aSubSel++) {
412 case SELTYPE_PRIMITIVE: {
413 Handle(TDataStd_ReferenceArray) anArray =
414 TDataStd_ReferenceArray::Set(myLab, kBASE_ARRAY, 0, 0);
415 anArray->SetValue(0, myFinal);
418 case SELTYPE_MODIFICATION: {
419 Handle(TDataStd_ReferenceArray) anArray =
420 TDataStd_ReferenceArray::Set(myLab, kBASE_ARRAY, 0, myBases.Extent());
421 TDF_LabelList::Iterator aBIter(myBases);
422 for(int anIndex = 0; aBIter.More(); aBIter.Next(), anIndex++) {
423 anArray->SetValue(anIndex, aBIter.Value());
425 anArray->SetValue(myBases.Extent(), myFinal); // final is in the end of array
428 case SELTYPE_FILTER_BY_NEIGHBOR: {
429 TDataStd_Integer::Set(myLab, kSHAPE_TYPE, (int)myShapeType);
430 // store numbers of levels corresponded to the neighbors in sub-selectors
431 Handle(TDataStd_IntegerArray) anArray =
432 TDataStd_IntegerArray::Set(myLab, kLEVELS_ARRAY, 0, int(myNBLevel.size()) - 1);
433 std::list<int>::iterator aLevel = myNBLevel.begin();
434 for(int anIndex = 0; aLevel != myNBLevel.end(); aLevel++, anIndex++) {
435 anArray->SetValue(anIndex, *aLevel);
437 // store all sub-selectors
438 std::list<Selector_Selector>::iterator aSubSel = mySubSelList.begin();
439 for(; aSubSel != mySubSelList.end(); aSubSel++) {
443 default: { // unknown case
449 bool Selector_Selector::restore()
451 Handle(TDataStd_Integer) aTypeAttr;
452 if (!myLab.FindAttribute(kSEL_TYPE, aTypeAttr))
454 myType = Selector_Type(aTypeAttr->Get());
456 case SELTYPE_CONTAINER:
457 case SELTYPE_INTERSECT: {
458 Handle(TDataStd_Integer) aShapeTypeAttr;
459 if (!myLab.FindAttribute(kSHAPE_TYPE, aShapeTypeAttr))
461 myShapeType = TopAbs_ShapeEnum(aShapeTypeAttr->Get());
462 // restore sub-selectors
463 bool aSubResult = true;
464 mySubSelList.clear();
465 for(TDF_ChildIDIterator aSub(myLab, kSEL_TYPE, false); aSub.More(); aSub.Next()) {
466 mySubSelList.push_back(Selector_Selector(aSub.Value()->Label()));
467 if (!mySubSelList.back().restore())
472 case SELTYPE_PRIMITIVE: {
473 Handle(TDataStd_ReferenceArray) anArray;
474 if (myLab.FindAttribute(kBASE_ARRAY, anArray)) {
475 myFinal = anArray->Value(0);
480 case SELTYPE_MODIFICATION: {
481 Handle(TDataStd_ReferenceArray) anArray;
482 if (myLab.FindAttribute(kBASE_ARRAY, anArray)) {
483 int anUpper = anArray->Upper();
484 for(int anIndex = 0; anIndex < anUpper; anIndex++) {
485 myBases.Append(anArray->Value(anIndex));
487 myFinal = anArray->Value(anUpper);
492 case SELTYPE_FILTER_BY_NEIGHBOR: {
493 Handle(TDataStd_Integer) aShapeTypeAttr;
494 if (!myLab.FindAttribute(kSHAPE_TYPE, aShapeTypeAttr))
496 myShapeType = TopAbs_ShapeEnum(aShapeTypeAttr->Get());
497 // restore sub-selectors
498 bool aSubResult = true;
499 mySubSelList.clear();
500 for(TDF_ChildIDIterator aSub(myLab, kSEL_TYPE, false); aSub.More(); aSub.Next()) {
501 mySubSelList.push_back(Selector_Selector(aSub.Value()->Label()));
502 if (!mySubSelList.back().restore())
505 // restore levels indices
506 Handle(TDataStd_IntegerArray) anArray;
507 if (!myLab.FindAttribute(kLEVELS_ARRAY, anArray))
509 for(int anIndex = 0; anIndex <= anArray->Upper(); anIndex++) {
510 myNBLevel.push_back(anArray->Value(anIndex));
514 default: { // unknown case
520 /// Returns in theResults all shapes with history started in theBase and ended in theFinal
521 static void findFinals(const TopoDS_Shape& theBase, const TDF_Label& theFinal,
522 TopTools_MapOfShape& theResults)
524 for(TNaming_NewShapeIterator aBaseIter(theBase, theFinal); aBaseIter.More(); aBaseIter.Next()) {
525 TNaming_Evolution anEvolution = aBaseIter.NamedShape()->Evolution();
526 if (anEvolution == TNaming_GENERATED || anEvolution == TNaming_MODIFY) {
527 if (aBaseIter.NamedShape()->Label().IsEqual(theFinal)) {
528 theResults.Add(aBaseIter.Shape());
530 findFinals(aBaseIter.Shape(), theFinal, theResults);
537 bool Selector_Selector::solve(const TopoDS_Shape& theContext)
539 TopoDS_Shape aResult; // null if invalid
541 case SELTYPE_CONTAINER: {
542 TopoDS_Builder aBuilder;
543 switch(myShapeType) {
544 case TopAbs_COMPOUND: {
545 TopoDS_Compound aComp;
546 aBuilder.MakeCompound(aComp);
550 case TopAbs_COMPSOLID: {
551 TopoDS_CompSolid aComp;
552 aBuilder.MakeCompSolid(aComp);
558 aBuilder.MakeShell(aShell);
564 aBuilder.MakeWire(aWire);
569 std::list<Selector_Selector>::iterator aSubSel = mySubSelList.begin();
570 for(; aSubSel != mySubSelList.end(); aSubSel++) {
571 if (!aSubSel->solve(theContext)) {
574 aBuilder.Add(aResult, aSubSel->value());
578 case SELTYPE_INTERSECT: {
579 TopoDS_ListOfShape aSubSelectorShapes;
580 std::list<Selector_Selector>::iterator aSubSel = mySubSelList.begin();
581 for(; aSubSel != mySubSelList.end(); aSubSel++) {
582 if (!aSubSel->solve(theContext)) {
585 aSubSelectorShapes.Append(aSubSel->value());
587 TopoDS_ListOfShape aCommon; // common sub shapes in each sub-selector (a result)
588 commonShapes(aSubSelectorShapes, myShapeType, aCommon);
589 if (aCommon.Extent() != 1)
591 aResult = aCommon.First();
594 case SELTYPE_PRIMITIVE: {
595 Handle(TNaming_NamedShape) aNS;
596 if (myFinal.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
597 aResult = aNS->Get();
600 case SELTYPE_MODIFICATION: {
601 TopoDS_ListOfShape aFinalsCommon; // final shapes presented in all results from bases
602 for(TDF_LabelList::Iterator aBase(myBases); aBase.More(); aBase.Next()) {
603 TopTools_MapOfShape aFinals;
604 for(TNaming_Iterator aBaseShape(aBase.Value()); aBaseShape.More(); aBaseShape.Next())
605 findFinals(aBaseShape.NewShape(), myFinal, aFinals);
606 if (!aFinals.IsEmpty()) {
607 if (aFinalsCommon.IsEmpty()) { // just copy all to common
608 for(TopTools_MapOfShape::Iterator aFinal(aFinals); aFinal.More(); aFinal.Next()) {
609 aFinalsCommon.Append(aFinal.Key());
611 } else { // keep only shapes presented in both lists
612 for(TopoDS_ListOfShape::Iterator aCommon(aFinalsCommon); aCommon.More(); ) {
613 if (aFinals.Contains(aCommon.Value())) {
615 } else { // common is not found, remove it
616 aFinalsCommon.Remove(aCommon);
622 if (aFinalsCommon.Extent() == 1) // only in this case result is valid: found only one shape
623 aResult = aFinalsCommon.First();
626 case SELTYPE_FILTER_BY_NEIGHBOR: {
627 std::list<std::pair<TopoDS_Shape, int> > aNBs; /// neighbor sub-shape -> level of neighborhood
628 std::list<int>::iterator aLevel = myNBLevel.begin();
629 std::list<Selector_Selector>::iterator aSubSel = mySubSelList.begin();
630 for(; aSubSel != mySubSelList.end(); aSubSel++, aLevel++) {
631 if (!aSubSel->solve(theContext)) {
634 aNBs.push_back(std::pair<TopoDS_Shape, int>(aSubSel->value(), *aLevel));
636 aResult = findNeighbor(theContext, aNBs);
638 default: { // unknown case
642 TNaming_Builder aBuilder(myLab);
643 if (!aResult.IsNull()) {
644 aBuilder.Select(aResult, aResult);
647 return false; // builder just erases the named shape in case of error
650 TopoDS_Shape Selector_Selector::value()
652 Handle(TNaming_NamedShape) aNS;
653 if (myLab.FindAttribute(TNaming_NamedShape::GetID(), aNS))
655 return TopoDS_Shape(); // empty, error shape
658 std::string Selector_Selector::name(Selector_NameGenerator* theNameGenerator) {
660 case SELTYPE_CONTAINER:
661 case SELTYPE_INTERSECT: {
663 // add names of sub-components one by one separated by "&"
664 std::list<Selector_Selector>::iterator aSubSel = mySubSelList.begin();
665 for(; aSubSel != mySubSelList.end(); aSubSel++) {
666 if (aSubSel != mySubSelList.begin())
668 aResult += aSubSel->name(theNameGenerator);
672 case SELTYPE_PRIMITIVE: {
673 Handle(TDataStd_Name) aName;
674 if (!myFinal.FindAttribute(TDataStd_Name::GetID(), aName))
676 return theNameGenerator->contextName(myFinal) + "/" +
677 std::string(TCollection_AsciiString(aName->Get()).ToCString());
679 case SELTYPE_MODIFICATION: {
680 // final&/base1&base2
682 Handle(TDataStd_Name) aName;
683 if (!myFinal.FindAttribute(TDataStd_Name::GetID(), aName))
685 aResult += theNameGenerator->contextName(myFinal) + "/" +
686 std::string(TCollection_AsciiString(aName->Get()).ToCString()) + "&/";
687 for(TDF_LabelList::iterator aBase = myBases.begin(); aBase != myBases.end(); aBase++) {
688 if (aBase != myBases.begin())
690 if (aBase->FindAttribute(TDataStd_Name::GetID(), aName))
692 aResult += theNameGenerator->contextName(*aBase) + "/" +
693 std::string(TCollection_AsciiString(aName->Get()).ToCString());
697 case SELTYPE_FILTER_BY_NEIGHBOR: {
698 // (nb1)level_if_more_than_1&(nb2)level_if_more_than_1&(nb3)level_if_more_than_1
700 std::list<int>::iterator aLevel = myNBLevel.begin();
701 std::list<Selector_Selector>::iterator aSubSel = mySubSelList.begin();
702 for(; aSubSel != mySubSelList.end(); aSubSel++, aLevel++) {
703 if (aSubSel != mySubSelList.begin())
705 aResult += "(" + aSubSel->name(theNameGenerator) + ")";
711 default: { // unknown case
717 bool Selector_Selector::selectBySubSelector(
718 const TopoDS_Shape theContext, const TopoDS_Shape theValue)
720 mySubSelList.push_back(Selector_Selector(myLab.FindChild(int(mySubSelList.size()) + 1)));
721 if (!mySubSelList.back().select(theContext, theValue)) {
722 mySubSelList.clear(); // if one of the selector is failed, all become invalid