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