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