0024023: Revamp the OCCT Handle -- downcast (automatic)
[occt.git] / src / TNaming / TNaming_Selector.cxx
1 // Created on: 1999-09-30
2 // Created by: Denis PASCAL
3 // Copyright (c) 1999-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <TNaming_Selector.ixx>
18 #include <TNaming.hxx>
19 #include <TNaming_Naming.hxx>
20 #include <TNaming_Builder.hxx> 
21 #include <TNaming_Identifier.hxx>
22 #include <TNaming_NameType.hxx>
23 #include <TDF_ChildIterator.hxx> 
24 #include <TDF_Tool.hxx>
25 #include <TDF_IDFilter.hxx>
26 #include <TNaming_NamingTool.hxx>
27 #include <TNaming_NewShapeIterator.hxx>
28
29 #include <TopTools_IndexedMapOfShape.hxx>
30 #include <TopTools_ListIteratorOfListOfShape.hxx>
31 #include <TopoDS_Iterator.hxx>
32
33 //#define MDTV_DEB_SEL
34 #ifdef OCCT_DEBUG_SEL
35 //#define MDTV_DEB_BNP
36 #include <TopExp_Explorer.hxx>
37 #include <TCollection_AsciiString.hxx>
38 #include <TNaming_Tool.hxx>
39 #include <BRep_Tool.hxx>
40 #include <TopoDS.hxx>
41 #include <TNaming_UsedShapes.hxx>
42 void PrintEntry(const TDF_Label&       label, const Standard_Boolean allLevels)
43 {
44   TCollection_AsciiString entry;
45   TDF_Tool::Entry(label, entry);
46   cout << "LabelEntry = "<< entry << endl;
47   if(allLevels) {
48     TDF_ChildIterator it (label, allLevels);
49     for (; it.More(); it.Next()) {
50       TDF_Tool::Entry(it.Value(), entry);
51         cout << "ChildLabelEntry = "<< entry << endl;
52       }
53   }
54 }
55 #include <BRepTools.hxx>
56 static void Write(const TopoDS_Shape& shape,
57                       const Standard_CString filename) 
58 {
59   char buf[256];
60   if(strlen(filename) > 255) return;
61 #if defined WNT
62   strcpy_s (buf, filename);
63 #else
64   strcpy (buf, filename);
65 #endif
66   char* p = buf;
67   while (*p) {
68     if(*p == ':')
69       *p = '-';
70     p++;
71   }
72   ofstream save (buf);
73   if(!save) 
74     cout << "File " << buf << " was not created: rdstate = " << save.rdstate() << endl;
75   save << "DBRep_DrawableShape" << endl << endl;
76   if(!shape.IsNull()) BRepTools::Write(shape, save);
77   save.close();
78 }
79 #endif
80
81 #define ORIENTATION_DSOPT
82 #ifdef ORIENTATION_DSOPT
83 #include <TopTools_MapOfOrientedShape.hxx>
84 #include <TopTools_MapIteratorOfMapOfOrientedShape.hxx>
85 #include <TDF_ChildIDIterator.hxx>
86 #include <TNaming_Tool.hxx>
87 #include <TNaming_Iterator.hxx>
88 #include <TNaming_OldShapeIterator.hxx>
89 #include <TNaming_NamedShape.hxx>
90 //==========================================================================================
91 inline static void MapOfOrientedShapes(const TopoDS_Shape& S, TopTools_MapOfOrientedShape& M) 
92 {
93   M.Add(S);
94   TopoDS_Iterator It(S,Standard_True,Standard_True);
95   while (It.More()) {
96     MapOfOrientedShapes(It.Value(),M);
97     It.Next();
98   }
99 }
100 //=======================================================================
101 static void BuildAtomicMap(const TopoDS_Shape& S, TopTools_MapOfOrientedShape& M)
102 {
103   if(S.ShapeType() > TopAbs_COMPSOLID) return;
104   TopoDS_Iterator it(S);
105   for(;it.More();it.Next()) {
106     if(it.Value().ShapeType() > TopAbs_COMPSOLID) 
107       M.Add(it.Value());
108     else 
109       BuildAtomicMap(it.Value(), M);   
110   }
111 }
112
113 //==========================================================================================
114 static const Handle(TNaming_NamedShape) FindPrevNDS(const Handle(TNaming_NamedShape)& CNS)
115 {
116   Handle(TNaming_NamedShape) aNS;
117   TNaming_Iterator it(CNS);
118   if(it.More()) {
119     if(!it.OldShape().IsNull()) {
120       aNS = TNaming_Tool::NamedShape(it.OldShape(), CNS->Label());
121       return aNS;
122     }
123   }
124   return aNS;
125 }
126
127 //==========================================================================================
128 // Purpose: checks correspondens between orientation of sub-shapes of Context and orientation
129 //          of sub-shapes registered in DF and put under result label
130 //==========================================================================================
131 static Standard_Boolean IsSpecificCase(const  TDF_Label& F, const TopoDS_Shape& Context)
132 {
133   Standard_Boolean isFound(Standard_False);
134   TopTools_MapOfOrientedShape shapesOfContext;
135   MapOfOrientedShapes(Context,shapesOfContext);
136   Handle(TNaming_NamedShape) CNS = TNaming_Tool::NamedShape(Context, F);
137 #ifdef OCCT_DEBUG_BNP
138   PrintEntry (CNS->Label(),0);
139 #endif
140   if(!CNS.IsNull()) {
141     TNaming_ListOfNamedShape aLNS;
142     TDF_ChildIDIterator cit(CNS->Label(), TNaming_NamedShape::GetID(), Standard_False);
143     if(!cit.More()) {
144       // Naming data structure is empty - no sub-shapes under resulting shape
145       const Handle(TNaming_NamedShape) aNS = FindPrevNDS(CNS); //look to old shape data structure if exist
146       if(!aNS.IsNull()) {
147 #ifdef OCCT_DEBUG_BNP
148         PrintEntry (aNS->Label(),0);
149 #endif
150         cit.Initialize(aNS->Label(), TNaming_NamedShape::GetID(), Standard_False);
151       } else
152         return Standard_True;
153     }
154
155     for(;cit.More();cit.Next()) {
156       Handle(TNaming_NamedShape) NS (Handle(TNaming_NamedShape)::DownCast(cit.Value())); 
157       if(!NS.IsNull()) {  
158         TopoDS_Shape aS = TNaming_Tool::CurrentShape(NS);
159         if(aS.IsNull()) continue;
160 #ifdef OCCT_DEBUG_BNP
161         PrintEntry(NS->Label(), 0);
162         cout <<"ShapeType =" << aS.ShapeType() <<endl;
163         Write (aS, "BNProblem.brep");
164 #endif  
165         if(aS.ShapeType() != TopAbs_COMPOUND) {//single shape at the child label
166           if(!shapesOfContext.Contains(aS)) {
167             isFound = Standard_True;
168             break;
169           }
170         }
171         else {
172           TopTools_MapOfOrientedShape M;
173           BuildAtomicMap(aS, M); 
174           TopTools_MapIteratorOfMapOfOrientedShape it(M);
175           for(;it.More();it.Next()) {         
176             if(!shapesOfContext.Contains(it.Key())) {
177 #ifdef OCCT_DEBUG_BNP
178               cout <<"BNProblem: ShapeType in AtomicMap = " << it.Key().ShapeType() << " TShape = " <<it.Key().TShape() <<" OR = " <<it.Key().Orientation()  <<endl;
179               Write (it.Key(), "BNProblem_AtomicMap_Item.brep");              
180               TopTools_MapIteratorOfMapOfOrientedShape itC(shapesOfContext);
181               for(;itC.More(); itC.Next())
182                 cout <<" ShapeType = " << itC.Key().ShapeType() << " TShape = " << itC.Key().TShape() << " OR = " << itC.Key().Orientation() << endl;
183               
184 #endif  
185               isFound = Standard_True;
186               break;
187             }
188             if(isFound) break;
189           }
190         }
191       }
192     }
193   }
194   return isFound;
195 }
196
197 //==========================================================================================
198 static Standard_Boolean IsSpecificCase2(const  TDF_Label& F, const TopoDS_Shape& Selection)
199 {
200   Standard_Boolean isTheCase(Standard_False);
201   if(Selection.ShapeType() == TopAbs_EDGE) {
202     Handle(TNaming_NamedShape) aNS = TNaming_Tool::NamedShape(Selection, F);
203     if(!aNS.IsNull()) { //presented in DF
204 #ifdef OCCT_DEBUG_BNP
205       PrintEntry (aNS->Label(),0);
206 #endif
207       const TopoDS_Shape& aS = TNaming_Tool::CurrentShape(aNS);
208       if(!aS.IsNull() && aS.ShapeType() == Selection.ShapeType()) {
209         if(Selection.Orientation() != aS.Orientation()) {
210           isTheCase = Standard_True;
211         }
212       }
213     }
214   }
215   return isTheCase;
216 }
217 #endif
218 //=======================================================================
219 //function : FindGenerated
220 //purpose  : Finds all generated from the <S>
221 //=======================================================================
222
223 static void FindGenerated(const Handle(TNaming_NamedShape)& NS, const TopoDS_Shape& S, 
224                                 TopTools_ListOfShape& theList)
225
226 {
227   const TDF_Label& LabNS = NS->Label();
228   for (TNaming_NewShapeIterator it (S, LabNS); it.More(); it.Next()) {
229     if (it.Label() == LabNS) {
230       theList.Append(it.Shape());
231     }
232   }
233 }
234 //=======================================================================
235 //function : IsIdentified
236 //purpose  : 
237 //=======================================================================
238 Standard_Boolean TNaming_Selector::IsIdentified (const TDF_Label& L,
239                                                  const TopoDS_Shape& Selection, 
240                                                  Handle(TNaming_NamedShape)& NS,
241                                                  const Standard_Boolean Geometry)
242 {  
243   TopoDS_Shape Context;
244   Standard_Boolean OnlyOne =!Geometry;
245   TNaming_Identifier Ident(L,Selection,Context,OnlyOne);   
246   if (Ident.IsFeature()) {  
247     if   (!OnlyOne)  return Standard_False;
248     else {
249       NS =   Ident.FeatureArg();
250
251       // mpv : external condition
252       TDF_LabelMap Forbiden,Valid;
253       TopTools_IndexedMapOfShape MS;
254       TNaming_NamingTool::CurrentShape(Valid,Forbiden,NS,MS);
255       return (MS.Contains(Selection) && MS.Extent() == 1);
256     }
257   }
258   else if(Ident.Type() == TNaming_GENERATION) {
259     NS = Ident.NamedShapeOfGeneration();
260     if(!NS.IsNull()) {
261       TDF_LabelMap Forbiden,Valid;
262       TopTools_IndexedMapOfShape MS;
263       TNaming_NamingTool::CurrentShape(Valid,Forbiden,NS,MS);
264       if(MS.Contains(Selection) && MS.Extent() == 1) {
265         const TopoDS_Shape& aS = Ident.ShapeArg();
266         TopTools_ListOfShape aList;
267         FindGenerated(NS, aS, aList);
268         Ident.NextArg();
269         while(Ident.MoreArgs()) {
270           const TopoDS_Shape& aS = Ident.ShapeArg();
271           FindGenerated(NS, aS, aList);
272           Ident.NextArg();
273         }
274         const TopoDS_Shape& aC = MS (1);
275         Standard_Boolean isEq(Standard_False);
276         TopTools_ListIteratorOfListOfShape itl(aList);
277         for(;itl.More();itl.Next()) {
278           if(itl.Value() == aC) 
279             isEq = Standard_True;
280           else {
281             isEq = Standard_False;
282             break;
283           }
284         }
285         return isEq;
286       }
287     } else 
288       return Standard_False;
289   }
290   return Standard_False;
291 }
292
293 //=======================================================================
294 //function : TNaming_Selector
295 //purpose  : 
296 //=======================================================================
297
298 TNaming_Selector::TNaming_Selector (const TDF_Label& L) 
299 {
300   myLabel = L;
301 }
302
303 //=======================================================================
304 //function : Select
305 //purpose  : 
306 //=======================================================================
307 Standard_Boolean TNaming_Selector::Select (const TopoDS_Shape& Selection, 
308                                            const TopoDS_Shape& Context,
309                                            const Standard_Boolean Geometry,
310                                            const Standard_Boolean KeepOrientation) const
311 {
312   myLabel.ForgetAllAttributes();  
313   Handle(TNaming_NamedShape)NS;
314   Standard_Boolean aKeepOrientation((Selection.ShapeType() == TopAbs_VERTEX) ? Standard_False : KeepOrientation);
315   if(Selection.ShapeType() == TopAbs_COMPOUND) {
316     Standard_Boolean isVertex(Standard_True);
317     TopoDS_Iterator it(Selection);
318     for(;it.More();it.Next())
319       if(it.Value().ShapeType() != TopAbs_VERTEX) {
320         isVertex = Standard_False;
321         break;
322       }
323     if(isVertex) aKeepOrientation = Standard_False;
324   }
325   /* 
326  // for debug opposite orientation
327  TopoDS_Shape selection;                                                 
328  Standard_Boolean found(Standard_False);
329  TopExp_Explorer exp(Context,TopAbs_EDGE);
330  for(;exp.More();exp.Next()) {
331    TopoDS_Shape E = exp.Current(); 
332    if(E.IsSame(Selection) && E.Orientation() != Selection.Orientation()) {
333      selection = E;
334    found = Standard_True;
335    cout <<" FOUND: Entity orientation = " << selection.Orientation() <<endl;
336    }
337  }
338  if (!found)
339    selection = Selection;
340   */
341
342 #ifdef OCCT_DEBUG_SEL
343   cout << "SELECTION ORIENTATION = " << Selection.Orientation() <<", TShape = " << Selection.TShape() <<endl;
344   //cout << "SELECTION ORIENTATION = " << selection.Orientation() <<", TShape = " << selection.TShape() <<endl;
345   PrintEntry(myLabel, 0);
346   TNaming::Print(myLabel, cout);
347 #endif
348
349   if(aKeepOrientation) {
350 #ifdef ORIENTATION_DSOPT
351     const Standard_Boolean aBNproblem = IsSpecificCase(myLabel, Context) || IsSpecificCase2(myLabel, Selection);
352
353     NS = TNaming_Naming::Name (myLabel,Selection,Context,Geometry,aKeepOrientation,aBNproblem);
354 #else
355       NS = TNaming_Naming::Name (myLabel,Selection,Context,Geometry,aKeepOrientation);
356 #endif    
357   }
358   else
359     if (!IsIdentified (myLabel,Selection,NS,Geometry)) { 
360       NS = TNaming_Naming::Name (myLabel,Selection,Context,Geometry,aKeepOrientation);
361     }
362   if (NS.IsNull()) return Standard_False; 
363   //
364   // namedshape with SELECTED Evolution
365   //
366   TNaming_Builder B (myLabel);
367   // mpv: if oldShape for selection is some shape from used map of shapes,
368   //      then naming structure becomes more complex, can be cycles
369   const TopoDS_Shape& aSelection = TNaming_Tool::CurrentShape(NS); //szy
370 #ifdef OCCT_DEBUG_CHECK_TYPE
371   if(!Selection.IsSame(aSelection) && Selection.ShapeType() != TopAbs_COMPOUND) {
372     TCollection_AsciiString entry;
373     TDF_Tool::Entry(NS->Label(), entry);
374     cout << "Selection is Not Same (NSLabel = " <<entry<<"): " << "TShape1 = " << 
375       Selection.TShape()->This() << " TShape2 = " <<aSelection.TShape()->This() <<endl;
376   }
377 #endif
378   if(aSelection.ShapeType() == TopAbs_COMPOUND && aSelection.ShapeType() != Selection.ShapeType())
379     B.Select(aSelection,aSelection); // type migration
380   else
381     B.Select(Selection,Selection);
382   //
383   // naming with IDENTITY NameType
384   //
385   Handle(TNaming_Naming) N = new TNaming_Naming (); 
386   N->ChangeName().Type(TNaming_IDENTITY);  
387   N->ChangeName().Append(NS);
388   N->ChangeName().Orientation(Selection.Orientation());
389 // inserted by vro 06.09.00:
390   N->ChangeName().ShapeType(Selection.ShapeType());
391
392   myLabel.AddAttribute(N);  
393   return Standard_True; 
394 }
395
396 //=======================================================================
397 //function : Select
398 //purpose  : 
399 //=======================================================================
400 Standard_Boolean TNaming_Selector::Select (const TopoDS_Shape& Selection,
401                                            const Standard_Boolean Geometry,
402                                            const Standard_Boolean KeepOrientation) const
403 {  
404   // we give a Null shape. How to guess what is the good context ?
405   TopoDS_Shape Context;
406 //  return Select (Selection,Context,Geometry);
407 // temporary!!!
408   return Select (Selection,Selection,Geometry, KeepOrientation);
409
410 }
411
412 //=======================================================================
413 //function : Solve
414 //purpose  : 
415 //=======================================================================
416 Standard_Boolean TNaming_Selector::Solve (TDF_LabelMap& Valid) const
417 {
418   Handle(TNaming_Naming) name;
419 #ifdef OCCT_DEBUG_SEL
420         cout <<"TNaming_Selector::Solve==> "; 
421         PrintEntry(myLabel,0);
422 #endif
423   if (myLabel.FindAttribute(TNaming_Naming::GetID(),name)) {
424     return name->Solve(Valid);
425   }
426   return Standard_False;
427 }
428
429 //=======================================================================
430 //function : Arguments
431 //purpose  : 
432 //=======================================================================
433 void TNaming_Selector::Arguments (TDF_AttributeMap& args) const
434 {  
435   TDF_Tool::OutReferences(myLabel,args);
436 }
437
438 //=======================================================================
439 //function : TNaming_Selector
440 //purpose  : 
441 //=======================================================================
442
443 Handle(TNaming_NamedShape) TNaming_Selector::NamedShape() const
444 {
445   Handle(TNaming_NamedShape) NS;
446   myLabel.FindAttribute(TNaming_NamedShape::GetID(),NS);
447   return NS;
448 }