0025938: BRepBuilderAPI_Transform is not thread safe
[occt.git] / src / TNaming / TNaming_Naming.cxx
1 // Created on: 1997-09-03
2 // Created by: Yves FRICAUD
3 // Copyright (c) 1997-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_Naming.ixx>
18
19 #include <TNaming_Builder.hxx>
20 #include <TNaming_Tool.hxx>
21 #include <TNaming_ListIteratorOfListOfNamedShape.hxx>
22 #include <TNaming_Iterator.hxx>
23 #include <TNaming_Scope.hxx>
24 #include <TNaming_NamingTool.hxx>
25 #include <TNaming_Name.hxx>
26 #include <TNaming_Identifier.hxx>
27 #include <TNaming_Localizer.hxx>
28 #include <TNaming_NewShapeIterator.hxx>
29 #include <TNaming_OldShapeIterator.hxx>
30 #include <TNaming_Selector.hxx>
31 #include <TNaming.hxx>
32 #include <TDF_ChildIterator.hxx>
33 #include <TDF_LabelList.hxx>
34 #include <TDF_Data.hxx>
35 #include <TDF_LabelMap.hxx>
36 #include <TDF_TagSource.hxx>
37 #include <TopoDS_Iterator.hxx>
38 #include <TopTools_MapOfShape.hxx>
39 #include <TopExp.hxx>
40 #include <TopExp_Explorer.hxx>
41 #include <TopTools_MapIteratorOfMapOfShape.hxx>
42 #include <Standard_DomainError.hxx>
43 #include <TopTools_ListOfShape.hxx>
44 #include <TopTools_ListIteratorOfListOfShape.hxx>
45 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
46 #include <TColStd_MapOfInteger.hxx>
47 #include <TColStd_MapIteratorOfMapOfInteger.hxx>
48 #include <TopTools_MapIteratorOfMapOfOrientedShape.hxx>
49 #include <TopTools_HArray1OfShape.hxx>
50 #include <BRepTools.hxx>
51 #include <BRep_Tool.hxx>
52 #include <TopoDS.hxx>
53 #include <TopoDS_Wire.hxx>
54 #include <TopoDS_Face.hxx>
55 #include <TopoDS_Shell.hxx>
56 #include <TopoDS_Solid.hxx>
57 // #include <TNaming_NCollections.hxx>
58 #include <NCollection_Map.hxx>   
59 #include <NCollection_DataMap.hxx>
60 typedef NCollection_Map<TopoDS_Shape> TNaming_MapOfShape; 
61 typedef TNaming_MapOfShape::Iterator TNaming_MapIteratorOfMapOfShape;
62 typedef NCollection_DataMap<TopoDS_Shape, TNaming_MapOfShape> TNaming_DataMapOfShapeMapOfShape; 
63 typedef TNaming_DataMapOfShapeMapOfShape::Iterator TNaming_DataMapIteratorOfDataMapOfShapeMapOfShape; 
64 // The bug concerns access to a null object in the method Filter():
65
66 #define ALLOW_CHILD_NBS
67 //#define MDTV_DEB_CC
68 //#define MDTV_DEB_OR
69 //#define MDTV_DEB_MOD
70 //#define MDTV_OR
71 //#define MDTV_DEB_INNS
72 //#define MDTV_DEB_NBS
73 //#define MDTV_DEB_71
74 //#define MDTV_DEB_WIN
75 #ifdef OCCT_DEBUG
76 #include <TDF_MapIteratorOfLabelMap.hxx> 
77 #include <TCollection_AsciiString.hxx>
78 #include <TDF_Tool.hxx>
79 #include <BRepTools.hxx>
80 #include <TNaming_Tool.hxx>
81 #include <TDF_Tool.hxx>
82 #include <TDF_MapIteratorOfLabelMap.hxx>
83
84 #include <TCollection_AsciiString.hxx>
85 #include <BRepTools.hxx>
86 void Print_Entry(const TDF_Label&       label)
87 {
88   TCollection_AsciiString entry;
89   TDF_Tool::Entry(label, entry);
90   cout << "LabelEntry = "<< entry << endl;
91 }
92 static void Write(const TopoDS_Shape& shape,
93                       const Standard_CString filename) 
94 {
95   char buf[256];
96   if(strlen(filename) > 256) return;
97   strcpy (buf, filename);
98   char* p = buf;
99   while (*p) {
100     if(*p == ':')
101       *p = '-';
102     p++;
103   }
104   ofstream save (buf);
105   if(!save) 
106     cout << "File " << buf << " was not created: rdstate = " << save.rdstate() << endl;
107   save << "DBRep_DrawableShape" << endl << endl;
108   if(!shape.IsNull()) BRepTools::Write(shape, save);
109   save.close();
110 }
111 void WriteNSOnLabel(const Handle(TNaming_NamedShape) & NS, const TCollection_AsciiString& Nam)
112 {
113   if (!NS.IsNull()) {
114     TCollection_AsciiString entry;
115     TDF_Tool::Entry(NS->Label(), entry);
116     TopoDS_Shape Sh = TNaming_Tool::GetShape (NS);
117     if(!Sh.IsNull()) {
118       TCollection_AsciiString Entry = Nam + entry + ".brep";
119       Write(Sh, Entry.ToCString());
120     }
121     else
122       cout << "WriteNSOnLabel>>> TopoDS_Shape IS NULL on Entry = "<< entry << endl;
123   }
124   else
125     cout << "WriteNSOnLabel >>>  NamedShape IS NULL" << endl;
126 }
127 #endif
128
129 //==========================================================================================
130 static Handle(TNaming_NamedShape) BuildName (const  TDF_Label&   F,
131                                              TNaming_Scope&                    MDF,
132                                              const TopoDS_Shape&               S,
133                                              const TopoDS_Shape&               Context, 
134                                              const Handle(TNaming_NamedShape)& Stop,
135                                              const Standard_Boolean            Geometry);
136
137 //=======================================================================
138 static Standard_Integer RepeatabilityInContext(const TopoDS_Shape& Selection, 
139                                                const TopoDS_Shape& Context);
140 //=======================================================================
141 extern Standard_Boolean IsEqual (const TopoDS_Shape& S1, const TopoDS_Shape& S2);
142
143 //=======================================================================
144 //function : Solve
145 //purpose  : voir avec YFR comment retrouver le bon resulat et le mettre 
146 //         : dans le NamedShape de L
147 //=======================================================================
148 Standard_Boolean  TNaming_Naming::Solve (TDF_LabelMap& Valid) 
149
150   Handle(TNaming_Naming) subname;
151   for (TDF_ChildIterator it (Label(),Standard_False); it.More(); it.Next()) {
152 #ifdef OCCT_DEBUG_NBS
153     TCollection_AsciiString anEntry;
154     TDF_Tool::Entry(it.Value(), anEntry);
155     cout << "TNaming_Naming::Solve: Label to be solved = " << anEntry << endl;
156 #endif
157     if (it.Value().FindAttribute(TNaming_Naming::GetID(),subname)) {
158       if (!subname->Solve (Valid)) {
159         return Standard_False; // not necessary to continue
160       }
161     }
162   }
163 #ifdef OCCT_DEBUG_CC
164   TDF_MapIteratorOfLabelMap anItr(Valid);
165   cout << "TNaming_Naming::Solve:: Valid label Map" << endl;
166   for (; anItr.More(); anItr.Next()) {
167     const TDF_Label& aLabel = anItr.Key();
168     TCollection_AsciiString anEntry;
169     TDF_Tool::Entry(aLabel, anEntry);
170     cout << "Label = " << anEntry << endl;
171   }
172 #endif
173   if (Regenerate(Valid)) {
174     if (!Valid.IsEmpty()) Valid.Add(Label());
175     return Standard_True;
176   }
177   return Standard_False; 
178 }
179  
180  
181 //=======================================================================
182 //function : GetID
183 //purpose  : 
184 //=======================================================================
185
186 const Standard_GUID& TNaming_Naming::GetID () 
187 {
188   static Standard_GUID TNaming_NamingID("c0a19201-5b78-11d1-8940-080009dc3333");
189   return TNaming_NamingID; 
190 }
191
192 //=======================================================================
193 //function : Insert
194 //purpose  : 
195 //=======================================================================
196
197 Handle(TNaming_Naming) TNaming_Naming::Insert (const TDF_Label& under) 
198 {
199   Handle(TNaming_Naming) N;  
200   TDF_Label child = TDF_TagSource::NewChild(under);
201   N = new TNaming_Naming ();  
202   child.AddAttribute (N);
203   return N;
204 }  
205   
206 //=======================================================================
207 //function : BuildNS
208 //purpose  : returns a new NamedShape, which is built as selection: 
209 //         : TNaming_Builder::Select("S","S") at the new child label of the label <F>. 
210 //=======================================================================
211
212 static Handle(TNaming_NamedShape)  BuildNS (const TDF_Label&        F,
213                                             const TopoDS_Shape&     S,
214                                             const TNaming_NameType& Name)
215 {
216   Handle (TNaming_Naming) Naming = TNaming_Naming::Insert (F);
217   
218   TNaming_Name& theName = Naming->ChangeName();
219   theName.ShapeType(S.ShapeType());
220   theName.Shape(S); 
221   theName.Orientation(S.Orientation());
222   theName.Type(Name);
223   TNaming_Builder B(Naming->Label());
224   B.Select(S,S);
225   return B.NamedShape();
226 }
227
228 //=======================================================================
229 //function : FindIndex
230 //purpose  : 
231 //=======================================================================
232
233 static Standard_Integer FindIndex(const Handle(TNaming_NamedShape)& NS,
234                                   const TopoDS_Shape&               S)
235 {
236   TDF_LabelList Labels;
237   TopoDS_Shape IS = TNaming_Tool::InitialShape(S,NS->Label(),Labels);
238   Standard_Integer Index = 1;
239   for (TNaming_Iterator itNS(NS); itNS.More(); itNS.Next(),Index++) {
240     if (IS.IsSame(itNS.NewShape())) break;
241   }
242   return Index;
243 }
244
245
246 //=======================================================================
247 //function : CompareInGeneration
248 //purpose  : returns true, only if the specified NS contains only <S> in 
249 //         : the "new shapes" set.
250 //=======================================================================
251
252 static Standard_Boolean CompareInGeneration (const Handle(TNaming_NamedShape)& NS,
253                                              const TopoDS_Shape&               S)
254 {
255   for (TNaming_Iterator it(NS); it.More(); it.Next()) {
256     if (!it.NewShape().IsSame(S)) return 0;
257   }
258   return 1;
259 }
260
261 //=======================================================================
262 //function : GetShapeEvolutions
263 //purpose  : returns Standard_True, if target has parent in source; list contains inheritance chain
264 //=======================================================================
265 static Standard_Boolean GetShapeEvolutions(const TopoDS_Shape&               theTarget, // this is changed in recursion
266                                            const Handle(TNaming_NamedShape)& theSource,
267                                            TopTools_ListOfShape&             aList)     // returns list in the backward order
268 {
269   Handle(TNaming_NamedShape) aTarget = TNaming_Tool::NamedShape(theTarget,theSource->Label());
270   if (!aTarget.IsNull()) {
271 #ifdef OCCT_DEBUG_71
272     cout <<"GetShapeEvolutions: target NS = ";
273     Print_Entry(aTarget->Label());
274     cout <<"GetShapeEvolutions: Source NS = ";
275     Print_Entry(theSource->Label());
276     TCollection_AsciiString aNam("GetShapeEvolutions");
277     WriteNSOnLabel(aTarget,aNam);
278 #endif
279     if (aTarget->Label() == theSource->Label()) return Standard_True; // check if target is in the source
280   } else return Standard_False;
281
282   TNaming_Iterator anIter(aTarget);
283   for(;anIter.More();anIter.Next()) { // check all appropriate old shapes of target
284 #ifdef OCCT_DEBUG_71
285     if(!anIter.OldShape().IsNull()) {
286       Write(anIter.OldShape(), "Target_OldS.brep");
287       cout <<"Target OldS TS =" <<anIter.OldShape().TShape()->This() <<endl;
288     }
289     if(!anIter.NewShape().IsNull()) {
290       Write(anIter.NewShape(), "Target_NewS.brep");
291       cout <<"Target NewS TS =" <<anIter.NewShape().TShape()->This() <<endl;
292     }  
293 #endif
294     if (anIter.OldShape().IsNull() || anIter.NewShape().IsNull()) continue;
295     if (!anIter.NewShape().IsSame(theTarget)) continue;
296     if (GetShapeEvolutions(anIter.OldShape(),theSource,aList)) { // recursion: now target is old shape
297       aList.Append(theTarget); // if oldshape has the source as parent (or belongs to it) , fill the list
298       return Standard_True;
299     }
300   }
301   return Standard_False;
302 }
303
304 //=======================================================================
305 //function : CompareInModification
306 //purpose  : returns empty named shape if naming is already done
307 //=======================================================================
308
309 static Handle(TNaming_NamedShape) CompareInModification (const Handle(TNaming_NamedShape)& NS, // parent
310                                                          const TopoDS_Shape&               S)  // target
311 {
312   Handle(TNaming_NamedShape) aResult;
313   if (S.IsNull() || NS.IsNull()) return aResult;
314 #ifdef OCCT_DEBUG_71
315   cout <<"CompareInModification: parent NS = ";
316   Print_Entry(NS->Label());
317   Write(S, "CompareInM_S.brep");
318   TCollection_AsciiString aNam("CompareInM");
319   WriteNSOnLabel(NS,aNam);
320 #endif
321   Handle(TNaming_NamedShape) aSource; // parent NamedShape, which can be found by TopoDS shape
322   TNaming_Iterator anIt(NS);
323   for(;anIt.More() && aSource.IsNull();anIt.Next()) {
324     if (!anIt.NewShape().IsNull()) {
325       aSource = TNaming_Tool::NamedShape(anIt.NewShape(),NS->Label());
326 #ifdef OCCT_DEBUG_71
327       TCollection_AsciiString aNam("CompareInM_Source");
328       WriteNSOnLabel(aSource,aNam);
329 #endif
330     }
331   }
332   // searching for 1:n to the same label modifications (in this case current naming is insufficient)
333   TopTools_ListOfShape aList;
334   if (GetShapeEvolutions(S,aSource,aList) && aList.Extent() > 0) {
335     TopTools_ListIteratorOfListOfShape anIter(aList);
336     for(;anIter.More();anIter.Next()) {
337       aResult = TNaming_Tool::NamedShape(anIter.Value(),NS->Label());
338       if (aResult->Evolution()!=TNaming_MODIFY) { // evolution must be modify, otherwise everything is OK
339         aResult.Nullify();
340         return aResult;
341       }
342       TopTools_MapOfShape aMap; // collection of the old shapes of the shape from list
343       TNaming_Iterator aNIter1(aResult);
344
345       for(;aNIter1.More();aNIter1.Next()) {
346         if (aNIter1.NewShape().IsSame(anIter.Value()))  {// if isSame 
347           aMap.Add(aNIter1.OldShape());
348         }
349       }
350       TNaming_Iterator aNIter2(aResult); // if some another shapes has oldshape from map, return namedshape with this oldshape
351
352       for(;aNIter2.More();aNIter2.Next()) {
353         if (aNIter2.NewShape().IsSame(anIter.Value())) continue;
354         if (aMap.Contains(aNIter2.OldShape())) { // if one shape was modified to the two at the shared label, return this one
355           aResult = TNaming_Tool::NamedShape(aNIter2.OldShape(),NS->Label());
356           if (!aResult.IsNull()) return aResult;
357         }
358       }
359     }
360     aResult.Nullify();
361   }
362   return aResult;
363 }
364
365 //=======================================================================
366 static Standard_Boolean FillSMap(const TopoDS_Shape& S, TopTools_MapOfShape& MS)
367 {   
368   if(S.IsNull()) return Standard_False; 
369   Standard_Boolean isHomogen(Standard_True);
370   TopAbs_ShapeEnum aPrevType(TopAbs_SHAPE);
371   TopoDS_Iterator it(S);
372   for (; it.More(); it.Next()) {
373     const TopAbs_ShapeEnum aType = it.Value().ShapeType();      
374 #ifdef OCCT_DEBUG_CC
375     cout <<"TestSolution_FillMap: S_Type = :" << it.Value().ShapeType() <<" TShape = " << it.Value().TShape()->This() <<endl;
376 #endif
377     if(aType > TopAbs_COMPSOLID) {
378       MS.Add(it.Value());
379       if(aPrevType == TopAbs_SHAPE)
380         aPrevType = aType;
381       else if(aPrevType != aType) 
382         isHomogen = Standard_False;       
383     }
384     else 
385       if(!FillSMap(it.Value(), MS))
386         isHomogen = Standard_False;  
387   }
388   return isHomogen;
389 }
390 //=======================================================================
391 //function : Compare
392 //purpose  : checks naming of the shape <S> in the NamedShape <NS>. 
393 //         : Returns true, if it's correct. Details ==>
394 //         : The method takes all modifications of the "NS" (see CurrentShape method), 
395 //         : which are in the "MDF" (if it's not empty) before <Stop> shape and check them.
396 //         : whether these modifications contain only "S". If yes then the method 
397 //         : returns true, otherwise it returns false.
398 //=======================================================================
399
400 static Standard_Boolean Compare (const Handle(TNaming_NamedShape)& NS,
401                                  const TNaming_Scope&              MDF,
402                                  const Handle(TNaming_NamedShape)& Stop,
403                                  const TopoDS_Shape&               S)
404 {
405   TDF_LabelMap Forbiden;
406   TopTools_MapOfShape MS;
407   if (!Stop.IsNull()) TNaming_NamingTool::BuildDescendants(Stop,Forbiden);
408   TNaming_NamingTool::CurrentShape(MDF.GetValid(),Forbiden,NS,MS);
409 #ifdef OCCT_DEBUG_NBS
410   Write(S, "Compare_S.brep");
411   cout <<  "S: TShape = " <<S.TShape()->This() <<endl;
412   Standard_Integer i =1;
413   TopTools_MapIteratorOfMapOfShape it(MS);
414   TCollection_AsciiString aNam("Compare_MS_");
415   TCollection_AsciiString ext(".brep");
416   for(;it.More();it.Next(), i++) {
417     TCollection_AsciiString aName = aNam + i + ext;
418     Write(it.Key(), aName.ToCString()) ;
419     cout << aName.ToCString()<< ": TShape = " <<it.Key().TShape()->This() <<endl;
420   }
421 #endif
422   return (MS.Contains(S) && MS.Extent() == 1);
423 }
424 //=======================================================================
425 //function : TestSolution
426 //purpose  : returns true, if last modification of shape from "NS" is equal to "S":
427 //         : If shape "S" has atomic type (TopAbs_FACE, TopAbs_EDGE, TopAbs_VERTEX), 
428 //         : then returns S.IsSame(shape from "NS"). 
429 //         : Otherwise the result of exploration of these shapes must be same.
430 //=======================================================================
431
432 static Standard_Boolean TestSolution(const TNaming_Scope&      MDF,
433                                      const Handle(TNaming_NamedShape)& NS,
434                                      const TopoDS_Shape&               S)
435
436
437   if (NS.IsNull()) return Standard_False;
438   TopoDS_Shape Res = MDF.CurrentShape(NS);// last modification of NS taken into account Valid map
439   if(S.IsNull() || Res.IsNull()) return Standard_False;
440 #ifdef OCCT_DEBUG_CC
441   Write(S, "TSol_S.brep");
442   Write(Res, "TSol_Res.brep");
443 #endif  
444
445   if ((S.ShapeType() == TopAbs_FACE  ||
446       S.ShapeType() == TopAbs_EDGE  ||
447       S.ShapeType() == TopAbs_VERTEX ) && 
448       Res.ShapeType() != TopAbs_COMPOUND) { 
449     return (Res.IsSame(S));
450   } else if (S.ShapeType() == TopAbs_SOLID ||
451         S.ShapeType() == TopAbs_COMPSOLID) {
452     TopTools_MapOfShape aMS;
453     TopExp_Explorer exp;
454     for (exp.Init(S,TopAbs_FACE) ; exp.More(); exp.Next()) {
455       aMS.Add(exp.Current());
456     }
457     for (exp.Init(Res,TopAbs_FACE) ; exp.More(); exp.Next()) { //content of MS and Res should be the same 
458       if (aMS.Contains(exp.Current())) {
459         aMS.Remove(exp.Current());
460       }
461       else return 0;
462     }
463     return aMS.IsEmpty();
464   } else {
465
466     TopTools_MapOfShape MS;
467     Standard_Boolean isHom = FillSMap(S, MS);
468     TopAbs_ShapeEnum aType(TopAbs_SHAPE); 
469     TColStd_MapOfInteger aView;
470     TopTools_MapIteratorOfMapOfShape itm(MS);
471     for(;itm.More();itm.Next()) {
472       aType = itm.Key().ShapeType();
473       if(isHom) 
474         break;
475        else 
476         aView.Add(itm.Key().ShapeType());      
477     }
478     
479     if (MS.Contains(Res)) {
480       MS.Remove(Res);
481       if (MS.IsEmpty()) return 1;
482     }
483     if (Res.ShapeType() == TopAbs_SOLID ||
484         Res.ShapeType() == TopAbs_COMPSOLID || 
485         Res.ShapeType() == TopAbs_COMPOUND) 
486       {
487         TopExp_Explorer exp;
488         if(isHom)
489           for (exp.Init(Res,aType) ; exp.More(); exp.Next()) {
490             if (MS.Contains(exp.Current())) {
491               MS.Remove(exp.Current());
492             }
493           } else {
494             TColStd_MapIteratorOfMapOfInteger itm(aView);
495             for(;itm.More();itm.Next()) {
496               TopAbs_ShapeEnum aType = (TopAbs_ShapeEnum)itm.Key();
497               for (exp.Init(Res,aType) ; exp.More(); exp.Next()) {
498                 if (MS.Contains(exp.Current())) {
499                   MS.Remove(exp.Current());
500                 }
501               }
502             }
503           }
504       } else {
505         if(S.IsSame(Res))
506           return Standard_True;
507         TopoDS_Iterator it(Res);
508         for (; it.More(); it.Next()) { //content of MS and Res should be the same 
509           if (MS.Contains(it.Value())) {
510             MS.Remove(it.Value());
511           }
512           else return 0; 
513         }
514       }
515     return MS.IsEmpty();
516   }
517 }
518
519 //=======================================================================
520 //function : FindNewShapeInFather
521 //purpose  :
522 //=======================================================================
523
524 static void FindNewShapeInFather (const Handle(TNaming_NamedShape)& NS,
525                                   TopoDS_Shape&                     SC)
526 {  
527   const TDF_Label& Father = NS->Label().Father(); 
528   TNaming_Iterator  itLab(Father);
529   if(itLab.More()) 
530     SC = itLab.NewShape();    
531 }
532
533 //=======================================================================
534 //function : NextModif
535 //purpose  : 
536 //=======================================================================
537
538 static Handle(TNaming_NamedShape) NextModif(const Handle(TNaming_NamedShape)& NS)
539 {
540   Handle (TNaming_NamedShape) Next;
541   if (!NS.IsNull()) {
542     TNaming_NewShapeIterator it(NS); 
543     if (it.More()&& it.IsModification()) Next = it.NamedShape();
544   }
545   return Next;
546 }
547 //=======================================================================
548 // C1 - cand shape of the father, C2 - shape of rebuild child Naming attr.
549 //      (to be Compound of elementary shapes)
550 //=======================================================================
551 static Standard_Boolean IsContSame(const TopoDS_Shape& C1, const TopoDS_Shape& C2)
552 {
553   Standard_Boolean aRes(Standard_False);
554   if(!C1.IsNull() && !C2.IsNull()) {
555     TopTools_MapOfShape aMap;
556     if(FillSMap(C1, aMap)) {
557       aRes = Standard_True;
558       TopoDS_Iterator it(C2);
559       for(;it.More();it.Next()) {
560         if(!aMap.Contains(it.Value())) {
561           aRes = Standard_False;
562           break;
563         }
564       }
565     }
566   }
567   return aRes;
568 }
569
570 //=======================================================================
571 // Identifies the case when Filter haven't sense because of multiplicity
572 //=======================================================================
573 static Standard_Boolean IsMultipleCase(const TopoDS_Shape&        S,
574                                  const TopoDS_Shape&        Context,
575                                  const TopTools_MapOfShape& Neighbourgs) {
576   
577   TopTools_IndexedDataMapOfShapeListOfShape aDM;
578   TNaming_MapOfShape aM;
579   TopTools_MapOfShape aNbs;
580   aNbs.Assign(Neighbourgs);
581   aNbs.Add(S);
582   TNaming_DataMapOfShapeMapOfShape aDMM;
583   TopExp::MapShapesAndAncestors (Context, TopAbs_EDGE, TopAbs_FACE, aDM);
584   TopTools_MapIteratorOfMapOfShape it(aNbs);
585   for(;it.More();it.Next()) {
586     if(aDM.Contains(it.Key())) {
587       TNaming_MapOfShape aMS;
588       const TopTools_ListOfShape& aL = aDM.FindFromKey(it.Key());      
589       TopTools_ListIteratorOfListOfShape lit(aL);
590       for(;lit.More();lit.Next()) {
591         aM.Add(lit.Value());
592         aMS.Add(lit.Value());
593       }
594       if(aMS.Extent())
595         aDMM.Bind(it.Key(), aMS);
596     } else {
597 #ifdef OCCT_DEBUG
598       cout << "Key is not BOUND!" <<endl;
599 #endif
600       return Standard_False;
601     }
602   }
603   
604   Standard_Boolean isCommon(Standard_True);
605   TNaming_MapIteratorOfMapOfShape itm(aM);
606   for(;itm.More();itm.Next()) {
607     isCommon = Standard_True; // statement: this shape (itm.Key()) is common (to be checked below)
608     TNaming_DataMapIteratorOfDataMapOfShapeMapOfShape itdm(aDMM);
609     for (;itdm.More();itdm.Next()) {
610       const TNaming_MapOfShape& aMap = itdm.Value();
611       if(!aMap.Contains(itm.Key())) {
612         isCommon = Standard_False;
613         break;
614       }
615     }
616     if(isCommon) break; // common single face found
617   }
618   if(isCommon && aM.Extent() < aNbs.Extent()) {// number of unique faces (to have single solution) 
619                                                //should be at least no less than (Nb of Neighbourgs) +1
620     return Standard_True;
621   }
622   return Standard_False;
623 }
624 //=======================================================================
625 //function : Filter
626 //purpose  : sets the name with type "FILTERBYNEIGHBOURGS" and returns true, 
627 //         : if it was correctly done.
628 //         : 
629 //         :
630 //=======================================================================
631
632 static Standard_Boolean Filter (const TDF_Label&                  F,
633                                 TNaming_Scope&                    MDF,
634                                 const TopoDS_Shape&               S,
635                                 const TopoDS_Shape&               Context,
636                                 TNaming_Localizer&                Localizer,
637                                 Handle(TNaming_NamedShape)&       NS,
638                                 const Standard_Integer            Lev)
639
640   // 1. Localizer.FindNeighbourg("Context", "S", "Neighbourg") - looks for neighbourgs of  "S" with the same shape type in the "Context" 
641   //    shape and adds them to the "Neighbourg" map;
642   // 2. If "Neighbourg" map is empty, tries to do the same with the new context shape: shape from the father label of the "S" named shape;
643   // 3. If "Neighbourg" map is still empty, returns false;
644   // 4. Adds to the new child of label "L" new TNaming_Naming attribute with the next properties name: shape type is shape type of the "S",
645   //     type is TNaming_FILTERBYNEIGHBOURGS, stop shape ( "Until" ) is "Context" of corresponding NamedShape; 
646   //     first argument of name is "NS" NamedShape.
647   // 5. Adds to the Name all shapes from "Neighbourg" map: build it with the BuildName( new generated TNaming_Naming attribute, MDF, 
648   //    argument shape from "Neighbourg", "Context", NextModif( "Until" ), true ) method.
649   // 6. Creates resulting NamedShape with the "Regenerate" ( it just calls TName::Solve method ) method from TNaming_Naming class.
650   // 7. If Compare( result NamedShape, MDF, stop, "S" ) returns true, "Filter" method returns true, else returns false.
651
652   //------------------------------
653   // Construction des voisins ==> of neighbors.
654   //------------------------------
655   Standard_Integer aLev(Lev);
656   TopTools_MapOfShape Neighbourg;
657   Localizer.FindNeighbourg (Context,S,Neighbourg);
658 #ifdef OCCT_DEBUG_NBS
659   //DbgTools::DisplayShape(Context, F, Quantity_NOC_GREEN);
660   //DbgTools::DisplayShape(S, F, Quantity_NOC_BLUE1);  
661   Write(Context, "FNBS_Context.brep");
662   Write(S, "FNBS_S.brep");
663   Write(Neighbourg, "NBS");
664 #endif
665   // mpv : NS and shape must be the same
666   Standard_Boolean isIn = Standard_False;
667   TNaming_Iterator anIter(NS);
668   for(;anIter.More();anIter.Next()) {
669 #ifdef OCCT_DEBUG
670           //DbgTools::DisplayShape(anIter.NewShape(), F, Quantity_NOC_RED);
671 #endif
672     if (anIter.NewShape().IsSame(S)) {
673       isIn = Standard_True;
674       break;
675     }
676   }
677   if (!isIn) if (!TNaming_Tool::NamedShape(S,F).IsNull()) NS = TNaming_Tool::NamedShape(S,F);
678 //  if (!TNaming_Tool::NamedShape(S,F).IsNull()) NS = TNaming_Tool::NamedShape(S,F);
679   
680   if (Neighbourg.IsEmpty()) {
681     // Recherche du vrai context. (Research of context truth)
682     Handle(TNaming_NamedShape) GenS = TNaming_Tool::NamedShape(S,NS->Label());
683     if (GenS.IsNull()) return Standard_False;
684     TDF_Label Father = (GenS->Label()).Father();
685     Father.FindAttribute(TNaming_NamedShape::GetID(),GenS);
686     TopoDS_Shape GoodContext = TNaming_Tool::GetShape(GenS);
687     Localizer.FindNeighbourg (GoodContext,S,Neighbourg);
688   }
689   
690
691   if (Neighbourg.IsEmpty()) {
692 #ifdef OCCT_DEBUG
693     cout <<"FindNeighbourg: impossible"<<endl;
694 #endif
695     return 0;  
696   } else {
697 #ifdef OCCT_DEBUG_NBS
698     Write(Neighbourg, "Neighbourgs");
699 #endif
700     aLev++;
701     //cout <<"Filter: Lev = " << aLev << endl;
702   }
703   if(aLev > 3) return 0; 
704 #ifdef ALLOW_CHILD_NBS   
705   Handle(TNaming_Naming) aFNaming;
706   TopoDS_Shape aFatherCandSh;
707   F.FindAttribute(TNaming_Naming::GetID(), aFNaming);
708   if(!aFNaming.IsNull()) {
709     const TNaming_Name& aName = aFNaming->GetName();
710     if (aName.Type() == TNaming_FILTERBYNEIGHBOURGS) {
711       aFatherCandSh = aName.Arguments().First()->Get();
712     }
713   } 
714   if(S.ShapeType() == TopAbs_EDGE && aFatherCandSh.IsNull()) {
715     //check the applicability
716     if(!NS.IsNull() && !NS->Get().IsNull() && NS->Get().ShapeType() == TopAbs_COMPOUND)
717       if(IsMultipleCase(S, Context, Neighbourg)) {
718         //cout << "Filter: ==> MultipleCase!" << endl;
719         NS->Label().FindAttribute(TNaming_Naming::GetID(), aFNaming);
720         if(!aFNaming.IsNull()) {
721           TNaming_Name& aName = aFNaming->ChangeName();
722           if (aName.Type() == TNaming_INTERSECTION) {
723             Standard_Integer ij(1);
724             TNaming_ListIteratorOfListOfNamedShape itA(aName.Arguments()); 
725             for (; itA.More(); itA.Next(), ij++) {
726               const TopoDS_Shape& aFace = TNaming_Tool::CurrentShape(itA.Value());
727 #ifdef OCCT_DEBUG_MOD
728               Write(aFace, "First_Face.brep");
729               cout <<"Selection TS = " << S.TShape()->This() <<endl;
730 #endif
731               Standard_Integer i(1), indxW(0),indxE(0),nbW(0),nbE(0), indxF(0);
732               Standard_Boolean isFound(Standard_False);
733               TopoDS_Iterator it(aFace);
734               for (;it.More();it.Next(),i++) {
735                 nbW++;
736 #ifdef OCCT_DEBUG_MOD
737                 Write(it.Value(), "First_Wire.brep");
738 #endif
739                 if(!isFound) {
740                   Standard_Integer j(1);
741                   TopoDS_Iterator it2(it.Value());
742                   for (;it2.More();it2.Next(),j++) {
743                     nbE++;
744 #ifdef OCCT_DEBUG_MOD
745                     Write(it2.Value(), "First_Wire.brep");
746                     cout <<"Edge TS = " << it2.Value().TShape()->This() <<endl;
747 #endif
748                     if(S.IsEqual(it2.Value())) {
749                       indxE = j;
750                       indxW = i;
751                       indxF = ij;
752                       isFound = Standard_True;              
753                     }
754                   }
755                 }             
756               }
757               if(isFound) {
758                 Standard_Integer Index = indxE & 0x000000FF;
759                 Index = Index | (nbE   << 8);
760                 Index = Index | (indxW << 16);
761                 Index = Index | (nbW   << 20);
762                 Index = Index | (indxF << 24);
763                 aName.Index(Index);           
764                 //------------------------------
765                 // Compute the TNaming_NamedShape
766                 //------------------------------
767                 aFNaming->Regenerate(MDF.ChangeValid());
768                 aFNaming->Label().FindAttribute(TNaming_NamedShape::GetID(),NS);
769                 Handle (TNaming_NamedShape) Until = TNaming_Tool::NamedShape(Context,NS->Label());
770                 Handle (TNaming_NamedShape) Stop  = NextModif(Until); 
771                 if (Compare (NS,MDF,Stop,S)) return 1;
772                 break; 
773               }    
774             }
775           } 
776         }       
777         return 0;
778       }
779   }
780 #endif
781
782   //-----------------------------------------------------
783   // Construction function de naming. et insertion sous F
784   //-----------------------------------------------------
785   Handle (TNaming_Naming) NF = TNaming_Naming::Insert (F);
786   
787   Handle (TNaming_NamedShape) Until = TNaming_Tool::NamedShape(Context,NS->Label());
788   Handle (TNaming_NamedShape) Stop  = NextModif(Until); 
789   TNaming_Name& theName = NF->ChangeName();
790   theName.ShapeType(S.ShapeType());
791   theName.Shape(S);
792   theName.Orientation(S.Orientation());
793   theName.Type(TNaming_FILTERBYNEIGHBOURGS);
794   theName.Append(NS);
795   theName.StopNamedShape (Until);
796 #ifdef OCCT_DEBUG_NBS
797   cout << "FilterByNBS: ";
798   Print_Entry(NF->Label());
799   cout <<"AppendNS = " ;
800   Print_Entry(NS->Label());
801 #endif
802   //---------------------
803   // Naming des voisins.
804   //---------------------
805
806   TopTools_MapIteratorOfMapOfShape itN(Neighbourg);
807   for (; itN.More(); itN.Next()) {
808 #ifdef ALLOW_CHILD_NBS    
809     const TopoDS_Shape& aS = itN.Key();   
810     Handle (TNaming_NamedShape) aNS = 
811       BuildName(NF->Label(), MDF, aS, Context, Stop, 1);          
812 #ifdef OCCT_DEBUG_NBS
813     const TopoDS_Shape& aS2 = aNS->Get(); 
814     if(!aS.IsNull())
815       cout << "Shape arg type = " << aS.ShapeType() <<" TSH = " << aS.TShape()->This()<<endl;
816     if(!aS2.IsNull()) {
817       cout << "Build shape type = " << aS2.ShapeType() <<" TSH = " << aS2.TShape()->This()<<endl;
818       Write (aS2, "NBS_BuildShape.brep");
819     }
820     if(aNS.IsNull()) {
821      cout <<"AppendNS = " ;
822      Print_Entry(aNS->Label());
823     }
824 #endif
825                   
826     const TopoDS_Shape aSNS = aNS->Get();  //allow child level
827     Standard_Boolean allowChild(Standard_True);
828     if(!aSNS.IsNull() && aSNS.ShapeType() == TopAbs_COMPOUND && !aFatherCandSh.IsNull()) 
829       allowChild = !IsContSame(aFatherCandSh, aSNS);
830     if(allowChild && !aSNS.IsNull() && aS.ShapeType() != aSNS.ShapeType() && 
831        aSNS.ShapeType() == TopAbs_COMPOUND)
832       { // aLev < 3 
833 #ifdef OCCT_DEBUG_NBS
834         cout <<"Father label = ";
835         Print_Entry(aNS->Label().Father());
836         Write(aS,"SelectionS.brep");
837         Write(aSNS,"SelectionSNS.brep");
838 #endif
839         Handle(TNaming_Naming) aNaming;
840         Standard_Boolean StandardFilter(Standard_True);
841         aNS->FindAttribute(TNaming_Naming::GetID(), aNaming);
842         if(!aNaming.IsNull()) {
843           const TNaming_Name& aName = aNaming->GetName();
844           if (aName.Type() == TNaming_GENERATION) 
845             StandardFilter = Standard_False;
846           if(StandardFilter)
847             if (!Compare (aNS,MDF,Stop,aS)) {
848               TNaming_Localizer aLocalizer;
849               Filter (NF->Label(), MDF,aS,Context, aLocalizer,aNS, aLev);
850             }
851         }
852       }    
853     theName.Append(aNS);
854 #else 
855     theName.Append(BuildName(NF->Label(), MDF, itN.Key(), Context, Stop, 1));
856 #endif
857   }
858   //------------------------------
859   // Compute the TNaming_NamedShape
860   //------------------------------
861   NF->Regenerate(MDF.ChangeValid());
862   NF->Label().FindAttribute(TNaming_NamedShape::GetID(),NS);
863
864   //-----------------
865   // Check du filtre.
866   //-----------------
867   if (Compare (NS,MDF,Stop,S)) return 1;
868 #ifdef OCCT_DEBUG
869   cout <<"TNaming_Naming::Name Filter insufficient"<<endl;
870 #endif
871   return 0;
872 }
873
874
875 //=======================================================================
876 //function : BuildNameInNS
877 //purpose  : Calls BuildName method, but with new context and new stop shape.  
878 //         : Context is searched at the father label of the "Context" label : 
879 //         : old shapes from the NamedShape at the defined father label.
880 //         : If it's impossible, then "S" set as context. 
881 //         : If "S" is in new context, then stop shape is named shape, 
882 //         : which belongs to the father label of the "Context" named shape.
883 //         : For example, face (F2) of prism (P) is generated from the edge (E) 
884 //         : of primitive face (F1) of box (B). F2 is named as GENERATION from E.
885 //         : Naming of E is done with help BuildNameInNS function:   
886 //         : with context B and stop shape P. 
887 //=======================================================================
888 static Handle(TNaming_NamedShape) BuildNameInNS (const TDF_Label&                  F,
889                                                  TNaming_Scope&                    MDF,
890                                                  const TopoDS_Shape&               S,
891                                                  const Handle(TNaming_NamedShape)& Context,
892                                                  const Handle(TNaming_NamedShape)& Stop,
893                                                  const Standard_Boolean            Geometry)
894
895 {
896   // il faut determiner un nouveau context et un nouveau Stop.
897   // it is necessary to determine a new context and a new Stop
898   TopoDS_Shape SC;
899   Handle(TNaming_NamedShape) NewStop = Stop;
900   
901   TNaming_Localizer::FindShapeContext (Context,S,SC);
902
903   if(!SC.IsNull()){
904 // <Context> is Ident.NamedShapeOfGeneration() ==
905     TDF_Label Father = Context->Label().Father();
906     Father.FindAttribute(TNaming_NamedShape::GetID(),NewStop);
907 #ifdef OCCT_DEBUG_INNS
908     if(!Stop.IsNull())
909       {cout <<" Stop NS : "; Print_Entry( Stop->Label());}
910     if(!NewStop.IsNull())
911       {cout <<" NewStop : ";  Print_Entry( NewStop->Label());}
912     cout <<"ContextLabel: "; Print_Entry( Context->Label());
913     cout <<"Father      : "; Print_Entry( Father);
914 #endif
915   }
916 #ifdef OCCT_DEBUG_INNS
917   if(NewStop.IsNull())
918     cout <<"BuildNameInNS:: NewStop shape is  NULL" << endl;  
919 #endif 
920   return BuildName (F,MDF,S,SC,NewStop,Geometry);
921 }
922
923 //=======================================================================
924 //function : 
925 //purpose  : 
926 //=======================================================================
927
928 static Handle(TNaming_NamedShape) BuildName (const TDF_Label&                  F,
929                                              TNaming_Scope&               MDF,
930                                              const TopoDS_Shape&               Selection,
931                                              const TopoDS_Shape&               Context,
932                                              const Handle(TNaming_NamedShape)& Stop,
933                                              const Standard_Boolean            Geom)
934 {
935
936  
937   
938   // Create an identifier
939   Standard_Boolean OnlyOne      = !Geom;
940   Standard_Boolean IsGeneration = Standard_False;
941 #ifdef OCCT_DEBUG_MOD
942   cout <<"BuildName: F =>  ";
943   Print_Entry(F);
944   cout <<" Selection type = " << Selection.ShapeType() << " TS = " << Selection.TShape()->This() << endl;
945   Write(Selection, "BName_Selection.brep");
946   Write(Context, "BName_Context.brep");
947 #endif
948   TNaming_Identifier Ident(F, Selection, Context,OnlyOne);
949
950   Handle (TNaming_Naming)  Naming;
951   Handle (TNaming_NamedShape) NS;
952
953   if (!Ident.IsDone()) {
954     return BuildNS (F,Selection, TNaming_UNKNOWN);
955   }
956   if (Ident.IsFeature() && Stop.IsNull()) {
957     //-------------
958     // Deja Nomme
959     //-------------
960     if   (!OnlyOne) return Ident.FeatureArg();
961     else            NS =   Ident.FeatureArg();
962   }
963   else {  
964     //---------------------------------------------
965     // Construction de la fonction d identification.
966     //---------------------------------------------
967     //Standard_Boolean NotOnlyOne = 0;
968
969     Naming = TNaming_Naming::Insert(F);
970    
971     TNaming_Name& theName = Naming->ChangeName();
972     theName.ShapeType(Selection.ShapeType());
973     theName.Shape(Selection);
974         theName.Orientation(Selection.Orientation());
975     theName.Type(Ident.Type());
976 #ifdef OCCT_DEBUG_MOD
977     cout <<"BuildName: Inserted Naming Att at ";
978     Print_Entry(Naming->Label());
979     cout <<" NameType = " << theName.Type() <<endl;             
980 #endif
981     if (Ident.IsFeature()) {
982       theName.Append(Ident.FeatureArg());
983     }
984     if (theName.Type() == TNaming_GENERATION) { 
985       theName.Append(Ident.NamedShapeOfGeneration());
986       IsGeneration = Standard_True;
987     } 
988     if (theName.Type() == TNaming_CONSTSHAPE) {
989       theName.Index(FindIndex(Ident.FeatureArg(),Selection));
990     } 
991     //------------------------------------
992     // Renseignement du NamedShape d arret.
993     //------------------------------------
994     theName.StopNamedShape (Stop);
995 #ifdef OCCT_DEBUG_MOD
996     if(!Stop.IsNull()) {
997         TCollection_AsciiString Es;
998       TDF_Tool::Entry(Stop->Label(), Es);
999       cout <<"StopNS at Label = "<< Es << endl;
1000     }
1001 #endif 
1002     //---------------------------------
1003     // Identification des arguments. 
1004     //---------------------------------
1005
1006     for (Ident.InitArgs(); Ident.MoreArgs(); Ident.NextArg()) {
1007       if (Ident.ArgIsFeature()) {
1008         theName.Append(Ident.FeatureArg());
1009 #ifdef OCCT_DEBUG_MOD
1010         if(!Ident.FeatureArg().IsNull()) {
1011           TCollection_AsciiString E;
1012           TDF_Tool::Entry(Ident.FeatureArg()->Label(), E);
1013           cout <<"Added argument NS from Label = "<< E << endl;
1014         }
1015 #endif 
1016       }
1017       else {
1018 #ifdef OCCT_DEBUG_MOD
1019           cout <<"BuildName: NameType = " <<theName.Type() << " NS ";
1020           Print_Entry(Naming->Label());
1021           cout <<"Ident.ShapeArg() type = " << Ident.ShapeArg().ShapeType() << " TS = " << Ident.ShapeArg().TShape()->This() << endl;   
1022            Write(Ident.ShapeArg(), "BName_ShapeArg.brep");
1023 #endif  
1024           if (theName.Type() == TNaming_GENERATION)
1025           theName.Append(BuildNameInNS(Naming->Label(),MDF,Ident.ShapeArg(),Ident.NamedShapeOfGeneration(),Stop,Geom));
1026         else 
1027           theName.Append(BuildName(Naming->Label(),MDF,Ident.ShapeArg(),Context,Stop,Geom));
1028       }
1029     }
1030
1031     //------------------------
1032     // Reconstruction of Name
1033     //------------------------
1034     Naming->Regenerate(MDF.ChangeValid()); 
1035 #ifdef OCCT_DEBUG_MOD
1036     TCollection_AsciiString E2;
1037     TDF_Tool::Entry(Naming->Label(), E2);
1038     cout <<"Regenerated Naming Att at Label = "<< E2 << endl;
1039 #endif 
1040     Naming->Label().FindAttribute(TNaming_NamedShape::GetID(),NS);
1041     if(NS.IsNull()) return NS; 
1042     if (MDF.WithValid()) MDF.Valid(NS->Label());
1043 #ifdef OCCT_DEBUG_MOD
1044     if(!NS.IsNull()) {
1045       TCollection_AsciiString E;
1046       TDF_Tool::Entry(NS->Label(), E);
1047       cout <<"Regenerated NS at Label = "<< E << endl;
1048     }
1049 #endif 
1050   }
1051
1052   if (OnlyOne) {
1053     //-------------------------------------------------
1054     // Filtre par les voisins
1055     // pour construire le nom correspondant a S.
1056     //------------------------------------------------- 
1057
1058    if(NS.IsNull()) return NS; 
1059
1060     TNaming_Localizer Localizer;
1061     TNaming_Iterator itNS(NS); 
1062     if (itNS.More()) {
1063       //----------------
1064       // Check + Filtre
1065       //----------------
1066
1067       Standard_Boolean StandardFilter = !IsGeneration;
1068       if (IsGeneration) {
1069         if (!CompareInGeneration (NS,Selection)) {
1070
1071           TopoDS_Shape               NewContext;
1072           Handle(TNaming_NamedShape) NewStop;
1073           FindNewShapeInFather (Ident.NamedShapeOfGeneration(),NewContext);
1074           Filter (F,MDF,Selection,NewContext,Localizer,NS,0);
1075         }
1076       } else if (Ident.Type() == TNaming_MODIFUNTIL ||
1077                  (Ident.Type() == TNaming_INTERSECTION && Naming->ChangeName().Arguments().Extent() == 1)) {
1078 #ifdef OCCT_DEBUG_MOD
1079         cout <<"BuildName(CompareInModification): NameType = " <<Ident.Type() << " NS ";
1080         Print_Entry(Ident.Type() == TNaming_MODIFUNTIL ? NS->Label() : Naming->ChangeName().Arguments().First()->Label());
1081         cout <<"Selection type = " << Selection.ShapeType() << " TS = " << Selection.TShape()->This() << endl;  
1082 #endif
1083         Handle(TNaming_NamedShape) NewNS =
1084           CompareInModification(Ident.Type() == TNaming_MODIFUNTIL ? NS : Naming->ChangeName().Arguments().First(), Selection);
1085         if (!NewNS.IsNull()) { // there is need to describe name in detail: modification with type 1:n in the same label
1086           StandardFilter = Standard_False;
1087           if (Ident.IsFeature()) { // for MODIFUNTIL: change it to the GENERATION
1088             Naming = TNaming_Naming::Insert(F);
1089             TNaming_Name& theName = Naming->ChangeName();
1090             theName.ShapeType(Selection.ShapeType());
1091             theName.Shape(Selection); 
1092                 theName.Orientation(Selection.Orientation());
1093             theName.Type(TNaming_GENERATION);
1094             theName.Append(TNaming_Tool::NamedShape(Selection,F));
1095             theName.Append(NewNS);
1096             Naming->Regenerate(MDF.ChangeValid());
1097             Naming->Label().FindAttribute(TNaming_NamedShape::GetID(),NS);
1098
1099           }
1100           Filter (F,MDF,Selection,Context,Localizer,NS,0);
1101         }
1102       }
1103       if (StandardFilter) if (!Compare (NS,MDF,Stop,Selection)) {
1104         Filter (F,MDF,Selection,Context,Localizer,NS,0);
1105       }
1106     }
1107   }
1108   if (MDF.WithValid()) MDF.Valid(NS->Label());
1109 #ifdef OCCT_DEBUG_MOD
1110     if(!NS.IsNull()) {
1111       TCollection_AsciiString E;
1112       TDF_Tool::Entry(NS->Label(), E);
1113       cout <<"Returned NS from Label = "<< E << endl;
1114     }
1115 #endif 
1116   return NS;
1117 }
1118
1119 //=======================================================================
1120 //function : Validate
1121 //purpose  : 
1122 //=======================================================================
1123
1124 static void Validate(TNaming_Scope&    MDF,
1125                      TNaming_OldShapeIterator& it)
1126 {
1127   MDF.Valid(it.Label()); 
1128   MDF.ValidChildren(it.Label());
1129
1130   TNaming_OldShapeIterator it2(it);
1131   for (; it2.More(); it2.Next()) {
1132     Validate (MDF,it2);
1133   }
1134 }
1135
1136 //=======================================================================
1137 //function : UnValidate
1138 //purpose  : 
1139 //=======================================================================
1140
1141 static void UnValidate(TNaming_Scope&    MDF,
1142                        TNaming_NewShapeIterator& it)
1143 {
1144   MDF.Unvalid(it.Label()); 
1145   MDF.UnvalidChildren(it.Label());
1146
1147   TNaming_NewShapeIterator it2(it);
1148   for (; it2.More(); it2.Next()) {
1149     UnValidate (MDF,it2);
1150   }
1151 }
1152
1153 //=======================================================================
1154 //function : BuildScope
1155 //purpose  : adds to the MDF the label of <Context> NamedShape, 
1156 //         : its children, all its oldShapes and its children.
1157 //         : unvalidates all newShapes and it's children.
1158 //         : If <Context> is null or next modification has an empty newShape 
1159 //         : ( this shape was deleted ), then MDF.WithValid(Standard_False) 
1160 //         : and nothing is added to the scope.
1161 //=======================================================================
1162
1163 static void BuildScope (TNaming_Scope&    MDF,
1164                              const TopoDS_Shape&    Context,
1165                              const TDF_Label&       Acces) 
1166 {
1167   if (Context.IsNull()) {
1168     MDF.WithValid(Standard_False);
1169     return;
1170   }
1171
1172   //----------------------------------------------------
1173   // Is context the current state
1174   //----------------------------------------------------
1175   Handle(TNaming_NamedShape) NS   = TNaming_Tool::NamedShape(Context,Acces);
1176   Handle(TNaming_NamedShape) Next = NextModif(NS); // if NS has subsequent evolution = MODIFY, return it
1177   if (Next.IsNull()) {  
1178     MDF.WithValid(Standard_False);
1179     return;
1180   }
1181   //----------------------------- 
1182   // a posteriori naming
1183   //-----------------------------  
1184   MDF.WithValid(Standard_True);
1185   MDF.Valid(NS->Label());
1186   MDF.ValidChildren(NS->Label());
1187   TNaming_OldShapeIterator it(Context,Acces);
1188
1189   for (; it.More(); it.Next()) {
1190     Validate(MDF,it);
1191   }
1192
1193   TNaming_NewShapeIterator it2(Context,Acces);
1194   for (;it2.More(); it2.Next()) {
1195     UnValidate (MDF,it2);
1196   }
1197 }
1198
1199 //=======================================================================
1200 //function : HasAncFace
1201 //purpose  : Returns True & <Face> if ancestor face is found
1202 //=======================================================================
1203 static Standard_Boolean HasAncFace(const TopoDS_Shape& Context, 
1204                                    const TopoDS_Shape& W, TopoDS_Shape& Face, Standard_Boolean& isOuter)
1205
1206   Standard_Boolean hasFace(Standard_False);
1207   if(W.ShapeType() != TopAbs_WIRE)
1208     return hasFace;
1209   TopExp_Explorer exp(Context, TopAbs_FACE);
1210   for(;exp.More(); exp.Next()) {
1211     for (TopoDS_Iterator it(exp.Current()) ; it.More(); it.Next()) {
1212       if(it.Value().IsEqual(W)) {// is the Wire ?
1213             Face = exp.Current();
1214             if(!Face.IsNull()) {
1215               hasFace = Standard_True;
1216         //        cout << "HasAncFace: TS = " <<theFace.TShape()->This() <<endl;
1217                   const TopoDS_Face aFace(TopoDS::Face(Face));
1218                   TopoDS_Wire anOuterW; 
1219                   if(TNaming::OuterWire(aFace, anOuterW)) {
1220                     if(!anOuterW.IsNull() && anOuterW.IsEqual(W)) 
1221                           isOuter = Standard_True;
1222                     else 
1223                           isOuter = Standard_False;             
1224                   }
1225               break;                              
1226                 }
1227           }
1228         }
1229     if(hasFace) break;
1230   }
1231   return hasFace;
1232 }
1233
1234 //=======================================================================
1235 //function : BuildNameWire
1236 //purpose  : Names Wire
1237 //=======================================================================
1238
1239 static Handle(TNaming_NamedShape) BuildNameWire (const TDF_Label&                  F,
1240                                                  TNaming_Scope&                    MDF,
1241                                                  const TopoDS_Shape&               Selection,
1242                                                  const TopoDS_Shape&               Context,
1243                                                  const Handle(TNaming_NamedShape)& Stop,
1244                                                  const Standard_Boolean            Geom)
1245 {  
1246   Handle (TNaming_NamedShape) NS;
1247   Standard_Boolean found(Standard_False);
1248   Handle (TNaming_Naming)  Naming;
1249   if(!F.FindAttribute(TNaming_Naming::GetID(), Naming)) {
1250     Naming = new TNaming_Naming ();
1251     F.AddAttribute (Naming);
1252     TNaming_Name& theName = Naming->ChangeName();
1253     theName.ShapeType(Selection.ShapeType());
1254     theName.Shape(Selection);
1255         theName.Orientation(Selection.Orientation());
1256   } 
1257
1258   TNaming_Name& theName = Naming->ChangeName();  
1259   TopoDS_Shape aFace;
1260   Standard_Boolean isOuter(Standard_False);
1261   Standard_Boolean hasFace = HasAncFace(Context, Selection, aFace, isOuter);  
1262   if(hasFace && Selection.ShapeType() > Context.ShapeType()) {
1263     theName.Type(TNaming_WIREIN);
1264         if(Context.ShapeType() == TopAbs_FACE) {
1265                 for (TopoDS_Iterator it(Context) ; it.More(); it.Next()) {
1266                   if(it.Value().IsEqual(Selection)) {
1267                 if (TNaming_Selector::IsIdentified (F, Context, NS, Geom)) {            
1268                   theName.Append(NS);
1269                   found = Standard_True;
1270                   break;
1271                         }
1272                   }
1273           }
1274                 if(found) {
1275                   theName.Append(BuildName (Naming->Label(),MDF,aFace,Context,Stop,Geom));
1276                   if(isOuter) {
1277                     theName.Index(1);
1278                   } else {
1279                           theName.Index(-1);
1280                           for (TopExp_Explorer exp(Selection,TopAbs_EDGE) ; exp.More(); exp.Next()) {
1281                             if(exp.Current().IsNull()) continue;
1282                             if (BRep_Tool::Degenerated(TopoDS::Edge(exp.Current()))) continue;
1283                              theName.Append(TNaming_Naming::Name(Naming->Label(),exp.Current(),Context, Geom, 1, 0));
1284                           }
1285                   }
1286                 } else
1287                return BuildNS (F,Selection, TNaming_UNKNOWN);
1288
1289         } else { // context is not Face
1290                 theName.Append(BuildName (Naming->Label(),MDF,aFace,Context,Stop,Geom));
1291                 if(isOuter) {
1292                 theName.Index(1);
1293                 } else {
1294                         for (TopExp_Explorer exp(Selection,TopAbs_EDGE) ; exp.More(); exp.Next()) {
1295                           if(exp.Current().IsNull()) continue;
1296                           if (BRep_Tool::Degenerated(TopoDS::Edge(exp.Current()))) continue;
1297                            theName.Append(TNaming_Naming::Name(Naming->Label(),exp.Current(),Context, Geom, 1, 0));
1298                         }
1299                 }
1300         }//
1301   } 
1302   else { // => no Face
1303     theName.Type(TNaming_UNION);
1304     for (TopExp_Explorer exp(Selection,TopAbs_EDGE) ; exp.More(); exp.Next()) {
1305           if(exp.Current().IsNull()) continue;
1306       if (BRep_Tool::Degenerated(TopoDS::Edge(exp.Current()))) continue;
1307       theName.Append(BuildName (Naming->Label(),MDF,exp.Current(),Context,Stop,Geom));
1308     }
1309   }
1310   //Naming->GetName().Solve(Naming->Label(),MDF.GetValid());
1311   Naming->Label().FindAttribute(TNaming_NamedShape::GetID(),NS);  
1312   return NS;
1313 }
1314
1315 //=======================================================================
1316 static Standard_Boolean IsOneIn (const TopoDS_Shape& S, const TopoDS_Shape& Context)
1317 {
1318   Standard_Boolean found(Standard_False);
1319   if(S.IsNull() || Context.IsNull()) return found;
1320   for (TopExp_Explorer exp(Context,S.ShapeType()); exp.More(); exp.Next()) {
1321     if (exp.Current().IsEqual(S)) {
1322       found = Standard_True;
1323       break;
1324     }
1325   }
1326   return found;
1327 }
1328
1329 //=======================================================================
1330 static Standard_Boolean IsAllIn (const TopoDS_Shape& S, const TopoDS_Shape& Context)
1331 {
1332 #ifdef OCCT_DEBUG_CC
1333   Write(S, "IsAllIn_Sel.brep");
1334 #endif
1335   Standard_Boolean found(Standard_False);
1336   if(S.IsNull() || Context.IsNull()) return found;
1337   Standard_Integer num1(0), num2(0);
1338   for(TopoDS_Iterator it(S);it.More();it.Next(),num1++) {
1339 #ifdef OCCT_DEBUG_CC
1340   cout <<"S sub-shape type = " << it.Value().ShapeType() <<endl;
1341   Write (it.Value(), "Sel_ItValue.brep");
1342 #endif
1343   if(it.Value().ShapeType() != TopAbs_COMPOUND)
1344     for (TopExp_Explorer exp(Context,it.Value().ShapeType()); exp.More(); exp.Next()) {
1345 #ifdef OCCT_DEBUG_CC
1346   cout <<"Context sub-shape type = " << exp.Current().ShapeType() <<endl;
1347   Write(exp.Current(), "Contex_Curnt.brep");
1348 #endif
1349       if (exp.Current().IsEqual(it.Value())) { 
1350         num2++;
1351         break;
1352       }
1353     } else {
1354       Standard_Boolean isAll = IsAllIn(it.Value(), Context);
1355       if(isAll) 
1356         num2++;
1357     }
1358   }
1359   if(num1 == num2)
1360     found = Standard_True;
1361 #ifdef OCCT_DEBUG_CC
1362   else
1363     cout <<"Compound case : selected num1 = " << num1 << " context contains num2 = " << num2 << endl;
1364 #endif
1365   return found;
1366 }
1367 //=======================================================================
1368 //function : RepeatabilityInContext
1369 //purpose  : 
1370 //=======================================================================
1371 static Standard_Integer RepeatabilityInContext(const TopoDS_Shape& Selection, 
1372                                                const TopoDS_Shape& Context)
1373 {
1374   Standard_Integer aNum(0);
1375   if (!Context.IsNull() && !Selection.IsNull()) {
1376 //    Write(Selection, "Repeat_Selection.brep");
1377 //    Write(Context, "Repeat_Context.brep");
1378     if (Context.ShapeType() < Selection.ShapeType()) {
1379           if(Selection.ShapeType() != TopAbs_SHELL) {
1380         for (TopExp_Explorer exp(Context,Selection.ShapeType()); exp.More(); exp.Next()) {
1381               if (exp.Current().IsSame(Selection)) 
1382                 aNum++;
1383                 }
1384           } 
1385         }
1386     else if(Selection.ShapeType() == TopAbs_COMPOUND) {
1387       TopoDS_Iterator it(Selection);
1388       for(;it.More();it.Next()) {
1389         Standard_Integer n(0);
1390         for (TopExp_Explorer exp(Context,it.Value().ShapeType()); exp.More(); exp.Next()) {
1391           if (exp.Current().IsSame(it.Value())) {
1392             n++;
1393           }
1394         }
1395         if(n > aNum) aNum = n;
1396       }
1397     } 
1398   }
1399 #ifdef OCCT_DEBUG_OR
1400       cout <<"RepeatabilityInContext: = " <<aNum <<endl;
1401 #endif 
1402   return aNum;
1403 }
1404
1405 //=======================================================================
1406 //function : HasAncSolid
1407 //purpose  : Returns true if Sh has ancestor solid in this context
1408 //=======================================================================
1409 static Standard_Boolean HasAncSolid(const TopoDS_Shape& Context, 
1410                                                const TopoDS_Shape& Sh, TopoDS_Shape& Solid, 
1411                                                Standard_Boolean& isOuter)
1412
1413   Standard_Boolean hasSolid(Standard_False);
1414   if(Sh.ShapeType() != TopAbs_SHELL)
1415     return hasSolid;
1416   TopExp_Explorer exp(Context, TopAbs_SOLID);
1417   for(;exp.More(); exp.Next()) {
1418     for (TopoDS_Iterator it(exp.Current()) ; it.More(); it.Next()) {
1419       if(it.Value().IsEqual(Sh)) {// is the Solid ?
1420             Solid = exp.Current();
1421             if(!Solid.IsNull()) {
1422               hasSolid = Standard_True;
1423                   TopoDS_Shell anOuterShell;            
1424                   if(TNaming::OuterShell(TopoDS::Solid(Solid), anOuterShell)) {
1425 #ifdef OCCT_DEBUG_TSOL
1426                 Write(anOuterShell, "OuterShell.brep");
1427 #endif
1428                     if(!anOuterShell.IsNull() && anOuterShell.IsEqual(Sh))
1429                           isOuter = Standard_True;
1430                     else 
1431                           isOuter = Standard_False;
1432                   }
1433               break;
1434                 }
1435           }
1436         }
1437     if(hasSolid) break;
1438   }
1439   return hasSolid;
1440 }
1441 //=======================================================================
1442 //function : BuildNameShell
1443 //purpose  : Names Shell
1444 //=======================================================================
1445
1446 static Handle(TNaming_NamedShape) BuildNameShell (const TDF_Label& F,
1447                                                  TNaming_Scope&                    MDF,
1448                                                  const TopoDS_Shape&               Selection,
1449                                                  const TopoDS_Shape&               Context,
1450                                                  const Handle(TNaming_NamedShape)& Stop,
1451                                                  const Standard_Boolean            Geom)
1452 {  
1453   Handle (TNaming_NamedShape) NS;
1454   Standard_Boolean found(Standard_False);
1455   Handle (TNaming_Naming)  Naming;
1456   if(!F.FindAttribute(TNaming_Naming::GetID(), Naming)) {
1457     Naming = new TNaming_Naming ();
1458     F.AddAttribute (Naming);
1459     TNaming_Name& theName = Naming->ChangeName();
1460     theName.ShapeType(Selection.ShapeType());
1461     theName.Shape(Selection);
1462         theName.Orientation(Selection.Orientation());
1463   } 
1464
1465   TNaming_Name& theName = Naming->ChangeName(); 
1466   TopoDS_Shape aSolid;
1467   Standard_Boolean isOuter(Standard_False);
1468   Standard_Boolean hasSolid = HasAncSolid(Context, Selection, aSolid, isOuter);  
1469   if(hasSolid && Selection.ShapeType() > Context.ShapeType()) {
1470     theName.Type(TNaming_SHELLIN);// SHELLIN
1471
1472         if(Context.ShapeType() == TopAbs_SOLID) {
1473                 for (TopoDS_Iterator it(Context) ; it.More(); it.Next()) {
1474 #ifdef OCCT_DEBUG_TSOL
1475           Write(it.Value(), "Shell_inSo.brep");
1476 #endif
1477                 if(it.Value().IsEqual(Selection)) {
1478                 found = Standard_True;
1479                 break;
1480                   }
1481           }
1482           if(found) {
1483                 // solid => aSolid which is also a context
1484                   Handle(TNaming_NamedShape) aNS = TNaming_Tool::NamedShape(Context,F);
1485                   if(!aNS.IsNull())
1486                         theName.ContextLabel(aNS->Label());       
1487                   theName.Append(aNS);
1488                   if(isOuter) {
1489                     theName.Index(1);                            
1490                   } else { //not OuterShell
1491             theName.Index(-1);
1492                         for (TopExp_Explorer exp(Selection,TopAbs_FACE) ; exp.More(); exp.Next()) {
1493                           if(exp.Current().IsNull()) continue;
1494                           theName.Append(BuildName (Naming->Label(),MDF,exp.Current(),Context,Stop,Geom));
1495                         }
1496                   }
1497           } else
1498                   return BuildNS (F,Selection, TNaming_UNKNOWN);
1499         } else { 
1500         // context is not SOLID
1501                 //theName.Append(BuildName (Naming->Label(),MDF,aSolid,Context,Stop,Geom));//###########                
1502                 if(isOuter) {
1503 #ifdef OCCT_DEBUG_TSOL
1504           Write(aSolid, "foundSolid.brep");
1505 #endif
1506                   theName.Index(1);
1507                   Handle (TNaming_Naming)  NamingSo = TNaming_Naming::Insert(F); 
1508                   TNaming_Name&           theNameSo = NamingSo->ChangeName();
1509           theNameSo.ShapeType(aSolid.ShapeType());
1510           theNameSo.Shape(aSolid);       
1511           theNameSo.Type(TNaming_UNION);
1512                   Handle(TNaming_NamedShape) aNS = TNaming_Tool::NamedShape(Context,F);
1513                   if(!aNS.IsNull())
1514                         theNameSo.ContextLabel(aNS->Label());
1515               for (TopExp_Explorer exp(aSolid,TopAbs_FACE) ; exp.More(); exp.Next()) 
1516                 theNameSo.Append(BuildName (NamingSo->Label(),MDF,exp.Current(),Context,Stop,Geom));
1517                   NamingSo->GetName().Solve(NamingSo->Label(),MDF.GetValid());
1518                   aNS.Nullify();
1519                   NamingSo->Label().FindAttribute(TNaming_NamedShape::GetID(),aNS); 
1520                   theName.Append(aNS);
1521                 } else {
1522                         theName.Index(-1);
1523                         // - name Solid: theName.Append(BuildName (Naming->Label(),MDF, aSolid,Context,Stop,Geom));
1524                     Handle (TNaming_Naming)  NamingSo = TNaming_Naming::Insert(F); 
1525                     TNaming_Name&           theNameSo = NamingSo->ChangeName();
1526             theNameSo.ShapeType(aSolid.ShapeType());
1527             theNameSo.Shape(aSolid);       
1528             theNameSo.Type(TNaming_UNION);
1529                     Handle(TNaming_NamedShape) aNS = TNaming_Tool::NamedShape(Context,F);
1530                     if(!aNS.IsNull())
1531                           theNameSo.ContextLabel(aNS->Label());
1532                 for (TopExp_Explorer exp(aSolid,TopAbs_FACE) ; exp.More(); exp.Next()) 
1533                   theNameSo.Append(BuildName (NamingSo->Label(),MDF,exp.Current(),Context,Stop,Geom));                  
1534                         NamingSo->GetName().Solve(NamingSo->Label(),MDF.GetValid());
1535                         aNS.Nullify();
1536                         NamingSo->Label().FindAttribute(TNaming_NamedShape::GetID(),aNS); 
1537                     theName.Append(aNS);
1538
1539                         for (TopExp_Explorer exp(Selection,TopAbs_FACE) ; exp.More(); exp.Next()) {
1540                           if(exp.Current().IsNull()) continue;
1541                           theName.Append(BuildName (Naming->Label(),MDF,exp.Current(),Context,Stop,Geom));
1542                         }
1543                 }
1544         }//
1545   } 
1546   else { // => no Solid
1547     theName.Type(TNaming_UNION);
1548         Handle(TNaming_NamedShape) aNS = TNaming_Tool::NamedShape(Context,F);
1549         if(!aNS.IsNull())
1550           theName.ContextLabel(aNS->Label());
1551     for (TopExp_Explorer exp(Selection,TopAbs_FACE) ; exp.More(); exp.Next()) {
1552           if(exp.Current().IsNull()) continue;     
1553       theName.Append(BuildName (Naming->Label(),MDF,exp.Current(),Context,Stop,Geom));
1554     }
1555   }
1556   //Naming->GetName().Solve(Naming->Label(),MDF.GetValid());
1557   Naming->Label().FindAttribute(TNaming_NamedShape::GetID(),NS);  
1558   return NS;
1559 }
1560
1561 //=======================================================================
1562 //function : BuildAggregationNam
1563 //purpose  : 
1564 //=======================================================================
1565 static void BuildAggregationName (const TDF_Label&                  F,
1566                                   TNaming_Scope&                    MDF,
1567                                   const TopoDS_Shape&               S,
1568                                   const TopoDS_Shape&               Context,
1569                                   const Handle(TNaming_NamedShape)& Stop,
1570                                   const Standard_Boolean            Geom)
1571 {
1572   const Standard_Boolean found2 = IsAllIn(S, Context); 
1573   Handle (TNaming_Naming)  Naming;
1574   if(!F.FindAttribute(TNaming_Naming::GetID(), Naming)) {
1575     Naming = new TNaming_Naming ();
1576     F.AddAttribute (Naming);
1577     TNaming_Name& theName = Naming->ChangeName();
1578     theName.ShapeType(S.ShapeType());
1579     theName.Shape(S); 
1580         theName.Orientation(S.Orientation());
1581   } 
1582 #ifdef OCCT_DEBUG_CC
1583   cout <<"BuildAggregationName ==> ";
1584   Print_Entry(Naming->Label());
1585 #endif
1586   TNaming_Name& theName = Naming->ChangeName();  
1587   for (TopoDS_Iterator itc(S) ; itc.More(); itc.Next()) {
1588     const TopoDS_Shape& aS = itc.Value();
1589     if ((aS.ShapeType() == TopAbs_SOLID && !TNaming_Tool::NamedShape(aS,Naming->Label()).IsNull()) ||
1590         aS.ShapeType() == TopAbs_FACE  ||
1591         aS.ShapeType() == TopAbs_EDGE  ||
1592         aS.ShapeType() == TopAbs_VERTEX ) {
1593       theName.Append(BuildName (F, MDF, aS,Context,Stop,Geom));
1594     } else { // ==> union of union || union of wires
1595       TopAbs_ShapeEnum atomTyp; 
1596       switch (aS.ShapeType()) 
1597         {
1598         case TopAbs_SOLID:
1599         case TopAbs_SHELL:
1600           atomTyp = TopAbs_FACE;
1601           break;
1602         case TopAbs_WIRE:
1603           atomTyp = TopAbs_EDGE;
1604           break;
1605         default: 
1606           atomTyp = TopAbs_SHAPE;
1607         }
1608       
1609       Handle(TNaming_NamedShape) aNS;
1610       Handle (TNaming_Naming)  aNaming = TNaming_Naming::Insert(F); 
1611       TNaming_Name&               aName = aNaming->ChangeName();          
1612       aName.ShapeType(aS.ShapeType());
1613       aName.Shape(aS);
1614           theName.Orientation(aS.Orientation());
1615       aName.Type(TNaming_UNION);
1616       
1617       if (atomTyp != TopAbs_SHAPE) {
1618         if(aS.ShapeType() == TopAbs_WIRE) {
1619           aNS = BuildNameWire (aNaming->Label(), MDF, aS, Context,Stop,Geom);
1620         }
1621          else if(aS.ShapeType() == TopAbs_SHELL) 
1622             aNS = BuildNameShell (aNaming->Label(), MDF, aS, Context,Stop,Geom);
1623         else {
1624           for (TopExp_Explorer exp(aS,atomTyp) ; exp.More(); exp.Next()) {
1625             aName.Append(BuildName (aNaming->Label(),MDF,exp.Current(),Context,Stop,Geom));
1626           }
1627         }
1628       } else {
1629 #ifdef OCCT_DEBUG_CC
1630         cout << "atomic type is NOT defined ... ==> Aggregation" <<endl;
1631 #endif
1632         BuildAggregationName(aNaming->Label(),MDF, aS, Context,Stop,Geom);
1633       }
1634       if(found2) {
1635         aNS = TNaming_Tool::NamedShape(Context, F);
1636         if(!aNS.IsNull()) 
1637           aNaming->ChangeName().ContextLabel(aNS->Label());
1638       }
1639       
1640       aNaming->GetName().Solve(aNaming->Label(),MDF.GetValid());
1641       if(aNaming->Label().FindAttribute(TNaming_NamedShape::GetID(),aNS))
1642         if (!Geom && TestSolution(MDF,aNS,aS)) {
1643           theName.Append(aNS);
1644         }
1645     }
1646   }
1647 }
1648
1649
1650 //=======================================================================
1651 //function : Name
1652 //purpose  : 
1653 //=======================================================================
1654
1655 Handle(TNaming_NamedShape) TNaming_Naming::Name (const TDF_Label&       F,
1656                                                  const TopoDS_Shape&    S,
1657                                                  const TopoDS_Shape&    Context,
1658                                                  const Standard_Boolean Geom,
1659                                                  const Standard_Boolean KeepOrientation,
1660                                                  const Standard_Boolean BNProblem)
1661
1662 {
1663   Handle(TNaming_NamedShape) NS;
1664   if (KeepOrientation) {
1665 #ifdef OCCT_DEBUG_INNS
1666     cout <<"KeepOR = 1: "; Print_Entry(F);
1667 #endif
1668     Standard_Integer aNum = RepeatabilityInContext(S, Context);
1669
1670     Standard_Boolean aBNproblem = (BNProblem) ? (aNum /*== 1*/ && S != Context) : Standard_False;
1671
1672     if (aNum > 1 || aBNproblem) {
1673       TopoDS_Shape UC = TNaming::FindUniqueContext(S, Context);
1674       Handle(TopTools_HArray1OfShape) Arr;
1675       if (UC.IsNull() && S.ShapeType() == TopAbs_COMPOUND) {
1676         UC = TNaming::FindUniqueContextSet(S, Context, Arr);
1677 #ifdef OCCT_DEBUG_CC
1678         Write(UC, "UniqueContextSet.brep");
1679         Write(S,  "InitialSelection.brep");
1680         if(S.ShapeType()==TopAbs_COMPOUND) {
1681           TCollection_AsciiString aNam("S_");
1682           TopoDS_Iterator it(S);
1683           for(int i=1;it.More();it.Next(),i++) {           
1684             TCollection_AsciiString aName = aNam + i + ".brep";     
1685             Write(it.Value(), aName.ToCString());
1686           }
1687         }
1688 #endif  
1689       }
1690       if(!UC.IsNull()) {
1691         Handle (TNaming_Naming)  Naming = TNaming_Naming::Insert(F);
1692         TNaming_Name&           theName = Naming->ChangeName();
1693         theName.ShapeType(S.ShapeType());
1694         theName.Shape(S); 
1695         theName.Type(TNaming_ORIENTATION);
1696         theName.Orientation(S.Orientation());
1697
1698         if (!TNaming_Selector::IsIdentified (F, S, NS, Geom)) 
1699           NS = TNaming_Naming::Name(Naming->Label(),S,Context,Geom,0);
1700         theName.Append (NS);
1701 #ifdef MDTV_OR
1702         cout << " Sel Label ==> "; Print_Entry(NS->Label());
1703 #endif
1704 //szy 21.10.2009        
1705         if(S.ShapeType() == TopAbs_EDGE && UC.ShapeType() == TopAbs_FACE) {
1706           if(RepeatabilityInContext(S, UC) == 2) { //sim. edge
1707             TopoDS_Iterator itw(UC);
1708             for(;itw.More();itw.Next()) {
1709               Standard_Boolean found(Standard_False);
1710               TopoDS_Iterator it(itw.Value());
1711               for(int i=1;it.More();it.Next(),i++) {
1712                 if(it.Value().IsEqual(S)) {
1713                   theName.Index(i);//We use this field to save a Seam Shape Index; Before this field was used for GENERATED only
1714                   found = Standard_True;
1715 #ifdef MDTV_OR
1716                   cout << "ORDER = " << i <<endl;
1717 #endif
1718                   break;
1719                 }
1720               }
1721               if(found) break;
1722             }
1723           }
1724         }
1725 //      
1726         if(S.ShapeType() == TopAbs_COMPOUND && Arr->Length() > 1) {
1727           // N arguments: to be optimized to avoid duplication of the same Context shape
1728           for(Standard_Integer i = Arr->Lower(); i <= Arr->Upper(); i++) {
1729             NS = TNaming_Naming::Name(Naming->Label(), Arr->Value(i), Context, Geom, 1, aBNproblem);
1730             theName.Append (NS);
1731           }
1732         } else {          
1733           NS = TNaming_Naming::Name(Naming->Label(),UC,Context, Geom, 1, aBNproblem);
1734           theName.Append (NS);
1735 #ifdef MDTV_OR
1736         cout << " Cont Label ==> "; Print_Entry(NS->Label());
1737 #endif
1738         }
1739       //Naming->Update();
1740         TNaming_Scope MDF;
1741         BuildScope (MDF,Context,F);
1742         Naming->GetName().Solve(Naming->Label(),MDF.GetValid());
1743         Naming->Label().FindAttribute(TNaming_NamedShape::GetID(),NS);
1744         theName.ContextLabel(NS->Label());
1745         if (Geom) return NS;
1746         if(NS.IsNull()) {
1747         cout <<" %%% WARNING: TNaming_Naming::Name:  FAILED"<<endl;
1748         return BuildNS (F,S, TNaming_UNKNOWN);
1749       }
1750
1751         if (!Geom && TestSolution(MDF,NS,S)) return NS;      
1752         cout <<" %%% WARNING: TNaming_Naming::Name:  FAILED"<<endl;
1753
1754         // Naming n is  unsatisfactory
1755         return BuildNS (F,S, TNaming_UNKNOWN);
1756       }
1757     } else
1758       if (TNaming_Selector::IsIdentified (F, S, NS, Geom))
1759         return NS;
1760   }
1761
1762   //------------------------------------------------------------
1763   // Construction du MDF tel que <Context> soit le dernier etat
1764   // valide,
1765   // Ceci pour les localisation a posteriori par exemple. 
1766   //------------------------------------------------------------  
1767
1768   TNaming_Scope MDF;
1769   BuildScope (MDF,Context,F);
1770   Handle(TNaming_NamedShape) Stop;
1771
1772
1773   if ((S.ShapeType() == TopAbs_SOLID && !TNaming_Tool::NamedShape(S,F).IsNull()) ||
1774
1775       S.ShapeType() == TopAbs_FACE  ||
1776       S.ShapeType() == TopAbs_EDGE  ||
1777       S.ShapeType() == TopAbs_VERTEX ) {
1778     //---------------------------------------
1779     // Localisation de S comme element simple.
1780     //---------------------------------------
1781     Handle(TNaming_NamedShape) NS = BuildName (F,MDF,S,Context,Stop,Geom);
1782     if (Geom) return NS; 
1783     if (!Geom && TestSolution(MDF,NS,S)) return NS; 
1784   }
1785   else {
1786     //----------------------------------------------------
1787     // Localisation de S comme ensemble d elements simples.
1788     //-----------------------------------------------------
1789     Handle(TNaming_NamedShape) NS;
1790     Handle (TNaming_Naming)  Naming = TNaming_Naming::Insert(F); 
1791     TNaming_Name&           theName = Naming->ChangeName();
1792
1793     theName.ShapeType(S.ShapeType());// modified by vro 05.09.00
1794     theName.Shape(S); 
1795         theName.Orientation(S.Orientation());
1796     if(S.ShapeType() != TopAbs_WIRE) 
1797       theName.Type(TNaming_UNION);
1798
1799     TopAbs_ShapeEnum atomType;
1800     switch (S.ShapeType()) {
1801     case TopAbs_COMPSOLID:
1802     case TopAbs_SOLID:
1803     case TopAbs_SHELL:
1804       atomType = TopAbs_FACE;
1805       break;
1806     case TopAbs_WIRE:
1807       atomType = TopAbs_EDGE;
1808       break;
1809     default:
1810       atomType = TopAbs_SHAPE;
1811     }
1812     Standard_Boolean found(Standard_False);
1813     if (!Context.IsNull()) {
1814       if (Context.ShapeType() < S.ShapeType()) 
1815         found = IsOneIn(S, Context);
1816       if(found) {
1817         NS = TNaming_Tool::NamedShape(Context, F);
1818         if(!NS.IsNull()) 
1819           theName.ContextLabel(NS->Label());
1820       }
1821     }
1822     if (atomType == TopAbs_SHAPE) {
1823       if(S.ShapeType() == TopAbs_COMPOUND) {
1824         BuildAggregationName(Naming->Label(),MDF, S, Context,Stop,Geom);
1825       } else { 
1826         for (TopoDS_Iterator it(S) ; it.More(); it.Next()) {
1827           theName.Append(BuildName (Naming->Label(),MDF,it.Value(),Context,Stop,Geom));
1828         }
1829       }
1830     } else {
1831       if(S.ShapeType() == TopAbs_WIRE)
1832             NS = BuildNameWire (Naming->Label(), MDF, S, Context,Stop,Geom);
1833           else if(S.ShapeType() == TopAbs_SHELL) {
1834                     NS = BuildNameShell (Naming->Label(), MDF, S, Context,Stop,Geom);
1835           }
1836           else {
1837             theName.Type(TNaming_UNION);
1838             for (TopExp_Explorer exp(S,atomType) ; exp.More(); exp.Next()) {
1839             theName.Append(BuildName (Naming->Label(),MDF,exp.Current(),Context,Stop,Geom));
1840                 }
1841           }
1842     }
1843
1844     //Naming->Update(); 
1845     Naming->GetName().Solve(Naming->Label(),MDF.GetValid());
1846     Naming->Label().FindAttribute(TNaming_NamedShape::GetID(),NS);
1847     if (Geom) return NS; 
1848
1849     if(NS.IsNull()) return BuildNS (F,S, TNaming_UNKNOWN); 
1850
1851     if (!Geom && TestSolution(MDF,NS,S)) return NS; 
1852   }
1853   
1854       cout <<" %%% WARNING: TNaming_Naming::Name:  FAILED"<<endl;
1855
1856   // Naming n is not satisfactory
1857   return BuildNS (F,S, TNaming_UNKNOWN); 
1858 }
1859
1860
1861 //=======================================================================
1862 //function : TNaming_Naming
1863 //purpose  : 
1864 //=======================================================================
1865
1866 TNaming_Naming::TNaming_Naming() {}
1867
1868 //=======================================================================
1869 //function : ID
1870 //purpose  : 
1871 //=======================================================================
1872
1873 const Standard_GUID& TNaming_Naming::ID () const
1874 {
1875   return GetID(); 
1876 }
1877
1878
1879 //=======================================================================
1880 //function : IsDefined
1881 //purpose  : 
1882 //=======================================================================
1883
1884 Standard_Boolean TNaming_Naming::IsDefined() const
1885 {
1886   return (myName.Type() != TNaming_UNKNOWN);
1887 }
1888
1889 //=======================================================================
1890 //function : GetName
1891 //purpose  : 
1892 //=======================================================================
1893
1894 const TNaming_Name& TNaming_Naming::GetName() const
1895 {
1896   return myName;
1897 }
1898
1899 //=======================================================================
1900 //function : ChangeName
1901 //purpose  : 
1902 //=======================================================================
1903
1904 TNaming_Name& TNaming_Naming::ChangeName()
1905 {
1906   return myName;
1907 }
1908
1909 //=======================================================================
1910 //function : Regenerate
1911 //purpose  : idem designer
1912 //=======================================================================
1913
1914 Standard_Boolean TNaming_Naming::Regenerate (TDF_LabelMap& MDF)  
1915
1916 {
1917   return myName.Solve(Label(),MDF);
1918 }
1919
1920
1921 //=======================================================================
1922 //function : NewEmpty
1923 //purpose  : 
1924 //=======================================================================
1925
1926 Handle(TDF_Attribute) TNaming_Naming::NewEmpty () const
1927 {  
1928   return new TNaming_Naming (); 
1929 }
1930
1931
1932 //=======================================================================
1933 //function : Restore
1934 //purpose  : 
1935 //=======================================================================
1936
1937 void TNaming_Naming::Restore(const Handle(TDF_Attribute)& other) 
1938 {
1939   Handle(TNaming_Naming) OtherNaming = Handle(TNaming_Naming)::DownCast(other);
1940   myName = OtherNaming->ChangeName();
1941 }
1942
1943 //=======================================================================
1944 //function : Paste
1945 //purpose  : 
1946 //=======================================================================
1947
1948 void TNaming_Naming::Paste (const Handle(TDF_Attribute)& into,
1949                                const Handle(TDF_RelocationTable)& RT) const
1950 {
1951   Handle(TNaming_Naming) NewNaming = Handle(TNaming_Naming)::DownCast(into);
1952   myName.Paste(NewNaming->ChangeName(),RT);
1953 }
1954   
1955 //=======================================================================
1956 //function : References
1957 //purpose  : Redefined from TDF_Attribute
1958 //=======================================================================
1959
1960 void TNaming_Naming::References(const Handle(TDF_DataSet)& DataSet) const
1961 {
1962   // Iteration on NamedShape of the name
1963   TNaming_ListIteratorOfListOfNamedShape it(myName.Arguments());
1964   for (;it.More();it.Next()) DataSet->AddAttribute(it.Value());
1965   if (!myName.StopNamedShape().IsNull()) DataSet->AddAttribute(myName.StopNamedShape());
1966 }
1967 //=======================================================================
1968 //function : Dump
1969 //purpose  : 
1970 //=======================================================================
1971
1972 Standard_OStream& TNaming_Naming::Dump (Standard_OStream& anOS) const
1973 {  
1974   anOS << "TNaming_Naming";
1975   return anOS;
1976 }
1977
1978
1979 //=======================================================================
1980 //function :ExtendedDump
1981 //purpose  : 
1982 //=======================================================================
1983
1984 void TNaming_Naming::ExtendedDump(Standard_OStream& anOS,
1985                                   const TDF_IDFilter& /*aFilter*/,
1986                                   TDF_AttributeIndexedMap& /*aMap*/) const
1987 {
1988   anOS << "TNaming_Naming ExtendedDump  ";
1989   //anOS<<"myContext: #" <<aMap.Add(myContext)<<endl; 
1990 }
1991