f69f7fd022a087024b5ac4190a0493dd3a6c4b11
[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_MapOfShape.hxx>
30 #include <TopTools_MapIteratorOfMapOfShape.hxx>
31 #include <TopTools_ListIteratorOfListOfShape.hxx>
32 #include <TopoDS_Iterator.hxx>
33
34 //#define MDTV_DEB_SEL
35 #ifdef OCCT_DEBUG_SEL
36 //#define MDTV_DEB_BNP
37 #include <TopExp_Explorer.hxx>
38 #include <TCollection_AsciiString.hxx>
39 #include <TNaming_Tool.hxx>
40 #include <BRep_Tool.hxx>
41 #include <TopoDS.hxx>
42 #include <TNaming_UsedShapes.hxx>
43 void PrintEntry(const TDF_Label&       label, const Standard_Boolean allLevels)
44 {
45   TCollection_AsciiString entry;
46   TDF_Tool::Entry(label, entry);
47   cout << "LabelEntry = "<< entry << endl;
48   if(allLevels) {
49     TDF_ChildIterator it (label, allLevels);
50     for (; it.More(); it.Next()) {
51       TDF_Tool::Entry(it.Value(), entry);
52         cout << "ChildLabelEntry = "<< entry << endl;
53       }
54   }
55 }
56 #include <BRepTools.hxx>
57 static void Write(const TopoDS_Shape& shape,
58                       const Standard_CString filename) 
59 {
60   char buf[256];
61   if(strlen(filename) > 255) return;
62 #if defined WNT
63   strcpy_s (buf, filename);
64 #else
65   strcpy (buf, filename);
66 #endif
67   char* p = buf;
68   while (*p) {
69     if(*p == ':')
70       *p = '-';
71     p++;
72   }
73   ofstream save (buf);
74   if(!save) 
75     cout << "File " << buf << " was not created: rdstate = " << save.rdstate() << endl;
76   save << "DBRep_DrawableShape" << endl << endl;
77   if(!shape.IsNull()) BRepTools::Write(shape, save);
78   save.close();
79 }
80 #endif
81
82 #define ORIENTATION_DSOPT
83 #ifdef ORIENTATION_DSOPT
84 #include <TopTools_MapOfOrientedShape.hxx>
85 #include <TopTools_MapIteratorOfMapOfOrientedShape.hxx>
86 #include <TDF_ChildIDIterator.hxx>
87 #include <TNaming_Tool.hxx>
88 #include <TNaming_Iterator.hxx>
89 #include <TNaming_OldShapeIterator.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       const 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_MapOfShape 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_MapOfShape 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         TopTools_MapIteratorOfMapOfShape itm(MS);
275         const TopoDS_Shape& aC = itm.Key();
276         Standard_Boolean isEq(Standard_False);
277         TopTools_ListIteratorOfListOfShape itl(aList);
278         for(;itl.More();itl.Next()) {
279           if(itl.Value() == aC) 
280             isEq = Standard_True;
281           else {
282             isEq = Standard_False;
283             break;
284           }
285         }
286         return isEq;
287       }
288     } else 
289       return Standard_False;
290   }
291   return Standard_False;
292 }
293
294 //=======================================================================
295 //function : TNaming_Selector
296 //purpose  : 
297 //=======================================================================
298
299 TNaming_Selector::TNaming_Selector (const TDF_Label& L) 
300 {
301   myLabel = L;
302 }
303
304 //=======================================================================
305 //function : Select
306 //purpose  : 
307 //=======================================================================
308 Standard_Boolean TNaming_Selector::Select (const TopoDS_Shape& Selection, 
309                                            const TopoDS_Shape& Context,
310                                            const Standard_Boolean Geometry,
311                                            const Standard_Boolean KeepOrientation) const
312 {
313   myLabel.ForgetAllAttributes();  
314   Handle(TNaming_NamedShape)NS;
315   Standard_Boolean aKeepOrientation((Selection.ShapeType() == TopAbs_VERTEX) ? Standard_False : KeepOrientation);
316   if(Selection.ShapeType() == TopAbs_COMPOUND) {
317     Standard_Boolean isVertex(Standard_True);
318     TopoDS_Iterator it(Selection);
319     for(;it.More();it.Next())
320       if(it.Value().ShapeType() != TopAbs_VERTEX) {
321         isVertex = Standard_False;
322         break;
323       }
324     if(isVertex) aKeepOrientation = Standard_False;
325   }
326   /* 
327  // for debug opposite orientation
328  TopoDS_Shape selection;                                                 
329  Standard_Boolean found(Standard_False);
330  TopExp_Explorer exp(Context,TopAbs_EDGE);
331  for(;exp.More();exp.Next()) {
332    TopoDS_Shape E = exp.Current(); 
333    if(E.IsSame(Selection) && E.Orientation() != Selection.Orientation()) {
334      selection = E;
335    found = Standard_True;
336    cout <<" FOUND: Entity orientation = " << selection.Orientation() <<endl;
337    }
338  }
339  if (!found)
340    selection = Selection;
341   */
342
343 #ifdef OCCT_DEBUG_SEL
344   cout << "SELECTION ORIENTATION = " << Selection.Orientation() <<", TShape = " << Selection.TShape() <<endl;
345   //cout << "SELECTION ORIENTATION = " << selection.Orientation() <<", TShape = " << selection.TShape() <<endl;
346   PrintEntry(myLabel, 0);
347   TNaming::Print(myLabel, cout);
348 #endif
349
350   if(aKeepOrientation) {
351 #ifdef ORIENTATION_DSOPT
352     const Standard_Boolean aBNproblem = IsSpecificCase(myLabel, Context) || IsSpecificCase2(myLabel, Selection);
353
354     NS = TNaming_Naming::Name (myLabel,Selection,Context,Geometry,aKeepOrientation,aBNproblem);
355 #else
356       NS = TNaming_Naming::Name (myLabel,Selection,Context,Geometry,aKeepOrientation);
357 #endif    
358   }
359   else
360     if (!IsIdentified (myLabel,Selection,NS,Geometry)) { 
361       NS = TNaming_Naming::Name (myLabel,Selection,Context,Geometry,aKeepOrientation);
362     }
363   if (NS.IsNull()) return Standard_False; 
364   //
365   // namedshape with SELECTED Evolution
366   //
367   TNaming_Builder B (myLabel);
368   // mpv: if oldShape for selection is some shape from used map of shapes,
369   //      then naming structure becomes more complex, can be cycles
370   const TopoDS_Shape& aSelection = TNaming_Tool::CurrentShape(NS); //szy
371 #ifdef OCCT_DEBUG_CHECK_TYPE
372   if(!Selection.IsSame(aSelection) && Selection.ShapeType() != TopAbs_COMPOUND) {
373     TCollection_AsciiString entry;
374     TDF_Tool::Entry(NS->Label(), entry);
375     cout << "Selection is Not Same (NSLabel = " <<entry<<"): " << "TShape1 = " << 
376       Selection.TShape()->This() << " TShape2 = " <<aSelection.TShape()->This() <<endl;
377   }
378 #endif
379   if(aSelection.ShapeType() == TopAbs_COMPOUND && aSelection.ShapeType() != Selection.ShapeType())
380     B.Select(aSelection,aSelection); // type migration
381   else
382     B.Select(Selection,Selection);
383   //
384   // naming with IDENTITY NameType
385   //
386   Handle(TNaming_Naming) N = new TNaming_Naming (); 
387   N->ChangeName().Type(TNaming_IDENTITY);  
388   N->ChangeName().Append(NS);
389   N->ChangeName().Orientation(Selection.Orientation());
390 // inserted by vro 06.09.00:
391   N->ChangeName().ShapeType(Selection.ShapeType());
392
393   myLabel.AddAttribute(N);  
394   return Standard_True; 
395 }
396
397 //=======================================================================
398 //function : Select
399 //purpose  : 
400 //=======================================================================
401 Standard_Boolean TNaming_Selector::Select (const TopoDS_Shape& Selection,
402                                            const Standard_Boolean Geometry,
403                                            const Standard_Boolean KeepOrientation) const
404 {  
405   // we give a Null shape. How to guess what is the good context ?
406   TopoDS_Shape Context;
407 //  return Select (Selection,Context,Geometry);
408 // temporary!!!
409   return Select (Selection,Selection,Geometry, KeepOrientation);
410
411 }
412
413 //=======================================================================
414 //function : Solve
415 //purpose  : 
416 //=======================================================================
417 Standard_Boolean TNaming_Selector::Solve (TDF_LabelMap& Valid) const
418 {
419   Handle(TNaming_Naming) name;
420 #ifdef OCCT_DEBUG_SEL
421         cout <<"TNaming_Selector::Solve==> "; 
422         PrintEntry(myLabel,0);
423 #endif
424   if (myLabel.FindAttribute(TNaming_Naming::GetID(),name)) {
425     return name->Solve(Valid);
426   }
427   return Standard_False;
428 }
429
430 //=======================================================================
431 //function : Arguments
432 //purpose  : 
433 //=======================================================================
434 void TNaming_Selector::Arguments (TDF_AttributeMap& args) const
435 {  
436   TDF_Tool::OutReferences(myLabel,args);
437 }
438
439 //=======================================================================
440 //function : TNaming_Selector
441 //purpose  : 
442 //=======================================================================
443
444 Handle(TNaming_NamedShape) TNaming_Selector::NamedShape() const
445 {
446   Handle(TNaming_NamedShape) NS;
447   myLabel.FindAttribute(TNaming_NamedShape::GetID(),NS);
448   return NS;
449 }