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>
24 #include <Selector_NExplode.h>
26 #include <TDF_ChildIDIterator.hxx>
27 #include <TopoDS_Iterator.hxx>
28 #include <TopoDS_Builder.hxx>
30 #include <TopExp_Explorer.hxx>
31 #include <TopoDS_Edge.hxx>
32 #include <TopoDS_Face.hxx>
33 #include <TNaming_Tool.hxx>
34 #include <TNaming_NewShapeIterator.hxx>
35 #include <TNaming_OldShapeIterator.hxx>
36 #include <TNaming_SameShapeIterator.hxx>
37 #include <TNaming_Iterator.hxx>
38 #include <TNaming_Builder.hxx>
39 #include <TopTools_MapOfShape.hxx>
40 #include <BRep_Tool.hxx>
42 #include <TDataStd_Integer.hxx>
43 #include <TDataStd_ReferenceArray.hxx>
44 #include <TDataStd_IntegerArray.hxx>
45 #include <TDataStd_Name.hxx>
46 #include <TDataStd_UAttribute.hxx>
50 /// type of the selection, integer keeps the Selector_Type value
51 static const Standard_GUID kSEL_TYPE("db174d59-c2e3-4a90-955e-55544df090d6");
52 /// type of the shape, stored in case it is intersection or container
53 static const Standard_GUID kSHAPE_TYPE("864b3267-cb9d-4107-bf58-c3ce1775b171");
54 // reference attribute that contains the reference to labels where the "from" or "base" shapes
55 // of selection are located
56 static const Standard_GUID kBASE_ARRAY("7c515b1a-9549-493d-9946-a4933a22f45f");
57 // array of the neighbor levels
58 static const Standard_GUID kLEVELS_ARRAY("ee4c4b45-e859-4e86-aa4f-6eac68e0ca1f");
59 // weak index (integer) of the sub-shape
60 static const Standard_GUID kWEAK_INDEX("e9373a61-cabc-4ee8-aabf-aea47c62ed87");
61 // geometrical naming indicator
62 static const Standard_GUID kGEOMETRICAL_NAMING("a5322d02-50fb-43ed-9255-75c7b93f6657");
64 // string identifier of the weak name in modification or intersection types of algorithm
65 static const std::string kWEAK_NAME_IDENTIFIER = "weak_name_";
66 // string identifier of the pure weak name algorithm
67 static const std::string kPUREWEAK_NAME_IDENTIFIER = "_weak_name_";
70 Selector_Selector::Selector_Selector(TDF_Label theLab) : myLab(theLab)
75 TDF_Label Selector_Selector::label()
80 void Selector_Selector::setBaseDocument(const TDF_Label theAccess)
82 myBaseDocumentLab = theAccess;
85 // adds to theResult all labels that contain initial shapes for theValue located in theFinal
86 static void findBases(TDF_Label theAccess, Handle(TNaming_NamedShape) theFinal,
87 const TopoDS_Shape& theValue,
88 bool aMustBeAtFinal, const TDF_Label& theAdditionalDocument, TDF_LabelList& theResult)
90 bool aFoundAnyShape = false;
91 TNaming_SameShapeIterator aLabIter(theValue, theAccess);
92 for(; aLabIter.More(); aLabIter.Next()) {
93 Handle(TNaming_NamedShape) aNS;
94 if (aLabIter.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
95 if (aMustBeAtFinal && aNS != theFinal)
96 continue; // looking for old at the same final label only
97 TNaming_Evolution anEvolution = aNS->Evolution();
98 if (anEvolution == TNaming_PRIMITIVE) {
99 // check that this is not in the results already
100 const TDF_Label aResult = aNS->Label();
101 TDF_LabelList::Iterator aResIter(theResult);
102 for(; aResIter.More(); aResIter.Next()) {
103 if (aResIter.Value().IsEqual(aResult))
106 if (!aResIter.More()) // not found, so add this new
107 theResult.Append(aResult);
108 aFoundAnyShape = true;
110 if (anEvolution == TNaming_GENERATED || anEvolution == TNaming_MODIFY) {
111 for(TNaming_Iterator aThisIter(aNS); aThisIter.More(); aThisIter.Next()) {
112 if (aThisIter.NewShape().IsSame(theValue)) {
113 // continue recursively, null NS means that any NS are ok
114 findBases(theAccess, theFinal, aThisIter.OldShape(),
115 false, theAdditionalDocument, theResult);
116 aFoundAnyShape = true;
122 if (!aFoundAnyShape && !theAdditionalDocument.IsNull()) { // try to find in additional document
123 static TDF_Label anEmpty;
124 if (TNaming_Tool::HasLabel(theAdditionalDocument, theValue))
125 findBases(theAdditionalDocument, Handle(TNaming_NamedShape)(), theValue,
126 false, anEmpty, theResult);
130 // returns the sub-shapes of theSubType which belong to all theShapes (so, common or intersection)
131 static void commonShapes(const TopoDS_ListOfShape& theShapes, TopAbs_ShapeEnum theSubType,
132 TopoDS_ListOfShape& theResults)
134 TopoDS_ListOfShape::iterator aSubSel = theShapes.begin();
135 for(; aSubSel != theShapes.end(); aSubSel++) {
136 TopTools_MapOfShape aCurrentMap;
137 for(TopExp_Explorer anExp(*aSubSel, theSubType); anExp.More(); anExp.Next()) {
138 if (aCurrentMap.Add(anExp.Current()) && aSubSel == theShapes.begin())
139 theResults.Append(anExp.Current());
141 if (aSubSel != theShapes.begin()) { // remove from common shapes not in aCurrentMap
142 for(TopoDS_ListOfShape::Iterator aComIter(theResults); aComIter.More(); ) {
143 if (aCurrentMap.Contains(aComIter.Value()))
146 theResults.Remove(aComIter);
152 /// Searches neighbor of theLevel of neighborhood to theValue in theContex
153 static void findNeighbors(const TopoDS_Shape theContext, const TopoDS_Shape theValue,
154 const int theLevel, TopTools_MapOfShape& theResult)
156 TopAbs_ShapeEnum aConnectorType = TopAbs_VERTEX; // type of the connector sub-shapes
157 if (theValue.ShapeType() == TopAbs_FACE)
158 aConnectorType = TopAbs_EDGE;
159 TopTools_MapOfShape aNBConnectors; // connector shapes that already belong to neighbors
160 for(TopExp_Explorer aValExp(theValue, aConnectorType); aValExp.More(); aValExp.Next()) {
161 aNBConnectors.Add(aValExp.Current());
164 TopTools_MapOfShape alreadyProcessed;
165 alreadyProcessed.Add(theValue);
167 for(int aLevel = 1; aLevel <= theLevel; aLevel++) {
168 TopoDS_ListOfShape aGoodCandidates;
169 TopExp_Explorer aCandidate(theContext, theValue.ShapeType());
170 for(; aCandidate.More(); aCandidate.Next()) {
171 if (alreadyProcessed.Contains(aCandidate.Current()))
173 TopExp_Explorer aCandConnector(aCandidate.Current(), aConnectorType);
174 for(; aCandConnector.More(); aCandConnector.Next()) {
175 if (aNBConnectors.Contains(aCandConnector.Current())) // candidate is neighbor
178 if (aCandConnector.More()) {
179 if (aLevel == theLevel) { // add a NB into result: it is connected to other neighbors
180 theResult.Add(aCandidate.Current());
181 } else { // add to the NB of the current level
182 aGoodCandidates.Append(aCandidate.Current());
186 if (aLevel != theLevel) { // good candidates are added to neighbor of this level by connectors
187 for(TopoDS_ListOfShape::Iterator aGood(aGoodCandidates); aGood.More(); aGood.Next()) {
188 TopExp_Explorer aGoodConnector(aGood.Value(), aConnectorType);
189 for(; aGoodConnector.More(); aGoodConnector.Next()) {
190 aNBConnectors.Add(aGoodConnector.Current());
192 alreadyProcessed.Add(aGood.Value());
198 /// Returns true if the given shapes are based on the same geometry
199 static bool sameGeometry(const TopoDS_Shape theShape1, const TopoDS_Shape theShape2) {
200 if (!theShape1.IsNull() && !theShape2.IsNull() && theShape1.ShapeType() == theShape2.ShapeType())
202 if (theShape1.ShapeType() == TopAbs_FACE) { // check surfaces
203 TopLoc_Location aLoc1, aLoc2;
204 TopoDS_Face aFace1 = TopoDS::Face(theShape1);
205 Handle(Geom_Surface) aSurf1 = BRep_Tool::Surface(aFace1, aLoc1);
206 TopoDS_Face aFace2 = TopoDS::Face(theShape2);
207 Handle(Geom_Surface) aSurf2 = BRep_Tool::Surface(aFace2, aLoc2);
208 return aSurf1 == aSurf2 && aLoc1.IsEqual(aLoc2);
209 } else if (theShape1.ShapeType() == TopAbs_EDGE) { // check curves
210 TopLoc_Location aLoc1, aLoc2;
211 Standard_Real aFirst, aLast;
212 TopoDS_Edge anEdge1 = TopoDS::Edge(theShape1);
213 Handle(Geom_Curve) aCurve1 = BRep_Tool::Curve(anEdge1, aLoc1, aFirst, aLast);
214 TopoDS_Edge anEdge2 = TopoDS::Edge(theShape2);
215 Handle(Geom_Curve) aCurve2 = BRep_Tool::Curve(anEdge2, aLoc2, aFirst, aLast);
216 return aCurve1 == aCurve2 && aLoc1.IsEqual(aLoc2);
222 /// Searches the neighbor shape by neighbors defined in theNB in theContext shape
223 static const TopoDS_Shape findNeighbor(const TopoDS_Shape theContext,
224 const std::list<std::pair<TopoDS_Shape, int> >& theNB, const bool theGeometrical)
226 // searching for neighbors with minimum level
228 std::list<std::pair<TopoDS_Shape, int> >::const_iterator aNBIter = theNB.cbegin();
229 for(; aNBIter != theNB.cend(); aNBIter++) {
230 if (aMinLevel == 0 || aNBIter->second < aMinLevel) {
231 aMinLevel = aNBIter->second;
234 // collect all neighbors which are neighbors of sub-shapes with minimum level
236 TopoDS_ListOfShape aMatches;
237 for(aNBIter = theNB.cbegin(); aNBIter != theNB.cend(); aNBIter++) {
238 if (aNBIter->second == aMinLevel) {
239 TopTools_MapOfShape aThisNBs;
240 findNeighbors(theContext, aNBIter->first, aMinLevel, aThisNBs);
241 // aMatches must contain common part of all NBs lists
242 for(TopTools_MapOfShape::Iterator aThisNB(aThisNBs); aThisNB.More(); aThisNB.Next()) {
244 aMatches.Append(aThisNB.Value());
246 // remove all in aMatches which are not in this NBs
247 for(TopoDS_ListOfShape::Iterator aMatch(aMatches); aMatch.More(); ) {
248 if (aThisNBs.Contains(aMatch.Value())) {
251 aMatches.Remove(aMatch);
259 if (aMatches.IsEmpty())
260 return TopoDS_Shape(); // not found any candidate
261 if (aMatches.Extent() == 1)
262 return aMatches.First(); // already found good candidate
263 TopoDS_Compound aResultCompound; // in case of geometrical name and many candidates
264 // iterate all matches to find by other (higher level) neighbors the best candidate
265 TopoDS_Shape aGoodCandidate;
266 for(TopoDS_ListOfShape::Iterator aCandidate(aMatches); aCandidate.More(); aCandidate.Next()) {
267 bool aValidCadidate = true;
268 for(int aLevel = aMinLevel + 1; true; aLevel++) {
269 bool aFooundHigherLevel = false;
270 TopoDS_ListOfShape aLevelNBs;
271 for(aNBIter = theNB.cbegin(); aNBIter != theNB.cend(); aNBIter++) {
272 if (aNBIter->second == aLevel)
273 aLevelNBs.Append(aNBIter->first);
274 else if (aNBIter->second >= aLevel)
275 aFooundHigherLevel = true;
277 if (!aFooundHigherLevel && aLevelNBs.IsEmpty()) { // iterated all, so, good candidate
278 if (aGoodCandidate.IsNull()) {
279 aGoodCandidate = aCandidate.Value();
280 } else { // another good candidate
281 if (theGeometrical && sameGeometry(aGoodCandidate, aCandidate.Value())) {
282 static TopoDS_Builder aBuilder;
283 if (aResultCompound.IsNull()) {
284 aBuilder.MakeCompound(aResultCompound);
285 aBuilder.Add(aResultCompound, aGoodCandidate);
287 aBuilder.Add(aResultCompound, aCandidate.Value());
289 return TopoDS_Shape();
292 if (!aLevelNBs.IsEmpty()) {
293 TopTools_MapOfShape aNBsOfCandidate;
294 findNeighbors(theContext, aCandidate.Value(), aLevel, aNBsOfCandidate);
295 // check all stored neighbors are in the map of real neighbors
296 for(TopoDS_ListOfShape::Iterator aLevIter(aLevelNBs); aLevIter.More(); aLevIter.Next()) {
297 if (!aNBsOfCandidate.Contains(aLevIter.Value())) {
298 aValidCadidate = false;
303 if (!aValidCadidate) // candidate is not valid, break the checking
307 if (!aResultCompound.IsNull())
308 return aResultCompound;
309 return aGoodCandidate;
312 bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape theValue,
313 const bool theGeometricalNaming, const bool theUseNeighbors, const bool theUseIntersections)
315 if (theValue.IsNull() || theContext.IsNull())
317 myGeometricalNaming = theGeometricalNaming;
318 // check the value shape can be named as it is, or it is needed to construct it from the
319 // higher level shapes (like a box vertex by faces that form this vertex)
320 bool aIsFound = TNaming_Tool::HasLabel(myLab, theValue);
321 if (aIsFound) { // additional check for selection and delete evolution only: also could not use
323 for(TNaming_SameShapeIterator aShapes(theValue, myLab); aShapes.More(); aShapes.Next())
325 Handle(TNaming_NamedShape) aNS;
326 if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
327 if (aNS->Evolution() == TNaming_MODIFY || aNS->Evolution() == TNaming_GENERATED ||
328 aNS->Evolution() == TNaming_PRIMITIVE) {
335 // searching in the base document
336 if (!aIsFound && !myBaseDocumentLab.IsNull() &&
337 TNaming_Tool::HasLabel(myBaseDocumentLab, theValue))
339 TNaming_SameShapeIterator aShapes(theValue, myBaseDocumentLab);
340 for(; aShapes.More(); aShapes.Next())
342 Handle(TNaming_NamedShape) aNS;
343 if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
344 if (aNS->Evolution() == TNaming_MODIFY || aNS->Evolution() == TNaming_GENERATED ||
345 aNS->Evolution() == TNaming_PRIMITIVE) {
353 TopAbs_ShapeEnum aSelectionType = theValue.ShapeType();
354 myShapeType = aSelectionType;
355 if (aSelectionType == TopAbs_COMPOUND || aSelectionType == TopAbs_COMPSOLID ||
356 aSelectionType == TopAbs_SHELL || aSelectionType == TopAbs_WIRE)
357 { // iterate all sub-shapes and select them on sublabels
358 for(TopoDS_Iterator aSubIter(theValue); aSubIter.More(); aSubIter.Next()) {
359 if (!selectBySubSelector(theContext, aSubIter.Value(),
360 theGeometricalNaming, theUseNeighbors, theUseIntersections)) {
361 return false; // if some selector is failed, everything is failed
364 myType = SELTYPE_CONTAINER;
368 // try to find the shape of the higher level type in the context shape
369 bool aFacesTried = false; // for identification of vertices, faces are tried, then edges
370 TopoDS_ListOfShape aLastCommon; // to store the commons not good, but may be used for weak
371 TopoDS_ListOfShape aLastIntersectors;
372 while(theUseIntersections && (aSelectionType != TopAbs_FACE || !aFacesTried)) {
373 if (aSelectionType == TopAbs_FACE) {
374 if (theValue.ShapeType() != TopAbs_VERTEX)
377 aSelectionType = TopAbs_EDGE;
379 aSelectionType = TopAbs_FACE;
380 TopTools_MapOfShape anIntersectors; // shapes of aSelectionType that contain theValue
381 TopoDS_ListOfShape anIntList; // same as anIntersectors
382 for(TopExp_Explorer aSelExp(theContext, aSelectionType); aSelExp.More(); aSelExp.Next()) {
383 if (aSelectionType == TopAbs_EDGE &&
384 BRep_Tool::Degenerated(TopoDS::Edge(aSelExp.Current())))
386 TopExp_Explorer aSubExp(aSelExp.Current(), theValue.ShapeType());
387 for(; aSubExp.More(); aSubExp.Next()) {
388 if (aSubExp.Current().IsSame(theValue)) {
389 if (anIntersectors.Add(aSelExp.Current()))
390 anIntList.Append(aSelExp.Current());
395 // check that solution is only one
396 TopoDS_ListOfShape aCommon;
397 commonShapes(anIntList, theValue.ShapeType(), aCommon);
398 if (aCommon.Extent() == 1 && aCommon.First().IsSame(theValue)) {
399 // name the intersectors
400 mySubSelList.clear();
401 TopoDS_ListOfShape::Iterator anInt(anIntList);
402 for (; anInt.More(); anInt.Next()) {
403 if (!selectBySubSelector(theContext, anInt.Value(),
404 theGeometricalNaming, theUseNeighbors, false)) {
405 break; // if some selector is failed, stop and search another solution
408 if (!anInt.More()) { // all intersectors were correctly named
409 myType = SELTYPE_INTERSECT;
412 } else if (aCommon.Extent() > 1 && aLastCommon.IsEmpty()) {
413 aLastCommon = aCommon;
414 aLastIntersectors = anIntList;
418 if (!theUseNeighbors)
421 // searching by neighbors
422 std::list<std::pair<TopoDS_Shape, int> > aNBs; /// neighbor sub-shape -> level of neighborhood
423 for(int aLevel = 1; true; aLevel++) {
424 TopTools_MapOfShape aNewNB;
425 findNeighbors(theContext, theValue, aLevel, aNewNB);
426 if (aNewNB.Extent() == 0) { // there are no neighbors of the given level, stop iteration
429 // iterate by the order in theContext to keep same naming names
430 TopExp_Explorer anOrder(theContext, theValue.ShapeType());
431 for (; anOrder.More(); anOrder.Next()) {
432 if (aNewNB.Contains(anOrder.Current())) {
433 TopoDS_Shape aNewNBShape = anOrder.Current();
434 // check which can be named correctly, without "by neighbors" type
435 Selector_Selector aSelector(myLab.FindChild(1));
436 aSelector.setBaseDocument(myBaseDocumentLab);
437 if (aSelector.select(theContext, aNewNBShape, theGeometricalNaming, false, false)) {
438 // add to list of good NBs
439 aNBs.push_back(std::pair<TopoDS_Shape, int>(aNewNBShape, aLevel));
443 TopoDS_Shape aResult = findNeighbor(theContext, aNBs, theGeometricalNaming);
444 if (!aResult.IsNull() && aResult.IsSame(theValue)) {
445 std::list<std::pair<TopoDS_Shape, int> >::iterator aNBIter = aNBs.begin();
446 for(; aNBIter != aNBs.end(); aNBIter++) {
447 if (!selectBySubSelector(theContext, aNBIter->first,
448 theGeometricalNaming, false, false)) {
449 return false; // something is wrong because before this selection was ok
451 myNBLevel.push_back(aNBIter->second);
454 myType = SELTYPE_FILTER_BY_NEIGHBOR;
459 // weak naming to distinguish commons coming from intersection
460 if (aLastCommon.Extent() > 1) {
461 Selector_NExplode aNexp(aLastCommon);
462 myWeakIndex = aNexp.index(theValue);
463 if (myWeakIndex != -1) {
464 // name the intersectors
465 mySubSelList.clear();
466 TopoDS_ListOfShape::Iterator anInt(aLastIntersectors);
467 for (; anInt.More(); anInt.Next()) {
468 if (!selectBySubSelector(theContext, anInt.Value(),
469 theGeometricalNaming, theUseNeighbors, theUseIntersections)) {
470 break; // if some selector is failed, stop and search another solution
473 if (!anInt.More()) { // all intersectors were correctly named
474 myType = SELTYPE_INTERSECT;
480 // pure weak naming: there is no sense to use pure weak naming for neighbors selection
481 if (theUseNeighbors) {
482 myType = SELTYPE_WEAK_NAMING;
483 Selector_NExplode aNexp(theContext, theValue.ShapeType());
484 myWeakIndex = aNexp.index(theValue);
485 if (myWeakIndex != -1) {
486 myShapeType = theValue.ShapeType();
487 // searching for context shape label to store in myFinal
489 if (TNaming_Tool::HasLabel(myLab, theContext)) {
490 for(TNaming_SameShapeIterator aShapes(theContext, myLab); aShapes.More(); aShapes.Next())
492 Handle(TNaming_NamedShape) aNS;
493 if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
494 TNaming_Evolution anEvolution = aNS->Evolution();
495 if (anEvolution == TNaming_PRIMITIVE || anEvolution == TNaming_GENERATED ||
496 anEvolution == TNaming_MODIFY) {
497 // check this is a new shape
498 for(TNaming_Iterator aNSIter(aNS); aNSIter.More(); aNSIter.Next()) {
499 if (aNSIter.NewShape().IsSame(theContext)) {
500 myFinal = aNS->Label();
508 return true; // could be final empty (in case it is called recursively) or not
514 // searching for the base shapes of the value
515 Handle(TNaming_NamedShape) aPrimitiveNS;
516 NCollection_List<Handle(TNaming_NamedShape)> aModifList;
517 for(int aUseExternal = 0; aUseExternal < 2; aUseExternal++) {
518 TDF_Label aLab = aUseExternal == 0 ? myLab : myBaseDocumentLab;
519 if (aLab.IsNull() || !TNaming_Tool::HasLabel(aLab, theValue))
521 for(TNaming_SameShapeIterator aShapes(theValue, aLab); aShapes.More(); aShapes.Next())
523 Handle(TNaming_NamedShape) aNS;
524 if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
525 TNaming_Evolution anEvolution = aNS->Evolution();
526 if (anEvolution == TNaming_PRIMITIVE) { // the value shape is declared as PRIMITIVE
529 } else if (anEvolution == TNaming_GENERATED || anEvolution == TNaming_MODIFY) {
530 // check this is a new shape
531 TNaming_Iterator aNSIter(aNS);
532 for(; aNSIter.More(); aNSIter.Next())
533 if (aNSIter.NewShape().IsSame(theValue))
535 if (aNSIter.More()) // new was found
536 aModifList.Append(aNS);
542 if (!aPrimitiveNS.IsNull()) {
543 myType = SELTYPE_PRIMITIVE;
544 myFinal = aPrimitiveNS->Label();
548 if (aModifList.Extent() > 1) { // searching for the best modification result: by context
549 Handle(TNaming_NamedShape) aCandidate;
550 NCollection_List<Handle(TNaming_NamedShape)>::Iterator aModIter(aModifList);
551 for(; !aModifList.IsEmpty() && aModIter.More(); aModIter.Next()) {
552 aCandidate = aModIter.Value();
553 TDF_Label aFatherLab = aCandidate->Label().Father();
554 Handle(TNaming_NamedShape) aFatherNS;
555 if (aFatherLab.FindAttribute(TNaming_NamedShape::GetID(), aFatherNS)) {
556 for(TNaming_Iterator anIter(aFatherNS); anIter.More(); anIter.Next()) {
557 if (theContext.IsSame(anIter.NewShape())) { // found the best modification
564 // take the best candidate, or the last in the iteration
566 aModifList.Append(aCandidate);
569 if (!aModifList.IsEmpty()) {
570 // searching for all the base shapes of this modification
571 findBases(myLab, aModifList.First(), theValue, true, myBaseDocumentLab, myBases);
572 if (!myBases.IsEmpty()) {
573 myFinal = aModifList.First()->Label();
574 TopoDS_ListOfShape aCommon;
575 findModificationResult(aCommon);
576 // trying to search by neighbors
577 if (aCommon.Extent() > 1) { // more complicated selection
578 if (!theUseNeighbors)
581 // searching by neighbors
582 std::list<std::pair<TopoDS_Shape, int> > aNBs;//neighbor sub-shape -> level of neighborhood
583 for(int aLevel = 1; true; aLevel++) {
584 TopTools_MapOfShape aNewNB;
585 findNeighbors(theContext, theValue, aLevel, aNewNB);
586 if (aNewNB.Extent() == 0) { // there are no neighbors of the given level, stop iteration
589 // iterate by the order in theContext to keep same naming names
590 TopExp_Explorer anOrder(theContext, theValue.ShapeType());
591 for (; anOrder.More(); anOrder.Next()) {
592 if (aNewNB.Contains(anOrder.Current())) {
593 TopoDS_Shape aNewNBShape = anOrder.Current();
594 // check which can be named correctly, without "by neighbors" type
595 Selector_Selector aSelector(myLab.FindChild(1));
596 if (!myBaseDocumentLab.IsNull())
597 aSelector.setBaseDocument(myBaseDocumentLab);
598 if (aSelector.select(theContext, aNewNBShape, theGeometricalNaming, false)) {
599 // add to list of good NBs
600 aNBs.push_back(std::pair<TopoDS_Shape, int>(aNewNBShape, aLevel));
604 TopoDS_Shape aResult = findNeighbor(theContext, aNBs, theGeometricalNaming);
605 if (!aResult.IsNull() && aResult.IsSame(theValue)) {
606 std::list<std::pair<TopoDS_Shape, int> >::iterator aNBIter = aNBs.begin();
607 for(; aNBIter != aNBs.end(); aNBIter++) {
608 if (!selectBySubSelector(theContext, aNBIter->first,
609 theGeometricalNaming, theUseNeighbors, theUseIntersections)) {
610 return false; // something is wrong because before this selection was ok
612 myNBLevel.push_back(aNBIter->second);
615 myType = SELTYPE_FILTER_BY_NEIGHBOR;
619 // filter by neighbors did not help
620 if (aCommon.Extent() > 1) { // weak naming between the common results
621 Selector_NExplode aNexp(aCommon);
622 myWeakIndex = aNexp.index(theValue);
623 if (myWeakIndex == -1)
628 myType = SELTYPE_MODIFICATION;
629 if (myBases.IsEmpty()) { // selection based on the external shape, weak name by finals compound
630 TopoDS_ListOfShape aCommon;
631 myFinal = aModifList.First()->Label();
632 Handle(TNaming_NamedShape) aNS;
633 if (myFinal.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
634 for(TNaming_Iterator aFinalIter(aNS); aFinalIter.More(); aFinalIter.Next()) {
635 const TopoDS_Shape& aNewShape = aFinalIter.NewShape();
636 if (!aNewShape.IsNull())
637 aCommon.Append(aNewShape);
640 Selector_NExplode aNexp(aCommon);
641 myWeakIndex = aNexp.index(theValue);
642 if (myWeakIndex == -1)
648 // not found a good result
652 void Selector_Selector::store()
654 myLab.ForgetAllAttributes(true); // remove old naming data
655 TDataStd_Integer::Set(myLab, kSEL_TYPE, (int)myType);
656 if (myGeometricalNaming)
657 TDataStd_UAttribute::Set(myLab, kGEOMETRICAL_NAMING);
659 case SELTYPE_CONTAINER:
660 case SELTYPE_INTERSECT: {
661 TDataStd_Integer::Set(myLab, kSHAPE_TYPE, (int)myShapeType);
662 // store also all sub-selectors
663 std::list<Selector_Selector>::iterator aSubSel = mySubSelList.begin();
664 for(; aSubSel != mySubSelList.end(); aSubSel++) {
667 if (myWeakIndex != -1) {
668 TDataStd_Integer::Set(myLab, kWEAK_INDEX, myWeakIndex);
672 case SELTYPE_PRIMITIVE: {
673 Handle(TDataStd_ReferenceArray) anArray =
674 TDataStd_ReferenceArray::Set(myLab, kBASE_ARRAY, 0, 0);
675 anArray->SetValue(0, myFinal);
678 case SELTYPE_MODIFICATION: {
679 Handle(TDataStd_ReferenceArray) anArray =
680 TDataStd_ReferenceArray::Set(myLab, kBASE_ARRAY, 0, myBases.Extent());
681 TDF_LabelList::Iterator aBIter(myBases);
682 for(int anIndex = 0; aBIter.More(); aBIter.Next(), anIndex++) {
683 anArray->SetValue(anIndex, aBIter.Value());
685 anArray->SetValue(myBases.Extent(), myFinal); // final is in the end of array
686 if (myWeakIndex != -1) {
687 TDataStd_Integer::Set(myLab, kWEAK_INDEX, myWeakIndex);
691 case SELTYPE_FILTER_BY_NEIGHBOR: {
692 TDataStd_Integer::Set(myLab, kSHAPE_TYPE, (int)myShapeType);
693 // store numbers of levels corresponded to the neighbors in sub-selectors
694 Handle(TDataStd_IntegerArray) anArray =
695 TDataStd_IntegerArray::Set(myLab, kLEVELS_ARRAY, 0, int(myNBLevel.size()) - 1);
696 std::list<int>::iterator aLevel = myNBLevel.begin();
697 for(int anIndex = 0; aLevel != myNBLevel.end(); aLevel++, anIndex++) {
698 anArray->SetValue(anIndex, *aLevel);
700 // store all sub-selectors
701 std::list<Selector_Selector>::iterator aSubSel = mySubSelList.begin();
702 for(; aSubSel != mySubSelList.end(); aSubSel++) {
707 case SELTYPE_WEAK_NAMING: {
708 TDataStd_Integer::Set(myLab, kWEAK_INDEX, myWeakIndex);
709 TDataStd_Integer::Set(myLab, kSHAPE_TYPE, (int)myShapeType);
710 // store myFinal in the base array
711 if (!myFinal.IsNull()) {
712 Handle(TDataStd_ReferenceArray) anArray =
713 TDataStd_ReferenceArray::Set(myLab, kBASE_ARRAY, 0, 0);
714 anArray->SetValue(0, myFinal);
718 default: { // unknown case
724 bool Selector_Selector::restore()
726 Handle(TDataStd_Integer) aTypeAttr;
727 if (!myLab.FindAttribute(kSEL_TYPE, aTypeAttr))
729 myGeometricalNaming = myLab.IsAttribute(kGEOMETRICAL_NAMING);
730 myType = Selector_Type(aTypeAttr->Get());
732 case SELTYPE_CONTAINER:
733 case SELTYPE_INTERSECT: {
734 Handle(TDataStd_Integer) aShapeTypeAttr;
735 if (!myLab.FindAttribute(kSHAPE_TYPE, aShapeTypeAttr))
737 myShapeType = TopAbs_ShapeEnum(aShapeTypeAttr->Get());
738 // restore sub-selectors
739 bool aSubResult = true;
740 mySubSelList.clear();
741 for(TDF_ChildIDIterator aSub(myLab, kSEL_TYPE, false); aSub.More(); aSub.Next()) {
742 mySubSelList.push_back(Selector_Selector(aSub.Value()->Label()));
743 mySubSelList.back().setBaseDocument(myBaseDocumentLab);
744 if (!mySubSelList.back().restore())
747 Handle(TDataStd_Integer) aWeakInt;
748 if (myLab.FindAttribute(kWEAK_INDEX, aWeakInt)) {
749 myWeakIndex = aWeakInt->Get();
753 case SELTYPE_PRIMITIVE: {
754 Handle(TDataStd_ReferenceArray) anArray;
755 if (myLab.FindAttribute(kBASE_ARRAY, anArray)) {
756 myFinal = anArray->Value(0);
761 case SELTYPE_MODIFICATION: {
762 Handle(TDataStd_ReferenceArray) anArray;
763 if (myLab.FindAttribute(kBASE_ARRAY, anArray)) {
764 int anUpper = anArray->Upper();
765 for(int anIndex = 0; anIndex < anUpper; anIndex++) {
766 myBases.Append(anArray->Value(anIndex));
768 myFinal = anArray->Value(anUpper);
769 Handle(TDataStd_Integer) aWeakInt;
770 if (myLab.FindAttribute(kWEAK_INDEX, aWeakInt)) {
771 myWeakIndex = aWeakInt->Get();
777 case SELTYPE_FILTER_BY_NEIGHBOR: {
778 Handle(TDataStd_Integer) aShapeTypeAttr;
779 if (!myLab.FindAttribute(kSHAPE_TYPE, aShapeTypeAttr))
781 myShapeType = TopAbs_ShapeEnum(aShapeTypeAttr->Get());
782 // restore sub-selectors
783 bool aSubResult = true;
784 mySubSelList.clear();
785 for(TDF_ChildIDIterator aSub(myLab, kSEL_TYPE, false); aSub.More(); aSub.Next()) {
786 mySubSelList.push_back(Selector_Selector(aSub.Value()->Label()));
787 mySubSelList.back().setBaseDocument(myBaseDocumentLab);
788 if (!mySubSelList.back().restore())
791 // restore levels indices
792 Handle(TDataStd_IntegerArray) anArray;
793 if (!myLab.FindAttribute(kLEVELS_ARRAY, anArray))
795 for(int anIndex = 0; anIndex <= anArray->Upper(); anIndex++) {
796 myNBLevel.push_back(anArray->Value(anIndex));
800 case SELTYPE_WEAK_NAMING: {
801 Handle(TDataStd_Integer) aWeakInt;
802 if (!myLab.FindAttribute(kWEAK_INDEX, aWeakInt))
804 myWeakIndex = aWeakInt->Get();
805 Handle(TDataStd_Integer) aShapeTypeAttr;
806 if (!myLab.FindAttribute(kSHAPE_TYPE, aShapeTypeAttr))
808 myShapeType = TopAbs_ShapeEnum(aShapeTypeAttr->Get());
809 Handle(TDataStd_ReferenceArray) anArray;
810 if (myLab.FindAttribute(kBASE_ARRAY, anArray)) {
811 myFinal = anArray->Value(0);
815 default: { // unknown case
821 /// Returns in theResults all shapes with history started in theBase and ended in theFinal
822 static void findFinals(const TDF_Label& anAccess, const TopoDS_Shape& theBase,
823 const TDF_Label& theFinal,
824 const TDF_Label& theAdditionalDoc, TopTools_MapOfShape& theResults)
826 if (TNaming_Tool::HasLabel(anAccess, theBase)) {
827 for(TNaming_NewShapeIterator aBaseIter(theBase, anAccess); aBaseIter.More(); aBaseIter.Next())
829 TNaming_Evolution anEvolution = aBaseIter.NamedShape()->Evolution();
830 if (anEvolution == TNaming_GENERATED || anEvolution == TNaming_MODIFY) {
831 if (aBaseIter.NamedShape()->Label().IsEqual(theFinal)) {
832 theResults.Add(aBaseIter.Shape());
834 findFinals(anAccess, aBaseIter.Shape(), theFinal, theAdditionalDoc, theResults);
839 if (!theAdditionalDoc.IsNull()) { // search additionally by the additional access label
840 static TDF_Label anEmpty;
841 findFinals(theAdditionalDoc, theBase, theFinal, anEmpty, theResults);
845 void Selector_Selector::findModificationResult(TopoDS_ListOfShape& theCommon) {
846 for(TDF_LabelList::Iterator aBase(myBases); aBase.More(); aBase.Next()) {
847 TDF_Label anAdditionalDoc; // this document if base is started in extra document
848 if (aBase.Value().Root() != myLab.Root()) {
849 anAdditionalDoc = myLab;
851 TopTools_MapOfShape aFinals;
852 for(TNaming_Iterator aBaseShape(aBase.Value()); aBaseShape.More(); aBaseShape.Next()) {
853 findFinals(aBase.Value(), aBaseShape.NewShape(), myFinal, anAdditionalDoc, aFinals);
855 if (!aFinals.IsEmpty()) {
856 if (theCommon.IsEmpty()) { // just copy all to common
857 for(TopTools_MapOfShape::Iterator aFinal(aFinals); aFinal.More(); aFinal.Next()) {
858 theCommon.Append(aFinal.Key());
860 } else { // keep only shapes presented in both lists
861 for(TopoDS_ListOfShape::Iterator aCommon(theCommon); aCommon.More(); ) {
862 if (aFinals.Contains(aCommon.Value())) {
864 } else { // common is not found, remove it
865 theCommon.Remove(aCommon);
873 bool Selector_Selector::solve(const TopoDS_Shape& theContext)
875 TopoDS_Shape aResult; // null if invalid
877 case SELTYPE_CONTAINER: {
878 TopoDS_Builder aBuilder;
879 switch(myShapeType) {
880 case TopAbs_COMPOUND: {
881 TopoDS_Compound aComp;
882 aBuilder.MakeCompound(aComp);
886 case TopAbs_COMPSOLID: {
887 TopoDS_CompSolid aComp;
888 aBuilder.MakeCompSolid(aComp);
894 aBuilder.MakeShell(aShell);
900 aBuilder.MakeWire(aWire);
905 std::list<Selector_Selector>::iterator aSubSel = mySubSelList.begin();
906 for(; aSubSel != mySubSelList.end(); aSubSel++) {
907 if (!aSubSel->solve(theContext)) {
910 aBuilder.Add(aResult, aSubSel->value());
914 case SELTYPE_INTERSECT: {
915 TopoDS_ListOfShape aSubSelectorShapes;
916 std::list<Selector_Selector>::iterator aSubSel = mySubSelList.begin();
917 for(; aSubSel != mySubSelList.end(); aSubSel++) {
918 if (!aSubSel->solve(theContext)) {
921 aSubSelectorShapes.Append(aSubSel->value());
923 TopoDS_ListOfShape aCommon; // common sub shapes in each sub-selector (a result)
924 commonShapes(aSubSelectorShapes, myShapeType, aCommon);
925 if (aCommon.Extent() != 1) {
926 if (myWeakIndex != -1) {
927 Selector_NExplode aNexp(aCommon);
928 aResult = aNexp.shape(myWeakIndex);
929 } else if (myGeometricalNaming && aCommon.Extent() > 1) {
930 // check results are on the same geometry, create compound
931 TopoDS_ListOfShape::Iterator aCommonIter(aCommon);
932 TopoDS_Shape aFirst = aCommonIter.Value();
933 for(aCommonIter.Next(); aCommonIter.More(); aCommonIter.Next()) {
934 if (!sameGeometry(aFirst, aCommonIter.Value()))
937 if (!aCommonIter.More()) { // all geometry is same, create a result compound
938 TopoDS_Builder aBuilder;
939 TopoDS_Compound aCompound;
940 aBuilder.MakeCompound(aCompound);
941 for(aCommonIter.Initialize(aCommon); aCommonIter.More(); aCommonIter.Next()) {
942 aBuilder.Add(aCompound, aCommonIter.Value());
950 aResult = aCommon.First();
954 case SELTYPE_PRIMITIVE: {
955 Handle(TNaming_NamedShape) aNS;
956 if (myFinal.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
957 aResult = aNS->Get();
961 case SELTYPE_MODIFICATION: {
962 if (myBases.IsEmpty() && myWeakIndex > 0) { // weak name by the final shapes index
963 TopoDS_ListOfShape aCommon;
964 Handle(TNaming_NamedShape) aNS;
965 if (myFinal.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
966 for(TNaming_Iterator aFinalIter(aNS); aFinalIter.More(); aFinalIter.Next()) {
967 const TopoDS_Shape& aNewShape = aFinalIter.NewShape();
968 if (!aNewShape.IsNull())
969 aCommon.Append(aNewShape);
972 Selector_NExplode aNexp(aCommon);
973 aResult = aNexp.shape(myWeakIndex);
974 } else { // standard case
975 TopoDS_ListOfShape aFinalsCommon; // final shapes presented in all results from bases
976 findModificationResult(aFinalsCommon);
977 if (aFinalsCommon.Extent() == 1) { // result is valid: found only one shape
978 aResult = aFinalsCommon.First();
979 } else if (aFinalsCommon.Extent() > 1 && myWeakIndex > 0) {
980 Selector_NExplode aNExp(aFinalsCommon);
981 aResult = aNExp.shape(myWeakIndex);
982 } else if (aFinalsCommon.Extent() > 1 && myGeometricalNaming) {// if same geometry - compound
983 TopoDS_ListOfShape::Iterator aCommonIter(aFinalsCommon);
984 TopoDS_Shape aFirst = aCommonIter.Value();
985 for(aCommonIter.Next(); aCommonIter.More(); aCommonIter.Next()) {
986 if (!sameGeometry(aFirst, aCommonIter.Value()))
989 if (!aCommonIter.More()) { // all geometry is same, create a result compound
990 TopoDS_Builder aBuilder;
991 TopoDS_Compound aCompound;
992 aBuilder.MakeCompound(aCompound);
993 for(aCommonIter.Initialize(aFinalsCommon); aCommonIter.More(); aCommonIter.Next()) {
994 aBuilder.Add(aCompound, aCommonIter.Value());
1003 case SELTYPE_FILTER_BY_NEIGHBOR: {
1004 std::list<std::pair<TopoDS_Shape, int> > aNBs; /// neighbor sub-shape -> level of neighborhood
1005 std::list<int>::iterator aLevel = myNBLevel.begin();
1006 std::list<Selector_Selector>::iterator aSubSel = mySubSelList.begin();
1007 for(; aSubSel != mySubSelList.end(); aSubSel++, aLevel++) {
1008 if (!aSubSel->solve(theContext)) {
1011 aNBs.push_back(std::pair<TopoDS_Shape, int>(aSubSel->value(), *aLevel));
1013 aResult = findNeighbor(theContext, aNBs, myGeometricalNaming);
1016 case SELTYPE_WEAK_NAMING: {
1017 TopoDS_Shape aContext;
1018 if (myFinal.IsNull()) {
1019 aContext = theContext;
1021 Handle(TNaming_NamedShape) aNS;
1022 if (myFinal.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
1023 aContext = aNS->Get();
1026 if (!aContext.IsNull()) {
1027 Selector_NExplode aNexp(aContext, myShapeType);
1028 aResult = aNexp.shape(myWeakIndex);
1031 default: { // unknown case
1035 TNaming_Builder aBuilder(myLab);
1036 if (!aResult.IsNull()) {
1037 aBuilder.Select(aResult, aResult);
1040 return false; // builder just erases the named shape in case of error
1043 TopoDS_Shape Selector_Selector::value()
1045 Handle(TNaming_NamedShape) aNS;
1046 if (myLab.FindAttribute(TNaming_NamedShape::GetID(), aNS))
1048 return TopoDS_Shape(); // empty, error shape
1051 std::string Selector_Selector::name(Selector_NameGenerator* theNameGenerator) {
1053 case SELTYPE_CONTAINER:
1054 case SELTYPE_INTERSECT: {
1055 std::string aResult;
1056 // add names of sub-components one by one in "[]" +optionally [weak_name_1]
1057 std::list<Selector_Selector>::iterator aSubSel = mySubSelList.begin();
1058 for(; aSubSel != mySubSelList.end(); aSubSel++) {
1060 aResult += aSubSel->name(theNameGenerator);
1062 TopoDS_Shape aSubVal = aSubSel->value();
1063 if (!aSubVal.IsNull()) {
1064 TopAbs_ShapeEnum aSubType = aSubVal.ShapeType();
1065 if (aSubType != TopAbs_FACE) { // in case the sub shape type must be stored
1067 case TopAbs_COMPOUND: aResult += "c"; break;
1068 case TopAbs_COMPSOLID: aResult += "o"; break;
1069 case TopAbs_SOLID: aResult += "s"; break;
1070 case TopAbs_SHELL: aResult += "h"; break;
1071 case TopAbs_WIRE: aResult += "w"; break;
1072 case TopAbs_EDGE: aResult += "e"; break;
1073 case TopAbs_VERTEX: aResult += "v"; break;
1080 if (myWeakIndex != -1) {
1081 std::ostringstream aWeakStr;
1082 aWeakStr<<"["<<kWEAK_NAME_IDENTIFIER<<myWeakIndex<<"]";
1083 aResult += aWeakStr.str();
1087 case SELTYPE_PRIMITIVE: {
1088 Handle(TDataStd_Name) aName;
1089 if (!myFinal.FindAttribute(TDataStd_Name::GetID(), aName))
1091 return theNameGenerator->contextName(myFinal) + "/" +
1092 std::string(TCollection_AsciiString(aName->Get()).ToCString());
1094 case SELTYPE_MODIFICATION: {
1095 // final&base1&base2 +optionally: [weak_name_1]
1096 std::string aResult;
1097 Handle(TDataStd_Name) aName;
1098 if (!myFinal.FindAttribute(TDataStd_Name::GetID(), aName))
1100 aResult += theNameGenerator->contextName(myFinal) + "/" +
1101 std::string(TCollection_AsciiString(aName->Get()).ToCString());
1102 for(TDF_LabelList::iterator aBase = myBases.begin(); aBase != myBases.end(); aBase++) {
1103 if (!aBase->FindAttribute(TDataStd_Name::GetID(), aName))
1106 aResult += theNameGenerator->contextName(*aBase) + "/" +
1107 std::string(TCollection_AsciiString(aName->Get()).ToCString());
1109 if (myWeakIndex != -1) {
1110 std::ostringstream aWeakStr;
1111 aWeakStr<<"&"<<kWEAK_NAME_IDENTIFIER<<myWeakIndex;
1112 aResult += aWeakStr.str();
1116 case SELTYPE_FILTER_BY_NEIGHBOR: {
1117 // (nb1)level_if_more_than_1(nb2)level_if_more_than_1(nb3)level_if_more_than_1
1118 std::string aResult;
1119 std::list<int>::iterator aLevel = myNBLevel.begin();
1120 std::list<Selector_Selector>::iterator aSubSel = mySubSelList.begin();
1121 for(; aSubSel != mySubSelList.end(); aSubSel++, aLevel++) {
1122 aResult += "(" + aSubSel->name(theNameGenerator) + ")";
1124 std::ostringstream aLevelStr;
1126 aResult += aLevelStr.str();
1131 case SELTYPE_WEAK_NAMING: {
1132 // _weak_naming_1_Context
1133 std::ostringstream aWeakStr;
1134 aWeakStr<<kPUREWEAK_NAME_IDENTIFIER<<myWeakIndex;
1135 std::string aResult = aWeakStr.str();
1136 if (!myFinal.IsNull())
1137 aResult += "_" + theNameGenerator->contextName(myFinal);
1140 default: { // unknown case
1146 TDF_Label Selector_Selector::restoreByName(
1147 std::string theName, const TopAbs_ShapeEnum theShapeType,
1148 Selector_NameGenerator* theNameGenerator, const bool theGeometricalNaming)
1150 myGeometricalNaming = theGeometricalNaming;
1151 if (theName[0] == '[') { // intersection or container
1152 switch(theShapeType) {
1153 case TopAbs_COMPOUND:
1154 case TopAbs_COMPSOLID:
1157 myType = SELTYPE_CONTAINER;
1162 myType = SELTYPE_INTERSECT;
1165 return TDF_Label(); // unknown case
1167 myShapeType = theShapeType;
1169 for(size_t aStart = 0; aStart != std::string::npos;
1170 aStart = theName.find('[', aStart + 1)) {
1171 size_t anEndPos = theName.find(']', aStart + 1);
1172 if (anEndPos != std::string::npos) {
1173 std::string aSubStr = theName.substr(aStart + 1, anEndPos - aStart - 1);
1174 if (aSubStr.find(kWEAK_NAME_IDENTIFIER) == 0) { // weak name identifier
1175 std::string aWeakIndex = aSubStr.substr(kWEAK_NAME_IDENTIFIER.size());
1176 myWeakIndex = atoi(aWeakIndex.c_str());
1179 TopAbs_ShapeEnum aSubShapeType = TopAbs_FACE;
1180 if (anEndPos != std::string::npos && anEndPos + 1 < theName.size()) {
1181 char aShapeChar = theName[anEndPos + 1];
1182 if (theName[anEndPos + 1] != '[') {
1183 switch(aShapeChar) {
1184 case 'c': aSubShapeType = TopAbs_COMPOUND; break;
1185 case 'o': aSubShapeType = TopAbs_COMPSOLID; break;
1186 case 's': aSubShapeType = TopAbs_SOLID; break;
1187 case 'h': aSubShapeType = TopAbs_SHELL; break;
1188 case 'w': aSubShapeType = TopAbs_WIRE; break;
1189 case 'e': aSubShapeType = TopAbs_EDGE; break;
1190 case 'v': aSubShapeType = TopAbs_VERTEX; break;
1195 mySubSelList.push_back(Selector_Selector(myLab.FindChild(int(mySubSelList.size()) + 1)));
1196 mySubSelList.back().setBaseDocument(myBaseDocumentLab);
1197 TDF_Label aSubContext = mySubSelList.back().restoreByName(
1198 aSubStr, aSubShapeType, theNameGenerator, theGeometricalNaming);
1199 if (aSubContext.IsNull())
1200 return aSubContext; // invalid sub-selection parsing
1201 if (!aContext.IsNull() && !aContext.IsEqual(aSubContext)) {
1202 if (!theNameGenerator->isLater(aContext, aSubContext))
1203 aContext = aSubContext;
1205 aContext = aSubContext;
1208 return TDF_Label(); // invalid parentheses
1211 } else if (theName[0] == '(') { // filter by neighbors
1212 myType = SELTYPE_FILTER_BY_NEIGHBOR;
1214 for(size_t aStart = 0; aStart != std::string::npos;
1215 aStart = theName.find('(', aStart + 1)) {
1216 size_t anEndPos = theName.find(')', aStart + 1);
1217 if (anEndPos != std::string::npos) {
1218 std::string aSubStr = theName.substr(aStart + 1, anEndPos - aStart - 1);
1219 mySubSelList.push_back(Selector_Selector(myLab.FindChild(int(mySubSelList.size()) + 1)));
1220 mySubSelList.back().setBaseDocument(myBaseDocumentLab);
1221 TDF_Label aSubContext = mySubSelList.back().restoreByName(
1222 aSubStr, theShapeType, theNameGenerator, theGeometricalNaming);
1223 if (aSubContext.IsNull())
1224 return aSubContext; // invalid sub-selection parsing
1225 if (!aContext.IsNull() && !aContext.IsEqual(aSubContext)) {
1226 if (!theNameGenerator->isLater(aContext, aSubContext))
1227 aContext = aSubContext;
1229 aContext = aSubContext;
1231 if (!aContext.IsNull()) // for filters by neighbor the latest context shape is vital
1232 aContext = theNameGenerator->newestContext(aContext);
1234 // searching for the level index
1236 for(anEndPos++; anEndPos != std::string::npos &&
1237 theName[anEndPos] != '(' && theName[anEndPos] != 0;
1239 aLevel += theName[anEndPos];
1242 myNBLevel.push_back(1); // by default it is 1
1244 int aNum = atoi(aLevel.c_str());
1246 myNBLevel.push_back(aNum);
1248 return TDF_Label(); // invalid number
1251 return TDF_Label(); // invalid parentheses
1254 } if (theName.find(kPUREWEAK_NAME_IDENTIFIER) == 0) { // weak naming identifier
1255 myType = SELTYPE_WEAK_NAMING;
1256 std::string aWeakIndex = theName.substr(kPUREWEAK_NAME_IDENTIFIER.size());
1257 std::size_t aContextPosition = aWeakIndex.find("_");
1258 myWeakIndex = atoi(aWeakIndex.c_str());
1259 myShapeType = theShapeType;
1261 if (aContextPosition != std::string::npos) { // context is also defined
1262 std::string aContextName = aWeakIndex.substr(aContextPosition + 1);
1263 theNameGenerator->restoreContext(aContextName, aContext, myFinal);
1266 } else if (theName.find('&') == std::string::npos) { // without '&' it can be only primitive
1267 myType = SELTYPE_PRIMITIVE;
1269 if (theNameGenerator->restoreContext(theName, aContext, myFinal)) {
1270 if (!myFinal.IsNull())
1273 } else { // modification
1274 myType = SELTYPE_MODIFICATION;
1276 for(size_t anEnd, aStart = 0; aStart != std::string::npos; aStart = anEnd) {
1279 anEnd = theName.find('&', aStart);
1280 std::string aSubStr =
1281 theName.substr(aStart, anEnd == std::string::npos ? anEnd : anEnd - aStart);
1282 if (aSubStr.find(kWEAK_NAME_IDENTIFIER) == 0) { // weak name identifier
1283 std::string aWeakIndex = aSubStr.substr(kWEAK_NAME_IDENTIFIER.size());
1284 myWeakIndex = atoi(aWeakIndex.c_str());
1287 TDF_Label aSubContext, aValue;
1288 if (!theNameGenerator->restoreContext(aSubStr, aSubContext, aValue))
1289 return TDF_Label(); // can not restore
1290 if(aSubContext.IsNull() || aValue.IsNull())
1291 return TDF_Label(); // can not restore
1292 if (myFinal.IsNull()) {
1294 aContext = aSubContext;
1296 myBases.Append(aValue);
1303 bool Selector_Selector::selectBySubSelector(const TopoDS_Shape theContext,
1304 const TopoDS_Shape theValue, const bool theGeometricalNaming,
1305 const bool theUseNeighbors, const bool theUseIntersections)
1307 mySubSelList.push_back(Selector_Selector(myLab.FindChild(int(mySubSelList.size()) + 1)));
1308 if (!myBaseDocumentLab.IsNull())
1309 mySubSelList.back().setBaseDocument(myBaseDocumentLab);
1310 if (!mySubSelList.back().select(theContext, theValue,
1311 theGeometricalNaming, theUseNeighbors, theUseIntersections)) {
1312 mySubSelList.clear(); // if one of the selector is failed, all become invalid