0024792: Remove unused hacks for compilers without STL
[occt.git] / src / XCAFDoc / XCAFDoc_ShapeTool.cxx
1 // Created on: 2000-08-03
2 // Created by: data exchange team
3 // Copyright (c) 2000-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <XCAFDoc_ShapeTool.ixx>
17 #include <XCAFDoc.hxx>
18
19 #include <TDF_Tool.hxx>
20 #include <TDF_Label.hxx>
21 #include <TDF_LabelMap.hxx>
22 #include <TDF_LabelSequence.hxx>
23 #include <TDF_ChildIterator.hxx>
24 #include <TDF_ChildIDIterator.hxx>
25 #include <TDF_MapIteratorOfLabelMap.hxx>
26
27 #include <TDataStd_Name.hxx>
28 #include <TDataStd_TreeNode.hxx>
29 #include <TDataStd_ChildNodeIterator.hxx>
30 #include <TDataStd_UAttribute.hxx>
31
32 #include <TDocStd_Document.hxx>
33
34 #include <TNaming_Builder.hxx>
35 #include <TNaming_NamedShape.hxx>
36 #include <TNaming_Tool.hxx>
37
38 #include <TopLoc_Location.hxx>
39 #include <TopoDS_Iterator.hxx>
40 #include <TopoDS_Shape.hxx>
41 #include <TopoDS_Compound.hxx>
42 #include <BRep_Builder.hxx>
43 #include <XCAFDoc_Location.hxx>
44
45 #include <TCollection_AsciiString.hxx>
46 #include <TCollection_HAsciiString.hxx>
47 #include <TCollection_ExtendedString.hxx>
48 #include <TColStd_SequenceOfHAsciiString.hxx>
49 #include <XCAFDoc_GraphNode.hxx>
50 #include <TopLoc_IndexedMapOfLocation.hxx>
51 #include <gp_Trsf.hxx>
52 #include <gp_Pnt.hxx>
53 #include <XCAFDoc_ShapeMapTool.hxx>
54
55 static Standard_Boolean theAutoNaming = Standard_True;
56
57 // attribute methods //////////////////////////////////////////////////
58
59 //=======================================================================
60 //function : GetID
61 //purpose  : 
62 //=======================================================================
63
64 const Standard_GUID& XCAFDoc_ShapeTool::GetID() 
65 {
66   static Standard_GUID ShapeToolID ("efd212ee-6dfd-11d4-b9c8-0060b0ee281b");
67   return ShapeToolID; 
68 }
69
70
71 //=======================================================================
72 //function : Set
73 //purpose  : 
74 //=======================================================================
75
76 Handle(XCAFDoc_ShapeTool) XCAFDoc_ShapeTool::Set(const TDF_Label& L) 
77 {
78   Handle(XCAFDoc_ShapeTool) A;
79   if (!L.FindAttribute (XCAFDoc_ShapeTool::GetID(), A)) {
80     A = new XCAFDoc_ShapeTool ();
81     L.AddAttribute(A);
82   }
83   A->Init();
84   return A;
85 }
86
87
88 //=======================================================================
89 //function : Constructor
90 //purpose  : 
91 //=======================================================================
92
93 XCAFDoc_ShapeTool::XCAFDoc_ShapeTool()
94 {
95   hasSimpleShapes = Standard_False;
96 }
97
98
99 //=======================================================================
100 //function : ID
101 //purpose  : 
102 //=======================================================================
103
104 const Standard_GUID& XCAFDoc_ShapeTool::ID() const
105 {
106   return GetID();
107 }
108
109 //=======================================================================
110 //function : Restore
111 //purpose  : 
112 //=======================================================================
113
114 void XCAFDoc_ShapeTool::Restore(const Handle(TDF_Attribute)& /*with*/) 
115 {
116 }
117
118 //=======================================================================
119 //function : NewEmpty
120 //purpose  : 
121 //=======================================================================
122
123 Handle(TDF_Attribute) XCAFDoc_ShapeTool::NewEmpty() const
124 {
125   return new XCAFDoc_ShapeTool;
126 }
127
128 //=======================================================================
129 //function : Paste
130 //purpose  : 
131 //=======================================================================
132
133 void XCAFDoc_ShapeTool::Paste (const Handle(TDF_Attribute)& /*into*/,
134                                const Handle(TDF_RelocationTable)& /*RT*/) const
135 {
136 }
137
138 // Auxiliary methods //////////////////////////////////////////////////
139
140 //=======================================================================
141 //function : SetLabelNameByLink
142 //purpose  : 
143 //=======================================================================
144 static void SetLabelNameByLink(const TDF_Label L) 
145 {
146   Handle(TDataStd_TreeNode) Node;
147   if (! L.FindAttribute(XCAFDoc::ShapeRefGUID(), Node) ||
148       ! Node->HasFather()) {
149     cout<<"Error: XCAFDoc_ShapeTool, SetLabelNameByLink(): NO NODE"<<endl;
150     return;
151   }
152   TCollection_AsciiString Entry;
153   TDF_Tool::Entry ( Node->Father()->Label(), Entry );
154   Entry.Insert(1, "=>[");
155   Entry += "]";
156
157   TDataStd_Name::Set(L, TCollection_ExtendedString( Entry ));
158 }
159
160
161 //=======================================================================
162 //function : SetLabelNameByShape
163 //purpose  : 
164 //=======================================================================
165 static void SetLabelNameByShape(const TDF_Label L) 
166 {
167   TopoDS_Shape S;
168   if (XCAFDoc_ShapeTool::GetShape(L, S) &&
169       ! L.IsAttribute(TDataStd_Name::GetID()) ) {
170     Standard_SStream Stream;
171 //    TopAbs_ShapeEnum Type = S.ShapeType();
172 //    if (Type == TopAbs_COMPOUND) Stream<<"ASSEMBLY";
173 //    else 
174     TopAbs::Print(S.ShapeType(), Stream);
175     TCollection_AsciiString aName (Stream.str().c_str());
176     TDataStd_Name::Set(L, TCollection_ExtendedString(aName));
177   }
178 }
179
180
181 //=======================================================================
182 //function : SearchUsingMap
183 //purpose  : 
184 //=======================================================================
185
186 Standard_Boolean XCAFDoc_ShapeTool::SearchUsingMap(const TopoDS_Shape &S, TDF_Label &L,
187                                                    const Standard_Boolean findWithoutLoc,
188                                                    const Standard_Boolean findSubShape) const
189 {
190
191   if(myShapeLabels.IsBound(S)) {
192     L = myShapeLabels.Find(S);
193     return Standard_True;
194   }
195   TopoDS_Shape S0 = S;
196   TopLoc_Location loc;
197   S0.Location(loc);
198   if(myShapeLabels.IsBound(S0)) {
199     TDF_Label L1 = myShapeLabels.Find(S0);
200     TDF_LabelSequence Labels;
201     if(GetUsers(L1, Labels, Standard_True)) {
202       for(Standard_Integer i=1; i<=Labels.Length(); i++) {
203         TopoDS_Shape c = GetShape(Labels.Value(i));
204         if(c.IsSame(S)) {
205           L = Labels.Value(i);
206           return Standard_True;
207         }
208       }
209     }
210     if(findWithoutLoc) {
211       L = L1;
212       return Standard_True;
213     }
214   }
215
216   if(hasSimpleShapes) {
217     if(mySimpleShapes.IsBound(S)) {
218       L = mySimpleShapes.Find(S);
219       return Standard_True;
220     }
221     if(mySimpleShapes.IsBound(S0)) {
222       L = mySimpleShapes.Find(S0);
223       return Standard_True;
224     }
225   }
226   // search subshapes
227   if(!findSubShape) return Standard_False;
228   TDF_Label mainL = FindMainShapeUsingMap(S);
229   if(mainL.IsNull()) return Standard_False;
230   L = AddSubShape(mainL,S);
231   return !L.IsNull();//Standard_True;
232 }
233
234
235 //=======================================================================
236 //function : Search
237 //purpose  : 
238 //=======================================================================
239
240 Standard_Boolean XCAFDoc_ShapeTool::Search (const TopoDS_Shape &S, 
241                                          TDF_Label &L,
242                                          const Standard_Boolean findInstance,
243                                          const Standard_Boolean findComponent,
244                                          const Standard_Boolean findSubShape) const
245 {
246   // search among shapes
247   Standard_Boolean isLocated = ! S.Location().IsIdentity();
248   
249   if ( isLocated ) {
250     // try to find top-level instance
251     if ( findInstance && FindShape ( S, L, Standard_True ) )
252       return Standard_True;
253     // try to find component of assembly
254     if ( findComponent ) {
255       TDF_LabelSequence labels;
256       GetShapes ( labels );
257       for ( Standard_Integer i=1; i <= labels.Length(); i++ ) {
258         if ( ! IsAssembly ( labels.Value(i) ) ) continue;
259         TDF_LabelSequence comp;
260         GetComponents ( labels.Value(i), comp );
261         for ( Standard_Integer j=1; j <= comp.Length(); j++ ) {
262           TopoDS_Shape c = GetShape ( comp.Value(j) );
263           if ( c.IsSame ( S ) ) {
264             L = comp.Value(j);
265             return Standard_True;
266           }
267         }
268       }
269     }
270   }
271   // try to find top-level simple shape
272   if ( FindShape ( S, L, Standard_False ) ) return Standard_True;
273   
274   // search subshapes
275   if ( ! findSubShape ) return Standard_False;
276   TDF_Label mainL = FindMainShape ( S );
277   if ( mainL.IsNull() ) return Standard_False;
278   L = AddSubShape ( mainL, S );
279   return !L.IsNull();//Standard_True;
280 }
281
282 //=======================================================================
283 //function : FindShape
284 //purpose  : 
285 //=======================================================================
286
287 Standard_Boolean XCAFDoc_ShapeTool::FindShape (const TopoDS_Shape& S, 
288                                                TDF_Label& L,
289                                                const Standard_Boolean findInstance) const
290 {
291   // search for null-located shape
292   TopoDS_Shape S0 = S;
293   if ( ! findInstance ) {
294     TopLoc_Location loc;
295     S0.Location ( loc );
296   }
297
298   // this code is used instead of the following for performance reasons
299   if (TNaming_Tool::HasLabel(Label(), S0)) {
300     int TransDef = 0;
301     L = TNaming_Tool::Label(Label(), S0, TransDef);
302     return Standard_True;
303   }
304 /*
305   TDF_ChildIDIterator it(myLabel,TNaming_NamedShape::GetID());
306   for (; it.More(); it.Next()) {
307     TDF_Label aLabel = it.Value()->Label();
308     Handle(TNaming_NamedShape) NS;
309     if ( aLabel.FindAttribute(TNaming_NamedShape::GetID(), NS) &&
310          S0.IsSame ( TNaming_Tool::GetShape(NS) ) ) {
311       L = aLabel;
312       return Standard_True;
313     }
314   }
315 */
316   return Standard_False;
317 }
318
319 //=======================================================================
320 //function : FindShape
321 //purpose  : 
322 //=======================================================================
323
324 TDF_Label XCAFDoc_ShapeTool::FindShape (const TopoDS_Shape& S,
325                                      const Standard_Boolean findInstance) const
326 {
327   TDF_Label L;
328   FindShape ( S, L, findInstance );
329   return L;
330 }
331
332 //=======================================================================
333 //function : GetShape
334 //purpose  : 
335 //=======================================================================
336
337 Standard_Boolean XCAFDoc_ShapeTool::GetShape (const TDF_Label& L, TopoDS_Shape& S) 
338 {
339   Handle(XCAFDoc_Location) LocationAttribute;
340
341   if(IsExternRef(L)) {
342     TopoDS_Compound EmptyComp;
343     BRep_Builder B;
344     B.MakeCompound(EmptyComp);
345     S = EmptyComp;
346   }
347
348   // for instance, get referred shape
349   Handle(TDataStd_TreeNode) Node;
350   if ( L.FindAttribute(XCAFDoc::ShapeRefGUID(), Node) && Node->HasFather() && 
351        L.FindAttribute(XCAFDoc_Location::GetID(), LocationAttribute)) {
352     if ( ! GetShape(Node->Father()->Label(), S) ) return Standard_False;
353     S.Move ( LocationAttribute->Get() );
354     return Standard_True;
355   }
356
357   // else just return shape on this label
358   Handle(TNaming_NamedShape) NS;
359   if ( ! L.FindAttribute(TNaming_NamedShape::GetID(), NS) ) return Standard_False;
360   S = TNaming_Tool::GetShape(NS);
361   return Standard_True;
362 }
363
364 //=======================================================================
365 //function : GetShape
366 //purpose  : 
367 //=======================================================================
368
369 TopoDS_Shape XCAFDoc_ShapeTool::GetShape(const TDF_Label& L) 
370 {
371   TopoDS_Shape aShape;
372   GetShape(L,aShape);
373   return aShape;
374 }
375
376 //=======================================================================
377 //function : NewShape
378 //purpose  : 
379 //=======================================================================
380
381 TDF_Label XCAFDoc_ShapeTool::NewShape() const
382 {
383   TopoDS_Compound aShape;
384   BRep_Builder tdsB;
385   tdsB.MakeCompound ( aShape );
386
387   TDF_TagSource aTag;
388   TDF_Label aLabel = aTag.NewChild(Label());
389   
390   TNaming_Builder tnBuild(aLabel);
391   tnBuild.Generated(aShape);
392   
393   return aLabel;
394 }
395
396 //=======================================================================
397 //function : SetShape
398 //purpose  : 
399 //=======================================================================
400
401 void XCAFDoc_ShapeTool::SetShape (const TDF_Label& L, const TopoDS_Shape& S)
402 {
403   TNaming_Builder tnBuild(L);
404   tnBuild.Generated(S);
405   Handle(XCAFDoc_ShapeMapTool) A = XCAFDoc_ShapeMapTool::Set(L);
406 //  if ( ! L.FindAttribute(XCAFDoc_ShapeMapTool::GetID(), A) ) {
407 //    A = XCAFDoc_ShapeMapTool::Set(L);
408 //    L.AddAttribute(A);
409 //  }
410   A->SetShape(S);
411
412   if(!myShapeLabels.IsBound(S)) {
413     myShapeLabels.Bind(S,L);
414   }
415   
416   //:abv 31.10.01: update assemblies that refer a shape
417   TDF_LabelSequence Labels;
418   if ( GetUsers ( L, Labels, Standard_True ) ) {
419     for ( Standard_Integer i=Labels.Length(); i >=1; i-- ) 
420       UpdateAssembly ( Labels(i) );
421   }
422 }
423
424 //=======================================================================
425 //function : MakeReference
426 //purpose  : 
427 //=======================================================================
428
429 void XCAFDoc_ShapeTool::MakeReference (const TDF_Label &L, 
430                                     const TDF_Label &refL,
431                                     const TopLoc_Location &loc)
432 {
433   // store location
434   XCAFDoc_Location::Set(L, loc);
435     
436     // set reference
437   Handle(TDataStd_TreeNode) refNode, mainNode;
438   mainNode = TDataStd_TreeNode::Set ( refL, XCAFDoc::ShapeRefGUID() );
439   refNode  = TDataStd_TreeNode::Set ( L,    XCAFDoc::ShapeRefGUID() );
440   refNode->Remove(); // abv: fix against bug in TreeNode::Append()
441   mainNode->Append(refNode);
442
443   if (theAutoNaming)
444     SetLabelNameByLink(L);
445 }
446
447 //=======================================================================
448 //function : addShape
449 //purpose  : private
450 //=======================================================================
451
452 TDF_Label XCAFDoc_ShapeTool::addShape (const TopoDS_Shape& S, const Standard_Boolean makeAssembly)
453 {
454   TDF_Label ShapeLabel;
455   TDF_TagSource aTag;
456
457   // search if the shape already exists (with the same location)
458   if ( S.IsNull() || FindShape ( S, ShapeLabel, Standard_True ) ) return ShapeLabel;
459   
460   // else add a new label
461   ShapeLabel = aTag.NewChild(Label());
462   
463   // if shape has location, make a reference to the same shape without location
464   if ( ! S.Location().IsIdentity() /*&& FindShape ( S, L )*/ ) {
465     TopoDS_Shape S0 = S;
466     TopLoc_Location loc;
467     S0.Location ( loc );
468     TDF_Label L = addShape ( S0, makeAssembly );
469     MakeReference ( ShapeLabel, L, S.Location() );
470     return ShapeLabel;
471   }
472   
473   // else add a shape to a label
474   TNaming_Builder tnBuild(ShapeLabel);
475   tnBuild.Generated(S);
476   
477   Handle(XCAFDoc_ShapeMapTool) A = XCAFDoc_ShapeMapTool::Set(ShapeLabel);
478 //  if ( ! ShapeLabel.FindAttribute(XCAFDoc_ShapeMapTool::GetID(), A) ) {
479 //    A = XCAFDoc_ShapeMapTool::Set(ShapeLabel);
480 //    ShapeLabel.AddAttribute(A);
481 //  }
482   A->SetShape(S);
483   
484   if (theAutoNaming)
485     SetLabelNameByShape(ShapeLabel);
486
487   // if shape is Compound and flag is set, create assembly
488   if ( makeAssembly && S.ShapeType() == TopAbs_COMPOUND ) {
489     // mark assembly by assigning UAttribute
490     Handle(TDataStd_UAttribute) Uattr;
491     Uattr = TDataStd_UAttribute::Set ( ShapeLabel, XCAFDoc::AssemblyGUID() );
492     if (theAutoNaming)
493       TDataStd_Name::Set(ShapeLabel, TCollection_ExtendedString("ASSEMBLY"));
494
495     // iterate on components
496     TopoDS_Iterator Iterator(S);
497     for (; Iterator.More(); Iterator.Next()) {
498       // get label for component`s shape
499       TopoDS_Shape Scomp = Iterator.Value(), S0 = Scomp;
500       TopLoc_Location loc;
501       S0.Location ( loc );
502       TDF_Label compL = addShape ( S0, makeAssembly );
503       
504       // add a component as reference
505       TDF_Label RefLabel = aTag.NewChild(ShapeLabel);
506       MakeReference ( RefLabel, compL, Scomp.Location() );
507     }
508   }
509   
510   if(!IsAssembly(ShapeLabel)) {
511     //const TopTools_IndexedMapOfShape tmpMap = A->GetMap();
512     //for(Standard_Integer i=1; i<=tmpMap.Extent(); i++)
513     //mySubShapes.Bind(tmpMap.FindKey(i),ShapeLabel);
514     for(Standard_Integer i=1; i<=A->GetMap().Extent(); i++)
515     {
516       TopoDS_Shape aSh = A->GetMap().FindKey(i);
517       mySubShapes.Bind(aSh,ShapeLabel);
518     }
519     //mySubShapes.Bind(ShapeLabel,A->GetMap());
520   }
521
522   return ShapeLabel;
523 }
524
525
526 //=======================================================================
527 //function : prepareAssembly
528 //purpose  : auxilary
529 //=======================================================================
530 static Standard_Boolean prepareAssembly (const TopoDS_Shape& theShape,
531                                          TopoDS_Shape& theOUTShape)
532 {
533   // iterate on components
534   theOUTShape = theShape;
535   if (theShape.ShapeType() == TopAbs_COMPOUND) {
536     BRep_Builder B;
537     // check if shape if frosen
538     if (!theOUTShape.Free())
539       theOUTShape.Free(Standard_True);
540     
541     TopTools_SequenceOfShape aSubShapeSeq;
542     TopoDS_Iterator Iterator(theShape);
543     for (; Iterator.More(); Iterator.Next())
544       aSubShapeSeq.Append(Iterator.Value());
545     for (Standard_Integer i = 1; i <= aSubShapeSeq.Length(); i++) {
546       TopoDS_Shape Scomp = aSubShapeSeq.Value(i);
547       TopoDS_Shape aNewScomp;
548       B.Remove(theOUTShape, Scomp);
549       prepareAssembly( Scomp, aNewScomp );
550       TopLoc_Location aLoc;
551       aLoc = aNewScomp.Location();
552       if ( aLoc.IsIdentity() ) {
553         // create an "empty" location
554         gp_Trsf aTrsf;
555         aTrsf.SetScale(gp_Pnt(0,0,0), 1);
556         aLoc = TopLoc_Location( aTrsf );
557         aNewScomp.Location( aLoc );
558       }
559       B.Add(theOUTShape, aNewScomp);
560     }
561   }
562   return Standard_True;
563 }
564
565
566 //=======================================================================
567 //function : AddShape
568 //purpose  : 
569 //=======================================================================
570
571 TDF_Label XCAFDoc_ShapeTool::AddShape (const TopoDS_Shape& theShape,
572                                        const Standard_Boolean makeAssembly,
573                                        const Standard_Boolean makePrepare)
574 {
575   // PTV 17.02.2003 to avoid components without location.
576   TopoDS_Shape S = theShape;
577   if ( makePrepare && makeAssembly && S.ShapeType() == TopAbs_COMPOUND )
578     prepareAssembly( theShape, S ); // OCC1669
579   
580   TDF_Label L = addShape(S,makeAssembly);
581
582   if(!myShapeLabels.IsBound(S)) {
583     myShapeLabels.Bind(S,L);
584   }
585
586   return L;
587
588   //return addShape( S, makeAssembly );
589 }
590
591 //=======================================================================
592 //function : RemoveShape
593 //purpose  : 
594 //=======================================================================
595
596 Standard_Boolean XCAFDoc_ShapeTool::RemoveShape (const TDF_Label& L,
597                                                  const Standard_Boolean removeCompletely) const
598 {
599   if ( ! IsTopLevel ( L ) || ! IsFree ( L ) ) return Standard_False;
600
601   Handle(TDataStd_TreeNode) aNode;
602   TDF_Label aLabel;
603   if (removeCompletely &&
604       L.FindAttribute (XCAFDoc::ShapeRefGUID(), aNode) &&
605       aNode->HasFather() &&
606       L.IsAttribute (XCAFDoc_Location::GetID()))
607   {
608     aLabel = aNode->Father()->Label();
609   }
610
611   L.ForgetAllAttributes (Standard_True);
612
613   if (removeCompletely && !aLabel.IsNull())
614   {
615     return RemoveShape(aLabel);
616   }
617   return Standard_True;
618 }
619
620
621 //=======================================================================
622 //function : Init
623 //purpose  : 
624 //=======================================================================
625
626 void XCAFDoc_ShapeTool::Init()
627 {
628   hasSimpleShapes = Standard_False;
629 }
630
631
632 //=======================================================================
633 //function : SetAutoNaming
634 //purpose  : 
635 //=======================================================================
636
637 void XCAFDoc_ShapeTool::SetAutoNaming (const Standard_Boolean V)
638 {
639   theAutoNaming = V;
640 }
641
642
643 //=======================================================================
644 //function : AutoNaming
645 //purpose  : 
646 //=======================================================================
647
648 Standard_Boolean XCAFDoc_ShapeTool::AutoNaming()
649 {
650   return theAutoNaming;
651 }
652
653
654 //=======================================================================
655 //function : ComputeShapes
656 //purpose  : 
657 //=======================================================================
658
659 void XCAFDoc_ShapeTool::ComputeShapes(const TDF_Label& L)
660 {
661   TDF_ChildIterator it(L); 
662   for(; it.More(); it.Next()) {
663     TDF_Label L1 = it.Value();
664     TopoDS_Shape S;
665     if(GetShape(L1,S)) {
666       if(!myShapeLabels.IsBound(S)) {
667         mySimpleShapes.Bind(S,L1);
668       }
669     }
670     ComputeShapes(L1);
671   }
672 }
673
674
675 //=======================================================================
676 //function : ComputeSimpleShapes
677 //purpose  : 
678 //=======================================================================
679
680 void XCAFDoc_ShapeTool::ComputeSimpleShapes()
681 {
682   ComputeShapes(Label());
683   hasSimpleShapes = Standard_True;
684 }
685
686
687 //=======================================================================
688 //function : GetShapes
689 //purpose  : 
690 //=======================================================================
691
692 void XCAFDoc_ShapeTool::GetShapes(TDF_LabelSequence& Labels) const
693 {
694   Labels.Clear();
695
696   TDF_ChildIterator it(Label()); 
697   for (; it.More(); it.Next()) {
698     TDF_Label L = it.Value();
699     TopoDS_Shape S;
700     if ( GetShape ( L, S ) ) Labels.Append ( L );
701   }
702 }
703
704
705 //=======================================================================
706 //function : GetFreeShapes
707 //purpose  : 
708 //=======================================================================
709
710 void XCAFDoc_ShapeTool::GetFreeShapes (TDF_LabelSequence& FreeLabels) const
711 {
712   FreeLabels.Clear();
713
714   TDF_ChildIterator it(Label());
715   for (; it.More(); it.Next()) {
716     TDF_Label L = it.Value();
717     TopoDS_Shape S;
718     if ( GetShape ( L, S ) && IsFree ( L ) ) FreeLabels.Append ( L );
719   }
720 }
721
722 //=======================================================================
723 //function : IsTopLevel
724 //purpose  : 
725 //=======================================================================
726
727 Standard_Boolean XCAFDoc_ShapeTool::IsTopLevel (const TDF_Label& L) const
728 {
729   return L.Father() == Label();
730 }
731
732 //=======================================================================
733 //function : IsShape
734 //purpose  : 
735 //=======================================================================
736
737 Standard_Boolean XCAFDoc_ShapeTool::IsShape (const TDF_Label& L) 
738 {
739   return IsSimpleShape ( L ) || IsAssembly ( L ) || IsReference ( L );
740 }
741
742 //=======================================================================
743 //function : IsSimpleShape
744 //purpose  : 
745 //=======================================================================
746
747 Standard_Boolean XCAFDoc_ShapeTool::IsSimpleShape (const TDF_Label& L) 
748 {
749   Handle(TNaming_NamedShape) NS;
750   return L.FindAttribute ( TNaming_NamedShape::GetID(), NS ) &&
751          ! IsAssembly ( L ) && ! IsReference ( L );
752 }
753
754 //=======================================================================
755 //function : IsReference
756 //purpose  : 
757 //=======================================================================
758
759 Standard_Boolean XCAFDoc_ShapeTool::IsReference (const TDF_Label& L)
760 {
761   Handle(TDataStd_TreeNode) Node;
762   return L.FindAttribute(XCAFDoc::ShapeRefGUID(), Node) && Node->HasFather();
763 }
764
765 //=======================================================================
766 //function : IsAssembly
767 //purpose  : 
768 //=======================================================================
769
770 Standard_Boolean XCAFDoc_ShapeTool::IsAssembly (const TDF_Label& L) 
771 {
772   Handle(TDataStd_UAttribute) Uattr;
773   return L.FindAttribute(XCAFDoc::AssemblyGUID(), Uattr);
774 }
775
776 //=======================================================================
777 //function : IsComponent
778 //purpose  : 
779 //=======================================================================
780
781 Standard_Boolean XCAFDoc_ShapeTool::IsComponent (const TDF_Label& L)
782 {
783   return IsReference ( L ) && IsAssembly ( L.Father() );
784 }
785
786 //=======================================================================
787 //function : IsCompound
788 //purpose  : 
789 //=======================================================================
790
791 Standard_Boolean XCAFDoc_ShapeTool::IsCompound (const TDF_Label& L) 
792 {
793   Handle(TDataStd_Name) Name;
794   if (L.FindAttribute(TDataStd_Name::GetID(),Name)) {
795     TCollection_ExtendedString estr1 = Name->Get();
796     TCollection_ExtendedString estr2("COMPOUND");
797     if(estr1==estr2) {
798       return Standard_True;
799     }
800   }
801   return Standard_False;
802 }
803
804 //=======================================================================
805 //function : IsSubShape
806 //purpose  : 
807 //=======================================================================
808
809 Standard_Boolean XCAFDoc_ShapeTool::IsSubShape (const TDF_Label& L)
810 {
811   return IsSimpleShape ( L ) && IsShape ( L.Father() );
812 }
813
814 //=======================================================================
815 //function : IsFree
816 //purpose  : 
817 //=======================================================================
818
819 Standard_Boolean XCAFDoc_ShapeTool::IsFree (const TDF_Label& L) 
820 {
821   Handle(TDataStd_TreeNode) Node;
822   if ( ! L.FindAttribute(XCAFDoc::ShapeRefGUID(), Node) || 
823        ! Node->HasFirst() ) return Standard_True;
824
825   return Standard_False;
826 }
827
828 //=======================================================================
829 //function : GetUsers
830 //purpose  : Returns number of users (0 if shape is free)
831 //=======================================================================
832
833 Standard_Integer XCAFDoc_ShapeTool::GetUsers (const TDF_Label& L, 
834                                               TDF_LabelSequence& Labels,
835                                               const Standard_Boolean getsubchilds)
836 {
837   Standard_Integer NbUsers=0;
838   Handle(TDataStd_TreeNode) Node  ;
839
840   if ( ! L.FindAttribute(XCAFDoc::ShapeRefGUID(), Node) ) return NbUsers;
841   
842   Node = Node->First();
843   while ( ! Node.IsNull() ) {
844     
845     if ( getsubchilds ) {
846       TDF_Label underL = Node->Label().Father();
847       NbUsers += GetUsers ( underL, Labels, getsubchilds );
848     }
849     
850     Labels.Append(Node->Label());
851     Node = Node->Next();
852     NbUsers++;
853   }
854   return NbUsers;
855 }
856   
857 //=======================================================================
858 //function : NbComponents
859 //purpose  : 
860 //=======================================================================
861
862 Standard_Integer XCAFDoc_ShapeTool::NbComponents (const TDF_Label& L,
863                                                   const Standard_Boolean getsubchilds) 
864 {
865   TDF_LabelSequence subLabels;
866   GetComponents (L, subLabels, getsubchilds);
867   return subLabels.Length();
868 }
869
870 //=======================================================================
871 //function : GetComponents
872 //purpose  : 
873 //=======================================================================
874
875 Standard_Boolean XCAFDoc_ShapeTool::GetComponents (const TDF_Label& L, TDF_LabelSequence& Labels,
876                                                    const Standard_Boolean getsubchilds) 
877 {
878   if ( ! IsAssembly(L) ) return Standard_False;
879   
880   TDF_ChildIterator It(L);
881   for (; It.More(); It.Next() ) {
882     TDF_Label comp = It.Value();
883     if ( IsComponent ( comp ) ) {
884       if ( getsubchilds ) {
885         TDF_Label underL;
886         if ( GetReferredShape ( comp, underL ) )
887           GetComponents ( underL, Labels, getsubchilds);
888       }
889       Labels.Append ( comp );
890     }
891   }
892   return Standard_True;
893 }
894
895 //=======================================================================
896 //function : GetLocation
897 //purpose  : 
898 //=======================================================================
899
900 TopLoc_Location XCAFDoc_ShapeTool::GetLocation (const TDF_Label& L)
901 {
902   Handle(XCAFDoc_Location) LocationAttribute;
903   if (L.FindAttribute(XCAFDoc_Location::GetID(), LocationAttribute)) 
904     return LocationAttribute->Get();
905   
906   Handle(TNaming_NamedShape) NS;
907   TopoDS_Shape S;
908   if ( L.FindAttribute ( TNaming_NamedShape::GetID(), NS ) ) {
909     S = TNaming_Tool::GetShape(NS);
910   }
911   return S.Location();
912 }
913
914 //=======================================================================
915 //function : GetReferredShape
916 //purpose  : 
917 //=======================================================================
918
919 Standard_Boolean XCAFDoc_ShapeTool::GetReferredShape (const TDF_Label& L, 
920                                                       TDF_Label& Label)
921 {
922   if ( ! IsReference(L) ) return Standard_False;
923   
924   Handle (TDataStd_TreeNode) Node;
925   L.FindAttribute(XCAFDoc::ShapeRefGUID(), Node);
926   Label = Node->Father()->Label();
927   return Standard_True;
928 }
929
930 //=======================================================================
931 //function : AddComponent
932 //purpose  : 
933 //=======================================================================
934
935 TDF_Label XCAFDoc_ShapeTool::AddComponent (const TDF_Label& assembly, 
936                                            const TDF_Label& compL, 
937                                            const TopLoc_Location &Loc) const
938 {
939   TDF_Label L;
940   
941   // check that shape is assembly
942   if ( ! IsAssembly(assembly) ) {
943     // if it is simple shape, make it assembly
944     if ( IsSimpleShape(assembly) ) 
945       TDataStd_UAttribute::Set ( assembly, XCAFDoc::AssemblyGUID() );
946     else return L;
947   }
948   
949   // add a component as reference
950   TDF_TagSource aTag;
951   L = aTag.NewChild(assembly);
952   MakeReference ( L, compL, Loc );
953
954   // update assembly`s TopoDS_Shape
955   UpdateAssembly ( assembly );
956   return L;
957 }
958
959 //=======================================================================
960 //function : AddComponent
961 //purpose  : 
962 //=======================================================================
963
964 TDF_Label XCAFDoc_ShapeTool::AddComponent (const TDF_Label& assembly, 
965                                            const TopoDS_Shape& comp,
966                                            const Standard_Boolean expand)
967 {
968   // get label for component`s shape
969   TopoDS_Shape S0 = comp;
970   TopLoc_Location loc;
971   S0.Location ( loc );
972   TDF_Label compL;
973   compL = AddShape ( S0, expand );
974   
975   // add component by its label
976   return AddComponent ( assembly, compL, comp.Location() );
977 }
978
979 //=======================================================================
980 //function : RemoveComponent
981 //purpose  : 
982 //=======================================================================
983
984 void XCAFDoc_ShapeTool::RemoveComponent (const TDF_Label& comp) const
985 {
986   if ( IsComponent(comp) ) {
987     comp.ForgetAllAttributes();
988     UpdateAssembly(comp.Father());
989   }
990 }
991
992 //=======================================================================
993 //function : UpdateAssembly
994 //purpose  : 
995 //=======================================================================
996
997 void XCAFDoc_ShapeTool::UpdateAssembly (const TDF_Label& L) const
998 {
999   if ( ! IsAssembly(L) ) return;
1000
1001   TopoDS_Compound newassembly;
1002   BRep_Builder b;
1003   b.MakeCompound(newassembly);
1004
1005   TDF_ChildIterator chldLabIt(L);
1006   for (; chldLabIt.More(); chldLabIt.Next() ) {
1007     TDF_Label subLabel = chldLabIt.Value();
1008     if ( IsComponent ( subLabel ) ) {
1009       b.Add(newassembly, GetShape(subLabel));
1010     }
1011   }
1012   TNaming_Builder tnBuild(L);
1013   tnBuild.Generated(newassembly);
1014 }
1015
1016 //=======================================================================
1017 //function : IsSubShape
1018 //purpose  : 
1019 //=======================================================================
1020
1021 //static Standard_Boolean CheckSubShape (const TopoDS_Shape &S, const TopoDS_Shape &sub)
1022 //{
1023 //  if ( S.IsSame ( sub ) ) return Standard_True;
1024 //  
1025 //  if ( S.ShapeType() >= sub.ShapeType() ) return Standard_False;
1026 //  
1027 //  for ( TopoDS_Iterator it(S); it.More(); it.Next() ) {
1028 //    if ( CheckSubShape ( it.Value(), sub ) ) return Standard_True;
1029 //  }
1030 //  return Standard_False;
1031 //}
1032
1033 //=======================================================================
1034 //function : IsSubShape
1035 //purpose  : 
1036 //=======================================================================
1037
1038 Standard_Boolean XCAFDoc_ShapeTool::IsSubShape (const TDF_Label &shapeL,
1039                                              const TopoDS_Shape &sub) const
1040 {
1041   Handle(XCAFDoc_ShapeMapTool) A;
1042   if ( ! shapeL.FindAttribute(XCAFDoc_ShapeMapTool::GetID(), A) )
1043     return Standard_False;
1044   
1045   //TopoDS_Shape S = GetShape ( shapeL );
1046   //return ! S.IsNull() && CheckSubShape ( S, sub );
1047   
1048   return A->IsSubShape(sub);
1049 }
1050
1051 //=======================================================================
1052 //function : FindSubShape
1053 //purpose  : 
1054 //=======================================================================
1055
1056 Standard_Boolean XCAFDoc_ShapeTool::FindSubShape (const TDF_Label &shapeL,
1057                                                   const TopoDS_Shape &sub,
1058                                                   TDF_Label &L) const
1059 {
1060   // this code is used instead of the following for performance reasons
1061   if ( TNaming_Tool::HasLabel(Label(), sub) ) {
1062     int TransDef = 0;
1063     L = TNaming_Tool::Label(Label(), sub, TransDef);
1064     return ( ! L.IsNull() && L.Father() == shapeL );
1065   }
1066
1067 /*
1068   TDF_ChildIterator chldLabIt(shapeL);
1069   for (; chldLabIt.More(); chldLabIt.Next() ) {
1070     TDF_Label subLabel = chldLabIt.Value();
1071     TopoDS_Shape S;
1072     if ( GetShape ( subLabel, S ) && S.IsSame ( sub ) ) {
1073       L = subLabel;
1074       return Standard_True;
1075     }
1076   }
1077 */
1078   return Standard_False;
1079 }
1080
1081 //=======================================================================
1082 //function : AddSubShape
1083 //purpose  : 
1084 //=======================================================================
1085
1086 TDF_Label XCAFDoc_ShapeTool::AddSubShape (const TDF_Label &shapeL,
1087                                           const TopoDS_Shape &sub) const
1088 {
1089   TDF_Label L;
1090   if ( FindSubShape ( shapeL, sub, L ) ) return L;
1091   
1092   if ( ! IsSubShape ( shapeL, sub ) ) return L;
1093   
1094   TDF_TagSource aTag;
1095   L = aTag.NewChild(shapeL);
1096   
1097   TNaming_Builder tnBuild(L);
1098   tnBuild.Generated(sub);
1099
1100 //  if(!mySubShapes.IsBound(sub))
1101 //    mySubShapes.Bind(sub,L);
1102    
1103   return L;
1104 }
1105
1106
1107 //=======================================================================
1108 //function : FindMainShapeUsingMap
1109 //purpose  : 
1110 //=======================================================================
1111
1112 TDF_Label XCAFDoc_ShapeTool::FindMainShapeUsingMap(const TopoDS_Shape &sub) const
1113 {
1114   //for(Standard_Integer i=1; i<=myNotAssemblies.Length(); i++) {
1115   //  TDF_Label L = myNotAssemblies.Value(i);
1116   //  if(IsSubShape(L,sub)) return L;
1117   //}
1118   if(mySubShapes.IsBound(sub))
1119     return mySubShapes.Find(sub);
1120   TDF_Label L0;
1121   return L0;
1122 }
1123
1124
1125 //=======================================================================
1126 //function : FindMainShape
1127 //purpose  : 
1128 //=======================================================================
1129
1130 TDF_Label XCAFDoc_ShapeTool::FindMainShape (const TopoDS_Shape &sub) const
1131 {
1132   TDF_ChildIterator it(Label());
1133   for (; it.More(); it.Next()) {
1134     TDF_Label L = it.Value();
1135     if ( ! IsAssembly ( L ) && IsSubShape ( L, sub ) ) return L;
1136   }
1137   TDF_Label L0;
1138   return L0;
1139 }
1140
1141
1142 //=======================================================================
1143 //function : GetSubShapes
1144 //purpose  : 
1145 //=======================================================================
1146
1147 Standard_Boolean XCAFDoc_ShapeTool::GetSubShapes (const TDF_Label &L, 
1148                                                TDF_LabelSequence& Labels)
1149 {
1150   TDF_ChildIterator It(L);
1151   for (; It.More(); It.Next() ) {
1152     TDF_Label sub = It.Value();
1153     if ( IsSubShape ( sub ) ) Labels.Append ( sub );
1154   }
1155   return Labels.Length() >0;
1156 }
1157
1158 //=======================================================================
1159 //function : BaseLabel
1160 //purpose  : 
1161 //=======================================================================
1162
1163 TDF_Label XCAFDoc_ShapeTool::BaseLabel () const
1164 {
1165   return Label();
1166 }
1167
1168 //=======================================================================
1169 //function : DumpAssembly
1170 //purpose  : recursive part of Dump()
1171 //=======================================================================
1172
1173 static void DumpAssembly(const TDF_Label L,
1174                          const Standard_Integer level,
1175                          const Standard_Boolean deep)
1176 {
1177   for (Standard_Integer i=0; i<level; i++)
1178     cout<<"\t";
1179   
1180   TCollection_AsciiString Entry;
1181   TDF_Tool::Entry(L, Entry);
1182
1183   cout<<"ASSEMBLY "<<Entry;
1184   Handle(TDataStd_Name) Name;
1185   if (L.FindAttribute(TDataStd_Name::GetID(), Name))
1186     cout<<" "<<Name->Get();
1187   
1188   if (deep) {
1189     TopoDS_Shape S;
1190     XCAFDoc_ShapeTool::GetShape(L, S);
1191     cout<<"("<<*(void**)&S.TShape();
1192     if (! S.Location().IsIdentity())
1193       cout<<", "<< *(void**)&S.Location();
1194     cout<<") ";
1195   }
1196   cout<<endl;
1197   
1198   Handle(TDataStd_TreeNode) Node;
1199   TDF_ChildIDIterator NodeIterator(L, XCAFDoc::ShapeRefGUID());
1200   for (; NodeIterator.More(); NodeIterator.Next()) {
1201     Node = Handle(TDataStd_TreeNode)::DownCast(NodeIterator.Value());
1202     if (Node->HasFather()) {
1203       if (Node->Father()->Label().HasChild())
1204         DumpAssembly(Node->Father()->Label(), level+1, deep);
1205       else {
1206         XCAFDoc_ShapeTool::DumpShape(Node->Father()->Label(), level+1, deep);
1207           cout<<endl;
1208         }
1209     }
1210   }
1211 }
1212
1213 //=======================================================================
1214 //function : Dump
1215 //purpose  : 
1216 //=======================================================================
1217
1218 void XCAFDoc_ShapeTool::Dump(const Standard_Boolean deep) const
1219 {
1220   Standard_Integer level = 0;
1221 //   TopTools_SequenceOfShape SeqShapes;
1222   TDF_LabelSequence SeqLabels;
1223   GetShapes( SeqLabels);
1224
1225   if (SeqLabels.Length()>0) cout<<endl;
1226   Standard_Integer i;
1227   for (i=1; i<=SeqLabels.Length(); i++) {
1228     DumpAssembly(SeqLabels.Value(i), level, deep);
1229   }
1230
1231   SeqLabels.Clear();
1232   GetFreeShapes(SeqLabels);
1233   cout<<endl<<"Free Shapes: "<<SeqLabels.Length()<<endl;
1234   for (i = 1; i<=SeqLabels.Length(); i++) {
1235     DumpShape(SeqLabels.Value(i), level, deep);
1236     cout<<endl;
1237   }
1238 }
1239
1240 //=======================================================================
1241 //function : DumpShape
1242 //purpose  : 
1243 //=======================================================================
1244
1245 void XCAFDoc_ShapeTool::DumpShape(const TDF_Label& L,const Standard_Integer level,const Standard_Boolean deep) 
1246 {
1247   TopoDS_Shape S;
1248   if(! XCAFDoc_ShapeTool::GetShape(L, S) ) return;
1249   for (Standard_Integer i=0; i<level; i++)
1250     cout<<"\t";
1251   
1252   if (S.ShapeType() == TopAbs_COMPOUND) cout<<"ASSEMBLY";
1253   else TopAbs::Print(S.ShapeType(), cout);
1254   
1255   TCollection_AsciiString Entry;
1256   TDF_Tool::Entry(L, Entry);
1257   cout<<"  "<<Entry;
1258   //cout<<endl;
1259   Handle(TDataStd_Name) Name;
1260   if (L.FindAttribute(TDataStd_Name::GetID(),Name)) 
1261     cout<<" "<<Name->Get();
1262   
1263   if (deep) {
1264     cout<<"("<<*(void**)&S.TShape();
1265     if (! S.Location().IsIdentity())
1266       cout<<", "<< *(void**)&S.Location();
1267     cout<<") ";
1268   }
1269 }
1270
1271 //=======================================================================
1272 //function : IsExternRef
1273 //purpose  : 
1274 //=======================================================================
1275
1276 Standard_Boolean XCAFDoc_ShapeTool::IsExternRef(const TDF_Label& L) 
1277 {
1278   Handle(TDataStd_UAttribute) Uattr;
1279   return L.FindAttribute(XCAFDoc::ExternRefGUID(), Uattr);
1280 }
1281
1282 //=======================================================================
1283 //function : SetExternRefs
1284 //purpose  : 
1285 //=======================================================================
1286
1287 void XCAFDoc_ShapeTool::SetExternRefs(const TDF_Label& L,
1288                                       const TColStd_SequenceOfHAsciiString& SHAS) const
1289 {
1290   TDF_Label ShapeLabel = L.NewChild();
1291   TDataStd_UAttribute::Set(ShapeLabel,XCAFDoc::ExternRefGUID());
1292   for(Standard_Integer i=1; i<=SHAS.Length(); i++) {
1293     TDF_Label tmplbl = ShapeLabel.FindChild(i,Standard_True);
1294     Handle(TCollection_HAsciiString) str = SHAS(i);
1295     TCollection_ExtendedString extstr(str->String());
1296     TDataStd_Name::Set(tmplbl,extstr);
1297   }
1298 }
1299
1300 //=======================================================================
1301 //function : SetExternRefs
1302 //purpose  : 
1303 //=======================================================================
1304
1305 TDF_Label XCAFDoc_ShapeTool::SetExternRefs(const TColStd_SequenceOfHAsciiString& SHAS) const
1306 {
1307   TDF_Label ShapeLabel;
1308   TDF_TagSource aTag;
1309   // add a new label
1310   ShapeLabel = aTag.NewChild(Label());
1311   TDataStd_UAttribute::Set(ShapeLabel,XCAFDoc::ExternRefGUID());
1312   for(Standard_Integer i=1; i<=SHAS.Length(); i++) {
1313     TDF_Label tmplbl = ShapeLabel.FindChild(i,Standard_True);
1314     Handle(TCollection_HAsciiString) str = SHAS(i);
1315     TCollection_ExtendedString extstr(str->String());
1316     TDataStd_Name::Set(tmplbl,extstr);
1317   }
1318   return ShapeLabel;
1319 }
1320
1321 //=======================================================================
1322 //function : GetExternRefs
1323 //purpose  : 
1324 //=======================================================================
1325
1326 void XCAFDoc_ShapeTool::GetExternRefs(const TDF_Label& L,
1327                                       TColStd_SequenceOfHAsciiString& SHAS)
1328 {
1329   Handle(TDataStd_Name) TDN;
1330   TDF_Label tmplbl;
1331   for(Standard_Integer i=1; i<=L.NbChildren(); i++) {
1332     tmplbl = L.FindChild(i);
1333     if(tmplbl.FindAttribute(TDataStd_Name::GetID(),TDN)) {
1334       TCollection_ExtendedString extstr = TDN->Get();
1335       Handle(TCollection_HAsciiString) str = 
1336         new TCollection_HAsciiString(TCollection_AsciiString(extstr, '?')); 
1337       SHAS.Append(str);
1338     }
1339   }
1340 }
1341
1342 // API: API work with SHUO (Specified Higher Usage Occurrance) structure
1343
1344 //=======================================================================
1345 //function : GetSHUO
1346 //purpose  : 
1347 //=======================================================================
1348
1349 Standard_Boolean XCAFDoc_ShapeTool::GetSHUO (const TDF_Label& SHUOLabel,
1350                                       Handle(XCAFDoc_GraphNode)& aSHUOAttr)
1351 {
1352   if ( !SHUOLabel.FindAttribute( XCAFDoc::SHUORefGUID(), aSHUOAttr ) )
1353     return Standard_False;
1354   return Standard_True;
1355 }
1356
1357 //=======================================================================
1358 //function : GetAllComponentSHUO
1359 //purpose  : 
1360 //=======================================================================
1361
1362 Standard_Boolean XCAFDoc_ShapeTool::GetAllComponentSHUO (const TDF_Label& theCompLabel,
1363                                                          TDF_AttributeSequence& theSHUOAttrs)
1364 {
1365   TDF_ChildIterator it(theCompLabel); 
1366   for (; it.More(); it.Next()) {
1367     TDF_Label L = it.Value();
1368     Handle(XCAFDoc_GraphNode) aSHUOAttr;
1369     if ( GetSHUO( L, aSHUOAttr ) )
1370       theSHUOAttrs.Append( aSHUOAttr );
1371   }
1372   return (theSHUOAttrs.Length() > 0);
1373 }
1374
1375 //=======================================================================
1376 //function : SetSHUO
1377 //purpose  : 
1378 //=======================================================================
1379
1380 Standard_Boolean XCAFDoc_ShapeTool::SetSHUO (const TDF_LabelSequence& labels,
1381                                              Handle(XCAFDoc_GraphNode)& MainSHUOAttr) const
1382 {
1383   MainSHUOAttr.Nullify();
1384   // check number of labels
1385   if (labels.Length() < 2)
1386     return Standard_False;
1387   // check is all labels contains components of any assemblyies 
1388   Standard_Integer i;
1389   for (i = 1; i <= labels.Length(); i++)
1390     if ( !IsComponent(labels.Value(i)) )
1391       return Standard_False;
1392   
1393   TDF_TagSource aTag;
1394   TDF_Label UpperSubL = aTag.NewChild( labels( 1 ) );
1395   if (theAutoNaming) {
1396     TCollection_ExtendedString Entry("SHUO");
1397     TDataStd_Name::Set(UpperSubL, TCollection_ExtendedString( Entry ));
1398   }
1399   Handle(XCAFDoc_GraphNode) aUpperSHUO;
1400   aUpperSHUO = XCAFDoc_GraphNode::Set( UpperSubL, XCAFDoc::SHUORefGUID() );
1401   // init out argument by main upper usage SHUO
1402   MainSHUOAttr = aUpperSHUO;
1403   // add other next_usage occurrences.
1404   for (i = 2; i <= labels.Length(); i++) {
1405     TDF_Label NextSubL = aTag.NewChild( labels( i ) );
1406     if (theAutoNaming) {
1407       TCollection_ExtendedString EntrySub("SHUO-");
1408       EntrySub += i;
1409       TDataStd_Name::Set(NextSubL, TCollection_ExtendedString( EntrySub ));
1410     }
1411     Handle(XCAFDoc_GraphNode) aNextSHUO;
1412     aNextSHUO = XCAFDoc_GraphNode::Set( NextSubL, XCAFDoc::SHUORefGUID() );
1413     // set references
1414     aUpperSHUO->SetChild( aNextSHUO );
1415     aNextSHUO->SetFather( aUpperSHUO );
1416     // now lets next_usage become upper_usage for next level of SHUO
1417     aUpperSHUO = aNextSHUO;
1418     UpperSubL = NextSubL;
1419   }
1420   
1421   return Standard_True;
1422 }
1423
1424 //=======================================================================
1425 //function : GetSHUOUpperUsage
1426 //purpose  : 
1427 //=======================================================================
1428
1429 Standard_Boolean XCAFDoc_ShapeTool::GetSHUOUpperUsage (const TDF_Label& NextUsageL,
1430                                                        TDF_LabelSequence& aLabels)
1431 {
1432   Handle(XCAFDoc_GraphNode) aNextSHUO;
1433   if( !GetSHUO( NextUsageL, aNextSHUO ) || aNextSHUO->NbFathers()<1 )
1434     return Standard_False;
1435   
1436   // get upper_usage SHAO
1437   for (Standard_Integer i = 1; i <= aNextSHUO->NbFathers(); i++)
1438     aLabels.Append( aNextSHUO->GetFather(i)->Label() );
1439   return Standard_True;
1440 }
1441
1442 //=======================================================================
1443 //function : GetSHUONextUsage
1444 //purpose  : 
1445 //=======================================================================
1446
1447 Standard_Boolean XCAFDoc_ShapeTool::GetSHUONextUsage (const TDF_Label& UpperUsageL,
1448                                                       TDF_LabelSequence& aLabels)
1449 {
1450   Handle(XCAFDoc_GraphNode) aUpperSHUO;
1451   if ( !GetSHUO( UpperUsageL, aUpperSHUO ) || aUpperSHUO->NbChildren()<1 )
1452     return Standard_False;
1453   // get upper_usage SHAO
1454   for (Standard_Integer i = 1; i <= aUpperSHUO->NbChildren(); i++)
1455     aLabels.Append( aUpperSHUO->GetChild(i)->Label() );
1456   return Standard_True;
1457 }
1458
1459 //=======================================================================
1460 //function : RemoveSHUO
1461 //purpose  : 
1462 //=======================================================================
1463
1464 Standard_Boolean XCAFDoc_ShapeTool::RemoveSHUO (const TDF_Label& L) const
1465 {
1466   L.ForgetAllAttributes (Standard_True);
1467   return Standard_True;
1468 }
1469
1470 //=======================================================================
1471 //function : checkForShape
1472 //purpose  : auxilary
1473 //=======================================================================
1474
1475 static Standard_Boolean checkForShape (const TopoDS_Shape& theShape,
1476                                        const TopoDS_Shape& theCurSh,
1477                                        const TDF_Label& theUserL,
1478                                        TDF_LabelSequence& theLabels)
1479 {
1480   // the label of an assembly which contains this component
1481   TDF_Label aSuperUserL = theUserL.Father();
1482   TopLoc_Location aSupLoc, aCompLoc;
1483   aSupLoc = ::XCAFDoc_ShapeTool::GetLocation ( aSuperUserL );
1484   aCompLoc = ::XCAFDoc_ShapeTool::GetLocation ( theUserL );
1485   TopoDS_Shape aCopySh = theCurSh;
1486   aCompLoc = aCompLoc.Multiplied( theCurSh.Location() );
1487   aSupLoc = aSupLoc.Multiplied( aCompLoc );
1488   aCopySh.Location( aSupLoc );
1489   if ( aCopySh.IsSame( theShape ) ) {
1490     theLabels.Prepend( theUserL );
1491     return Standard_True;
1492   }
1493   // try to search deeply (upper by assmebly structure)
1494   TDF_LabelSequence aNewLabels;
1495   for (Standard_Integer j = 1; j <= theLabels.Length(); j++)
1496     aNewLabels.Append( theLabels.Value( j ) );
1497   aNewLabels.Prepend( theUserL );
1498   TDF_LabelSequence aUsers;
1499   ::XCAFDoc_ShapeTool::GetUsers( aSuperUserL, aUsers );
1500   for (Standard_Integer i = 1; i <= aUsers.Length(); i++)
1501     if ( checkForShape( theShape, aCopySh, aUsers.Value( i ), aNewLabels ) ) {
1502       // get solution
1503       theLabels = aNewLabels;
1504       return Standard_True;
1505     }
1506   return Standard_False;
1507 }
1508
1509 //=======================================================================
1510 //function : FindComponent
1511 //purpose  : 
1512 //=======================================================================
1513
1514 Standard_Boolean XCAFDoc_ShapeTool::FindComponent (const TopoDS_Shape& theShape,
1515                                                   TDF_LabelSequence& theLabels) const
1516 {
1517   theLabels.Clear();
1518   // search for a top-level shape that corresponds to this component
1519   TopoDS_Shape S0 = theShape;
1520   TopLoc_Location loc;
1521   S0.Location ( loc );
1522   TDF_Label aRefL = FindShape( S0 );
1523   if (aRefL.IsNull())
1524     return Standard_False; // cannot find top-level shape.
1525   
1526   TDF_LabelSequence aUsers;
1527   ::XCAFDoc_ShapeTool::GetUsers( aRefL, aUsers );
1528   for (Standard_Integer i = 1; i <= aUsers.Length(); i++)
1529     if ( checkForShape( theShape, S0, aUsers.Value( i ), theLabels ) )
1530       break;
1531   
1532   return (theLabels.Length() > 0);
1533 }
1534
1535 //=======================================================================
1536 //function : getShapesOfSHUO
1537 //purpose  : auxilary
1538 //=======================================================================
1539
1540 static Standard_Boolean getShapesOfSHUO (TopLoc_IndexedMapOfLocation& theaPrevLocMap,
1541                                          const Handle(XCAFDoc_ShapeTool)& theSTool,
1542                                          const TDF_Label& theSHUOlab,
1543                                          TopoDS_Shape& theShape)
1544 {
1545   Handle(XCAFDoc_GraphNode) SHUO;
1546   TDF_LabelSequence aLabSeq;
1547   theSTool->GetSHUONextUsage( theSHUOlab, aLabSeq );
1548   if (aLabSeq.Length() >= 1)
1549     for (Standard_Integer i = 1; i <= aLabSeq.Length(); i++) {
1550       TDF_Label aSubCompL = aLabSeq.Value( i );
1551       TopLoc_Location compLoc = XCAFDoc_ShapeTool::GetLocation ( aSubCompL.Father() );
1552       // create new map of laocation (to not merge locations from different shapes)
1553       TopLoc_IndexedMapOfLocation aNewPrevLocMap;
1554       for (Standard_Integer m = 1; m <= theaPrevLocMap.Extent(); m++)
1555         aNewPrevLocMap.Add( theaPrevLocMap.FindKey( m ) );
1556       aNewPrevLocMap.Add( compLoc );
1557       // got for the new sublocations and corresponding shape
1558       getShapesOfSHUO( aNewPrevLocMap, theSTool, aSubCompL, theShape );
1559     }
1560   else {
1561     TopoDS_Shape aSHUO_NUSh = theSTool->GetShape ( theSHUOlab.Father() );
1562     if ( aSHUO_NUSh.IsNull() ) return Standard_False;
1563     // cause got shape with location already.
1564     TopLoc_Location nullLoc;
1565     aSHUO_NUSh.Location ( nullLoc );
1566     // multiply the locations
1567     Standard_Integer intMapLenght = theaPrevLocMap.Extent();
1568     if ( intMapLenght < 1 )
1569       return Standard_False; // should not be, but to avoid exception...?
1570     TopLoc_Location SupcompLoc;
1571     SupcompLoc = theaPrevLocMap.FindKey( intMapLenght );
1572     if (intMapLenght > 1) {
1573       Standard_Integer l = intMapLenght - 1;
1574       while (l >= 1) {
1575         SupcompLoc = theaPrevLocMap.FindKey( l ).Multiplied( SupcompLoc );
1576         l--;
1577       }
1578     }
1579     aSHUO_NUSh.Location( SupcompLoc );
1580     theShape = aSHUO_NUSh;
1581   }
1582   return (!theShape.IsNull());
1583 }
1584
1585 //=======================================================================
1586 //function : GetSHUOInstance
1587 //purpose  : 
1588 //=======================================================================
1589
1590 TopoDS_Shape XCAFDoc_ShapeTool::GetSHUOInstance (const Handle(XCAFDoc_GraphNode)& theSHUO) const
1591 {
1592   TopoDS_Shape aShape;
1593   if (theSHUO.IsNull())
1594     return aShape;
1595   
1596   TDF_Label aSHUOlab = theSHUO->Label();
1597   // get location of the assembly
1598   TopLoc_Location loc = XCAFDoc_ShapeTool::GetLocation ( aSHUOlab.Father().Father() );
1599   // get location of the component
1600   TopLoc_Location compLoc = XCAFDoc_ShapeTool::GetLocation ( aSHUOlab.Father() );
1601   TopLoc_IndexedMapOfLocation aPrevLocMap;
1602   // get previous setted location 
1603   if ( !loc.IsIdentity() )
1604     aPrevLocMap.Add( loc );
1605   aPrevLocMap.Add( compLoc );
1606   // get shape by recurse method
1607   const Handle(XCAFDoc_ShapeTool)& STool = this;
1608   getShapesOfSHUO( aPrevLocMap, STool, aSHUOlab, aShape );
1609   
1610   return aShape;
1611 }
1612
1613 //=======================================================================
1614 //function : getUsersShapesOfSHUO
1615 //purpose  : auxilary
1616 //=======================================================================
1617
1618 static Standard_Boolean getUsersShapesOfSHUO (TopLoc_IndexedMapOfLocation& aPrevLocMap,
1619                                               const Handle(XCAFDoc_ShapeTool)& STool,
1620                                               const TDF_Label& aSHUOlab,
1621                                               const TDF_Label& theUserL,
1622                                               TopTools_SequenceOfShape& theSHUOShapeSeq)
1623 {
1624   TopLoc_IndexedMapOfLocation aNewPrevLocMap;
1625   // get location of the assembly
1626   TopLoc_Location loc = XCAFDoc_ShapeTool::GetLocation ( theUserL.Father() );
1627   // get location of the component
1628   TopLoc_Location compLoc = XCAFDoc_ShapeTool::GetLocation ( theUserL );
1629   // get previous setted location 
1630   aNewPrevLocMap.Add( loc );
1631   aNewPrevLocMap.Add( compLoc );
1632   Standard_Integer i;
1633   for (i = 1; i <= aPrevLocMap.Extent(); i++)
1634     aNewPrevLocMap.Add( aPrevLocMap.FindKey(i) );
1635   TDF_Label L = theUserL.Father();
1636   TDF_LabelSequence usersLab;
1637   ::XCAFDoc_ShapeTool::GetUsers( L, usersLab );
1638   if (usersLab.Length() == 0) {
1639     TopoDS_Shape aShape;
1640     getShapesOfSHUO( aNewPrevLocMap, STool, aSHUOlab, aShape );
1641     if (!aShape.IsNull()) {
1642       theSHUOShapeSeq.Append(aShape);
1643       return Standard_True;
1644     }
1645   }
1646   // now iterates on users of this assembly as component
1647   for ( i = 1; i <= usersLab.Length(); i++ ) {
1648     TDF_Label aNewUserL = usersLab.Value(i);
1649     getUsersShapesOfSHUO( aNewPrevLocMap, STool, aSHUOlab, aNewUserL, theSHUOShapeSeq );
1650   }
1651   
1652   return (theSHUOShapeSeq.Length() > 1);
1653 }
1654
1655 //=======================================================================
1656 //function : GetAllSHUOInstances
1657 //purpose  : auxilary
1658 //=======================================================================
1659
1660 Standard_Boolean XCAFDoc_ShapeTool::GetAllSHUOInstances (const Handle(XCAFDoc_GraphNode)& theSHUO,
1661                                                          TopTools_SequenceOfShape& theSHUOShapeSeq) const
1662 {
1663   if (theSHUO.IsNull())
1664     return Standard_False;
1665
1666   TDF_Label aSHUOlab = theSHUO->Label();
1667   TopLoc_IndexedMapOfLocation aPrevLocMap;
1668   // get location of the assembly
1669   TopLoc_Location loc = XCAFDoc_ShapeTool::GetLocation ( aSHUOlab.Father().Father() );
1670   // get location of the component
1671   TopLoc_Location compLoc = XCAFDoc_ShapeTool::GetLocation ( aSHUOlab.Father() );
1672   // get previous setted location 
1673   if ( !loc.IsIdentity() )
1674     aPrevLocMap.Add( loc );
1675   aPrevLocMap.Add( compLoc );
1676   // get label of assembly
1677   TDF_Label L = aSHUOlab.Father().Father();
1678   TDF_LabelSequence usersLab;
1679   ::XCAFDoc_ShapeTool::GetUsers( L, usersLab );
1680   TopoDS_Shape aShape;
1681   const Handle(XCAFDoc_ShapeTool)& STool = this;
1682   if (usersLab.Length() == 0) {
1683     getShapesOfSHUO( aPrevLocMap, STool, aSHUOlab, aShape );
1684     if (!aShape.IsNull()) {
1685       theSHUOShapeSeq.Append(aShape);
1686       return Standard_True;
1687     }
1688   }
1689   // now iterates on users of this assembly as component
1690   for (Standard_Integer i = 1; i <= usersLab.Length(); i++) {
1691     TDF_Label aUserL = usersLab.Value(i);
1692     getUsersShapesOfSHUO( aPrevLocMap, STool, aSHUOlab, aUserL, theSHUOShapeSeq );
1693   }
1694   
1695   return (theSHUOShapeSeq.Length() > 1);
1696 }
1697
1698 //=======================================================================
1699 //function : SetInstanceSHUO
1700 //purpose  : 
1701 //=======================================================================
1702
1703 Handle(XCAFDoc_GraphNode) XCAFDoc_ShapeTool::SetInstanceSHUO (const TopoDS_Shape& theShape) const
1704 {
1705   Handle(XCAFDoc_GraphNode) SHUO;
1706   TDF_LabelSequence aLabels;
1707   if ( FindComponent( theShape, aLabels ) )
1708     // set shuo structure on labels of component-assembly structure
1709     SetSHUO( aLabels, SHUO );
1710   return SHUO;
1711 }
1712
1713 //=======================================================================
1714 //function : FindSHUO
1715 //purpose  : 
1716 //=======================================================================
1717
1718 Standard_Boolean XCAFDoc_ShapeTool::FindSHUO (const TDF_LabelSequence& theLabels,
1719                                               Handle(XCAFDoc_GraphNode)& theSHUOAttr)
1720 {
1721   TDF_AttributeSequence SHUOAttrs;
1722   TDF_Label aCompLabel = theLabels.Value(1);
1723   if (! ::XCAFDoc_ShapeTool::GetAllComponentSHUO( aCompLabel, SHUOAttrs ) )
1724     return Standard_False;
1725   // WARNING: manage that each SHUO upper_usage have only one SHUO next_usage
1726   for (Standard_Integer i = 1; i <= SHUOAttrs.Length(); i++) {
1727     TDF_LabelSequence aCondidate;
1728     Handle(XCAFDoc_GraphNode) anSHUO = Handle(XCAFDoc_GraphNode)::DownCast(SHUOAttrs.Value(i));
1729     aCondidate.Append( anSHUO->Label().Father() );
1730     while (anSHUO->NbChildren()) {
1731       anSHUO = anSHUO->GetChild( 1 );
1732       aCondidate.Append( anSHUO->Label().Father() );
1733     }
1734     // check the label sequences
1735     Standard_Boolean isEqual = Standard_True;
1736     if (theLabels.Length() != aCondidate.Length())
1737       isEqual = Standard_False;
1738     else
1739       for (Standard_Integer li = 1; li <= theLabels.Length(); li++)
1740         if ( theLabels.Value(li) != aCondidate.Value(li) ) {
1741           isEqual = Standard_False;
1742           break;
1743         }
1744     if (!isEqual)
1745       continue;
1746       
1747     theSHUOAttr = Handle(XCAFDoc_GraphNode)::DownCast(SHUOAttrs.Value(i));
1748     break;
1749   }
1750   return ( !theSHUOAttr.IsNull() );
1751 }