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