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