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