7f85299ba9a1cb4e47da595ed6dd884dded346c5
[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,
611                                                  const Standard_Boolean removeCompletely) const
612 {
613   if ( ! IsTopLevel ( L ) || ! IsFree ( L ) ) return Standard_False;
614
615   Handle(TDataStd_TreeNode) aNode;
616   TDF_Label aLabel;
617   if (removeCompletely &&
618       L.FindAttribute (XCAFDoc::ShapeRefGUID(), aNode) &&
619       aNode->HasFather() &&
620       L.IsAttribute (XCAFDoc_Location::GetID()))
621   {
622     aLabel = aNode->Father()->Label();
623   }
624
625   L.ForgetAllAttributes (Standard_True);
626
627   if (removeCompletely && !aLabel.IsNull())
628   {
629     return RemoveShape(aLabel);
630   }
631   return Standard_True;
632 }
633
634
635 //=======================================================================
636 //function : Init
637 //purpose  : 
638 //=======================================================================
639
640 void XCAFDoc_ShapeTool::Init()
641 {
642   hasSimpleShapes = Standard_False;
643 }
644
645
646 //=======================================================================
647 //function : ComputeShapes
648 //purpose  : 
649 //=======================================================================
650
651 void XCAFDoc_ShapeTool::ComputeShapes(const TDF_Label& L)
652 {
653   TDF_ChildIterator it(L); 
654   for(; it.More(); it.Next()) {
655     TDF_Label L1 = it.Value();
656     TopoDS_Shape S;
657     if(GetShape(L1,S)) {
658       if(!myShapeLabels.IsBound(S)) {
659         mySimpleShapes.Bind(S,L1);
660       }
661     }
662     ComputeShapes(L1);
663   }
664 }
665
666
667 //=======================================================================
668 //function : ComputeSimpleShapes
669 //purpose  : 
670 //=======================================================================
671
672 void XCAFDoc_ShapeTool::ComputeSimpleShapes()
673 {
674   ComputeShapes(Label());
675   hasSimpleShapes = Standard_True;
676 }
677
678
679 //=======================================================================
680 //function : GetShapes
681 //purpose  : 
682 //=======================================================================
683
684 void XCAFDoc_ShapeTool::GetShapes(TDF_LabelSequence& Labels) const
685 {
686   Labels.Clear();
687
688   TDF_ChildIterator it(Label()); 
689   for (; it.More(); it.Next()) {
690     TDF_Label L = it.Value();
691     TopoDS_Shape S;
692     if ( GetShape ( L, S ) ) Labels.Append ( L );
693   }
694 }
695
696
697 //=======================================================================
698 //function : GetFreeShapes
699 //purpose  : 
700 //=======================================================================
701
702 void XCAFDoc_ShapeTool::GetFreeShapes (TDF_LabelSequence& FreeLabels) const
703 {
704   FreeLabels.Clear();
705
706   TDF_ChildIterator it(Label());
707   for (; it.More(); it.Next()) {
708     TDF_Label L = it.Value();
709     TopoDS_Shape S;
710     if ( GetShape ( L, S ) && IsFree ( L ) ) FreeLabels.Append ( L );
711   }
712 }
713
714 //=======================================================================
715 //function : IsTopLevel
716 //purpose  : 
717 //=======================================================================
718
719 Standard_Boolean XCAFDoc_ShapeTool::IsTopLevel (const TDF_Label& L) const
720 {
721   return L.Father() == Label();
722 }
723
724 //=======================================================================
725 //function : IsShape
726 //purpose  : 
727 //=======================================================================
728
729 Standard_Boolean XCAFDoc_ShapeTool::IsShape (const TDF_Label& L) 
730 {
731   return IsSimpleShape ( L ) || IsAssembly ( L ) || IsReference ( L );
732 }
733
734 //=======================================================================
735 //function : IsSimpleShape
736 //purpose  : 
737 //=======================================================================
738
739 Standard_Boolean XCAFDoc_ShapeTool::IsSimpleShape (const TDF_Label& L) 
740 {
741   Handle(TNaming_NamedShape) NS;
742   return L.FindAttribute ( TNaming_NamedShape::GetID(), NS ) &&
743          ! IsAssembly ( L ) && ! IsReference ( L );
744 }
745
746 //=======================================================================
747 //function : IsReference
748 //purpose  : 
749 //=======================================================================
750
751 Standard_Boolean XCAFDoc_ShapeTool::IsReference (const TDF_Label& L)
752 {
753   Handle(TDataStd_TreeNode) Node;
754   return L.FindAttribute(XCAFDoc::ShapeRefGUID(), Node) && Node->HasFather();
755 }
756
757 //=======================================================================
758 //function : IsAssembly
759 //purpose  : 
760 //=======================================================================
761
762 Standard_Boolean XCAFDoc_ShapeTool::IsAssembly (const TDF_Label& L) 
763 {
764   Handle(TDataStd_UAttribute) Uattr;
765   return L.FindAttribute(XCAFDoc::AssemblyGUID(), Uattr);
766 }
767
768 //=======================================================================
769 //function : IsComponent
770 //purpose  : 
771 //=======================================================================
772
773 Standard_Boolean XCAFDoc_ShapeTool::IsComponent (const TDF_Label& L)
774 {
775   return IsReference ( L ) && IsAssembly ( L.Father() );
776 }
777
778 //=======================================================================
779 //function : IsCompound
780 //purpose  : 
781 //=======================================================================
782
783 Standard_Boolean XCAFDoc_ShapeTool::IsCompound (const TDF_Label& L) 
784 {
785   Handle(TDataStd_Name) Name;
786   if (L.FindAttribute(TDataStd_Name::GetID(),Name)) {
787     TCollection_ExtendedString estr1 = Name->Get();
788     TCollection_ExtendedString estr2("COMPOUND");
789     if(estr1==estr2) {
790       return Standard_True;
791     }
792   }
793   return Standard_False;
794 }
795
796 //=======================================================================
797 //function : IsSubShape
798 //purpose  : 
799 //=======================================================================
800
801 Standard_Boolean XCAFDoc_ShapeTool::IsSubShape (const TDF_Label& L)
802 {
803   return IsSimpleShape ( L ) && IsShape ( L.Father() );
804 }
805
806 //=======================================================================
807 //function : IsFree
808 //purpose  : 
809 //=======================================================================
810
811 Standard_Boolean XCAFDoc_ShapeTool::IsFree (const TDF_Label& L) 
812 {
813   Handle(TDataStd_TreeNode) Node;
814   if ( ! L.FindAttribute(XCAFDoc::ShapeRefGUID(), Node) || 
815        ! Node->HasFirst() ) return Standard_True;
816
817   return Standard_False;
818 }
819
820 //=======================================================================
821 //function : GetUsers
822 //purpose  : Returns number of users (0 if shape is free)
823 //=======================================================================
824
825 Standard_Integer XCAFDoc_ShapeTool::GetUsers (const TDF_Label& L, 
826                                               TDF_LabelSequence& Labels,
827                                               const Standard_Boolean getsubchilds)
828 {
829   Standard_Integer NbUsers=0;
830   Handle(TDataStd_TreeNode) Node  ;
831
832   if ( ! L.FindAttribute(XCAFDoc::ShapeRefGUID(), Node) ) return NbUsers;
833   
834   Node = Node->First();
835   while ( ! Node.IsNull() ) {
836     
837     if ( getsubchilds ) {
838       TDF_Label underL = Node->Label().Father();
839       NbUsers += GetUsers ( underL, Labels, getsubchilds );
840     }
841     
842     Labels.Append(Node->Label());
843     Node = Node->Next();
844     NbUsers++;
845   }
846   return NbUsers;
847 }
848   
849 //=======================================================================
850 //function : NbComponents
851 //purpose  : 
852 //=======================================================================
853
854 Standard_Integer XCAFDoc_ShapeTool::NbComponents (const TDF_Label& L,
855                                                   const Standard_Boolean getsubchilds) 
856 {
857   TDF_LabelSequence subLabels;
858   GetComponents (L, subLabels, getsubchilds);
859   return subLabels.Length();
860 }
861
862 //=======================================================================
863 //function : GetComponents
864 //purpose  : 
865 //=======================================================================
866
867 Standard_Boolean XCAFDoc_ShapeTool::GetComponents (const TDF_Label& L, TDF_LabelSequence& Labels,
868                                                    const Standard_Boolean getsubchilds) 
869 {
870   if ( ! IsAssembly(L) ) return Standard_False;
871   
872   TDF_ChildIterator It(L);
873   for (; It.More(); It.Next() ) {
874     TDF_Label comp = It.Value();
875     if ( IsComponent ( comp ) ) {
876       if ( getsubchilds ) {
877         TDF_Label underL;
878         if ( GetReferredShape ( comp, underL ) )
879           GetComponents ( underL, Labels, getsubchilds);
880       }
881       Labels.Append ( comp );
882     }
883   }
884   return Standard_True;
885 }
886
887 //=======================================================================
888 //function : GetLocation
889 //purpose  : 
890 //=======================================================================
891
892 TopLoc_Location XCAFDoc_ShapeTool::GetLocation (const TDF_Label& L)
893 {
894   Handle(XCAFDoc_Location) LocationAttribute;
895   if (L.FindAttribute(XCAFDoc_Location::GetID(), LocationAttribute)) 
896     return LocationAttribute->Get();
897   
898   Handle(TNaming_NamedShape) NS;
899   TopoDS_Shape S;
900   if ( L.FindAttribute ( TNaming_NamedShape::GetID(), NS ) ) {
901     S = TNaming_Tool::GetShape(NS);
902   }
903   return S.Location();
904 }
905
906 //=======================================================================
907 //function : GetReferredShape
908 //purpose  : 
909 //=======================================================================
910
911 Standard_Boolean XCAFDoc_ShapeTool::GetReferredShape (const TDF_Label& L, 
912                                                       TDF_Label& Label)
913 {
914   if ( ! IsReference(L) ) return Standard_False;
915   
916   Handle (TDataStd_TreeNode) Node;
917   L.FindAttribute(XCAFDoc::ShapeRefGUID(), Node);
918   Label = Node->Father()->Label();
919   return Standard_True;
920 }
921
922 //=======================================================================
923 //function : AddComponent
924 //purpose  : 
925 //=======================================================================
926
927 TDF_Label XCAFDoc_ShapeTool::AddComponent (const TDF_Label& assembly, 
928                                            const TDF_Label& compL, 
929                                            const TopLoc_Location &Loc) const
930 {
931   TDF_Label L;
932   
933   // check that shape is assembly
934   if ( ! IsAssembly(assembly) ) {
935     // if it is simple shape, make it assembly
936     if ( IsSimpleShape(assembly) ) 
937       TDataStd_UAttribute::Set ( assembly, XCAFDoc::AssemblyGUID() );
938     else return L;
939   }
940   
941   // add a component as reference
942   TDF_TagSource aTag;
943   L = aTag.NewChild(assembly);
944   MakeReference ( L, compL, Loc );
945
946   // update assembly`s TopoDS_Shape
947   UpdateAssembly ( assembly );
948   return L;
949 }
950
951 //=======================================================================
952 //function : AddComponent
953 //purpose  : 
954 //=======================================================================
955
956 TDF_Label XCAFDoc_ShapeTool::AddComponent (const TDF_Label& assembly, 
957                                            const TopoDS_Shape& comp,
958                                            const Standard_Boolean expand)
959 {
960   // get label for component`s shape
961   TopoDS_Shape S0 = comp;
962   TopLoc_Location loc;
963   S0.Location ( loc );
964   TDF_Label compL;
965   compL = AddShape ( S0, expand );
966   
967   // add component by its label
968   return AddComponent ( assembly, compL, comp.Location() );
969 }
970
971 //=======================================================================
972 //function : RemoveComponent
973 //purpose  : 
974 //=======================================================================
975
976 void XCAFDoc_ShapeTool::RemoveComponent (const TDF_Label& comp) const
977 {
978   if ( IsComponent(comp) ) {
979     comp.ForgetAllAttributes();
980     UpdateAssembly(comp.Father());
981   }
982 }
983
984 //=======================================================================
985 //function : UpdateAssembly
986 //purpose  : 
987 //=======================================================================
988
989 void XCAFDoc_ShapeTool::UpdateAssembly (const TDF_Label& L) const
990 {
991   if ( ! IsAssembly(L) ) return;
992
993   TopoDS_Compound newassembly;
994   BRep_Builder b;
995   b.MakeCompound(newassembly);
996
997   TDF_ChildIterator chldLabIt(L);
998   for (; chldLabIt.More(); chldLabIt.Next() ) {
999     TDF_Label subLabel = chldLabIt.Value();
1000     if ( IsComponent ( subLabel ) ) {
1001       b.Add(newassembly, GetShape(subLabel));
1002     }
1003   }
1004   TNaming_Builder tnBuild(L);
1005   tnBuild.Generated(newassembly);
1006 }
1007
1008 //=======================================================================
1009 //function : IsSubShape
1010 //purpose  : 
1011 //=======================================================================
1012
1013 //static Standard_Boolean CheckSubShape (const TopoDS_Shape &S, const TopoDS_Shape &sub)
1014 //{
1015 //  if ( S.IsSame ( sub ) ) return Standard_True;
1016 //  
1017 //  if ( S.ShapeType() >= sub.ShapeType() ) return Standard_False;
1018 //  
1019 //  for ( TopoDS_Iterator it(S); it.More(); it.Next() ) {
1020 //    if ( CheckSubShape ( it.Value(), sub ) ) return Standard_True;
1021 //  }
1022 //  return Standard_False;
1023 //}
1024
1025 //=======================================================================
1026 //function : IsSubShape
1027 //purpose  : 
1028 //=======================================================================
1029
1030 Standard_Boolean XCAFDoc_ShapeTool::IsSubShape (const TDF_Label &shapeL,
1031                                              const TopoDS_Shape &sub) const
1032 {
1033   Handle(XCAFDoc_ShapeMapTool) A;
1034   if ( ! shapeL.FindAttribute(XCAFDoc_ShapeMapTool::GetID(), A) )
1035     return Standard_False;
1036   
1037   //TopoDS_Shape S = GetShape ( shapeL );
1038   //return ! S.IsNull() && CheckSubShape ( S, sub );
1039   
1040   return A->IsSubShape(sub);
1041 }
1042
1043 //=======================================================================
1044 //function : FindSubShape
1045 //purpose  : 
1046 //=======================================================================
1047
1048 Standard_Boolean XCAFDoc_ShapeTool::FindSubShape (const TDF_Label &shapeL,
1049                                                   const TopoDS_Shape &sub,
1050                                                   TDF_Label &L) const
1051 {
1052   // this code is used instead of the following for performance reasons
1053   if ( TNaming_Tool::HasLabel(Label(), sub) ) {
1054     int TransDef = 0;
1055     L = TNaming_Tool::Label(Label(), sub, TransDef);
1056     return ( ! L.IsNull() && L.Father() == shapeL );
1057   }
1058
1059 /*
1060   TDF_ChildIterator chldLabIt(shapeL);
1061   for (; chldLabIt.More(); chldLabIt.Next() ) {
1062     TDF_Label subLabel = chldLabIt.Value();
1063     TopoDS_Shape S;
1064     if ( GetShape ( subLabel, S ) && S.IsSame ( sub ) ) {
1065       L = subLabel;
1066       return Standard_True;
1067     }
1068   }
1069 */
1070   return Standard_False;
1071 }
1072
1073 //=======================================================================
1074 //function : AddSubShape
1075 //purpose  : 
1076 //=======================================================================
1077
1078 TDF_Label XCAFDoc_ShapeTool::AddSubShape (const TDF_Label &shapeL,
1079                                           const TopoDS_Shape &sub) const
1080 {
1081   TDF_Label L;
1082   if ( FindSubShape ( shapeL, sub, L ) ) return L;
1083   
1084   if ( ! IsSubShape ( shapeL, sub ) ) return L;
1085   
1086   TDF_TagSource aTag;
1087   L = aTag.NewChild(shapeL);
1088   
1089   TNaming_Builder tnBuild(L);
1090   tnBuild.Generated(sub);
1091
1092 //  if(!mySubShapes.IsBound(sub))
1093 //    mySubShapes.Bind(sub,L);
1094    
1095   return L;
1096 }
1097
1098
1099 //=======================================================================
1100 //function : FindMainShapeUsingMap
1101 //purpose  : 
1102 //=======================================================================
1103
1104 TDF_Label XCAFDoc_ShapeTool::FindMainShapeUsingMap(const TopoDS_Shape &sub) const
1105 {
1106   //for(Standard_Integer i=1; i<=myNotAssemblies.Length(); i++) {
1107   //  TDF_Label L = myNotAssemblies.Value(i);
1108   //  if(IsSubShape(L,sub)) return L;
1109   //}
1110   if(mySubShapes.IsBound(sub))
1111     return mySubShapes.Find(sub);
1112   TDF_Label L0;
1113   return L0;
1114 }
1115
1116
1117 //=======================================================================
1118 //function : FindMainShape
1119 //purpose  : 
1120 //=======================================================================
1121
1122 TDF_Label XCAFDoc_ShapeTool::FindMainShape (const TopoDS_Shape &sub) const
1123 {
1124   TDF_ChildIterator it(Label());
1125   for (; it.More(); it.Next()) {
1126     TDF_Label L = it.Value();
1127     if ( ! IsAssembly ( L ) && IsSubShape ( L, sub ) ) return L;
1128   }
1129   TDF_Label L0;
1130   return L0;
1131 }
1132
1133
1134 //=======================================================================
1135 //function : GetSubShapes
1136 //purpose  : 
1137 //=======================================================================
1138
1139 Standard_Boolean XCAFDoc_ShapeTool::GetSubShapes (const TDF_Label &L, 
1140                                                TDF_LabelSequence& Labels)
1141 {
1142   TDF_ChildIterator It(L);
1143   for (; It.More(); It.Next() ) {
1144     TDF_Label sub = It.Value();
1145     if ( IsSubShape ( sub ) ) Labels.Append ( sub );
1146   }
1147   return Labels.Length() >0;
1148 }
1149
1150 //=======================================================================
1151 //function : BaseLabel
1152 //purpose  : 
1153 //=======================================================================
1154
1155 TDF_Label XCAFDoc_ShapeTool::BaseLabel () const
1156 {
1157   return Label();
1158 }
1159
1160 //=======================================================================
1161 //function : DumpAssembly
1162 //purpose  : recursive part of Dump()
1163 //=======================================================================
1164
1165 static void DumpAssembly(const TDF_Label L,
1166                          const Standard_Integer level,
1167                          const Standard_Boolean deep)
1168 {
1169   for (Standard_Integer i=0; i<level; i++)
1170     cout<<"\t";
1171   
1172   TCollection_AsciiString Entry;
1173   TDF_Tool::Entry(L, Entry);
1174
1175   cout<<"ASSEMBLY "<<Entry;
1176   Handle(TDataStd_Name) Name;
1177   if (L.FindAttribute(TDataStd_Name::GetID(), Name))
1178     cout<<" "<<Name->Get();
1179   
1180   if (deep) {
1181     TopoDS_Shape S;
1182     XCAFDoc_ShapeTool::GetShape(L, S);
1183     cout<<"("<<*(void**)&S.TShape();
1184     if (! S.Location().IsIdentity())
1185       cout<<", "<< *(void**)&S.Location();
1186     cout<<") ";
1187   }
1188   cout<<endl;
1189   
1190   Handle(TDataStd_TreeNode) Node;
1191   TDF_ChildIDIterator NodeIterator(L, XCAFDoc::ShapeRefGUID());
1192   for (; NodeIterator.More(); NodeIterator.Next()) {
1193     Node = Handle(TDataStd_TreeNode)::DownCast(NodeIterator.Value());
1194     if (Node->HasFather()) {
1195       if (Node->Father()->Label().HasChild())
1196         DumpAssembly(Node->Father()->Label(), level+1, deep);
1197       else {
1198         XCAFDoc_ShapeTool::DumpShape(Node->Father()->Label(), level+1, deep);
1199           cout<<endl;
1200         }
1201     }
1202   }
1203 }
1204
1205 //=======================================================================
1206 //function : Dump
1207 //purpose  : 
1208 //=======================================================================
1209
1210 void XCAFDoc_ShapeTool::Dump(const Standard_Boolean deep) const
1211 {
1212   Standard_Integer level = 0;
1213 //   TopTools_SequenceOfShape SeqShapes;
1214   TDF_LabelSequence SeqLabels;
1215   GetShapes( SeqLabels);
1216
1217   if (SeqLabels.Length()>0) cout<<endl;
1218   Standard_Integer i;
1219   for (i=1; i<=SeqLabels.Length(); i++) {
1220     DumpAssembly(SeqLabels.Value(i), level, deep);
1221   }
1222
1223   SeqLabels.Clear();
1224   GetFreeShapes(SeqLabels);
1225   cout<<endl<<"Free Shapes: "<<SeqLabels.Length()<<endl;
1226   for (i = 1; i<=SeqLabels.Length(); i++) {
1227     DumpShape(SeqLabels.Value(i), level, deep);
1228     cout<<endl;
1229   }
1230 }
1231
1232 //=======================================================================
1233 //function : DumpShape
1234 //purpose  : 
1235 //=======================================================================
1236
1237 void XCAFDoc_ShapeTool::DumpShape(const TDF_Label& L,const Standard_Integer level,const Standard_Boolean deep) 
1238 {
1239   TopoDS_Shape S;
1240   if(! XCAFDoc_ShapeTool::GetShape(L, S) ) return;
1241   for (Standard_Integer i=0; i<level; i++)
1242     cout<<"\t";
1243   
1244   if (S.ShapeType() == TopAbs_COMPOUND) cout<<"ASSEMBLY";
1245   else TopAbs::Print(S.ShapeType(), cout);
1246   
1247   TCollection_AsciiString Entry;
1248   TDF_Tool::Entry(L, Entry);
1249   cout<<"  "<<Entry;
1250   //cout<<endl;
1251   Handle(TDataStd_Name) Name;
1252   if (L.FindAttribute(TDataStd_Name::GetID(),Name)) 
1253     cout<<" "<<Name->Get();
1254   
1255   if (deep) {
1256     cout<<"("<<*(void**)&S.TShape();
1257     if (! S.Location().IsIdentity())
1258       cout<<", "<< *(void**)&S.Location();
1259     cout<<") ";
1260   }
1261 }
1262
1263 //=======================================================================
1264 //function : IsExternRef
1265 //purpose  : 
1266 //=======================================================================
1267
1268 Standard_Boolean XCAFDoc_ShapeTool::IsExternRef(const TDF_Label& L) 
1269 {
1270   Handle(TDataStd_UAttribute) Uattr;
1271   return L.FindAttribute(XCAFDoc::ExternRefGUID(), Uattr);
1272 }
1273
1274 //=======================================================================
1275 //function : SetExternRefs
1276 //purpose  : 
1277 //=======================================================================
1278
1279 void XCAFDoc_ShapeTool::SetExternRefs(const TDF_Label& L,
1280                                       const TColStd_SequenceOfHAsciiString& SHAS) const
1281 {
1282   TDF_Label ShapeLabel = L.NewChild();
1283   TDataStd_UAttribute::Set(ShapeLabel,XCAFDoc::ExternRefGUID());
1284   for(Standard_Integer i=1; i<=SHAS.Length(); i++) {
1285     TDF_Label tmplbl = ShapeLabel.FindChild(i,Standard_True);
1286     Handle(TCollection_HAsciiString) str = SHAS(i);
1287     TCollection_ExtendedString extstr(str->String());
1288     TDataStd_Name::Set(tmplbl,extstr);
1289   }
1290 }
1291
1292 //=======================================================================
1293 //function : SetExternRefs
1294 //purpose  : 
1295 //=======================================================================
1296
1297 TDF_Label XCAFDoc_ShapeTool::SetExternRefs(const TColStd_SequenceOfHAsciiString& SHAS) const
1298 {
1299   TDF_Label ShapeLabel;
1300   TDF_TagSource aTag;
1301   // add a new label
1302   ShapeLabel = aTag.NewChild(Label());
1303   TDataStd_UAttribute::Set(ShapeLabel,XCAFDoc::ExternRefGUID());
1304   for(Standard_Integer i=1; i<=SHAS.Length(); i++) {
1305     TDF_Label tmplbl = ShapeLabel.FindChild(i,Standard_True);
1306     Handle(TCollection_HAsciiString) str = SHAS(i);
1307     TCollection_ExtendedString extstr(str->String());
1308     TDataStd_Name::Set(tmplbl,extstr);
1309   }
1310   return ShapeLabel;
1311 }
1312
1313 //=======================================================================
1314 //function : GetExternRefs
1315 //purpose  : 
1316 //=======================================================================
1317
1318 void XCAFDoc_ShapeTool::GetExternRefs(const TDF_Label& L,
1319                                       TColStd_SequenceOfHAsciiString& SHAS)
1320 {
1321   Handle(TDataStd_Name) TDN;
1322   TDF_Label tmplbl;
1323   for(Standard_Integer i=1; i<=L.NbChildren(); i++) {
1324     tmplbl = L.FindChild(i);
1325     if(tmplbl.FindAttribute(TDataStd_Name::GetID(),TDN)) {
1326       TCollection_ExtendedString extstr = TDN->Get();
1327       Handle(TCollection_HAsciiString) str = 
1328         new TCollection_HAsciiString(TCollection_AsciiString(extstr, '?')); 
1329       SHAS.Append(str);
1330     }
1331   }
1332 }
1333
1334 // API: API work with SHUO (Specified Higher Usage Occurrance) structure
1335
1336 //=======================================================================
1337 //function : GetSHUO
1338 //purpose  : 
1339 //=======================================================================
1340
1341 Standard_Boolean XCAFDoc_ShapeTool::GetSHUO (const TDF_Label& SHUOLabel,
1342                                       Handle(XCAFDoc_GraphNode)& aSHUOAttr)
1343 {
1344   if ( !SHUOLabel.FindAttribute( XCAFDoc::SHUORefGUID(), aSHUOAttr ) )
1345     return Standard_False;
1346   return Standard_True;
1347 }
1348
1349 //=======================================================================
1350 //function : GetAllComponentSHUO
1351 //purpose  : 
1352 //=======================================================================
1353
1354 Standard_Boolean XCAFDoc_ShapeTool::GetAllComponentSHUO (const TDF_Label& theCompLabel,
1355                                                          TDF_AttributeSequence& theSHUOAttrs)
1356 {
1357   TDF_ChildIterator it(theCompLabel); 
1358   for (; it.More(); it.Next()) {
1359     TDF_Label L = it.Value();
1360     Handle(XCAFDoc_GraphNode) aSHUOAttr;
1361     if ( GetSHUO( L, aSHUOAttr ) )
1362       theSHUOAttrs.Append( aSHUOAttr );
1363   }
1364   return (theSHUOAttrs.Length() > 0);
1365 }
1366
1367 //=======================================================================
1368 //function : SetSHUO
1369 //purpose  : 
1370 //=======================================================================
1371
1372 Standard_Boolean XCAFDoc_ShapeTool::SetSHUO (const TDF_LabelSequence& labels,
1373                                              Handle(XCAFDoc_GraphNode)& MainSHUOAttr) const
1374 {
1375   MainSHUOAttr.Nullify();
1376   // check number of labels
1377   if (labels.Length() < 2)
1378     return Standard_False;
1379   // check is all labels contains components of any assemblyies 
1380   Standard_Integer i;
1381   for (i = 1; i <= labels.Length(); i++)
1382     if ( !IsComponent(labels.Value(i)) )
1383       return Standard_False;
1384   
1385   TDF_TagSource aTag;
1386   TDF_Label UpperSubL = aTag.NewChild( labels( 1 ) );
1387 #ifdef AUTONAMING
1388   TCollection_ExtendedString Entry("SHUO");
1389   TDataStd_Name::Set(UpperSubL, TCollection_ExtendedString( Entry ));
1390 #endif
1391   Handle(XCAFDoc_GraphNode) aUpperSHUO;
1392   aUpperSHUO = XCAFDoc_GraphNode::Set( UpperSubL, XCAFDoc::SHUORefGUID() );
1393   // init out argument by main upper usage SHUO
1394   MainSHUOAttr = aUpperSHUO;
1395   // add other next_usage occurrences.
1396   for (i = 2; i <= labels.Length(); i++) {
1397     TDF_Label NextSubL = aTag.NewChild( labels( i ) );
1398 #ifdef AUTONAMING
1399     TCollection_ExtendedString EntrySub("SHUO-");
1400     EntrySub += i;
1401     TDataStd_Name::Set(NextSubL, TCollection_ExtendedString( EntrySub ));
1402 #endif
1403     Handle(XCAFDoc_GraphNode) aNextSHUO;
1404     aNextSHUO = XCAFDoc_GraphNode::Set( NextSubL, XCAFDoc::SHUORefGUID() );
1405     // set references
1406     aUpperSHUO->SetChild( aNextSHUO );
1407     aNextSHUO->SetFather( aUpperSHUO );
1408     // now lets next_usage become upper_usage for next level of SHUO
1409     aUpperSHUO = aNextSHUO;
1410     UpperSubL = NextSubL;
1411   }
1412   
1413   return Standard_True;
1414 }
1415
1416 //=======================================================================
1417 //function : GetSHUOUpperUsage
1418 //purpose  : 
1419 //=======================================================================
1420
1421 Standard_Boolean XCAFDoc_ShapeTool::GetSHUOUpperUsage (const TDF_Label& NextUsageL,
1422                                                        TDF_LabelSequence& aLabels)
1423 {
1424   Handle(XCAFDoc_GraphNode) aNextSHUO;
1425   if( !GetSHUO( NextUsageL, aNextSHUO ) || aNextSHUO->NbFathers()<1 )
1426     return Standard_False;
1427   
1428   // get upper_usage SHAO
1429   for (Standard_Integer i = 1; i <= aNextSHUO->NbFathers(); i++)
1430     aLabels.Append( aNextSHUO->GetFather(i)->Label() );
1431   return Standard_True;
1432 }
1433
1434 //=======================================================================
1435 //function : GetSHUONextUsage
1436 //purpose  : 
1437 //=======================================================================
1438
1439 Standard_Boolean XCAFDoc_ShapeTool::GetSHUONextUsage (const TDF_Label& UpperUsageL,
1440                                                       TDF_LabelSequence& aLabels)
1441 {
1442   Handle(XCAFDoc_GraphNode) aUpperSHUO;
1443   if ( !GetSHUO( UpperUsageL, aUpperSHUO ) || aUpperSHUO->NbChildren()<1 )
1444     return Standard_False;
1445   // get upper_usage SHAO
1446   for (Standard_Integer i = 1; i <= aUpperSHUO->NbChildren(); i++)
1447     aLabels.Append( aUpperSHUO->GetChild(i)->Label() );
1448   return Standard_True;
1449 }
1450
1451 //=======================================================================
1452 //function : RemoveSHUO
1453 //purpose  : 
1454 //=======================================================================
1455
1456 Standard_Boolean XCAFDoc_ShapeTool::RemoveSHUO (const TDF_Label& L) const
1457 {
1458   L.ForgetAllAttributes (Standard_True);
1459   return Standard_True;
1460 }
1461
1462 //=======================================================================
1463 //function : checkForShape
1464 //purpose  : auxilary
1465 //=======================================================================
1466
1467 static Standard_Boolean checkForShape (const TopoDS_Shape& theShape,
1468                                        const TopoDS_Shape& theCurSh,
1469                                        const TDF_Label& theUserL,
1470                                        TDF_LabelSequence& theLabels)
1471 {
1472   // the label of an assembly which contains this component
1473   TDF_Label aSuperUserL = theUserL.Father();
1474   TopLoc_Location aSupLoc, aCompLoc;
1475   aSupLoc = ::XCAFDoc_ShapeTool::GetLocation ( aSuperUserL );
1476   aCompLoc = ::XCAFDoc_ShapeTool::GetLocation ( theUserL );
1477   TopoDS_Shape aCopySh = theCurSh;
1478   aCompLoc = aCompLoc.Multiplied( theCurSh.Location() );
1479   aSupLoc = aSupLoc.Multiplied( aCompLoc );
1480   aCopySh.Location( aSupLoc );
1481   if ( aCopySh.IsSame( theShape ) ) {
1482     theLabels.Prepend( theUserL );
1483     return Standard_True;
1484   }
1485   // try to search deeply (upper by assmebly structure)
1486   TDF_LabelSequence aNewLabels;
1487   for (Standard_Integer j = 1; j <= theLabels.Length(); j++)
1488     aNewLabels.Append( theLabels.Value( j ) );
1489   aNewLabels.Prepend( theUserL );
1490   TDF_LabelSequence aUsers;
1491   ::XCAFDoc_ShapeTool::GetUsers( aSuperUserL, aUsers );
1492   for (Standard_Integer i = 1; i <= aUsers.Length(); i++)
1493     if ( checkForShape( theShape, aCopySh, aUsers.Value( i ), aNewLabels ) ) {
1494       // get solution
1495       theLabels = aNewLabels;
1496       return Standard_True;
1497     }
1498   return Standard_False;
1499 }
1500
1501 //=======================================================================
1502 //function : FindComponent
1503 //purpose  : 
1504 //=======================================================================
1505
1506 Standard_Boolean XCAFDoc_ShapeTool::FindComponent (const TopoDS_Shape& theShape,
1507                                                   TDF_LabelSequence& theLabels) const
1508 {
1509   theLabels.Clear();
1510   // search for a top-level shape that corresponds to this component
1511   TopoDS_Shape S0 = theShape;
1512   TopLoc_Location loc;
1513   S0.Location ( loc );
1514   TDF_Label aRefL = FindShape( S0 );
1515   if (aRefL.IsNull())
1516     return Standard_False; // cannot find top-level shape.
1517   
1518   TDF_LabelSequence aUsers;
1519   ::XCAFDoc_ShapeTool::GetUsers( aRefL, aUsers );
1520   for (Standard_Integer i = 1; i <= aUsers.Length(); i++)
1521     if ( checkForShape( theShape, S0, aUsers.Value( i ), theLabels ) )
1522       break;
1523   
1524   return (theLabels.Length() > 0);
1525 }
1526
1527 //=======================================================================
1528 //function : getShapesOfSHUO
1529 //purpose  : auxilary
1530 //=======================================================================
1531
1532 static Standard_Boolean getShapesOfSHUO (TopLoc_IndexedMapOfLocation& theaPrevLocMap,
1533                                          const Handle(XCAFDoc_ShapeTool)& theSTool,
1534                                          const TDF_Label& theSHUOlab,
1535                                          TopoDS_Shape& theShape)
1536 {
1537   Handle(XCAFDoc_GraphNode) SHUO;
1538   TDF_LabelSequence aLabSeq;
1539   theSTool->GetSHUONextUsage( theSHUOlab, aLabSeq );
1540   if (aLabSeq.Length() >= 1)
1541     for (Standard_Integer i = 1; i <= aLabSeq.Length(); i++) {
1542       TDF_Label aSubCompL = aLabSeq.Value( i );
1543       TopLoc_Location compLoc = XCAFDoc_ShapeTool::GetLocation ( aSubCompL.Father() );
1544       // create new map of laocation (to not merge locations from different shapes)
1545       TopLoc_IndexedMapOfLocation aNewPrevLocMap;
1546       for (Standard_Integer m = 1; m <= theaPrevLocMap.Extent(); m++)
1547         aNewPrevLocMap.Add( theaPrevLocMap.FindKey( m ) );
1548       aNewPrevLocMap.Add( compLoc );
1549       // got for the new sublocations and corresponding shape
1550       getShapesOfSHUO( aNewPrevLocMap, theSTool, aSubCompL, theShape );
1551     }
1552   else {
1553     TopoDS_Shape aSHUO_NUSh = theSTool->GetShape ( theSHUOlab.Father() );
1554     if ( aSHUO_NUSh.IsNull() ) return Standard_False;
1555     // cause got shape with location already.
1556     TopLoc_Location nullLoc;
1557     aSHUO_NUSh.Location ( nullLoc );
1558     // multiply the locations
1559     Standard_Integer intMapLenght = theaPrevLocMap.Extent();
1560     if ( intMapLenght < 1 )
1561       return Standard_False; // should not be, but to avoid exception...?
1562     TopLoc_Location SupcompLoc;
1563     SupcompLoc = theaPrevLocMap.FindKey( intMapLenght );
1564     if (intMapLenght > 1) {
1565       Standard_Integer l = intMapLenght - 1;
1566       while (l >= 1) {
1567         SupcompLoc = theaPrevLocMap.FindKey( l ).Multiplied( SupcompLoc );
1568         l--;
1569       }
1570     }
1571     aSHUO_NUSh.Location( SupcompLoc );
1572     theShape = aSHUO_NUSh;
1573   }
1574   return (!theShape.IsNull());
1575 }
1576
1577 //=======================================================================
1578 //function : GetSHUOInstance
1579 //purpose  : 
1580 //=======================================================================
1581
1582 TopoDS_Shape XCAFDoc_ShapeTool::GetSHUOInstance (const Handle(XCAFDoc_GraphNode)& theSHUO) const
1583 {
1584   TopoDS_Shape aShape;
1585   if (theSHUO.IsNull())
1586     return aShape;
1587   
1588   TDF_Label aSHUOlab = theSHUO->Label();
1589   // get location of the assembly
1590   TopLoc_Location loc = XCAFDoc_ShapeTool::GetLocation ( aSHUOlab.Father().Father() );
1591   // get location of the component
1592   TopLoc_Location compLoc = XCAFDoc_ShapeTool::GetLocation ( aSHUOlab.Father() );
1593   TopLoc_IndexedMapOfLocation aPrevLocMap;
1594   // get previous setted location 
1595   if ( !loc.IsIdentity() )
1596     aPrevLocMap.Add( loc );
1597   aPrevLocMap.Add( compLoc );
1598   // get shape by recurse method
1599   const Handle(XCAFDoc_ShapeTool)& STool = this;
1600   getShapesOfSHUO( aPrevLocMap, STool, aSHUOlab, aShape );
1601   
1602   return aShape;
1603 }
1604
1605 //=======================================================================
1606 //function : getUsersShapesOfSHUO
1607 //purpose  : auxilary
1608 //=======================================================================
1609
1610 static Standard_Boolean getUsersShapesOfSHUO (TopLoc_IndexedMapOfLocation& aPrevLocMap,
1611                                               const Handle(XCAFDoc_ShapeTool)& STool,
1612                                               const TDF_Label& aSHUOlab,
1613                                               const TDF_Label& theUserL,
1614                                               TopTools_SequenceOfShape& theSHUOShapeSeq)
1615 {
1616   TopLoc_IndexedMapOfLocation aNewPrevLocMap;
1617   // get location of the assembly
1618   TopLoc_Location loc = XCAFDoc_ShapeTool::GetLocation ( theUserL.Father() );
1619   // get location of the component
1620   TopLoc_Location compLoc = XCAFDoc_ShapeTool::GetLocation ( theUserL );
1621   // get previous setted location 
1622   aNewPrevLocMap.Add( loc );
1623   aNewPrevLocMap.Add( compLoc );
1624   Standard_Integer i;
1625   for (i = 1; i <= aPrevLocMap.Extent(); i++)
1626     aNewPrevLocMap.Add( aPrevLocMap.FindKey(i) );
1627   TDF_Label L = theUserL.Father();
1628   TDF_LabelSequence usersLab;
1629   ::XCAFDoc_ShapeTool::GetUsers( L, usersLab );
1630   if (usersLab.Length() == 0) {
1631     TopoDS_Shape aShape;
1632     getShapesOfSHUO( aNewPrevLocMap, STool, aSHUOlab, aShape );
1633     if (!aShape.IsNull()) {
1634       theSHUOShapeSeq.Append(aShape);
1635       return Standard_True;
1636     }
1637   }
1638   // now iterates on users of this assembly as component
1639   for ( i = 1; i <= usersLab.Length(); i++ ) {
1640     TDF_Label aNewUserL = usersLab.Value(i);
1641     getUsersShapesOfSHUO( aNewPrevLocMap, STool, aSHUOlab, aNewUserL, theSHUOShapeSeq );
1642   }
1643   
1644   return (theSHUOShapeSeq.Length() > 1);
1645 }
1646
1647 //=======================================================================
1648 //function : GetAllSHUOInstances
1649 //purpose  : auxilary
1650 //=======================================================================
1651
1652 Standard_Boolean XCAFDoc_ShapeTool::GetAllSHUOInstances (const Handle(XCAFDoc_GraphNode)& theSHUO,
1653                                                          TopTools_SequenceOfShape& theSHUOShapeSeq) const
1654 {
1655   if (theSHUO.IsNull())
1656     return Standard_False;
1657
1658   TDF_Label aSHUOlab = theSHUO->Label();
1659   TopLoc_IndexedMapOfLocation aPrevLocMap;
1660   // get location of the assembly
1661   TopLoc_Location loc = XCAFDoc_ShapeTool::GetLocation ( aSHUOlab.Father().Father() );
1662   // get location of the component
1663   TopLoc_Location compLoc = XCAFDoc_ShapeTool::GetLocation ( aSHUOlab.Father() );
1664   // get previous setted location 
1665   if ( !loc.IsIdentity() )
1666     aPrevLocMap.Add( loc );
1667   aPrevLocMap.Add( compLoc );
1668   // get label of assembly
1669   TDF_Label L = aSHUOlab.Father().Father();
1670   TDF_LabelSequence usersLab;
1671   ::XCAFDoc_ShapeTool::GetUsers( L, usersLab );
1672   TopoDS_Shape aShape;
1673   const Handle(XCAFDoc_ShapeTool)& STool = this;
1674   if (usersLab.Length() == 0) {
1675     getShapesOfSHUO( aPrevLocMap, STool, aSHUOlab, aShape );
1676     if (!aShape.IsNull()) {
1677       theSHUOShapeSeq.Append(aShape);
1678       return Standard_True;
1679     }
1680   }
1681   // now iterates on users of this assembly as component
1682   for (Standard_Integer i = 1; i <= usersLab.Length(); i++) {
1683     TDF_Label aUserL = usersLab.Value(i);
1684     getUsersShapesOfSHUO( aPrevLocMap, STool, aSHUOlab, aUserL, theSHUOShapeSeq );
1685   }
1686   
1687   return (theSHUOShapeSeq.Length() > 1);
1688 }
1689
1690 //=======================================================================
1691 //function : SetInstanceSHUO
1692 //purpose  : 
1693 //=======================================================================
1694
1695 Handle(XCAFDoc_GraphNode) XCAFDoc_ShapeTool::SetInstanceSHUO (const TopoDS_Shape& theShape) const
1696 {
1697   Handle(XCAFDoc_GraphNode) SHUO;
1698   TDF_LabelSequence aLabels;
1699   if ( FindComponent( theShape, aLabels ) )
1700     // set shuo structure on labels of component-assembly structure
1701     SetSHUO( aLabels, SHUO );
1702   return SHUO;
1703 }
1704
1705 //=======================================================================
1706 //function : FindSHUO
1707 //purpose  : 
1708 //=======================================================================
1709
1710 Standard_Boolean XCAFDoc_ShapeTool::FindSHUO (const TDF_LabelSequence& theLabels,
1711                                               Handle(XCAFDoc_GraphNode)& theSHUOAttr)
1712 {
1713   TDF_AttributeSequence SHUOAttrs;
1714   TDF_Label aCompLabel = theLabels.Value(1);
1715   if (! ::XCAFDoc_ShapeTool::GetAllComponentSHUO( aCompLabel, SHUOAttrs ) )
1716     return Standard_False;
1717   // WARNING: manage that each SHUO upper_usage have only one SHUO next_usage
1718   for (Standard_Integer i = 1; i <= SHUOAttrs.Length(); i++) {
1719     TDF_LabelSequence aCondidate;
1720     Handle(XCAFDoc_GraphNode) anSHUO = Handle(XCAFDoc_GraphNode)::DownCast(SHUOAttrs.Value(i));
1721     aCondidate.Append( anSHUO->Label().Father() );
1722     while (anSHUO->NbChildren()) {
1723       anSHUO = anSHUO->GetChild( 1 );
1724       aCondidate.Append( anSHUO->Label().Father() );
1725     }
1726     // check the label sequences
1727     Standard_Boolean isEqual = Standard_True;
1728     if (theLabels.Length() != aCondidate.Length())
1729       isEqual = Standard_False;
1730     else
1731       for (Standard_Integer li = 1; li <= theLabels.Length(); li++)
1732         if ( theLabels.Value(li) != aCondidate.Value(li) ) {
1733           isEqual = Standard_False;
1734           break;
1735         }
1736     if (!isEqual)
1737       continue;
1738       
1739     theSHUOAttr = Handle(XCAFDoc_GraphNode)::DownCast(SHUOAttrs.Value(i));
1740     break;
1741   }
1742   return ( !theSHUOAttr.IsNull() );
1743 }