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