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