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