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 <TopoDS_Iterator.hxx>
27 #include <TopoDS_Builder.hxx>
29 #include <TopExp_Explorer.hxx>
30 #include <TopoDS_Edge.hxx>
31 #include <TopoDS_Face.hxx>
32 #include <TNaming_Tool.hxx>
33 #include <TNaming_NewShapeIterator.hxx>
34 #include <TNaming_OldShapeIterator.hxx>
35 #include <TNaming_SameShapeIterator.hxx>
36 #include <TNaming_Iterator.hxx>
37 #include <TNaming_Builder.hxx>
38 #include <TopTools_MapOfShape.hxx>
39 #include <BRep_Tool.hxx>
41 #include <TDF_ChildIDIterator.hxx>
42 #include <TDF_Tool.hxx>
43 #include <TDataStd_Integer.hxx>
44 #include <TDataStd_ReferenceArray.hxx>
45 #include <TDataStd_IntegerArray.hxx>
46 #include <TDataStd_Name.hxx>
47 #include <TDataStd_UAttribute.hxx>
48 #include <TDataStd_ExtStringList.hxx>
52 /// type of the selection, integer keeps the Selector_Type value
53 static const Standard_GUID kSEL_TYPE("db174d59-c2e3-4a90-955e-55544df090d6");
54 /// type of the shape, stored in case it is intersection or container
55 static const Standard_GUID kSHAPE_TYPE("864b3267-cb9d-4107-bf58-c3ce1775b171");
56 // reference attribute that contains the reference to labels where the "from" or "base" shapes
57 // of selection are located
58 static const Standard_GUID kBASE_ARRAY("7c515b1a-9549-493d-9946-a4933a22f45f");
59 // if the base array contains reference to the root label, this means that it refers to an
60 // external document and this list contains a tag in the document
61 static const Standard_GUID kBASE_LIST("7c515b1a-9549-493d-9946-a4933a22f45a");
62 // array of the neighbor levels
63 static const Standard_GUID kLEVELS_ARRAY("ee4c4b45-e859-4e86-aa4f-6eac68e0ca1f");
64 // weak index (integer) of the sub-shape
65 static const Standard_GUID kWEAK_INDEX("e9373a61-cabc-4ee8-aabf-aea47c62ed87");
66 // geometrical naming indicator
67 static const Standard_GUID kGEOMETRICAL_NAMING("a5322d02-50fb-43ed-9255-75c7b93f6657");
69 // string identifier of the weak name in modification or intersection types of algorithm
70 static const std::string kWEAK_NAME_IDENTIFIER = "weak_name_";
71 // string identifier of the pure weak name algorithm
72 static const std::string kPUREWEAK_NAME_IDENTIFIER = "_weak_name_";
75 Selector_Selector::Selector_Selector(TDF_Label theLab) : myLab(theLab)
80 TDF_Label Selector_Selector::label()
85 void Selector_Selector::setBaseDocument(const TDF_Label theAccess)
87 myBaseDocumentLab = theAccess;
90 // adds to theResult all labels that contain initial shapes for theValue located in theFinal
91 static void findBases(TDF_Label theAccess, Handle(TNaming_NamedShape) theFinal,
92 const TopoDS_Shape& theValue,
93 bool aMustBeAtFinal, const TDF_Label& theAdditionalDocument, TDF_LabelList& theResult)
95 bool aFoundAnyShape = false;
96 TNaming_SameShapeIterator aLabIter(theValue, theAccess);
97 for(; aLabIter.More(); aLabIter.Next()) {
98 Handle(TNaming_NamedShape) aNS;
99 if (aLabIter.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
100 if (aMustBeAtFinal && aNS != theFinal)
101 continue; // looking for old at the same final label only
102 TNaming_Evolution anEvolution = aNS->Evolution();
103 if (anEvolution == TNaming_PRIMITIVE) {
104 // check that this is not in the results already
105 const TDF_Label aResult = aNS->Label();
106 TDF_LabelList::Iterator aResIter(theResult);
107 for(; aResIter.More(); aResIter.Next()) {
108 if (aResIter.Value().IsEqual(aResult))
111 if (!aResIter.More()) // not found, so add this new
112 theResult.Append(aResult);
113 aFoundAnyShape = true;
115 if (anEvolution == TNaming_GENERATED || anEvolution == TNaming_MODIFY) {
116 for(TNaming_Iterator aThisIter(aNS); aThisIter.More(); aThisIter.Next()) {
117 if (aThisIter.NewShape().IsSame(theValue)) {
118 // continue recursively, null NS means that any NS are ok
119 findBases(theAccess, theFinal, aThisIter.OldShape(),
120 false, theAdditionalDocument, theResult);
121 aFoundAnyShape = true;
127 if (!aFoundAnyShape && !theAdditionalDocument.IsNull()) { // try to find in additional document
128 static TDF_Label anEmpty;
129 if (TNaming_Tool::HasLabel(theAdditionalDocument, theValue))
130 findBases(theAdditionalDocument, Handle(TNaming_NamedShape)(), theValue,
131 false, anEmpty, theResult);
135 // returns the sub-shapes of theSubType which belong to all theShapes (so, common or intersection)
136 static void commonShapes(const TopoDS_ListOfShape& theShapes, TopAbs_ShapeEnum theSubType,
137 TopoDS_ListOfShape& theResults)
139 TopoDS_ListOfShape::iterator aSubSel = theShapes.begin();
140 for(; aSubSel != theShapes.end(); aSubSel++) {
141 TopTools_MapOfShape aCurrentMap;
142 for(TopExp_Explorer anExp(*aSubSel, theSubType); anExp.More(); anExp.Next()) {
143 if (aCurrentMap.Add(anExp.Current()) && aSubSel == theShapes.begin())
144 theResults.Append(anExp.Current());
146 if (aSubSel != theShapes.begin()) { // remove from common shapes not in aCurrentMap
147 for(TopoDS_ListOfShape::Iterator aComIter(theResults); aComIter.More(); ) {
148 if (aCurrentMap.Contains(aComIter.Value()))
151 theResults.Remove(aComIter);
157 /// Searches neighbor of theLevel of neighborhood to theValue in theContex
158 static void findNeighbors(const TopoDS_Shape theContext, const TopoDS_Shape theValue,
159 const int theLevel, TopTools_MapOfShape& theResult)
161 TopAbs_ShapeEnum aConnectorType = TopAbs_VERTEX; // type of the connector sub-shapes
162 if (theValue.ShapeType() == TopAbs_FACE)
163 aConnectorType = TopAbs_EDGE;
164 TopTools_MapOfShape aNBConnectors; // connector shapes that already belong to neighbors
165 for(TopExp_Explorer aValExp(theValue, aConnectorType); aValExp.More(); aValExp.Next()) {
166 aNBConnectors.Add(aValExp.Current());
169 TopTools_MapOfShape alreadyProcessed;
170 alreadyProcessed.Add(theValue);
172 for(int aLevel = 1; aLevel <= theLevel; aLevel++) {
173 TopoDS_ListOfShape aGoodCandidates;
174 TopExp_Explorer aCandidate(theContext, theValue.ShapeType());
175 for(; aCandidate.More(); aCandidate.Next()) {
176 if (alreadyProcessed.Contains(aCandidate.Current()))
178 TopExp_Explorer aCandConnector(aCandidate.Current(), aConnectorType);
179 for(; aCandConnector.More(); aCandConnector.Next()) {
180 if (aNBConnectors.Contains(aCandConnector.Current())) // candidate is neighbor
183 if (aCandConnector.More()) {
184 if (aLevel == theLevel) { // add a NB into result: it is connected to other neighbors
185 theResult.Add(aCandidate.Current());
186 } else { // add to the NB of the current level
187 aGoodCandidates.Append(aCandidate.Current());
191 if (aLevel != theLevel) { // good candidates are added to neighbor of this level by connectors
192 for(TopoDS_ListOfShape::Iterator aGood(aGoodCandidates); aGood.More(); aGood.Next()) {
193 TopExp_Explorer aGoodConnector(aGood.Value(), aConnectorType);
194 for(; aGoodConnector.More(); aGoodConnector.Next()) {
195 aNBConnectors.Add(aGoodConnector.Current());
197 alreadyProcessed.Add(aGood.Value());
203 /// Returns true if the given shapes are based on the same geometry
204 static bool sameGeometry(const TopoDS_Shape theShape1, const TopoDS_Shape theShape2) {
205 if (!theShape1.IsNull() && !theShape2.IsNull() && theShape1.ShapeType() == theShape2.ShapeType())
207 if (theShape1.ShapeType() == TopAbs_FACE) { // check surfaces
208 TopLoc_Location aLoc1, aLoc2;
209 TopoDS_Face aFace1 = TopoDS::Face(theShape1);
210 Handle(Geom_Surface) aSurf1 = BRep_Tool::Surface(aFace1, aLoc1);
211 TopoDS_Face aFace2 = TopoDS::Face(theShape2);
212 Handle(Geom_Surface) aSurf2 = BRep_Tool::Surface(aFace2, aLoc2);
213 return aSurf1 == aSurf2 && aLoc1.IsEqual(aLoc2);
214 } else if (theShape1.ShapeType() == TopAbs_EDGE) { // check curves
215 TopLoc_Location aLoc1, aLoc2;
216 Standard_Real aFirst, aLast;
217 TopoDS_Edge anEdge1 = TopoDS::Edge(theShape1);
218 Handle(Geom_Curve) aCurve1 = BRep_Tool::Curve(anEdge1, aLoc1, aFirst, aLast);
219 TopoDS_Edge anEdge2 = TopoDS::Edge(theShape2);
220 Handle(Geom_Curve) aCurve2 = BRep_Tool::Curve(anEdge2, aLoc2, aFirst, aLast);
221 return aCurve1 == aCurve2 && aLoc1.IsEqual(aLoc2);
227 /// Searches the neighbor shape by neighbors defined in theNB in theContext shape
228 static const TopoDS_Shape findNeighbor(const TopoDS_Shape theContext,
229 const std::list<std::pair<TopoDS_Shape, int> >& theNB, const bool theGeometrical)
231 // searching for neighbors with minimum level
233 std::list<std::pair<TopoDS_Shape, int> >::const_iterator aNBIter = theNB.cbegin();
234 for(; aNBIter != theNB.cend(); aNBIter++) {
235 if (aMinLevel == 0 || aNBIter->second < aMinLevel) {
236 aMinLevel = aNBIter->second;
239 // collect all neighbors which are neighbors of sub-shapes with minimum level
241 TopoDS_ListOfShape aMatches;
242 for(aNBIter = theNB.cbegin(); aNBIter != theNB.cend(); aNBIter++) {
243 if (aNBIter->second == aMinLevel) {
244 TopTools_MapOfShape aThisNBs;
245 findNeighbors(theContext, aNBIter->first, aMinLevel, aThisNBs);
246 // aMatches must contain common part of all NBs lists
247 for(TopTools_MapOfShape::Iterator aThisNB(aThisNBs); aThisNB.More(); aThisNB.Next()) {
249 aMatches.Append(aThisNB.Value());
251 // remove all in aMatches which are not in this NBs
252 for(TopoDS_ListOfShape::Iterator aMatch(aMatches); aMatch.More(); ) {
253 if (aThisNBs.Contains(aMatch.Value())) {
256 aMatches.Remove(aMatch);
264 if (aMatches.IsEmpty())
265 return TopoDS_Shape(); // not found any candidate
266 if (aMatches.Extent() == 1)
267 return aMatches.First(); // already found good candidate
268 TopoDS_Compound aResultCompound; // in case of geometrical name and many candidates
269 // iterate all matches to find by other (higher level) neighbors the best candidate
270 TopoDS_Shape aGoodCandidate;
271 for(TopoDS_ListOfShape::Iterator aCandidate(aMatches); aCandidate.More(); aCandidate.Next()) {
272 bool aValidCadidate = true;
273 for(int aLevel = aMinLevel + 1; true; aLevel++) {
274 bool aFooundHigherLevel = false;
275 TopoDS_ListOfShape aLevelNBs;
276 for(aNBIter = theNB.cbegin(); aNBIter != theNB.cend(); aNBIter++) {
277 if (aNBIter->second == aLevel)
278 aLevelNBs.Append(aNBIter->first);
279 else if (aNBIter->second >= aLevel)
280 aFooundHigherLevel = true;
282 if (!aFooundHigherLevel && aLevelNBs.IsEmpty()) { // iterated all, so, good candidate
283 if (aGoodCandidate.IsNull()) {
284 aGoodCandidate = aCandidate.Value();
285 } else { // another good candidate
286 if (theGeometrical && sameGeometry(aGoodCandidate, aCandidate.Value())) {
287 static TopoDS_Builder aBuilder;
288 if (aResultCompound.IsNull()) {
289 aBuilder.MakeCompound(aResultCompound);
290 aBuilder.Add(aResultCompound, aGoodCandidate);
292 aBuilder.Add(aResultCompound, aCandidate.Value());
294 return TopoDS_Shape();
297 if (!aLevelNBs.IsEmpty()) {
298 TopTools_MapOfShape aNBsOfCandidate;
299 findNeighbors(theContext, aCandidate.Value(), aLevel, aNBsOfCandidate);
300 // check all stored neighbors are in the map of real neighbors
301 for(TopoDS_ListOfShape::Iterator aLevIter(aLevelNBs); aLevIter.More(); aLevIter.Next()) {
302 if (!aNBsOfCandidate.Contains(aLevIter.Value())) {
303 aValidCadidate = false;
308 if (!aValidCadidate) // candidate is not valid, break the checking
312 if (!aResultCompound.IsNull())
313 return aResultCompound;
314 return aGoodCandidate;
317 bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape theValue,
318 const bool theGeometricalNaming, const bool theUseNeighbors, const bool theUseIntersections)
320 if (theValue.IsNull() || theContext.IsNull())
322 myGeometricalNaming = theGeometricalNaming;
323 // check the value shape can be named as it is, or it is needed to construct it from the
324 // higher level shapes (like a box vertex by faces that form this vertex)
325 bool aIsFound = TNaming_Tool::HasLabel(myLab, theValue);
326 if (aIsFound) { // additional check for selection and delete evolution only: also could not use
328 for(TNaming_SameShapeIterator aShapes(theValue, myLab); aShapes.More(); aShapes.Next())
330 Handle(TNaming_NamedShape) aNS;
331 if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
332 if (aNS->Evolution() == TNaming_MODIFY || aNS->Evolution() == TNaming_GENERATED ||
333 aNS->Evolution() == TNaming_PRIMITIVE) {
340 // searching in the base document
341 if (!aIsFound && !myBaseDocumentLab.IsNull() &&
342 TNaming_Tool::HasLabel(myBaseDocumentLab, theValue))
344 TNaming_SameShapeIterator aShapes(theValue, myBaseDocumentLab);
345 for(; aShapes.More(); aShapes.Next())
347 Handle(TNaming_NamedShape) aNS;
348 if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
349 if (aNS->Evolution() == TNaming_MODIFY || aNS->Evolution() == TNaming_GENERATED ||
350 aNS->Evolution() == TNaming_PRIMITIVE) {
358 TopAbs_ShapeEnum aSelectionType = theValue.ShapeType();
359 myShapeType = aSelectionType;
360 if (aSelectionType == TopAbs_COMPOUND || aSelectionType == TopAbs_COMPSOLID ||
361 aSelectionType == TopAbs_SHELL || aSelectionType == TopAbs_WIRE)
362 { // iterate all sub-shapes and select them on sublabels
363 for(TopoDS_Iterator aSubIter(theValue); aSubIter.More(); aSubIter.Next()) {
364 if (!selectBySubSelector(theContext, aSubIter.Value(),
365 theGeometricalNaming, theUseNeighbors, theUseIntersections)) {
366 return false; // if some selector is failed, everything is failed
369 myType = SELTYPE_CONTAINER;
373 // try to find the shape of the higher level type in the context shape
374 bool aFacesTried = false; // for identification of vertices, faces are tried, then edges
375 TopoDS_ListOfShape aLastCommon; // to store the commons not good, but may be used for weak
376 TopoDS_ListOfShape aLastIntersectors;
377 while(theUseIntersections && (aSelectionType != TopAbs_FACE || !aFacesTried)) {
378 if (aSelectionType == TopAbs_FACE) {
379 if (theValue.ShapeType() != TopAbs_VERTEX)
382 aSelectionType = TopAbs_EDGE;
384 aSelectionType = TopAbs_FACE;
385 TopTools_MapOfShape anIntersectors; // shapes of aSelectionType that contain theValue
386 TopoDS_ListOfShape anIntList; // same as anIntersectors
387 for(TopExp_Explorer aSelExp(theContext, aSelectionType); aSelExp.More(); aSelExp.Next()) {
388 if (aSelectionType == TopAbs_EDGE &&
389 BRep_Tool::Degenerated(TopoDS::Edge(aSelExp.Current())))
391 TopExp_Explorer aSubExp(aSelExp.Current(), theValue.ShapeType());
392 for(; aSubExp.More(); aSubExp.Next()) {
393 if (aSubExp.Current().IsSame(theValue)) {
394 if (anIntersectors.Add(aSelExp.Current()))
395 anIntList.Append(aSelExp.Current());
400 // check that solution is only one
401 TopoDS_ListOfShape aCommon;
402 commonShapes(anIntList, theValue.ShapeType(), aCommon);
403 if (aCommon.Extent() == 1 && aCommon.First().IsSame(theValue)) {
404 // name the intersectors
405 mySubSelList.clear();
406 TopoDS_ListOfShape::Iterator anInt(anIntList);
407 for (; anInt.More(); anInt.Next()) {
408 if (!selectBySubSelector(theContext, anInt.Value(),
409 theGeometricalNaming, theUseNeighbors, false)) {
410 break; // if some selector is failed, stop and search another solution
413 if (!anInt.More()) { // all intersectors were correctly named
414 myType = SELTYPE_INTERSECT;
417 } else if (aCommon.Extent() > 1 && aLastCommon.IsEmpty()) {
418 aLastCommon = aCommon;
419 aLastIntersectors = anIntList;
423 if (!theUseNeighbors)
426 // searching by neighbors
427 std::list<std::pair<TopoDS_Shape, int> > aNBs; /// neighbor sub-shape -> level of neighborhood
428 for(int aLevel = 1; true; aLevel++) {
429 TopTools_MapOfShape aNewNB;
430 findNeighbors(theContext, theValue, aLevel, aNewNB);
431 if (aNewNB.Extent() == 0) { // there are no neighbors of the given level, stop iteration
434 // iterate by the order in theContext to keep same naming names
435 TopExp_Explorer anOrder(theContext, theValue.ShapeType());
436 for (; anOrder.More(); anOrder.Next()) {
437 if (aNewNB.Contains(anOrder.Current())) {
438 TopoDS_Shape aNewNBShape = anOrder.Current();
439 // check which can be named correctly, without "by neighbors" type
440 Selector_Selector aSelector(myLab.FindChild(1));
441 aSelector.setBaseDocument(myBaseDocumentLab);
442 if (aSelector.select(theContext, aNewNBShape, theGeometricalNaming, false, false)) {
443 // add to list of good NBs
444 aNBs.push_back(std::pair<TopoDS_Shape, int>(aNewNBShape, aLevel));
448 TopoDS_Shape aResult = findNeighbor(theContext, aNBs, theGeometricalNaming);
449 if (!aResult.IsNull() && aResult.IsSame(theValue)) {
450 std::list<std::pair<TopoDS_Shape, int> >::iterator aNBIter = aNBs.begin();
451 for(; aNBIter != aNBs.end(); aNBIter++) {
452 if (!selectBySubSelector(theContext, aNBIter->first,
453 theGeometricalNaming, false, false)) {
454 return false; // something is wrong because before this selection was ok
456 myNBLevel.push_back(aNBIter->second);
459 myType = SELTYPE_FILTER_BY_NEIGHBOR;
464 // weak naming to distinguish commons coming from intersection
465 if (aLastCommon.Extent() > 1) {
466 Selector_NExplode aNexp(aLastCommon);
467 myWeakIndex = aNexp.index(theValue);
468 if (myWeakIndex != -1) {
469 // name the intersectors
470 mySubSelList.clear();
471 TopoDS_ListOfShape::Iterator anInt(aLastIntersectors);
472 for (; anInt.More(); anInt.Next()) {
473 if (!selectBySubSelector(theContext, anInt.Value(),
474 theGeometricalNaming, theUseNeighbors, theUseIntersections)) {
475 break; // if some selector is failed, stop and search another solution
478 if (!anInt.More()) { // all intersectors were correctly named
479 myType = SELTYPE_INTERSECT;
485 // pure weak naming: there is no sense to use pure weak naming for neighbors selection
486 if (theUseNeighbors) {
487 myType = SELTYPE_WEAK_NAMING;
488 Selector_NExplode aNexp(theContext, theValue.ShapeType());
489 myWeakIndex = aNexp.index(theValue);
490 if (myWeakIndex != -1) {
491 myShapeType = theValue.ShapeType();
492 // searching for context shape label to store in myFinal
494 if (TNaming_Tool::HasLabel(myLab, theContext)) {
495 for(TNaming_SameShapeIterator aShapes(theContext, myLab); aShapes.More(); aShapes.Next())
497 Handle(TNaming_NamedShape) aNS;
498 if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
499 TNaming_Evolution anEvolution = aNS->Evolution();
500 if (anEvolution == TNaming_PRIMITIVE || anEvolution == TNaming_GENERATED ||
501 anEvolution == TNaming_MODIFY) {
502 // check this is a new shape
503 for(TNaming_Iterator aNSIter(aNS); aNSIter.More(); aNSIter.Next()) {
504 if (aNSIter.NewShape().IsSame(theContext)) {
505 myFinal = aNS->Label();
513 return true; // could be final empty (in case it is called recursively) or not
519 // searching for the base shapes of the value
520 Handle(TNaming_NamedShape) aPrimitiveNS;
521 NCollection_List<Handle(TNaming_NamedShape)> aModifList;
522 for(int aUseExternal = 0; aUseExternal < 2; aUseExternal++) {
523 TDF_Label aLab = aUseExternal == 0 ? myLab : myBaseDocumentLab;
524 if (aLab.IsNull() || !TNaming_Tool::HasLabel(aLab, theValue))
526 for(TNaming_SameShapeIterator aShapes(theValue, aLab); aShapes.More(); aShapes.Next())
528 Handle(TNaming_NamedShape) aNS;
529 if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
530 TNaming_Evolution anEvolution = aNS->Evolution();
531 if (anEvolution == TNaming_PRIMITIVE) { // the value shape is declared as PRIMITIVE
534 } else if (anEvolution == TNaming_GENERATED || anEvolution == TNaming_MODIFY) {
535 // check this is a new shape
536 TNaming_Iterator aNSIter(aNS);
537 for(; aNSIter.More(); aNSIter.Next())
538 if (aNSIter.NewShape().IsSame(theValue))
540 if (aNSIter.More()) // new was found
541 aModifList.Append(aNS);
547 if (!aPrimitiveNS.IsNull()) {
548 myType = SELTYPE_PRIMITIVE;
549 myFinal = aPrimitiveNS->Label();
553 if (aModifList.Extent() > 1) { // searching for the best modification result: by context
554 Handle(TNaming_NamedShape) aCandidate;
555 NCollection_List<Handle(TNaming_NamedShape)>::Iterator aModIter(aModifList);
556 for(; !aModifList.IsEmpty() && aModIter.More(); aModIter.Next()) {
557 aCandidate = aModIter.Value();
558 TDF_Label aFatherLab = aCandidate->Label().Father();
559 Handle(TNaming_NamedShape) aFatherNS;
560 if (aFatherLab.FindAttribute(TNaming_NamedShape::GetID(), aFatherNS)) {
561 for(TNaming_Iterator anIter(aFatherNS); anIter.More(); anIter.Next()) {
562 if (theContext.IsSame(anIter.NewShape())) { // found the best modification
569 // take the best candidate, or the last in the iteration
571 aModifList.Append(aCandidate);
574 if (!aModifList.IsEmpty()) {
575 // searching for all the base shapes of this modification
576 findBases(myLab, aModifList.First(), theValue, true, myBaseDocumentLab, myBases);
577 if (!myBases.IsEmpty()) {
578 myFinal = aModifList.First()->Label();
579 TopoDS_ListOfShape aCommon;
580 findModificationResult(aCommon);
581 // trying to search by neighbors
582 if (aCommon.Extent() > 1) { // more complicated selection
583 if (!theUseNeighbors)
586 // searching by neighbors
587 std::list<std::pair<TopoDS_Shape, int> > aNBs;//neighbor sub-shape -> level of neighborhood
588 for(int aLevel = 1; true; aLevel++) {
589 TopTools_MapOfShape aNewNB;
590 findNeighbors(theContext, theValue, aLevel, aNewNB);
591 if (aNewNB.Extent() == 0) { // there are no neighbors of the given level, stop iteration
594 // iterate by the order in theContext to keep same naming names
595 TopExp_Explorer anOrder(theContext, theValue.ShapeType());
596 for (; anOrder.More(); anOrder.Next()) {
597 if (aNewNB.Contains(anOrder.Current())) {
598 TopoDS_Shape aNewNBShape = anOrder.Current();
599 // check which can be named correctly, without "by neighbors" type
600 Selector_Selector aSelector(myLab.FindChild(1));
601 if (!myBaseDocumentLab.IsNull())
602 aSelector.setBaseDocument(myBaseDocumentLab);
603 if (aSelector.select(theContext, aNewNBShape, theGeometricalNaming, false)) {
604 // add to list of good NBs
605 aNBs.push_back(std::pair<TopoDS_Shape, int>(aNewNBShape, aLevel));
609 TopoDS_Shape aResult = findNeighbor(theContext, aNBs, theGeometricalNaming);
610 if (!aResult.IsNull() && aResult.IsSame(theValue)) {
611 std::list<std::pair<TopoDS_Shape, int> >::iterator aNBIter = aNBs.begin();
612 for(; aNBIter != aNBs.end(); aNBIter++) {
613 if (!selectBySubSelector(theContext, aNBIter->first,
614 theGeometricalNaming, theUseNeighbors, theUseIntersections)) {
615 return false; // something is wrong because before this selection was ok
617 myNBLevel.push_back(aNBIter->second);
620 myType = SELTYPE_FILTER_BY_NEIGHBOR;
624 // filter by neighbors did not help
625 if (aCommon.Extent() > 1) { // weak naming between the common results
626 Selector_NExplode aNexp(aCommon);
627 myWeakIndex = aNexp.index(theValue);
628 if (myWeakIndex == -1)
633 myType = SELTYPE_MODIFICATION;
634 if (myBases.IsEmpty()) { // selection based on the external shape, weak name by finals compound
635 TopoDS_ListOfShape aCommon;
636 myFinal = aModifList.First()->Label();
637 Handle(TNaming_NamedShape) aNS;
638 if (myFinal.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
639 for(TNaming_Iterator aFinalIter(aNS); aFinalIter.More(); aFinalIter.Next()) {
640 const TopoDS_Shape& aNewShape = aFinalIter.NewShape();
641 if (!aNewShape.IsNull())
642 aCommon.Append(aNewShape);
645 Selector_NExplode aNexp(aCommon);
646 myWeakIndex = aNexp.index(theValue);
647 if (myWeakIndex == -1)
653 // not found a good result
657 /// Stores the array of references to the label: references to elements of ref-list, then the last
658 static void storeBaseArray(const TDF_Label& theLab,
659 const TDF_LabelList& theRef, const TDF_Label& theLast)
661 Handle(TDataStd_ReferenceArray) anArray =
662 TDataStd_ReferenceArray::Set(theLab, kBASE_ARRAY, 0, theRef.Extent());
663 Handle(TDataStd_ExtStringList) anEntries; // entries of references to external document
664 const TDF_Label aThisDocRoot = theLab.Root();
665 TDF_LabelList::Iterator aBIter(theRef);
666 for(int anIndex = 0; true; aBIter.Next(), anIndex++) {
667 const TDF_Label& aLab = aBIter.More() ? aBIter.Value() : theLast;
668 // check this is a label of this document
669 if (aLab.Root().IsEqual(aThisDocRoot)) {
670 anArray->SetValue(anIndex, aLab);
671 } else { // store reference to external document as an entry-string
672 if (anEntries.IsNull()) {
673 anEntries = TDataStd_ExtStringList::Set(theLab, kBASE_LIST);
675 TCollection_AsciiString anEntry;
676 TDF_Tool::Entry(aLab, anEntry);
677 anEntries->Append(anEntry);
678 anArray->SetValue(anIndex, aThisDocRoot); // stored root means it is external reference
685 void Selector_Selector::store()
687 static const TDF_LabelList anEmptyRefList;
688 myLab.ForgetAllAttributes(true); // remove old naming data
689 TDataStd_Integer::Set(myLab, kSEL_TYPE, (int)myType);
690 if (myGeometricalNaming)
691 TDataStd_UAttribute::Set(myLab, kGEOMETRICAL_NAMING);
693 case SELTYPE_CONTAINER:
694 case SELTYPE_INTERSECT: {
695 TDataStd_Integer::Set(myLab, kSHAPE_TYPE, (int)myShapeType);
696 // store also all sub-selectors
697 std::list<Selector_Selector>::iterator aSubSel = mySubSelList.begin();
698 for(; aSubSel != mySubSelList.end(); aSubSel++) {
701 if (myWeakIndex != -1) {
702 TDataStd_Integer::Set(myLab, kWEAK_INDEX, myWeakIndex);
706 case SELTYPE_PRIMITIVE: {
707 storeBaseArray(myLab, anEmptyRefList, myFinal);
710 case SELTYPE_MODIFICATION: {
711 storeBaseArray(myLab, myBases, myFinal);
712 if (myWeakIndex != -1) {
713 TDataStd_Integer::Set(myLab, kWEAK_INDEX, myWeakIndex);
717 case SELTYPE_FILTER_BY_NEIGHBOR: {
718 TDataStd_Integer::Set(myLab, kSHAPE_TYPE, (int)myShapeType);
719 // store numbers of levels corresponded to the neighbors in sub-selectors
720 Handle(TDataStd_IntegerArray) anArray =
721 TDataStd_IntegerArray::Set(myLab, kLEVELS_ARRAY, 0, int(myNBLevel.size()) - 1);
722 std::list<int>::iterator aLevel = myNBLevel.begin();
723 for(int anIndex = 0; aLevel != myNBLevel.end(); aLevel++, anIndex++) {
724 anArray->SetValue(anIndex, *aLevel);
726 // store all sub-selectors
727 std::list<Selector_Selector>::iterator aSubSel = mySubSelList.begin();
728 for(; aSubSel != mySubSelList.end(); aSubSel++) {
733 case SELTYPE_WEAK_NAMING: {
734 TDataStd_Integer::Set(myLab, kWEAK_INDEX, myWeakIndex);
735 TDataStd_Integer::Set(myLab, kSHAPE_TYPE, (int)myShapeType);
736 if (!myFinal.IsNull()) {
737 storeBaseArray(myLab, anEmptyRefList, myFinal);
741 default: { // unknown case
747 /// Restores references to the labels: references to elements of ref-list, then the last
748 static bool restoreBaseArray(const TDF_Label& theLab, const TDF_Label& theBaseDocumetnLab,
749 TDF_LabelList& theRef, TDF_Label& theLast)
751 const TDF_Label aThisDocRoot = theLab.Root();
752 Handle(TDataStd_ExtStringList) anEntries; // entries of references to external document
753 TDataStd_ListOfExtendedString::Iterator anIter;
754 Handle(TDataStd_ReferenceArray) anArray;
755 if (theLab.FindAttribute(kBASE_ARRAY, anArray)) {
756 int anUpper = anArray->Upper();
757 for(int anIndex = anArray->Lower(); anIndex <= anUpper; anIndex++) {
758 TDF_Label aLab = anArray->Value(anIndex);
759 if (aLab.IsEqual(aThisDocRoot)) { // external document reference
760 if (theBaseDocumetnLab.IsNull())
762 if (anEntries.IsNull()) {
763 if (!theLab.FindAttribute(kBASE_LIST, anEntries))
765 anIter.Initialize(anEntries->List());
769 TDF_Tool::Label(theBaseDocumetnLab.Data(), anIter.Value(), aLab);
772 if (anIndex == anUpper) {
784 bool Selector_Selector::restore()
786 Handle(TDataStd_Integer) aTypeAttr;
787 if (!myLab.FindAttribute(kSEL_TYPE, aTypeAttr))
789 myGeometricalNaming = myLab.IsAttribute(kGEOMETRICAL_NAMING);
790 myType = Selector_Type(aTypeAttr->Get());
792 case SELTYPE_CONTAINER:
793 case SELTYPE_INTERSECT: {
794 Handle(TDataStd_Integer) aShapeTypeAttr;
795 if (!myLab.FindAttribute(kSHAPE_TYPE, aShapeTypeAttr))
797 myShapeType = TopAbs_ShapeEnum(aShapeTypeAttr->Get());
798 // restore sub-selectors
799 bool aSubResult = true;
800 mySubSelList.clear();
801 for(TDF_ChildIDIterator aSub(myLab, kSEL_TYPE, false); aSub.More(); aSub.Next()) {
802 mySubSelList.push_back(Selector_Selector(aSub.Value()->Label()));
803 mySubSelList.back().setBaseDocument(myBaseDocumentLab);
804 if (!mySubSelList.back().restore())
807 Handle(TDataStd_Integer) aWeakInt;
808 if (myLab.FindAttribute(kWEAK_INDEX, aWeakInt)) {
809 myWeakIndex = aWeakInt->Get();
813 case SELTYPE_PRIMITIVE: {
814 return restoreBaseArray(myLab, myBaseDocumentLab, myBases, myFinal);
816 case SELTYPE_MODIFICATION: {
817 if (restoreBaseArray(myLab, myBaseDocumentLab, myBases, myFinal)) {
818 Handle(TDataStd_Integer) aWeakInt;
819 if (myLab.FindAttribute(kWEAK_INDEX, aWeakInt)) {
820 myWeakIndex = aWeakInt->Get();
826 case SELTYPE_FILTER_BY_NEIGHBOR: {
827 Handle(TDataStd_Integer) aShapeTypeAttr;
828 if (!myLab.FindAttribute(kSHAPE_TYPE, aShapeTypeAttr))
830 myShapeType = TopAbs_ShapeEnum(aShapeTypeAttr->Get());
831 // restore sub-selectors
832 bool aSubResult = true;
833 mySubSelList.clear();
834 for(TDF_ChildIDIterator aSub(myLab, kSEL_TYPE, false); aSub.More(); aSub.Next()) {
835 mySubSelList.push_back(Selector_Selector(aSub.Value()->Label()));
836 mySubSelList.back().setBaseDocument(myBaseDocumentLab);
837 if (!mySubSelList.back().restore())
840 // restore levels indices
841 Handle(TDataStd_IntegerArray) anArray;
842 if (!myLab.FindAttribute(kLEVELS_ARRAY, anArray))
844 for(int anIndex = 0; anIndex <= anArray->Upper(); anIndex++) {
845 myNBLevel.push_back(anArray->Value(anIndex));
849 case SELTYPE_WEAK_NAMING: {
850 Handle(TDataStd_Integer) aWeakInt;
851 if (!myLab.FindAttribute(kWEAK_INDEX, aWeakInt))
853 myWeakIndex = aWeakInt->Get();
854 Handle(TDataStd_Integer) aShapeTypeAttr;
855 if (!myLab.FindAttribute(kSHAPE_TYPE, aShapeTypeAttr))
857 myShapeType = TopAbs_ShapeEnum(aShapeTypeAttr->Get());
858 if (!restoreBaseArray(myLab, myBaseDocumentLab, myBases, myFinal))
862 default: { // unknown case
868 /// Returns in theResults all shapes with history started in theBase and ended in theFinal
869 static void findFinals(const TDF_Label& anAccess, const TopoDS_Shape& theBase,
870 const TDF_Label& theFinal,
871 const TDF_Label& theAdditionalDoc, TopTools_MapOfShape& theResults)
873 if (TNaming_Tool::HasLabel(anAccess, theBase)) {
874 for(TNaming_NewShapeIterator aBaseIter(theBase, anAccess); aBaseIter.More(); aBaseIter.Next())
876 TNaming_Evolution anEvolution = aBaseIter.NamedShape()->Evolution();
877 if (anEvolution == TNaming_GENERATED || anEvolution == TNaming_MODIFY) {
878 if (aBaseIter.NamedShape()->Label().IsEqual(theFinal)) {
879 theResults.Add(aBaseIter.Shape());
881 findFinals(anAccess, aBaseIter.Shape(), theFinal, theAdditionalDoc, theResults);
886 if (!theAdditionalDoc.IsNull()) { // search additionally by the additional access label
887 static TDF_Label anEmpty;
888 findFinals(theAdditionalDoc, theBase, theFinal, anEmpty, theResults);
892 void Selector_Selector::findModificationResult(TopoDS_ListOfShape& theCommon) {
893 for(TDF_LabelList::Iterator aBase(myBases); aBase.More(); aBase.Next()) {
894 TDF_Label anAdditionalDoc; // this document if base is started in extra document
895 if (aBase.Value().Root() != myLab.Root()) {
896 anAdditionalDoc = myLab;
898 TopTools_MapOfShape aFinals;
899 for(TNaming_Iterator aBaseShape(aBase.Value()); aBaseShape.More(); aBaseShape.Next()) {
900 findFinals(aBase.Value(), aBaseShape.NewShape(), myFinal, anAdditionalDoc, aFinals);
902 if (!aFinals.IsEmpty()) {
903 if (theCommon.IsEmpty()) { // just copy all to common
904 for(TopTools_MapOfShape::Iterator aFinal(aFinals); aFinal.More(); aFinal.Next()) {
905 theCommon.Append(aFinal.Key());
907 } else { // keep only shapes presented in both lists
908 for(TopoDS_ListOfShape::Iterator aCommon(theCommon); aCommon.More(); ) {
909 if (aFinals.Contains(aCommon.Value())) {
911 } else { // common is not found, remove it
912 theCommon.Remove(aCommon);
920 bool Selector_Selector::solve(const TopoDS_Shape& theContext)
922 TopoDS_Shape aResult; // null if invalid
924 case SELTYPE_CONTAINER: {
925 TopoDS_Builder aBuilder;
926 switch(myShapeType) {
927 case TopAbs_COMPOUND: {
928 TopoDS_Compound aComp;
929 aBuilder.MakeCompound(aComp);
933 case TopAbs_COMPSOLID: {
934 TopoDS_CompSolid aComp;
935 aBuilder.MakeCompSolid(aComp);
941 aBuilder.MakeShell(aShell);
947 aBuilder.MakeWire(aWire);
952 std::list<Selector_Selector>::iterator aSubSel = mySubSelList.begin();
953 for(; aSubSel != mySubSelList.end(); aSubSel++) {
954 if (!aSubSel->solve(theContext)) {
957 aBuilder.Add(aResult, aSubSel->value());
961 case SELTYPE_INTERSECT: {
962 TopoDS_ListOfShape aSubSelectorShapes;
963 std::list<Selector_Selector>::iterator aSubSel = mySubSelList.begin();
964 for(; aSubSel != mySubSelList.end(); aSubSel++) {
965 if (!aSubSel->solve(theContext)) {
968 aSubSelectorShapes.Append(aSubSel->value());
970 TopoDS_ListOfShape aCommon; // common sub shapes in each sub-selector (a result)
971 commonShapes(aSubSelectorShapes, myShapeType, aCommon);
972 if (aCommon.Extent() != 1) {
973 if (myWeakIndex != -1) {
974 Selector_NExplode aNexp(aCommon);
975 aResult = aNexp.shape(myWeakIndex);
976 } else if (myGeometricalNaming && aCommon.Extent() > 1) {
977 // check results are on the same geometry, create compound
978 TopoDS_ListOfShape::Iterator aCommonIter(aCommon);
979 TopoDS_Shape aFirst = aCommonIter.Value();
980 for(aCommonIter.Next(); aCommonIter.More(); aCommonIter.Next()) {
981 if (!sameGeometry(aFirst, aCommonIter.Value()))
984 if (!aCommonIter.More()) { // all geometry is same, create a result compound
985 TopoDS_Builder aBuilder;
986 TopoDS_Compound aCompound;
987 aBuilder.MakeCompound(aCompound);
988 for(aCommonIter.Initialize(aCommon); aCommonIter.More(); aCommonIter.Next()) {
989 aBuilder.Add(aCompound, aCommonIter.Value());
997 aResult = aCommon.First();
1001 case SELTYPE_PRIMITIVE: {
1002 Handle(TNaming_NamedShape) aNS;
1003 if (myFinal.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
1004 aResult = aNS->Get();
1008 case SELTYPE_MODIFICATION: {
1009 if (myBases.IsEmpty() && myWeakIndex > 0) { // weak name by the final shapes index
1010 TopoDS_ListOfShape aCommon;
1011 Handle(TNaming_NamedShape) aNS;
1012 if (myFinal.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
1013 for(TNaming_Iterator aFinalIter(aNS); aFinalIter.More(); aFinalIter.Next()) {
1014 const TopoDS_Shape& aNewShape = aFinalIter.NewShape();
1015 if (!aNewShape.IsNull())
1016 aCommon.Append(aNewShape);
1019 Selector_NExplode aNexp(aCommon);
1020 aResult = aNexp.shape(myWeakIndex);
1021 } else { // standard case
1022 TopoDS_ListOfShape aFinalsCommon; // final shapes presented in all results from bases
1023 findModificationResult(aFinalsCommon);
1024 if (aFinalsCommon.Extent() == 1) { // result is valid: found only one shape
1025 aResult = aFinalsCommon.First();
1026 } else if (aFinalsCommon.Extent() > 1 && myWeakIndex > 0) {
1027 Selector_NExplode aNExp(aFinalsCommon);
1028 aResult = aNExp.shape(myWeakIndex);
1029 } else if (aFinalsCommon.Extent() > 1 && myGeometricalNaming) {// if same geometry - compound
1030 TopoDS_ListOfShape::Iterator aCommonIter(aFinalsCommon);
1031 TopoDS_Shape aFirst = aCommonIter.Value();
1032 for(aCommonIter.Next(); aCommonIter.More(); aCommonIter.Next()) {
1033 if (!sameGeometry(aFirst, aCommonIter.Value()))
1036 if (!aCommonIter.More()) { // all geometry is same, create a result compound
1037 TopoDS_Builder aBuilder;
1038 TopoDS_Compound aCompound;
1039 aBuilder.MakeCompound(aCompound);
1040 for(aCommonIter.Initialize(aFinalsCommon); aCommonIter.More(); aCommonIter.Next()) {
1041 aBuilder.Add(aCompound, aCommonIter.Value());
1043 aResult = aCompound;
1050 case SELTYPE_FILTER_BY_NEIGHBOR: {
1051 std::list<std::pair<TopoDS_Shape, int> > aNBs; /// neighbor sub-shape -> level of neighborhood
1052 std::list<int>::iterator aLevel = myNBLevel.begin();
1053 std::list<Selector_Selector>::iterator aSubSel = mySubSelList.begin();
1054 for(; aSubSel != mySubSelList.end(); aSubSel++, aLevel++) {
1055 if (!aSubSel->solve(theContext)) {
1058 aNBs.push_back(std::pair<TopoDS_Shape, int>(aSubSel->value(), *aLevel));
1060 aResult = findNeighbor(theContext, aNBs, myGeometricalNaming);
1063 case SELTYPE_WEAK_NAMING: {
1064 TopoDS_Shape aContext;
1065 if (myFinal.IsNull()) {
1066 aContext = theContext;
1068 Handle(TNaming_NamedShape) aNS;
1069 if (myFinal.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
1070 aContext = aNS->Get();
1073 if (!aContext.IsNull()) {
1074 Selector_NExplode aNexp(aContext, myShapeType);
1075 aResult = aNexp.shape(myWeakIndex);
1078 default: { // unknown case
1082 TNaming_Builder aBuilder(myLab);
1083 if (!aResult.IsNull()) {
1084 aBuilder.Select(aResult, aResult);
1087 return false; // builder just erases the named shape in case of error
1090 TopoDS_Shape Selector_Selector::value()
1092 Handle(TNaming_NamedShape) aNS;
1093 if (myLab.FindAttribute(TNaming_NamedShape::GetID(), aNS))
1095 return TopoDS_Shape(); // empty, error shape
1098 std::string Selector_Selector::name(Selector_NameGenerator* theNameGenerator) {
1100 case SELTYPE_CONTAINER:
1101 case SELTYPE_INTERSECT: {
1102 std::string aResult;
1103 // add names of sub-components one by one in "[]" +optionally [weak_name_1]
1104 std::list<Selector_Selector>::iterator aSubSel = mySubSelList.begin();
1105 for(; aSubSel != mySubSelList.end(); aSubSel++) {
1107 aResult += aSubSel->name(theNameGenerator);
1109 TopoDS_Shape aSubVal = aSubSel->value();
1110 if (!aSubVal.IsNull()) {
1111 TopAbs_ShapeEnum aSubType = aSubVal.ShapeType();
1112 if (aSubType != TopAbs_FACE) { // in case the sub shape type must be stored
1114 case TopAbs_COMPOUND: aResult += "c"; break;
1115 case TopAbs_COMPSOLID: aResult += "o"; break;
1116 case TopAbs_SOLID: aResult += "s"; break;
1117 case TopAbs_SHELL: aResult += "h"; break;
1118 case TopAbs_WIRE: aResult += "w"; break;
1119 case TopAbs_EDGE: aResult += "e"; break;
1120 case TopAbs_VERTEX: aResult += "v"; break;
1127 if (myWeakIndex != -1) {
1128 std::ostringstream aWeakStr;
1129 aWeakStr<<"["<<kWEAK_NAME_IDENTIFIER<<myWeakIndex<<"]";
1130 aResult += aWeakStr.str();
1134 case SELTYPE_PRIMITIVE: {
1135 Handle(TDataStd_Name) aName;
1136 if (!myFinal.FindAttribute(TDataStd_Name::GetID(), aName))
1138 return theNameGenerator->contextName(myFinal) + "/" +
1139 std::string(TCollection_AsciiString(aName->Get()).ToCString());
1141 case SELTYPE_MODIFICATION: {
1142 // final&base1&base2 +optionally: [weak_name_1]
1143 std::string aResult;
1144 Handle(TDataStd_Name) aName;
1145 if (!myFinal.FindAttribute(TDataStd_Name::GetID(), aName))
1147 aResult += theNameGenerator->contextName(myFinal) + "/" +
1148 std::string(TCollection_AsciiString(aName->Get()).ToCString());
1149 for(TDF_LabelList::iterator aBase = myBases.begin(); aBase != myBases.end(); aBase++) {
1150 if (!aBase->FindAttribute(TDataStd_Name::GetID(), aName))
1153 aResult += theNameGenerator->contextName(*aBase) + "/" +
1154 std::string(TCollection_AsciiString(aName->Get()).ToCString());
1156 if (myWeakIndex != -1) {
1157 std::ostringstream aWeakStr;
1158 aWeakStr<<"&"<<kWEAK_NAME_IDENTIFIER<<myWeakIndex;
1159 aResult += aWeakStr.str();
1163 case SELTYPE_FILTER_BY_NEIGHBOR: {
1164 // (nb1)level_if_more_than_1(nb2)level_if_more_than_1(nb3)level_if_more_than_1
1165 std::string aResult;
1166 std::list<int>::iterator aLevel = myNBLevel.begin();
1167 std::list<Selector_Selector>::iterator aSubSel = mySubSelList.begin();
1168 for(; aSubSel != mySubSelList.end(); aSubSel++, aLevel++) {
1169 aResult += "(" + aSubSel->name(theNameGenerator) + ")";
1171 std::ostringstream aLevelStr;
1173 aResult += aLevelStr.str();
1178 case SELTYPE_WEAK_NAMING: {
1179 // _weak_naming_1_Context
1180 std::ostringstream aWeakStr;
1181 aWeakStr<<kPUREWEAK_NAME_IDENTIFIER<<myWeakIndex;
1182 std::string aResult = aWeakStr.str();
1183 if (!myFinal.IsNull())
1184 aResult += "_" + theNameGenerator->contextName(myFinal);
1187 default: { // unknown case
1193 TDF_Label Selector_Selector::restoreByName(
1194 std::string theName, const TopAbs_ShapeEnum theShapeType,
1195 Selector_NameGenerator* theNameGenerator, const bool theGeometricalNaming)
1197 myGeometricalNaming = theGeometricalNaming;
1198 if (theName[0] == '[') { // intersection or container
1199 switch(theShapeType) {
1200 case TopAbs_COMPOUND:
1201 case TopAbs_COMPSOLID:
1204 myType = SELTYPE_CONTAINER;
1209 myType = SELTYPE_INTERSECT;
1212 return TDF_Label(); // unknown case
1214 myShapeType = theShapeType;
1216 for(size_t aStart = 0; aStart != std::string::npos;
1217 aStart = theName.find('[', aStart + 1)) {
1218 size_t anEndPos = theName.find(']', aStart + 1);
1219 if (anEndPos != std::string::npos) {
1220 std::string aSubStr = theName.substr(aStart + 1, anEndPos - aStart - 1);
1221 if (aSubStr.find(kWEAK_NAME_IDENTIFIER) == 0) { // weak name identifier
1222 std::string aWeakIndex = aSubStr.substr(kWEAK_NAME_IDENTIFIER.size());
1223 myWeakIndex = atoi(aWeakIndex.c_str());
1226 TopAbs_ShapeEnum aSubShapeType = TopAbs_FACE;
1227 if (anEndPos != std::string::npos && anEndPos + 1 < theName.size()) {
1228 char aShapeChar = theName[anEndPos + 1];
1229 if (theName[anEndPos + 1] != '[') {
1230 switch(aShapeChar) {
1231 case 'c': aSubShapeType = TopAbs_COMPOUND; break;
1232 case 'o': aSubShapeType = TopAbs_COMPSOLID; break;
1233 case 's': aSubShapeType = TopAbs_SOLID; break;
1234 case 'h': aSubShapeType = TopAbs_SHELL; break;
1235 case 'w': aSubShapeType = TopAbs_WIRE; break;
1236 case 'e': aSubShapeType = TopAbs_EDGE; break;
1237 case 'v': aSubShapeType = TopAbs_VERTEX; break;
1242 mySubSelList.push_back(Selector_Selector(myLab.FindChild(int(mySubSelList.size()) + 1)));
1243 mySubSelList.back().setBaseDocument(myBaseDocumentLab);
1244 TDF_Label aSubContext = mySubSelList.back().restoreByName(
1245 aSubStr, aSubShapeType, theNameGenerator, theGeometricalNaming);
1246 if (aSubContext.IsNull())
1247 return aSubContext; // invalid sub-selection parsing
1248 if (!aContext.IsNull() && !aContext.IsEqual(aSubContext)) {
1249 if (!theNameGenerator->isLater(aContext, aSubContext))
1250 aContext = aSubContext;
1252 aContext = aSubContext;
1255 return TDF_Label(); // invalid parentheses
1258 } else if (theName[0] == '(') { // filter by neighbors
1259 myType = SELTYPE_FILTER_BY_NEIGHBOR;
1261 for(size_t aStart = 0; aStart != std::string::npos;
1262 aStart = theName.find('(', aStart + 1)) {
1263 size_t anEndPos = theName.find(')', aStart + 1);
1264 if (anEndPos != std::string::npos) {
1265 std::string aSubStr = theName.substr(aStart + 1, anEndPos - aStart - 1);
1266 mySubSelList.push_back(Selector_Selector(myLab.FindChild(int(mySubSelList.size()) + 1)));
1267 mySubSelList.back().setBaseDocument(myBaseDocumentLab);
1268 TDF_Label aSubContext = mySubSelList.back().restoreByName(
1269 aSubStr, theShapeType, theNameGenerator, theGeometricalNaming);
1270 if (aSubContext.IsNull())
1271 return aSubContext; // invalid sub-selection parsing
1272 if (!aContext.IsNull() && !aContext.IsEqual(aSubContext)) {
1273 if (!theNameGenerator->isLater(aContext, aSubContext))
1274 aContext = aSubContext;
1276 aContext = aSubContext;
1278 if (!aContext.IsNull()) // for filters by neighbor the latest context shape is vital
1279 aContext = theNameGenerator->newestContext(aContext);
1281 // searching for the level index
1283 for(anEndPos++; anEndPos != std::string::npos &&
1284 theName[anEndPos] != '(' && theName[anEndPos] != 0;
1286 aLevel += theName[anEndPos];
1289 myNBLevel.push_back(1); // by default it is 1
1291 int aNum = atoi(aLevel.c_str());
1293 myNBLevel.push_back(aNum);
1295 return TDF_Label(); // invalid number
1298 return TDF_Label(); // invalid parentheses
1301 } if (theName.find(kPUREWEAK_NAME_IDENTIFIER) == 0) { // weak naming identifier
1302 myType = SELTYPE_WEAK_NAMING;
1303 std::string aWeakIndex = theName.substr(kPUREWEAK_NAME_IDENTIFIER.size());
1304 std::size_t aContextPosition = aWeakIndex.find("_");
1305 myWeakIndex = atoi(aWeakIndex.c_str());
1306 myShapeType = theShapeType;
1308 if (aContextPosition != std::string::npos) { // context is also defined
1309 std::string aContextName = aWeakIndex.substr(aContextPosition + 1);
1310 theNameGenerator->restoreContext(aContextName, aContext, myFinal);
1313 } else if (theName.find('&') == std::string::npos) { // without '&' it can be only primitive
1314 myType = SELTYPE_PRIMITIVE;
1316 if (theNameGenerator->restoreContext(theName, aContext, myFinal)) {
1317 if (!myFinal.IsNull())
1320 } else { // modification
1321 myType = SELTYPE_MODIFICATION;
1323 for(size_t anEnd, aStart = 0; aStart != std::string::npos; aStart = anEnd) {
1326 anEnd = theName.find('&', aStart);
1327 std::string aSubStr =
1328 theName.substr(aStart, anEnd == std::string::npos ? anEnd : anEnd - aStart);
1329 if (aSubStr.find(kWEAK_NAME_IDENTIFIER) == 0) { // weak name identifier
1330 std::string aWeakIndex = aSubStr.substr(kWEAK_NAME_IDENTIFIER.size());
1331 myWeakIndex = atoi(aWeakIndex.c_str());
1334 TDF_Label aSubContext, aValue;
1335 if (!theNameGenerator->restoreContext(aSubStr, aSubContext, aValue))
1336 return TDF_Label(); // can not restore
1337 if(aSubContext.IsNull() || aValue.IsNull())
1338 return TDF_Label(); // can not restore
1339 if (myFinal.IsNull()) {
1341 aContext = aSubContext;
1343 myBases.Append(aValue);
1350 bool Selector_Selector::selectBySubSelector(const TopoDS_Shape theContext,
1351 const TopoDS_Shape theValue, const bool theGeometricalNaming,
1352 const bool theUseNeighbors, const bool theUseIntersections)
1354 mySubSelList.push_back(Selector_Selector(myLab.FindChild(int(mySubSelList.size()) + 1)));
1355 if (!myBaseDocumentLab.IsNull())
1356 mySubSelList.back().setBaseDocument(myBaseDocumentLab);
1357 if (!mySubSelList.back().select(theContext, theValue,
1358 theGeometricalNaming, theUseNeighbors, theUseIntersections)) {
1359 mySubSelList.clear(); // if one of the selector is failed, all become invalid