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