014926ac27529747a8afe69fa1c26dc48fe223ce
[occt.git] / src / XCAFDoc / XCAFDoc_ShapeTool.cxx
1 // Created on: 2000-08-03
2 // Created by: data exchange team
3 // Copyright (c) 2000-2012 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20
21
22 #include <XCAFDoc_ShapeTool.ixx>
23 #include <XCAFDoc.hxx>
24
25 #include <TDF_Tool.hxx>
26 #include <TDF_Label.hxx>
27 #include <TDF_LabelMap.hxx>
28 #include <TDF_LabelSequence.hxx>
29 #include <TDF_ChildIterator.hxx>
30 #include <TDF_ChildIDIterator.hxx>
31 #include <TDF_MapIteratorOfLabelMap.hxx>
32
33 #include <TDataStd_Name.hxx>
34 #include <TDataStd_TreeNode.hxx>
35 #include <TDataStd_ChildNodeIterator.hxx>
36 #include <TDataStd_UAttribute.hxx>
37
38 #include <TDocStd_Document.hxx>
39
40 #include <TNaming_Builder.hxx>
41 #include <TNaming_NamedShape.hxx>
42 #include <TNaming_Tool.hxx>
43
44 #include <TopLoc_Location.hxx>
45 #include <TopoDS_Iterator.hxx>
46 #include <TopoDS_Shape.hxx>
47 #include <TopoDS_Compound.hxx>
48 #include <BRep_Builder.hxx>
49 #include <XCAFDoc_Location.hxx>
50
51 #include <TCollection_AsciiString.hxx>
52 #include <TCollection_HAsciiString.hxx>
53 #include <TCollection_ExtendedString.hxx>
54 #include <TColStd_SequenceOfHAsciiString.hxx>
55 #include <XCAFDoc_GraphNode.hxx>
56 #include <TopLoc_IndexedMapOfLocation.hxx>
57 #include <gp_Trsf.hxx>
58 #include <gp_Pnt.hxx>
59 #include <XCAFDoc_ShapeMapTool.hxx>
60
61 #define AUTONAMING // automatically set names for labels
62
63 // attribute methods //////////////////////////////////////////////////
64
65 //=======================================================================
66 //function : GetID
67 //purpose  : 
68 //=======================================================================
69
70 const Standard_GUID& XCAFDoc_ShapeTool::GetID() 
71 {
72   static Standard_GUID ShapeToolID ("efd212ee-6dfd-11d4-b9c8-0060b0ee281b");
73   return ShapeToolID; 
74 }
75
76
77 //=======================================================================
78 //function : Set
79 //purpose  : 
80 //=======================================================================
81
82 Handle(XCAFDoc_ShapeTool) XCAFDoc_ShapeTool::Set(const TDF_Label& L) 
83 {
84   Handle(XCAFDoc_ShapeTool) A;
85   if (!L.FindAttribute (XCAFDoc_ShapeTool::GetID(), A)) {
86     A = new XCAFDoc_ShapeTool ();
87     L.AddAttribute(A);
88   }
89   A->Init();
90   return A;
91 }
92
93
94 //=======================================================================
95 //function : Constructor
96 //purpose  : 
97 //=======================================================================
98
99 XCAFDoc_ShapeTool::XCAFDoc_ShapeTool()
100 {
101   hasSimpleShapes = Standard_False;
102 }
103
104
105 //=======================================================================
106 //function : ID
107 //purpose  : 
108 //=======================================================================
109
110 const Standard_GUID& XCAFDoc_ShapeTool::ID() const
111 {
112   return GetID();
113 }
114
115 //=======================================================================
116 //function : Restore
117 //purpose  : 
118 //=======================================================================
119
120 void XCAFDoc_ShapeTool::Restore(const Handle(TDF_Attribute)& /*with*/) 
121 {
122 }
123
124 //=======================================================================
125 //function : NewEmpty
126 //purpose  : 
127 //=======================================================================
128
129 Handle(TDF_Attribute) XCAFDoc_ShapeTool::NewEmpty() const
130 {
131   return new XCAFDoc_ShapeTool;
132 }
133
134 //=======================================================================
135 //function : Paste
136 //purpose  : 
137 //=======================================================================
138
139 void XCAFDoc_ShapeTool::Paste (const Handle(TDF_Attribute)& /*into*/,
140                                const Handle(TDF_RelocationTable)& /*RT*/) const
141 {
142 }
143
144 #ifdef AUTONAMING
145 // Auxiliary methods //////////////////////////////////////////////////
146
147 //=======================================================================
148 //function : SetLabelNameByLink
149 //purpose  : 
150 //=======================================================================
151 static void SetLabelNameByLink(const TDF_Label L) 
152 {
153   Handle(TDataStd_TreeNode) Node;
154   if (! L.FindAttribute(XCAFDoc::ShapeRefGUID(), Node) ||
155       ! Node->HasFather()) {
156     cout<<"Error: XCAFDoc_ShapeTool, SetLabelNameByLink(): NO NODE"<<endl;
157     return;
158   }
159   TCollection_AsciiString Entry;
160   TDF_Tool::Entry ( Node->Father()->Label(), Entry );
161   Entry.Insert(1, "=>[");
162   Entry += "]";
163
164   TDataStd_Name::Set(L, TCollection_ExtendedString( Entry ));
165 }
166
167
168 //=======================================================================
169 //function : SetLabelNameByShape
170 //purpose  : 
171 //=======================================================================
172 static void SetLabelNameByShape(const TDF_Label L) 
173 {
174   TopoDS_Shape S;
175   if (XCAFDoc_ShapeTool::GetShape(L, S) &&
176       ! L.IsAttribute(TDataStd_Name::GetID()) ) {
177     Standard_SStream Stream;
178 //    TopAbs_ShapeEnum Type = S.ShapeType();
179 //    if (Type == TopAbs_COMPOUND) Stream<<"ASSEMBLY";
180 //    else 
181     TopAbs::Print(S.ShapeType(), Stream);
182    
183 #ifdef USE_STL_STREAM    
184     TCollection_AsciiString aName (Stream.str().c_str());
185 #else
186     Stream << ends;
187     TCollection_AsciiString aName (Stream.str());
188 #endif    
189     TDataStd_Name::Set(L, TCollection_ExtendedString(aName));
190   }
191 }
192 #endif
193
194
195 //=======================================================================
196 //function : SearchUsingMap
197 //purpose  : 
198 //=======================================================================
199
200 Standard_Boolean XCAFDoc_ShapeTool::SearchUsingMap(const TopoDS_Shape &S, TDF_Label &L,
201                                                    const Standard_Boolean findWithoutLoc,
202                                                    const Standard_Boolean findSubShape) const
203 {
204
205   if(myShapeLabels.IsBound(S)) {
206     L = myShapeLabels.Find(S);
207     return Standard_True;
208   }
209   TopoDS_Shape S0 = S;
210   TopLoc_Location loc;
211   S0.Location(loc);
212   if(myShapeLabels.IsBound(S0)) {
213     TDF_Label L1 = myShapeLabels.Find(S0);
214     TDF_LabelSequence Labels;
215     if(GetUsers(L1, Labels, Standard_True)) {
216       for(Standard_Integer i=1; i<=Labels.Length(); i++) {
217         TopoDS_Shape c = GetShape(Labels.Value(i));
218         if(c.IsSame(S)) {
219           L = Labels.Value(i);
220           return Standard_True;
221         }
222       }
223     }
224     if(findWithoutLoc) {
225       L = L1;
226       return Standard_True;
227     }
228   }
229
230   if(hasSimpleShapes) {
231     if(mySimpleShapes.IsBound(S)) {
232       L = mySimpleShapes.Find(S);
233       return Standard_True;
234     }
235     if(mySimpleShapes.IsBound(S0)) {
236       L = mySimpleShapes.Find(S0);
237       return Standard_True;
238     }
239   }
240   // search subshapes
241   if(!findSubShape) return Standard_False;
242   TDF_Label mainL = FindMainShapeUsingMap(S);
243   if(mainL.IsNull()) return Standard_False;
244   L = AddSubShape(mainL,S);
245   return !L.IsNull();//Standard_True;
246 }
247
248
249 //=======================================================================
250 //function : Search
251 //purpose  : 
252 //=======================================================================
253
254 Standard_Boolean XCAFDoc_ShapeTool::Search (const TopoDS_Shape &S, 
255                                          TDF_Label &L,
256                                          const Standard_Boolean findInstance,
257                                          const Standard_Boolean findComponent,
258                                          const Standard_Boolean findSubShape) const
259 {
260   // search among shapes
261   Standard_Boolean isLocated = ! S.Location().IsIdentity();
262   
263   if ( isLocated ) {
264     // try to find top-level instance
265     if ( findInstance && FindShape ( S, L, Standard_True ) )
266       return Standard_True;
267     // try to find component of assembly
268     if ( findComponent ) {
269       TDF_LabelSequence labels;
270       GetShapes ( labels );
271       for ( Standard_Integer i=1; i <= labels.Length(); i++ ) {
272         if ( ! IsAssembly ( labels.Value(i) ) ) continue;
273         TDF_LabelSequence comp;
274         GetComponents ( labels.Value(i), comp );
275         for ( Standard_Integer j=1; j <= comp.Length(); j++ ) {
276           TopoDS_Shape c = GetShape ( comp.Value(j) );
277           if ( c.IsSame ( S ) ) {
278             L = comp.Value(j);
279             return Standard_True;
280           }
281         }
282       }
283     }
284   }
285   // try to find top-level simple shape
286   if ( FindShape ( S, L, Standard_False ) ) return Standard_True;
287   
288   // search subshapes
289   if ( ! findSubShape ) return Standard_False;
290   TDF_Label mainL = FindMainShape ( S );
291   if ( mainL.IsNull() ) return Standard_False;
292   L = AddSubShape ( mainL, S );
293   return !L.IsNull();//Standard_True;
294 }
295
296 //=======================================================================
297 //function : FindShape
298 //purpose  : 
299 //=======================================================================
300
301 Standard_Boolean XCAFDoc_ShapeTool::FindShape (const TopoDS_Shape& S, 
302                                                TDF_Label& L,
303                                                const Standard_Boolean findInstance) const
304 {
305   // search for null-located shape
306   TopoDS_Shape S0 = S;
307   if ( ! findInstance ) {
308     TopLoc_Location loc;
309     S0.Location ( loc );
310   }
311
312   // this code is used instead of the following for performance reasons
313   if (TNaming_Tool::HasLabel(Label(), S0)) {
314     int TransDef = 0;
315     L = TNaming_Tool::Label(Label(), S0, TransDef);
316     return Standard_True;
317   }
318 /*
319   TDF_ChildIDIterator it(myLabel,TNaming_NamedShape::GetID());
320   for (; it.More(); it.Next()) {
321     TDF_Label aLabel = it.Value()->Label();
322     Handle(TNaming_NamedShape) NS;
323     if ( aLabel.FindAttribute(TNaming_NamedShape::GetID(), NS) &&
324          S0.IsSame ( TNaming_Tool::GetShape(NS) ) ) {
325       L = aLabel;
326       return Standard_True;
327     }
328   }
329 */
330   return Standard_False;
331 }
332
333 //=======================================================================
334 //function : FindShape
335 //purpose  : 
336 //=======================================================================
337
338 TDF_Label XCAFDoc_ShapeTool::FindShape (const TopoDS_Shape& S,
339                                      const Standard_Boolean findInstance) const
340 {
341   TDF_Label L;
342   FindShape ( S, L, findInstance );
343   return L;
344 }
345
346 //=======================================================================
347 //function : GetShape
348 //purpose  : 
349 //=======================================================================
350
351 Standard_Boolean XCAFDoc_ShapeTool::GetShape (const TDF_Label& L, TopoDS_Shape& S) 
352 {
353   Handle(XCAFDoc_Location) LocationAttribute;
354
355   if(IsExternRef(L)) {
356     TopoDS_Compound EmptyComp;
357     BRep_Builder B;
358     B.MakeCompound(EmptyComp);
359     S = EmptyComp;
360   }
361
362   // for instance, get referred shape
363   Handle(TDataStd_TreeNode) Node;
364   if ( L.FindAttribute(XCAFDoc::ShapeRefGUID(), Node) && Node->HasFather() && 
365        L.FindAttribute(XCAFDoc_Location::GetID(), LocationAttribute)) {
366     if ( ! GetShape(Node->Father()->Label(), S) ) return Standard_False;
367     S.Move ( LocationAttribute->Get() );
368     return Standard_True;
369   }
370
371   // else just return shape on this label
372   Handle(TNaming_NamedShape) NS;
373   if ( ! L.FindAttribute(TNaming_NamedShape::GetID(), NS) ) return Standard_False;
374   S = TNaming_Tool::GetShape(NS);
375   return Standard_True;
376 }
377
378 //=======================================================================
379 //function : GetShape
380 //purpose  : 
381 //=======================================================================
382
383 TopoDS_Shape XCAFDoc_ShapeTool::GetShape(const TDF_Label& L) 
384 {
385   TopoDS_Shape aShape;
386   GetShape(L,aShape);
387   return aShape;
388 }
389
390 //=======================================================================
391 //function : NewShape
392 //purpose  : 
393 //=======================================================================
394
395 TDF_Label XCAFDoc_ShapeTool::NewShape() const
396 {
397   TopoDS_Compound aShape;
398   BRep_Builder tdsB;
399   tdsB.MakeCompound ( aShape );
400
401   TDF_TagSource aTag;
402   TDF_Label aLabel = aTag.NewChild(Label());
403   
404   TNaming_Builder tnBuild(aLabel);
405   tnBuild.Generated(aShape);
406   
407   return aLabel;
408 }
409
410 //=======================================================================
411 //function : SetShape
412 //purpose  : 
413 //=======================================================================
414
415 void XCAFDoc_ShapeTool::SetShape (const TDF_Label& L, const TopoDS_Shape& S)
416 {
417   TNaming_Builder tnBuild(L);
418   tnBuild.Generated(S);
419   Handle(XCAFDoc_ShapeMapTool) A = XCAFDoc_ShapeMapTool::Set(L);
420 //  if ( ! L.FindAttribute(XCAFDoc_ShapeMapTool::GetID(), A) ) {
421 //    A = XCAFDoc_ShapeMapTool::Set(L);
422 //    L.AddAttribute(A);
423 //  }
424   A->SetShape(S);
425
426   if(!myShapeLabels.IsBound(S)) {
427     myShapeLabels.Bind(S,L);
428   }
429   
430   //:abv 31.10.01: update assemblies that refer a shape
431   TDF_LabelSequence Labels;
432   if ( GetUsers ( L, Labels, Standard_True ) ) {
433     for ( Standard_Integer i=Labels.Length(); i >=1; i-- ) 
434       UpdateAssembly ( Labels(i) );
435   }
436 }
437
438 //=======================================================================
439 //function : MakeReference
440 //purpose  : 
441 //=======================================================================
442
443 void XCAFDoc_ShapeTool::MakeReference (const TDF_Label &L, 
444                                     const TDF_Label &refL,
445                                     const TopLoc_Location &loc)
446 {
447   // store location
448   XCAFDoc_Location::Set(L, loc);
449     
450     // set reference
451   Handle(TDataStd_TreeNode) refNode, mainNode;
452   mainNode = TDataStd_TreeNode::Set ( refL, XCAFDoc::ShapeRefGUID() );
453   refNode  = TDataStd_TreeNode::Set ( L,    XCAFDoc::ShapeRefGUID() );
454   refNode->Remove(); // abv: fix against bug in TreeNode::Append()
455   mainNode->Append(refNode);
456
457 #ifdef AUTONAMING
458   SetLabelNameByLink(L);
459 #endif
460 }
461
462 //=======================================================================
463 //function : addShape
464 //purpose  : private
465 //=======================================================================
466
467 TDF_Label XCAFDoc_ShapeTool::addShape (const TopoDS_Shape& S, const Standard_Boolean makeAssembly)
468 {
469   TDF_Label ShapeLabel;
470   TDF_TagSource aTag;
471
472   // search if the shape already exists (with the same location)
473   if ( S.IsNull() || FindShape ( S, ShapeLabel, Standard_True ) ) return ShapeLabel;
474   
475   // else add a new label
476   ShapeLabel = aTag.NewChild(Label());
477   
478   // if shape has location, make a reference to the same shape without location
479   if ( ! S.Location().IsIdentity() /*&& FindShape ( S, L )*/ ) {
480     TopoDS_Shape S0 = S;
481     TopLoc_Location loc;
482     S0.Location ( loc );
483     TDF_Label L = addShape ( S0, makeAssembly );
484     MakeReference ( ShapeLabel, L, S.Location() );
485     return ShapeLabel;
486   }
487   
488   // else add a shape to a label
489   TNaming_Builder tnBuild(ShapeLabel);
490   tnBuild.Generated(S);
491   
492   Handle(XCAFDoc_ShapeMapTool) A = XCAFDoc_ShapeMapTool::Set(ShapeLabel);
493 //  if ( ! ShapeLabel.FindAttribute(XCAFDoc_ShapeMapTool::GetID(), A) ) {
494 //    A = XCAFDoc_ShapeMapTool::Set(ShapeLabel);
495 //    ShapeLabel.AddAttribute(A);
496 //  }
497   A->SetShape(S);
498   
499 #ifdef AUTONAMING
500   SetLabelNameByShape(ShapeLabel);
501 #endif
502
503   // if shape is Compound and flag is set, create assembly
504   if ( makeAssembly && S.ShapeType() == TopAbs_COMPOUND ) {
505     // mark assembly by assigning UAttribute
506     Handle(TDataStd_UAttribute) Uattr;
507     Uattr = TDataStd_UAttribute::Set ( ShapeLabel, XCAFDoc::AssemblyGUID() );
508 #ifdef AUTONAMING
509     TDataStd_Name::Set(ShapeLabel, TCollection_ExtendedString("ASSEMBLY"));
510 #endif
511
512     // iterate on components
513     TopoDS_Iterator Iterator(S);
514     for (; Iterator.More(); Iterator.Next()) {
515       // get label for component`s shape
516       TopoDS_Shape Scomp = Iterator.Value(), S0 = Scomp;
517       TopLoc_Location loc;
518       S0.Location ( loc );
519       TDF_Label compL = addShape ( S0, makeAssembly );
520       
521       // add a component as reference
522       TDF_Label RefLabel = aTag.NewChild(ShapeLabel);
523       MakeReference ( RefLabel, compL, Scomp.Location() );
524     }
525   }
526   
527   if(!IsAssembly(ShapeLabel)) {
528     //const TopTools_IndexedMapOfShape tmpMap = A->GetMap();
529     //for(Standard_Integer i=1; i<=tmpMap.Extent(); i++)
530     //mySubShapes.Bind(tmpMap.FindKey(i),ShapeLabel);
531     for(Standard_Integer i=1; i<=A->GetMap().Extent(); i++)
532     mySubShapes.Bind(A->GetMap().FindKey(i),ShapeLabel);
533     //mySubShapes.Bind(ShapeLabel,A->GetMap());
534   }
535
536   return ShapeLabel;
537 }
538
539
540 //=======================================================================
541 //function : prepareAssembly
542 //purpose  : auxilary
543 //=======================================================================
544 static Standard_Boolean prepareAssembly (const TopoDS_Shape& theShape,
545                                          TopoDS_Shape& theOUTShape)
546 {
547   // iterate on components
548   theOUTShape = theShape;
549   if (theShape.ShapeType() == TopAbs_COMPOUND) {
550     BRep_Builder B;
551     // check if shape if frosen
552     if (!theOUTShape.Free())
553       theOUTShape.Free(Standard_True);
554     
555     TopTools_SequenceOfShape aSubShapeSeq;
556     TopoDS_Iterator Iterator(theShape);
557     for (; Iterator.More(); Iterator.Next())
558       aSubShapeSeq.Append(Iterator.Value());
559     for (Standard_Integer i = 1; i <= aSubShapeSeq.Length(); i++) {
560       TopoDS_Shape Scomp = aSubShapeSeq.Value(i);
561       TopoDS_Shape aNewScomp;
562       B.Remove(theOUTShape, Scomp);
563       prepareAssembly( Scomp, aNewScomp );
564       TopLoc_Location aLoc;
565       aLoc = aNewScomp.Location();
566       if ( aLoc.IsIdentity() ) {
567         // create an "empty" location
568         gp_Trsf aTrsf;
569         aTrsf.SetScale(gp_Pnt(0,0,0), 1);
570         aLoc = TopLoc_Location( aTrsf );
571         aNewScomp.Location( aLoc );
572       }
573       B.Add(theOUTShape, aNewScomp);
574     }
575   }
576   return Standard_True;
577 }
578
579
580 //=======================================================================
581 //function : AddShape
582 //purpose  : 
583 //=======================================================================
584
585 TDF_Label XCAFDoc_ShapeTool::AddShape (const TopoDS_Shape& theShape,
586                                        const Standard_Boolean makeAssembly,
587                                        const Standard_Boolean makePrepare)
588 {
589   // PTV 17.02.2003 to avoid components without location.
590   TopoDS_Shape S = theShape;
591   if ( makePrepare && makeAssembly && S.ShapeType() == TopAbs_COMPOUND )
592     prepareAssembly( theShape, S ); // OCC1669
593   
594   TDF_Label L = addShape(S,makeAssembly);
595
596   if(!myShapeLabels.IsBound(S)) {
597     myShapeLabels.Bind(S,L);
598   }
599
600   return L;
601
602   //return addShape( S, makeAssembly );
603 }
604
605 //=======================================================================
606 //function : RemoveShape
607 //purpose  : 
608 //=======================================================================
609
610 Standard_Boolean XCAFDoc_ShapeTool::RemoveShape (const TDF_Label& L) const
611 {
612   if ( ! IsTopLevel ( L ) || ! IsFree ( L ) ) return Standard_False;
613   L.ForgetAllAttributes (Standard_True);
614   return Standard_True;
615 }
616
617
618 //=======================================================================
619 //function : Init
620 //purpose  : 
621 //=======================================================================
622
623 void XCAFDoc_ShapeTool::Init()
624 {
625   hasSimpleShapes = Standard_False;
626 }
627
628
629 //=======================================================================
630 //function : ComputeShapes
631 //purpose  : 
632 //=======================================================================
633
634 void XCAFDoc_ShapeTool::ComputeShapes(const TDF_Label& L)
635 {
636   TDF_ChildIterator it(L); 
637   for(; it.More(); it.Next()) {
638     TDF_Label L1 = it.Value();
639     TopoDS_Shape S;
640     if(GetShape(L1,S)) {
641       if(!myShapeLabels.IsBound(S)) {
642         mySimpleShapes.Bind(S,L1);
643       }
644     }
645     ComputeShapes(L1);
646   }
647 }
648
649
650 //=======================================================================
651 //function : ComputeSimpleShapes
652 //purpose  : 
653 //=======================================================================
654
655 void XCAFDoc_ShapeTool::ComputeSimpleShapes()
656 {
657   ComputeShapes(Label());
658   hasSimpleShapes = Standard_True;
659 }
660
661
662 //=======================================================================
663 //function : GetShapes
664 //purpose  : 
665 //=======================================================================
666
667 void XCAFDoc_ShapeTool::GetShapes(TDF_LabelSequence& Labels) const
668 {
669   Labels.Clear();
670
671   TDF_ChildIterator it(Label()); 
672   for (; it.More(); it.Next()) {
673     TDF_Label L = it.Value();
674     TopoDS_Shape S;
675     if ( GetShape ( L, S ) ) Labels.Append ( L );
676   }
677 }
678
679
680 //=======================================================================
681 //function : GetFreeShapes
682 //purpose  : 
683 //=======================================================================
684
685 void XCAFDoc_ShapeTool::GetFreeShapes (TDF_LabelSequence& FreeLabels) const
686 {
687   FreeLabels.Clear();
688
689   TDF_ChildIterator it(Label());
690   for (; it.More(); it.Next()) {
691     TDF_Label L = it.Value();
692     TopoDS_Shape S;
693     if ( GetShape ( L, S ) && IsFree ( L ) ) FreeLabels.Append ( L );
694   }
695 }
696
697 //=======================================================================
698 //function : IsTopLevel
699 //purpose  : 
700 //=======================================================================
701
702 Standard_Boolean XCAFDoc_ShapeTool::IsTopLevel (const TDF_Label& L) const
703 {
704   return L.Father() == Label();
705 }
706
707 //=======================================================================
708 //function : IsShape
709 //purpose  : 
710 //=======================================================================
711
712 Standard_Boolean XCAFDoc_ShapeTool::IsShape (const TDF_Label& L) 
713 {
714   return IsSimpleShape ( L ) || IsAssembly ( L ) || IsReference ( L );
715 }
716
717 //=======================================================================
718 //function : IsSimpleShape
719 //purpose  : 
720 //=======================================================================
721
722 Standard_Boolean XCAFDoc_ShapeTool::IsSimpleShape (const TDF_Label& L) 
723 {
724   Handle(TNaming_NamedShape) NS;
725   return L.FindAttribute ( TNaming_NamedShape::GetID(), NS ) &&
726          ! IsAssembly ( L ) && ! IsReference ( L );
727 }
728
729 //=======================================================================
730 //function : IsReference
731 //purpose  : 
732 //=======================================================================
733
734 Standard_Boolean XCAFDoc_ShapeTool::IsReference (const TDF_Label& L)
735 {
736   Handle(TDataStd_TreeNode) Node;
737   return L.FindAttribute(XCAFDoc::ShapeRefGUID(), Node) && Node->HasFather();
738 }
739
740 //=======================================================================
741 //function : IsAssembly
742 //purpose  : 
743 //=======================================================================
744
745 Standard_Boolean XCAFDoc_ShapeTool::IsAssembly (const TDF_Label& L) 
746 {
747   Handle(TDataStd_UAttribute) Uattr;
748   return L.FindAttribute(XCAFDoc::AssemblyGUID(), Uattr);
749 }
750
751 //=======================================================================
752 //function : IsComponent
753 //purpose  : 
754 //=======================================================================
755
756 Standard_Boolean XCAFDoc_ShapeTool::IsComponent (const TDF_Label& L)
757 {
758   return IsReference ( L ) && IsAssembly ( L.Father() );
759 }
760
761 //=======================================================================
762 //function : IsCompound
763 //purpose  : 
764 //=======================================================================
765
766 Standard_Boolean XCAFDoc_ShapeTool::IsCompound (const TDF_Label& L) 
767 {
768   Handle(TDataStd_Name) Name;
769   if (L.FindAttribute(TDataStd_Name::GetID(),Name)) {
770     TCollection_ExtendedString estr1 = Name->Get();
771     TCollection_ExtendedString estr2("COMPOUND");
772     if(estr1==estr2) {
773       return Standard_True;
774     }
775   }
776   return Standard_False;
777 }
778
779 //=======================================================================
780 //function : IsSubShape
781 //purpose  : 
782 //=======================================================================
783
784 Standard_Boolean XCAFDoc_ShapeTool::IsSubShape (const TDF_Label& L)
785 {
786   return IsSimpleShape ( L ) && IsShape ( L.Father() );
787 }
788
789 //=======================================================================
790 //function : IsFree
791 //purpose  : 
792 //=======================================================================
793
794 Standard_Boolean XCAFDoc_ShapeTool::IsFree (const TDF_Label& L) 
795 {
796   Handle(TDataStd_TreeNode) Node;
797   if ( ! L.FindAttribute(XCAFDoc::ShapeRefGUID(), Node) || 
798        ! Node->HasFirst() ) return Standard_True;
799
800   return Standard_False;
801 }
802
803 //=======================================================================
804 //function : GetUsers
805 //purpose  : Returns number of users (0 if shape is free)
806 //=======================================================================
807
808 Standard_Integer XCAFDoc_ShapeTool::GetUsers (const TDF_Label& L, 
809                                               TDF_LabelSequence& Labels,
810                                               const Standard_Boolean getsubchilds)
811 {
812   Standard_Integer NbUsers=0;
813   Handle(TDataStd_TreeNode) Node  ;
814
815   if ( ! L.FindAttribute(XCAFDoc::ShapeRefGUID(), Node) ) return NbUsers;
816   
817   Node = Node->First();
818   while ( ! Node.IsNull() ) {
819     
820     if ( getsubchilds ) {
821       TDF_Label underL = Node->Label().Father();
822       NbUsers += GetUsers ( underL, Labels, getsubchilds );
823     }
824     
825     Labels.Append(Node->Label());
826     Node = Node->Next();
827     NbUsers++;
828   }
829   return NbUsers;
830 }
831   
832 //=======================================================================
833 //function : NbComponents
834 //purpose  : 
835 //=======================================================================
836
837 Standard_Integer XCAFDoc_ShapeTool::NbComponents (const TDF_Label& L,
838                                                   const Standard_Boolean getsubchilds) 
839 {
840   TDF_LabelSequence subLabels;
841   GetComponents (L, subLabels, getsubchilds);
842   return subLabels.Length();
843 }
844
845 //=======================================================================
846 //function : GetComponents
847 //purpose  : 
848 //=======================================================================
849
850 Standard_Boolean XCAFDoc_ShapeTool::GetComponents (const TDF_Label& L, TDF_LabelSequence& Labels,
851                                                    const Standard_Boolean getsubchilds) 
852 {
853   if ( ! IsAssembly(L) ) return Standard_False;
854   
855   TDF_ChildIterator It(L);
856   for (; It.More(); It.Next() ) {
857     TDF_Label comp = It.Value();
858     if ( IsComponent ( comp ) ) {
859       if ( getsubchilds ) {
860         TDF_Label underL;
861         if ( GetReferredShape ( comp, underL ) )
862           GetComponents ( underL, Labels, getsubchilds);
863       }
864       Labels.Append ( comp );
865     }
866   }
867   return Standard_True;
868 }
869
870 //=======================================================================
871 //function : GetLocation
872 //purpose  : 
873 //=======================================================================
874
875 TopLoc_Location XCAFDoc_ShapeTool::GetLocation (const TDF_Label& L)
876 {
877   Handle(XCAFDoc_Location) LocationAttribute;
878   if (L.FindAttribute(XCAFDoc_Location::GetID(), LocationAttribute)) 
879     return LocationAttribute->Get();
880   
881   Handle(TNaming_NamedShape) NS;
882   TopoDS_Shape S;
883   if ( L.FindAttribute ( TNaming_NamedShape::GetID(), NS ) ) {
884     S = TNaming_Tool::GetShape(NS);
885   }
886   return S.Location();
887 }
888
889 //=======================================================================
890 //function : GetReferredShape
891 //purpose  : 
892 //=======================================================================
893
894 Standard_Boolean XCAFDoc_ShapeTool::GetReferredShape (const TDF_Label& L, 
895                                                       TDF_Label& Label)
896 {
897   if ( ! IsReference(L) ) return Standard_False;
898   
899   Handle (TDataStd_TreeNode) Node;
900   L.FindAttribute(XCAFDoc::ShapeRefGUID(), Node);
901   Label = Node->Father()->Label();
902   return Standard_True;
903 }
904
905 //=======================================================================
906 //function : AddComponent
907 //purpose  : 
908 //=======================================================================
909
910 TDF_Label XCAFDoc_ShapeTool::AddComponent (const TDF_Label& assembly, 
911                                            const TDF_Label& compL, 
912                                            const TopLoc_Location &Loc) const
913 {
914   TDF_Label L;
915   
916   // check that shape is assembly
917   if ( ! IsAssembly(assembly) ) {
918     // if it is simple shape, make it assembly
919     if ( IsSimpleShape(assembly) ) 
920       TDataStd_UAttribute::Set ( assembly, XCAFDoc::AssemblyGUID() );
921     else return L;
922   }
923   
924   // add a component as reference
925   TDF_TagSource aTag;
926   L = aTag.NewChild(assembly);
927   MakeReference ( L, compL, Loc );
928
929   // update assembly`s TopoDS_Shape
930   UpdateAssembly ( assembly );
931   return L;
932 }
933
934 //=======================================================================
935 //function : AddComponent
936 //purpose  : 
937 //=======================================================================
938
939 TDF_Label XCAFDoc_ShapeTool::AddComponent (const TDF_Label& assembly, 
940                                            const TopoDS_Shape& comp,
941                                            const Standard_Boolean expand)
942 {
943   // get label for component`s shape
944   TopoDS_Shape S0 = comp;
945   TopLoc_Location loc;
946   S0.Location ( loc );
947   TDF_Label compL;
948   compL = AddShape ( S0, expand );
949   
950   // add component by its label
951   return AddComponent ( assembly, compL, comp.Location() );
952 }
953
954 //=======================================================================
955 //function : RemoveComponent
956 //purpose  : 
957 //=======================================================================
958
959 void XCAFDoc_ShapeTool::RemoveComponent (const TDF_Label& comp) const
960 {
961   if ( IsComponent(comp) ) {
962     comp.ForgetAllAttributes();
963     UpdateAssembly(comp.Father());
964   }
965 }
966
967 //=======================================================================
968 //function : UpdateAssembly
969 //purpose  : 
970 //=======================================================================
971
972 void XCAFDoc_ShapeTool::UpdateAssembly (const TDF_Label& L) const
973 {
974   if ( ! IsAssembly(L) ) return;
975
976   TopoDS_Compound newassembly;
977   BRep_Builder b;
978   b.MakeCompound(newassembly);
979
980   TDF_ChildIterator chldLabIt(L);
981   for (; chldLabIt.More(); chldLabIt.Next() ) {
982     TDF_Label subLabel = chldLabIt.Value();
983     if ( IsComponent ( subLabel ) ) {
984       b.Add(newassembly, GetShape(subLabel));
985     }
986   }
987   TNaming_Builder tnBuild(L);
988   tnBuild.Generated(newassembly);
989 }
990
991 //=======================================================================
992 //function : IsSubShape
993 //purpose  : 
994 //=======================================================================
995
996 //static Standard_Boolean CheckSubShape (const TopoDS_Shape &S, const TopoDS_Shape &sub)
997 //{
998 //  if ( S.IsSame ( sub ) ) return Standard_True;
999 //  
1000 //  if ( S.ShapeType() >= sub.ShapeType() ) return Standard_False;
1001 //  
1002 //  for ( TopoDS_Iterator it(S); it.More(); it.Next() ) {
1003 //    if ( CheckSubShape ( it.Value(), sub ) ) return Standard_True;
1004 //  }
1005 //  return Standard_False;
1006 //}
1007
1008 //=======================================================================
1009 //function : IsSubShape
1010 //purpose  : 
1011 //=======================================================================
1012
1013 Standard_Boolean XCAFDoc_ShapeTool::IsSubShape (const TDF_Label &shapeL,
1014                                              const TopoDS_Shape &sub) const
1015 {
1016   Handle(XCAFDoc_ShapeMapTool) A;
1017   if ( ! shapeL.FindAttribute(XCAFDoc_ShapeMapTool::GetID(), A) )
1018     return Standard_False;
1019   
1020   //TopoDS_Shape S = GetShape ( shapeL );
1021   //return ! S.IsNull() && CheckSubShape ( S, sub );
1022   
1023   return A->IsSubShape(sub);
1024 }
1025
1026 //=======================================================================
1027 //function : FindSubShape
1028 //purpose  : 
1029 //=======================================================================
1030
1031 Standard_Boolean XCAFDoc_ShapeTool::FindSubShape (const TDF_Label &shapeL,
1032                                                   const TopoDS_Shape &sub,
1033                                                   TDF_Label &L) const
1034 {
1035   // this code is used instead of the following for performance reasons
1036   if ( TNaming_Tool::HasLabel(Label(), sub) ) {
1037     int TransDef = 0;
1038     L = TNaming_Tool::Label(Label(), sub, TransDef);
1039     return ( ! L.IsNull() && L.Father() == shapeL );
1040   }
1041
1042 /*
1043   TDF_ChildIterator chldLabIt(shapeL);
1044   for (; chldLabIt.More(); chldLabIt.Next() ) {
1045     TDF_Label subLabel = chldLabIt.Value();
1046     TopoDS_Shape S;
1047     if ( GetShape ( subLabel, S ) && S.IsSame ( sub ) ) {
1048       L = subLabel;
1049       return Standard_True;
1050     }
1051   }
1052 */
1053   return Standard_False;
1054 }
1055
1056 //=======================================================================
1057 //function : AddSubShape
1058 //purpose  : 
1059 //=======================================================================
1060
1061 TDF_Label XCAFDoc_ShapeTool::AddSubShape (const TDF_Label &shapeL,
1062                                           const TopoDS_Shape &sub) const
1063 {
1064   TDF_Label L;
1065   if ( FindSubShape ( shapeL, sub, L ) ) return L;
1066   
1067   if ( ! IsSubShape ( shapeL, sub ) ) return L;
1068   
1069   TDF_TagSource aTag;
1070   L = aTag.NewChild(shapeL);
1071   
1072   TNaming_Builder tnBuild(L);
1073   tnBuild.Generated(sub);
1074
1075 //  if(!mySubShapes.IsBound(sub))
1076 //    mySubShapes.Bind(sub,L);
1077    
1078   return L;
1079 }
1080
1081
1082 //=======================================================================
1083 //function : FindMainShapeUsingMap
1084 //purpose  : 
1085 //=======================================================================
1086
1087 TDF_Label XCAFDoc_ShapeTool::FindMainShapeUsingMap(const TopoDS_Shape &sub) const
1088 {
1089   //for(Standard_Integer i=1; i<=myNotAssemblies.Length(); i++) {
1090   //  TDF_Label L = myNotAssemblies.Value(i);
1091   //  if(IsSubShape(L,sub)) return L;
1092   //}
1093   if(mySubShapes.IsBound(sub))
1094     return mySubShapes.Find(sub);
1095   TDF_Label L0;
1096   return L0;
1097 }
1098
1099
1100 //=======================================================================
1101 //function : FindMainShape
1102 //purpose  : 
1103 //=======================================================================
1104
1105 TDF_Label XCAFDoc_ShapeTool::FindMainShape (const TopoDS_Shape &sub) const
1106 {
1107   TDF_ChildIterator it(Label());
1108   for (; it.More(); it.Next()) {
1109     TDF_Label L = it.Value();
1110     if ( ! IsAssembly ( L ) && IsSubShape ( L, sub ) ) return L;
1111   }
1112   TDF_Label L0;
1113   return L0;
1114 }
1115
1116
1117 //=======================================================================
1118 //function : GetSubShapes
1119 //purpose  : 
1120 //=======================================================================
1121
1122 Standard_Boolean XCAFDoc_ShapeTool::GetSubShapes (const TDF_Label &L, 
1123                                                TDF_LabelSequence& Labels)
1124 {
1125   TDF_ChildIterator It(L);
1126   for (; It.More(); It.Next() ) {
1127     TDF_Label sub = It.Value();
1128     if ( IsSubShape ( sub ) ) Labels.Append ( sub );
1129   }
1130   return Labels.Length() >0;
1131 }
1132
1133 //=======================================================================
1134 //function : BaseLabel
1135 //purpose  : 
1136 //=======================================================================
1137
1138 TDF_Label XCAFDoc_ShapeTool::BaseLabel () const
1139 {
1140   return Label();
1141 }
1142
1143 //=======================================================================
1144 //function : DumpAssembly
1145 //purpose  : recursive part of Dump()
1146 //=======================================================================
1147
1148 static void DumpAssembly(const TDF_Label L,
1149                          const Standard_Integer level,
1150                          const Standard_Boolean deep)
1151 {
1152   for (Standard_Integer i=0; i<level; i++)
1153     cout<<"\t";
1154   
1155   TCollection_AsciiString Entry;
1156   TDF_Tool::Entry(L, Entry);
1157
1158   cout<<"ASSEMBLY "<<Entry;
1159   Handle(TDataStd_Name) Name;
1160   if (L.FindAttribute(TDataStd_Name::GetID(), Name))
1161     cout<<" "<<Name->Get();
1162   
1163   if (deep) {
1164     TopoDS_Shape S;
1165     XCAFDoc_ShapeTool::GetShape(L, S);
1166     cout<<"("<<*(void**)&S.TShape();
1167     if (! S.Location().IsIdentity())
1168       cout<<", "<< *(void**)&S.Location();
1169     cout<<") ";
1170   }
1171   cout<<endl;
1172   
1173   Handle(TDataStd_TreeNode) Node;
1174   TDF_ChildIDIterator NodeIterator(L, XCAFDoc::ShapeRefGUID());
1175   for (; NodeIterator.More(); NodeIterator.Next()) {
1176     Node = Handle(TDataStd_TreeNode)::DownCast(NodeIterator.Value());
1177     if (Node->HasFather()) {
1178       if (Node->Father()->Label().HasChild())
1179         DumpAssembly(Node->Father()->Label(), level+1, deep);
1180       else {
1181         XCAFDoc_ShapeTool::DumpShape(Node->Father()->Label(), level+1, deep);
1182           cout<<endl;
1183         }
1184     }
1185   }
1186 }
1187
1188 //=======================================================================
1189 //function : Dump
1190 //purpose  : 
1191 //=======================================================================
1192
1193 void XCAFDoc_ShapeTool::Dump(const Standard_Boolean deep) const
1194 {
1195   Standard_Integer level = 0;
1196 //   TopTools_SequenceOfShape SeqShapes;
1197   TDF_LabelSequence SeqLabels;
1198   GetShapes( SeqLabels);
1199
1200   if (SeqLabels.Length()>0) cout<<endl;
1201   Standard_Integer i;
1202   for (i=1; i<=SeqLabels.Length(); i++) {
1203     DumpAssembly(SeqLabels.Value(i), level, deep);
1204   }
1205
1206   SeqLabels.Clear();
1207   GetFreeShapes(SeqLabels);
1208   cout<<endl<<"Free Shapes: "<<SeqLabels.Length()<<endl;
1209   for (i = 1; i<=SeqLabels.Length(); i++) {
1210     DumpShape(SeqLabels.Value(i), level, deep);
1211     cout<<endl;
1212   }
1213 }
1214
1215 //=======================================================================
1216 //function : DumpShape
1217 //purpose  : 
1218 //=======================================================================
1219
1220 void XCAFDoc_ShapeTool::DumpShape(const TDF_Label& L,const Standard_Integer level,const Standard_Boolean deep) 
1221 {
1222   TopoDS_Shape S;
1223   if(! XCAFDoc_ShapeTool::GetShape(L, S) ) return;
1224   for (Standard_Integer i=0; i<level; i++)
1225     cout<<"\t";
1226   
1227   if (S.ShapeType() == TopAbs_COMPOUND) cout<<"ASSEMBLY";
1228   else TopAbs::Print(S.ShapeType(), cout);
1229   
1230   TCollection_AsciiString Entry;
1231   TDF_Tool::Entry(L, Entry);
1232   cout<<"  "<<Entry;
1233   //cout<<endl;
1234   Handle(TDataStd_Name) Name;
1235   if (L.FindAttribute(TDataStd_Name::GetID(),Name)) 
1236     cout<<" "<<Name->Get();
1237   
1238   if (deep) {
1239     cout<<"("<<*(void**)&S.TShape();
1240     if (! S.Location().IsIdentity())
1241       cout<<", "<< *(void**)&S.Location();
1242     cout<<") ";
1243   }
1244 }
1245
1246 //=======================================================================
1247 //function : IsExternRef
1248 //purpose  : 
1249 //=======================================================================
1250
1251 Standard_Boolean XCAFDoc_ShapeTool::IsExternRef(const TDF_Label& L) 
1252 {
1253   Handle(TDataStd_UAttribute) Uattr;
1254   return L.FindAttribute(XCAFDoc::ExternRefGUID(), Uattr);
1255 }
1256
1257 //=======================================================================
1258 //function : SetExternRefs
1259 //purpose  : 
1260 //=======================================================================
1261
1262 void XCAFDoc_ShapeTool::SetExternRefs(const TDF_Label& L,
1263                                       const TColStd_SequenceOfHAsciiString& SHAS) const
1264 {
1265   TDF_Label ShapeLabel = L.NewChild();
1266   TDataStd_UAttribute::Set(ShapeLabel,XCAFDoc::ExternRefGUID());
1267   for(Standard_Integer i=1; i<=SHAS.Length(); i++) {
1268     TDF_Label tmplbl = ShapeLabel.FindChild(i,Standard_True);
1269     Handle(TCollection_HAsciiString) str = SHAS(i);
1270     TCollection_ExtendedString extstr(str->String());
1271     TDataStd_Name::Set(tmplbl,extstr);
1272   }
1273 }
1274
1275 //=======================================================================
1276 //function : SetExternRefs
1277 //purpose  : 
1278 //=======================================================================
1279
1280 TDF_Label XCAFDoc_ShapeTool::SetExternRefs(const TColStd_SequenceOfHAsciiString& SHAS) const
1281 {
1282   TDF_Label ShapeLabel;
1283   TDF_TagSource aTag;
1284   // add a new label
1285   ShapeLabel = aTag.NewChild(Label());
1286   TDataStd_UAttribute::Set(ShapeLabel,XCAFDoc::ExternRefGUID());
1287   for(Standard_Integer i=1; i<=SHAS.Length(); i++) {
1288     TDF_Label tmplbl = ShapeLabel.FindChild(i,Standard_True);
1289     Handle(TCollection_HAsciiString) str = SHAS(i);
1290     TCollection_ExtendedString extstr(str->String());
1291     TDataStd_Name::Set(tmplbl,extstr);
1292   }
1293   return ShapeLabel;
1294 }
1295
1296 //=======================================================================
1297 //function : GetExternRefs
1298 //purpose  : 
1299 //=======================================================================
1300
1301 void XCAFDoc_ShapeTool::GetExternRefs(const TDF_Label& L,
1302                                       TColStd_SequenceOfHAsciiString& SHAS)
1303 {
1304   Handle(TDataStd_Name) TDN;
1305   TDF_Label tmplbl;
1306   for(Standard_Integer i=1; i<=L.NbChildren(); i++) {
1307     tmplbl = L.FindChild(i);
1308     if(tmplbl.FindAttribute(TDataStd_Name::GetID(),TDN)) {
1309       TCollection_ExtendedString extstr = TDN->Get();
1310       Handle(TCollection_HAsciiString) str = 
1311         new TCollection_HAsciiString(TCollection_AsciiString(extstr, '?')); 
1312       SHAS.Append(str);
1313     }
1314   }
1315 }
1316
1317 // API: API work with SHUO (Specified Higher Usage Occurrance) structure
1318
1319 //=======================================================================
1320 //function : GetSHUO
1321 //purpose  : 
1322 //=======================================================================
1323
1324 Standard_Boolean XCAFDoc_ShapeTool::GetSHUO (const TDF_Label& SHUOLabel,
1325                                       Handle(XCAFDoc_GraphNode)& aSHUOAttr)
1326 {
1327   if ( !SHUOLabel.FindAttribute( XCAFDoc::SHUORefGUID(), aSHUOAttr ) )
1328     return Standard_False;
1329   return Standard_True;
1330 }
1331
1332 //=======================================================================
1333 //function : GetAllComponentSHUO
1334 //purpose  : 
1335 //=======================================================================
1336
1337 Standard_Boolean XCAFDoc_ShapeTool::GetAllComponentSHUO (const TDF_Label& theCompLabel,
1338                                                          TDF_AttributeSequence& theSHUOAttrs)
1339 {
1340   TDF_ChildIterator it(theCompLabel); 
1341   for (; it.More(); it.Next()) {
1342     TDF_Label L = it.Value();
1343     Handle(XCAFDoc_GraphNode) aSHUOAttr;
1344     if ( GetSHUO( L, aSHUOAttr ) )
1345       theSHUOAttrs.Append( aSHUOAttr );
1346   }
1347   return (theSHUOAttrs.Length() > 0);
1348 }
1349
1350 //=======================================================================
1351 //function : SetSHUO
1352 //purpose  : 
1353 //=======================================================================
1354
1355 Standard_Boolean XCAFDoc_ShapeTool::SetSHUO (const TDF_LabelSequence& labels,
1356                                              Handle(XCAFDoc_GraphNode)& MainSHUOAttr) const
1357 {
1358   MainSHUOAttr.Nullify();
1359   // check number of labels
1360   if (labels.Length() < 2)
1361     return Standard_False;
1362   // check is all labels contains components of any assemblyies 
1363   Standard_Integer i;
1364   for (i = 1; i <= labels.Length(); i++)
1365     if ( !IsComponent(labels.Value(i)) )
1366       return Standard_False;
1367   
1368   TDF_TagSource aTag;
1369   TDF_Label UpperSubL = aTag.NewChild( labels( 1 ) );
1370 #ifdef AUTONAMING
1371   TCollection_ExtendedString Entry("SHUO");
1372   TDataStd_Name::Set(UpperSubL, TCollection_ExtendedString( Entry ));
1373 #endif
1374   Handle(XCAFDoc_GraphNode) aUpperSHUO;
1375   aUpperSHUO = XCAFDoc_GraphNode::Set( UpperSubL, XCAFDoc::SHUORefGUID() );
1376   // init out argument by main upper usage SHUO
1377   MainSHUOAttr = aUpperSHUO;
1378   // add other next_usage occurrences.
1379   for (i = 2; i <= labels.Length(); i++) {
1380     TDF_Label NextSubL = aTag.NewChild( labels( i ) );
1381 #ifdef AUTONAMING
1382     TCollection_ExtendedString EntrySub("SHUO-");
1383     EntrySub += i;
1384     TDataStd_Name::Set(NextSubL, TCollection_ExtendedString( EntrySub ));
1385 #endif
1386     Handle(XCAFDoc_GraphNode) aNextSHUO;
1387     aNextSHUO = XCAFDoc_GraphNode::Set( NextSubL, XCAFDoc::SHUORefGUID() );
1388     // set references
1389     aUpperSHUO->SetChild( aNextSHUO );
1390     aNextSHUO->SetFather( aUpperSHUO );
1391     // now lets next_usage become upper_usage for next level of SHUO
1392     aUpperSHUO = aNextSHUO;
1393     UpperSubL = NextSubL;
1394   }
1395   
1396   return Standard_True;
1397 }
1398
1399 //=======================================================================
1400 //function : GetSHUOUpperUsage
1401 //purpose  : 
1402 //=======================================================================
1403
1404 Standard_Boolean XCAFDoc_ShapeTool::GetSHUOUpperUsage (const TDF_Label& NextUsageL,
1405                                                        TDF_LabelSequence& aLabels)
1406 {
1407   Handle(XCAFDoc_GraphNode) aNextSHUO;
1408   if( !GetSHUO( NextUsageL, aNextSHUO ) || aNextSHUO->NbFathers()<1 )
1409     return Standard_False;
1410   
1411   // get upper_usage SHAO
1412   for (Standard_Integer i = 1; i <= aNextSHUO->NbFathers(); i++)
1413     aLabels.Append( aNextSHUO->GetFather(i)->Label() );
1414   return Standard_True;
1415 }
1416
1417 //=======================================================================
1418 //function : GetSHUONextUsage
1419 //purpose  : 
1420 //=======================================================================
1421
1422 Standard_Boolean XCAFDoc_ShapeTool::GetSHUONextUsage (const TDF_Label& UpperUsageL,
1423                                                       TDF_LabelSequence& aLabels)
1424 {
1425   Handle(XCAFDoc_GraphNode) aUpperSHUO;
1426   if ( !GetSHUO( UpperUsageL, aUpperSHUO ) || aUpperSHUO->NbChildren()<1 )
1427     return Standard_False;
1428   // get upper_usage SHAO
1429   for (Standard_Integer i = 1; i <= aUpperSHUO->NbChildren(); i++)
1430     aLabels.Append( aUpperSHUO->GetChild(i)->Label() );
1431   return Standard_True;
1432 }
1433
1434 //=======================================================================
1435 //function : RemoveSHUO
1436 //purpose  : 
1437 //=======================================================================
1438
1439 Standard_Boolean XCAFDoc_ShapeTool::RemoveSHUO (const TDF_Label& L) const
1440 {
1441   L.ForgetAllAttributes (Standard_True);
1442   return Standard_True;
1443 }
1444
1445 //=======================================================================
1446 //function : checkForShape
1447 //purpose  : auxilary
1448 //=======================================================================
1449
1450 static Standard_Boolean checkForShape (const TopoDS_Shape& theShape,
1451                                        const TopoDS_Shape& theCurSh,
1452                                        const TDF_Label& theUserL,
1453                                        TDF_LabelSequence& theLabels)
1454 {
1455   // the label of an assembly which contains this component
1456   TDF_Label aSuperUserL = theUserL.Father();
1457   TopLoc_Location aSupLoc, aCompLoc;
1458   aSupLoc = ::XCAFDoc_ShapeTool::GetLocation ( aSuperUserL );
1459   aCompLoc = ::XCAFDoc_ShapeTool::GetLocation ( theUserL );
1460   TopoDS_Shape aCopySh = theCurSh;
1461   aCompLoc = aCompLoc.Multiplied( theCurSh.Location() );
1462   aSupLoc = aSupLoc.Multiplied( aCompLoc );
1463   aCopySh.Location( aSupLoc );
1464   if ( aCopySh.IsSame( theShape ) ) {
1465     theLabels.Prepend( theUserL );
1466     return Standard_True;
1467   }
1468   // try to search deeply (upper by assmebly structure)
1469   TDF_LabelSequence aNewLabels;
1470   for (Standard_Integer j = 1; j <= theLabels.Length(); j++)
1471     aNewLabels.Append( theLabels.Value( j ) );
1472   aNewLabels.Prepend( theUserL );
1473   TDF_LabelSequence aUsers;
1474   ::XCAFDoc_ShapeTool::GetUsers( aSuperUserL, aUsers );
1475   for (Standard_Integer i = 1; i <= aUsers.Length(); i++)
1476     if ( checkForShape( theShape, aCopySh, aUsers.Value( i ), aNewLabels ) ) {
1477       // get solution
1478       theLabels = aNewLabels;
1479       return Standard_True;
1480     }
1481   return Standard_False;
1482 }
1483
1484 //=======================================================================
1485 //function : FindComponent
1486 //purpose  : 
1487 //=======================================================================
1488
1489 Standard_Boolean XCAFDoc_ShapeTool::FindComponent (const TopoDS_Shape& theShape,
1490                                                   TDF_LabelSequence& theLabels) const
1491 {
1492   theLabels.Clear();
1493   // search for a top-level shape that corresponds to this component
1494   TopoDS_Shape S0 = theShape;
1495   TopLoc_Location loc;
1496   S0.Location ( loc );
1497   TDF_Label aRefL = FindShape( S0 );
1498   if (aRefL.IsNull())
1499     return Standard_False; // cannot find top-level shape.
1500   
1501   TDF_LabelSequence aUsers;
1502   ::XCAFDoc_ShapeTool::GetUsers( aRefL, aUsers );
1503   for (Standard_Integer i = 1; i <= aUsers.Length(); i++)
1504     if ( checkForShape( theShape, S0, aUsers.Value( i ), theLabels ) )
1505       break;
1506   
1507   return (theLabels.Length() > 0);
1508 }
1509
1510 //=======================================================================
1511 //function : getShapesOfSHUO
1512 //purpose  : auxilary
1513 //=======================================================================
1514
1515 static Standard_Boolean getShapesOfSHUO (TopLoc_IndexedMapOfLocation& theaPrevLocMap,
1516                                          const Handle(XCAFDoc_ShapeTool)& theSTool,
1517                                          const TDF_Label& theSHUOlab,
1518                                          TopoDS_Shape& theShape)
1519 {
1520   Handle(XCAFDoc_GraphNode) SHUO;
1521   TDF_LabelSequence aLabSeq;
1522   theSTool->GetSHUONextUsage( theSHUOlab, aLabSeq );
1523   if (aLabSeq.Length() >= 1)
1524     for (Standard_Integer i = 1; i <= aLabSeq.Length(); i++) {
1525       TDF_Label aSubCompL = aLabSeq.Value( i );
1526       TopLoc_Location compLoc = XCAFDoc_ShapeTool::GetLocation ( aSubCompL.Father() );
1527       // create new map of laocation (to not merge locations from different shapes)
1528       TopLoc_IndexedMapOfLocation aNewPrevLocMap;
1529       for (Standard_Integer m = 1; m <= theaPrevLocMap.Extent(); m++)
1530         aNewPrevLocMap.Add( theaPrevLocMap.FindKey( m ) );
1531       aNewPrevLocMap.Add( compLoc );
1532       // got for the new sublocations and corresponding shape
1533       getShapesOfSHUO( aNewPrevLocMap, theSTool, aSubCompL, theShape );
1534     }
1535   else {
1536     TopoDS_Shape aSHUO_NUSh = theSTool->GetShape ( theSHUOlab.Father() );
1537     if ( aSHUO_NUSh.IsNull() ) return Standard_False;
1538     // cause got shape with location already.
1539     TopLoc_Location nullLoc;
1540     aSHUO_NUSh.Location ( nullLoc );
1541     // multiply the locations
1542     Standard_Integer intMapLenght = theaPrevLocMap.Extent();
1543     if ( intMapLenght < 1 )
1544       return Standard_False; // should not be, but to avoid exception...?
1545     TopLoc_Location SupcompLoc;
1546     SupcompLoc = theaPrevLocMap.FindKey( intMapLenght );
1547     if (intMapLenght > 1) {
1548       Standard_Integer l = intMapLenght - 1;
1549       while (l >= 1) {
1550         SupcompLoc = theaPrevLocMap.FindKey( l ).Multiplied( SupcompLoc );
1551         l--;
1552       }
1553     }
1554     aSHUO_NUSh.Location( SupcompLoc );
1555     theShape = aSHUO_NUSh;
1556   }
1557   return (!theShape.IsNull());
1558 }
1559
1560 //=======================================================================
1561 //function : GetSHUOInstance
1562 //purpose  : 
1563 //=======================================================================
1564
1565 TopoDS_Shape XCAFDoc_ShapeTool::GetSHUOInstance (const Handle(XCAFDoc_GraphNode)& theSHUO) const
1566 {
1567   TopoDS_Shape aShape;
1568   if (theSHUO.IsNull())
1569     return aShape;
1570   
1571   TDF_Label aSHUOlab = theSHUO->Label();
1572   // get location of the assembly
1573   TopLoc_Location loc = XCAFDoc_ShapeTool::GetLocation ( aSHUOlab.Father().Father() );
1574   // get location of the component
1575   TopLoc_Location compLoc = XCAFDoc_ShapeTool::GetLocation ( aSHUOlab.Father() );
1576   TopLoc_IndexedMapOfLocation aPrevLocMap;
1577   // get previous setted location 
1578   if ( !loc.IsIdentity() )
1579     aPrevLocMap.Add( loc );
1580   aPrevLocMap.Add( compLoc );
1581   // get shape by recurse method
1582   const Handle(XCAFDoc_ShapeTool)& STool = this;
1583   getShapesOfSHUO( aPrevLocMap, STool, aSHUOlab, aShape );
1584   
1585   return aShape;
1586 }
1587
1588 //=======================================================================
1589 //function : getUsersShapesOfSHUO
1590 //purpose  : auxilary
1591 //=======================================================================
1592
1593 static Standard_Boolean getUsersShapesOfSHUO (TopLoc_IndexedMapOfLocation& aPrevLocMap,
1594                                               const Handle(XCAFDoc_ShapeTool)& STool,
1595                                               const TDF_Label& aSHUOlab,
1596                                               const TDF_Label& theUserL,
1597                                               TopTools_SequenceOfShape& theSHUOShapeSeq)
1598 {
1599   TopLoc_IndexedMapOfLocation aNewPrevLocMap;
1600   // get location of the assembly
1601   TopLoc_Location loc = XCAFDoc_ShapeTool::GetLocation ( theUserL.Father() );
1602   // get location of the component
1603   TopLoc_Location compLoc = XCAFDoc_ShapeTool::GetLocation ( theUserL );
1604   // get previous setted location 
1605   aNewPrevLocMap.Add( loc );
1606   aNewPrevLocMap.Add( compLoc );
1607   Standard_Integer i;
1608   for (i = 1; i <= aPrevLocMap.Extent(); i++)
1609     aNewPrevLocMap.Add( aPrevLocMap.FindKey(i) );
1610   TDF_Label L = theUserL.Father();
1611   TDF_LabelSequence usersLab;
1612   ::XCAFDoc_ShapeTool::GetUsers( L, usersLab );
1613   if (usersLab.Length() == 0) {
1614     TopoDS_Shape aShape;
1615     getShapesOfSHUO( aNewPrevLocMap, STool, aSHUOlab, aShape );
1616     if (!aShape.IsNull()) {
1617       theSHUOShapeSeq.Append(aShape);
1618       return Standard_True;
1619     }
1620   }
1621   // now iterates on users of this assembly as component
1622   for ( i = 1; i <= usersLab.Length(); i++ ) {
1623     TDF_Label aNewUserL = usersLab.Value(i);
1624     getUsersShapesOfSHUO( aNewPrevLocMap, STool, aSHUOlab, aNewUserL, theSHUOShapeSeq );
1625   }
1626   
1627   return (theSHUOShapeSeq.Length() > 1);
1628 }
1629
1630 //=======================================================================
1631 //function : GetAllSHUOInstances
1632 //purpose  : auxilary
1633 //=======================================================================
1634
1635 Standard_Boolean XCAFDoc_ShapeTool::GetAllSHUOInstances (const Handle(XCAFDoc_GraphNode)& theSHUO,
1636                                                          TopTools_SequenceOfShape& theSHUOShapeSeq) const
1637 {
1638   if (theSHUO.IsNull())
1639     return Standard_False;
1640
1641   TDF_Label aSHUOlab = theSHUO->Label();
1642   TopLoc_IndexedMapOfLocation aPrevLocMap;
1643   // get location of the assembly
1644   TopLoc_Location loc = XCAFDoc_ShapeTool::GetLocation ( aSHUOlab.Father().Father() );
1645   // get location of the component
1646   TopLoc_Location compLoc = XCAFDoc_ShapeTool::GetLocation ( aSHUOlab.Father() );
1647   // get previous setted location 
1648   if ( !loc.IsIdentity() )
1649     aPrevLocMap.Add( loc );
1650   aPrevLocMap.Add( compLoc );
1651   // get label of assembly
1652   TDF_Label L = aSHUOlab.Father().Father();
1653   TDF_LabelSequence usersLab;
1654   ::XCAFDoc_ShapeTool::GetUsers( L, usersLab );
1655   TopoDS_Shape aShape;
1656   const Handle(XCAFDoc_ShapeTool)& STool = this;
1657   if (usersLab.Length() == 0) {
1658     getShapesOfSHUO( aPrevLocMap, STool, aSHUOlab, aShape );
1659     if (!aShape.IsNull()) {
1660       theSHUOShapeSeq.Append(aShape);
1661       return Standard_True;
1662     }
1663   }
1664   // now iterates on users of this assembly as component
1665   for (Standard_Integer i = 1; i <= usersLab.Length(); i++) {
1666     TDF_Label aUserL = usersLab.Value(i);
1667     getUsersShapesOfSHUO( aPrevLocMap, STool, aSHUOlab, aUserL, theSHUOShapeSeq );
1668   }
1669   
1670   return (theSHUOShapeSeq.Length() > 1);
1671 }
1672
1673 //=======================================================================
1674 //function : SetInstanceSHUO
1675 //purpose  : 
1676 //=======================================================================
1677
1678 Handle(XCAFDoc_GraphNode) XCAFDoc_ShapeTool::SetInstanceSHUO (const TopoDS_Shape& theShape) const
1679 {
1680   Handle(XCAFDoc_GraphNode) SHUO;
1681   TDF_LabelSequence aLabels;
1682   if ( FindComponent( theShape, aLabels ) )
1683     // set shuo structure on labels of component-assembly structure
1684     SetSHUO( aLabels, SHUO );
1685   return SHUO;
1686 }
1687
1688 //=======================================================================
1689 //function : FindSHUO
1690 //purpose  : 
1691 //=======================================================================
1692
1693 Standard_Boolean XCAFDoc_ShapeTool::FindSHUO (const TDF_LabelSequence& theLabels,
1694                                               Handle(XCAFDoc_GraphNode)& theSHUOAttr)
1695 {
1696   TDF_AttributeSequence SHUOAttrs;
1697   TDF_Label aCompLabel = theLabels.Value(1);
1698   if (! ::XCAFDoc_ShapeTool::GetAllComponentSHUO( aCompLabel, SHUOAttrs ) )
1699     return Standard_False;
1700   // WARNING: manage that each SHUO upper_usage have only one SHUO next_usage
1701   for (Standard_Integer i = 1; i <= SHUOAttrs.Length(); i++) {
1702     TDF_LabelSequence aCondidate;
1703     Handle(XCAFDoc_GraphNode) anSHUO = Handle(XCAFDoc_GraphNode)::DownCast(SHUOAttrs.Value(i));
1704     aCondidate.Append( anSHUO->Label().Father() );
1705     while (anSHUO->NbChildren()) {
1706       anSHUO = anSHUO->GetChild( 1 );
1707       aCondidate.Append( anSHUO->Label().Father() );
1708     }
1709     // check the label sequences
1710     Standard_Boolean isEqual = Standard_True;
1711     if (theLabels.Length() != aCondidate.Length())
1712       isEqual = Standard_False;
1713     else
1714       for (Standard_Integer li = 1; li <= theLabels.Length(); li++)
1715         if ( theLabels.Value(li) != aCondidate.Value(li) ) {
1716           isEqual = Standard_False;
1717           break;
1718         }
1719     if (!isEqual)
1720       continue;
1721       
1722     theSHUOAttr = Handle(XCAFDoc_GraphNode)::DownCast(SHUOAttrs.Value(i));
1723     break;
1724   }
1725   return ( !theSHUOAttr.IsNull() );
1726 }