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