1 // Created on: 2000-08-03
2 // Created by: data exchange team
3 // Copyright (c) 2000-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
17 #include <BRep_Builder.hxx>
19 #include <gp_Trsf.hxx>
20 #include <Standard_GUID.hxx>
21 #include <Standard_Type.hxx>
22 #include <TCollection_AsciiString.hxx>
23 #include <TCollection_ExtendedString.hxx>
24 #include <TCollection_HAsciiString.hxx>
25 #include <TColStd_SequenceOfHAsciiString.hxx>
26 #include <TDataStd_ChildNodeIterator.hxx>
27 #include <TDataStd_Name.hxx>
28 #include <TDataStd_TreeNode.hxx>
29 #include <TDataStd_UAttribute.hxx>
30 #include <TDF_Attribute.hxx>
31 #include <TDF_ChildIDIterator.hxx>
32 #include <TDF_ChildIterator.hxx>
33 #include <TDF_Label.hxx>
34 #include <TDF_LabelMap.hxx>
35 #include <TDF_LabelSequence.hxx>
36 #include <TDF_MapIteratorOfLabelMap.hxx>
37 #include <TDF_RelocationTable.hxx>
38 #include <TDF_Tool.hxx>
39 #include <TDocStd_Document.hxx>
40 #include <TNaming_Builder.hxx>
41 #include <TNaming_NamedShape.hxx>
42 #include <TNaming_Tool.hxx>
43 #include <TopLoc_IndexedMapOfLocation.hxx>
44 #include <TopLoc_Location.hxx>
45 #include <TopoDS_Compound.hxx>
46 #include <TopoDS_Iterator.hxx>
47 #include <TopoDS_Shape.hxx>
48 #include <TopTools_ListOfShape.hxx>
49 #include <TopTools_MapOfOrientedShape.hxx>
50 #include <XCAFDoc.hxx>
51 #include <XCAFDoc_GraphNode.hxx>
52 #include <XCAFDoc_Location.hxx>
53 #include <XCAFDoc_ShapeMapTool.hxx>
54 #include <XCAFDoc_ShapeTool.hxx>
56 IMPLEMENT_STANDARD_RTTIEXT(XCAFDoc_ShapeTool,TDF_Attribute)
58 static Standard_Boolean theAutoNaming = Standard_True;
60 // attribute methods //////////////////////////////////////////////////
62 //=======================================================================
65 //=======================================================================
67 const Standard_GUID& XCAFDoc_ShapeTool::GetID()
69 static Standard_GUID ShapeToolID ("efd212ee-6dfd-11d4-b9c8-0060b0ee281b");
74 //=======================================================================
77 //=======================================================================
79 Handle(XCAFDoc_ShapeTool) XCAFDoc_ShapeTool::Set(const TDF_Label& L)
81 Handle(XCAFDoc_ShapeTool) A;
82 if (!L.FindAttribute (XCAFDoc_ShapeTool::GetID(), A)) {
83 A = new XCAFDoc_ShapeTool ();
91 //=======================================================================
92 //function : Constructor
94 //=======================================================================
96 XCAFDoc_ShapeTool::XCAFDoc_ShapeTool()
98 hasSimpleShapes = Standard_False;
102 //=======================================================================
105 //=======================================================================
107 const Standard_GUID& XCAFDoc_ShapeTool::ID() const
112 //=======================================================================
115 //=======================================================================
117 void XCAFDoc_ShapeTool::Restore(const Handle(TDF_Attribute)& /*with*/)
121 //=======================================================================
122 //function : NewEmpty
124 //=======================================================================
126 Handle(TDF_Attribute) XCAFDoc_ShapeTool::NewEmpty() const
128 return new XCAFDoc_ShapeTool;
131 //=======================================================================
134 //=======================================================================
136 void XCAFDoc_ShapeTool::Paste (const Handle(TDF_Attribute)& /*into*/,
137 const Handle(TDF_RelocationTable)& /*RT*/) const
141 // Auxiliary methods //////////////////////////////////////////////////
143 //=======================================================================
144 //function : SetLabelNameByLink
146 //=======================================================================
147 static void SetLabelNameByLink(const TDF_Label L)
149 Handle(TDataStd_TreeNode) Node;
150 if (! L.FindAttribute(XCAFDoc::ShapeRefGUID(), Node) ||
151 ! Node->HasFather()) {
153 cout<<"Error: XCAFDoc_ShapeTool, SetLabelNameByLink(): NO NODE"<<endl;
157 TCollection_AsciiString Entry;
158 TDF_Tool::Entry ( Node->Father()->Label(), Entry );
159 Entry.Insert(1, "=>[");
162 TDataStd_Name::Set(L, TCollection_ExtendedString( Entry ));
166 //=======================================================================
167 //function : SetLabelNameByShape
169 //=======================================================================
170 static void SetLabelNameByShape(const TDF_Label L)
173 if (XCAFDoc_ShapeTool::GetShape(L, S) &&
174 ! L.IsAttribute(TDataStd_Name::GetID()) ) {
175 Standard_SStream Stream;
176 // TopAbs_ShapeEnum Type = S.ShapeType();
177 // if (Type == TopAbs_COMPOUND) Stream<<"ASSEMBLY";
179 TopAbs::Print(S.ShapeType(), Stream);
180 TCollection_AsciiString aName (Stream.str().c_str());
181 TDataStd_Name::Set(L, TCollection_ExtendedString(aName));
186 //=======================================================================
187 //function : SearchUsingMap
189 //=======================================================================
191 Standard_Boolean XCAFDoc_ShapeTool::SearchUsingMap(const TopoDS_Shape &S, TDF_Label &L,
192 const Standard_Boolean findWithoutLoc,
193 const Standard_Boolean findSubShape) const
196 if(myShapeLabels.IsBound(S)) {
197 L = myShapeLabels.Find(S);
198 return Standard_True;
203 if(myShapeLabels.IsBound(S0)) {
204 TDF_Label L1 = myShapeLabels.Find(S0);
205 TDF_LabelSequence Labels;
206 if(GetUsers(L1, Labels, Standard_True)) {
207 for(Standard_Integer i=1; i<=Labels.Length(); i++) {
208 TopoDS_Shape c = GetShape(Labels.Value(i));
211 return Standard_True;
217 return Standard_True;
221 if(hasSimpleShapes) {
222 if(mySimpleShapes.IsBound(S)) {
223 L = mySimpleShapes.Find(S);
224 return Standard_True;
226 if(mySimpleShapes.IsBound(S0)) {
227 L = mySimpleShapes.Find(S0);
228 return Standard_True;
232 if(!findSubShape) return Standard_False;
233 TDF_Label mainL = FindMainShapeUsingMap(S);
234 if(mainL.IsNull()) return Standard_False;
235 L = AddSubShape(mainL,S);
236 return !L.IsNull();//Standard_True;
240 //=======================================================================
243 //=======================================================================
245 Standard_Boolean XCAFDoc_ShapeTool::Search (const TopoDS_Shape &S,
247 const Standard_Boolean findInstance,
248 const Standard_Boolean findComponent,
249 const Standard_Boolean findSubShape) const
251 // search among shapes
252 Standard_Boolean isLocated = ! S.Location().IsIdentity();
255 // try to find top-level instance
256 if ( findInstance && FindShape ( S, L, Standard_True ) )
257 return Standard_True;
258 // try to find component of assembly
259 if ( findComponent ) {
260 TDF_LabelSequence labels;
261 GetShapes ( labels );
262 for ( Standard_Integer i=1; i <= labels.Length(); i++ ) {
263 if ( ! IsAssembly ( labels.Value(i) ) ) continue;
264 TDF_LabelSequence comp;
265 GetComponents ( labels.Value(i), comp );
266 for ( Standard_Integer j=1; j <= comp.Length(); j++ ) {
267 TopoDS_Shape c = GetShape ( comp.Value(j) );
268 if ( c.IsSame ( S ) ) {
270 return Standard_True;
276 // try to find top-level simple shape
277 if ( FindShape ( S, L, Standard_False ) ) return Standard_True;
280 if ( ! findSubShape ) return Standard_False;
281 TDF_Label mainL = FindMainShape ( S );
282 if ( mainL.IsNull() ) return Standard_False;
283 L = AddSubShape ( mainL, S );
284 return !L.IsNull();//Standard_True;
287 //=======================================================================
288 //function : FindShape
290 //=======================================================================
292 Standard_Boolean XCAFDoc_ShapeTool::FindShape (const TopoDS_Shape& S,
294 const Standard_Boolean findInstance) const
296 // search for null-located shape
298 if ( ! findInstance ) {
303 // this code is used instead of the following for performance reasons
304 if (TNaming_Tool::HasLabel(Label(), S0)) {
306 L = TNaming_Tool::Label(Label(), S0, TransDef);
309 return Standard_False;
312 return Standard_True;
314 // Try to find shape manually
315 TDF_ChildIDIterator it(Label(), TNaming_NamedShape::GetID());
316 for (; it.More(); it.Next()) {
317 TDF_Label aLabel = it.Value()->Label();
318 Handle(TNaming_NamedShape) NS;
319 if ( aLabel.FindAttribute(TNaming_NamedShape::GetID(), NS) &&
320 S0.IsSame ( TNaming_Tool::GetShape(NS) ) ) {
322 return Standard_True;
327 return Standard_False;
330 //=======================================================================
331 //function : FindShape
333 //=======================================================================
335 TDF_Label XCAFDoc_ShapeTool::FindShape (const TopoDS_Shape& S,
336 const Standard_Boolean findInstance) const
339 if (FindShape(S, L, findInstance))
344 //=======================================================================
345 //function : GetShape
347 //=======================================================================
349 Standard_Boolean XCAFDoc_ShapeTool::GetShape (const TDF_Label& L, TopoDS_Shape& S)
351 Handle(XCAFDoc_Location) LocationAttribute;
354 TopoDS_Compound EmptyComp;
356 B.MakeCompound(EmptyComp);
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;
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;
376 //=======================================================================
377 //function : GetShape
379 //=======================================================================
381 TopoDS_Shape XCAFDoc_ShapeTool::GetShape(const TDF_Label& L)
388 //=======================================================================
389 //function : NewShape
391 //=======================================================================
393 TDF_Label XCAFDoc_ShapeTool::NewShape() const
395 TopoDS_Compound aShape;
397 tdsB.MakeCompound ( aShape );
400 TDF_Label aLabel = aTag.NewChild(Label());
402 TNaming_Builder tnBuild(aLabel);
403 tnBuild.Generated(aShape);
408 //=======================================================================
409 //function : SetShape
411 //=======================================================================
413 void XCAFDoc_ShapeTool::SetShape (const TDF_Label& L, const TopoDS_Shape& S)
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);
424 if(!myShapeLabels.IsBound(S)) {
425 myShapeLabels.Bind(S,L);
429 //=======================================================================
430 //function : MakeReference
432 //=======================================================================
434 void XCAFDoc_ShapeTool::MakeReference (const TDF_Label &L,
435 const TDF_Label &refL,
436 const TopLoc_Location &loc)
439 XCAFDoc_Location::Set(L, loc);
442 Handle(TDataStd_TreeNode) refNode, mainNode;
443 mainNode = TDataStd_TreeNode::Set ( refL, XCAFDoc::ShapeRefGUID() );
444 refNode = TDataStd_TreeNode::Set ( L, XCAFDoc::ShapeRefGUID() );
445 refNode->Remove(); // abv: fix against bug in TreeNode::Append()
446 mainNode->Append(refNode);
449 SetLabelNameByLink(L);
452 //=======================================================================
453 //function : addShape
455 //=======================================================================
457 TDF_Label XCAFDoc_ShapeTool::addShape (const TopoDS_Shape& S, const Standard_Boolean makeAssembly)
459 TDF_Label ShapeLabel;
462 // search if the shape already exists (with the same location)
463 if ( S.IsNull() || FindShape ( S, ShapeLabel, Standard_True ) ) return ShapeLabel;
465 // else add a new label
466 ShapeLabel = aTag.NewChild(Label());
468 // if shape has location, make a reference to the same shape without location
469 if ( ! S.Location().IsIdentity() /*&& FindShape ( S, L )*/ ) {
473 TDF_Label L = addShape ( S0, makeAssembly );
474 MakeReference ( ShapeLabel, L, S.Location() );
478 // else add a shape to a label
479 TNaming_Builder tnBuild(ShapeLabel);
480 tnBuild.Generated(S);
482 Handle(XCAFDoc_ShapeMapTool) A = XCAFDoc_ShapeMapTool::Set(ShapeLabel);
483 // if ( ! ShapeLabel.FindAttribute(XCAFDoc_ShapeMapTool::GetID(), A) ) {
484 // A = XCAFDoc_ShapeMapTool::Set(ShapeLabel);
485 // ShapeLabel.AddAttribute(A);
490 SetLabelNameByShape(ShapeLabel);
492 // if shape is Compound and flag is set, create assembly
493 if ( makeAssembly && S.ShapeType() == TopAbs_COMPOUND ) {
494 // mark assembly by assigning UAttribute
495 Handle(TDataStd_UAttribute) Uattr;
496 Uattr = TDataStd_UAttribute::Set ( ShapeLabel, XCAFDoc::AssemblyGUID() );
498 TDataStd_Name::Set(ShapeLabel, TCollection_ExtendedString("ASSEMBLY"));
500 // iterate on components
501 TopoDS_Iterator Iterator(S);
502 for (; Iterator.More(); Iterator.Next()) {
503 // get label for component`s shape
504 TopoDS_Shape Scomp = Iterator.Value(), S0 = Scomp;
507 TDF_Label compL = addShape ( S0, makeAssembly );
509 // add a component as reference
510 TDF_Label RefLabel = aTag.NewChild(ShapeLabel);
511 MakeReference ( RefLabel, compL, Scomp.Location() );
515 if(!IsAssembly(ShapeLabel)) {
516 //const TopTools_IndexedMapOfShape tmpMap = A->GetMap();
517 //for(Standard_Integer i=1; i<=tmpMap.Extent(); i++)
518 //mySubShapes.Bind(tmpMap.FindKey(i),ShapeLabel);
519 for(Standard_Integer i=1; i<=A->GetMap().Extent(); i++)
521 TopoDS_Shape aSh = A->GetMap().FindKey(i);
522 mySubShapes.Bind(aSh,ShapeLabel);
524 //mySubShapes.Bind(ShapeLabel,A->GetMap());
531 //=======================================================================
532 //function : prepareAssembly
534 //=======================================================================
535 static Standard_Boolean prepareAssembly (const TopoDS_Shape& theShape,
536 TopoDS_Shape& theOUTShape)
538 // iterate on components
539 theOUTShape = theShape;
540 if (theShape.ShapeType() == TopAbs_COMPOUND) {
542 // check if shape if frosen
543 if (!theOUTShape.Free())
544 theOUTShape.Free(Standard_True);
546 TopTools_SequenceOfShape aSubShapeSeq;
547 TopoDS_Iterator Iterator(theShape);
548 for (; Iterator.More(); Iterator.Next())
549 aSubShapeSeq.Append(Iterator.Value());
550 for (Standard_Integer i = 1; i <= aSubShapeSeq.Length(); i++) {
551 TopoDS_Shape Scomp = aSubShapeSeq.Value(i);
552 TopoDS_Shape aNewScomp;
553 B.Remove(theOUTShape, Scomp);
554 prepareAssembly( Scomp, aNewScomp );
555 TopLoc_Location aLoc;
556 aLoc = aNewScomp.Location();
557 if ( aLoc.IsIdentity() ) {
558 // create an "empty" location
560 aTrsf.SetScale(gp_Pnt(0,0,0), 1);
561 aLoc = TopLoc_Location( aTrsf );
562 aNewScomp.Location( aLoc );
564 B.Add(theOUTShape, aNewScomp);
567 return Standard_True;
571 //=======================================================================
572 //function : AddShape
574 //=======================================================================
576 TDF_Label XCAFDoc_ShapeTool::AddShape (const TopoDS_Shape& theShape,
577 const Standard_Boolean makeAssembly,
578 const Standard_Boolean makePrepare)
580 // PTV 17.02.2003 to avoid components without location.
581 TopoDS_Shape S = theShape;
582 if ( makePrepare && makeAssembly && S.ShapeType() == TopAbs_COMPOUND )
583 prepareAssembly( theShape, S ); // OCC1669
585 TDF_Label L = addShape(S,makeAssembly);
587 if(!myShapeLabels.IsBound(S)) {
588 myShapeLabels.Bind(S,L);
593 //return addShape( S, makeAssembly );
596 //=======================================================================
597 //function : RemoveShape
599 //=======================================================================
601 Standard_Boolean XCAFDoc_ShapeTool::RemoveShape (const TDF_Label& L,
602 const Standard_Boolean removeCompletely) const
604 if ( ! IsTopLevel ( L ) || ! IsFree ( L ) ) return Standard_False;
606 Handle(TDataStd_TreeNode) aNode;
608 if (removeCompletely &&
609 L.FindAttribute (XCAFDoc::ShapeRefGUID(), aNode) &&
610 aNode->HasFather() &&
611 L.IsAttribute (XCAFDoc_Location::GetID()))
613 aLabel = aNode->Father()->Label();
616 L.ForgetAllAttributes (Standard_True);
618 if (removeCompletely && !aLabel.IsNull())
620 return RemoveShape(aLabel);
622 return Standard_True;
626 //=======================================================================
629 //=======================================================================
631 void XCAFDoc_ShapeTool::Init()
633 hasSimpleShapes = Standard_False;
637 //=======================================================================
638 //function : SetAutoNaming
640 //=======================================================================
642 void XCAFDoc_ShapeTool::SetAutoNaming (const Standard_Boolean V)
648 //=======================================================================
649 //function : AutoNaming
651 //=======================================================================
653 Standard_Boolean XCAFDoc_ShapeTool::AutoNaming()
655 return theAutoNaming;
659 //=======================================================================
660 //function : ComputeShapes
662 //=======================================================================
664 void XCAFDoc_ShapeTool::ComputeShapes(const TDF_Label& L)
666 TDF_ChildIterator it(L);
667 for(; it.More(); it.Next()) {
668 TDF_Label L1 = it.Value();
671 if(!myShapeLabels.IsBound(S)) {
672 mySimpleShapes.Bind(S,L1);
680 //=======================================================================
681 //function : ComputeSimpleShapes
683 //=======================================================================
685 void XCAFDoc_ShapeTool::ComputeSimpleShapes()
687 ComputeShapes(Label());
688 hasSimpleShapes = Standard_True;
692 //=======================================================================
693 //function : GetShapes
695 //=======================================================================
697 void XCAFDoc_ShapeTool::GetShapes(TDF_LabelSequence& Labels) const
701 TDF_ChildIterator it(Label());
702 for (; it.More(); it.Next()) {
703 TDF_Label L = it.Value();
705 if ( GetShape ( L, S ) ) Labels.Append ( L );
710 //=======================================================================
711 //function : GetFreeShapes
713 //=======================================================================
715 void XCAFDoc_ShapeTool::GetFreeShapes (TDF_LabelSequence& FreeLabels) const
719 TDF_ChildIterator it(Label());
720 for (; it.More(); it.Next()) {
721 TDF_Label L = it.Value();
723 if ( GetShape ( L, S ) && IsFree ( L ) ) FreeLabels.Append ( L );
727 //=======================================================================
728 //function : IsTopLevel
730 //=======================================================================
732 Standard_Boolean XCAFDoc_ShapeTool::IsTopLevel (const TDF_Label& L) const
734 return L.Father() == Label();
737 //=======================================================================
740 //=======================================================================
742 Standard_Boolean XCAFDoc_ShapeTool::IsShape (const TDF_Label& L)
744 return IsSimpleShape ( L ) || IsAssembly ( L ) || IsReference ( L );
747 //=======================================================================
748 //function : IsSimpleShape
750 //=======================================================================
752 Standard_Boolean XCAFDoc_ShapeTool::IsSimpleShape (const TDF_Label& L)
754 Handle(TNaming_NamedShape) NS;
755 return L.FindAttribute ( TNaming_NamedShape::GetID(), NS ) &&
756 ! IsAssembly ( L ) && ! IsReference ( L );
759 //=======================================================================
760 //function : IsReference
762 //=======================================================================
764 Standard_Boolean XCAFDoc_ShapeTool::IsReference (const TDF_Label& L)
766 Handle(TDataStd_TreeNode) Node;
767 return L.FindAttribute(XCAFDoc::ShapeRefGUID(), Node) && Node->HasFather();
770 //=======================================================================
771 //function : IsAssembly
773 //=======================================================================
775 Standard_Boolean XCAFDoc_ShapeTool::IsAssembly (const TDF_Label& L)
777 Handle(TDataStd_UAttribute) Uattr;
778 return L.FindAttribute(XCAFDoc::AssemblyGUID(), Uattr);
781 //=======================================================================
782 //function : IsComponent
784 //=======================================================================
786 Standard_Boolean XCAFDoc_ShapeTool::IsComponent (const TDF_Label& L)
788 return IsReference ( L ) && IsAssembly ( L.Father() );
791 //=======================================================================
792 //function : IsCompound
794 //=======================================================================
796 Standard_Boolean XCAFDoc_ShapeTool::IsCompound (const TDF_Label& L)
798 Handle(TDataStd_Name) Name;
799 if (L.FindAttribute(TDataStd_Name::GetID(),Name)) {
800 TCollection_ExtendedString estr1 = Name->Get();
801 TCollection_ExtendedString estr2("COMPOUND");
803 return Standard_True;
806 return Standard_False;
809 //=======================================================================
810 //function : IsSubShape
812 //=======================================================================
814 Standard_Boolean XCAFDoc_ShapeTool::IsSubShape (const TDF_Label& L)
816 return IsSimpleShape ( L ) && IsShape ( L.Father() );
819 //=======================================================================
822 //=======================================================================
824 Standard_Boolean XCAFDoc_ShapeTool::IsFree (const TDF_Label& L)
826 Handle(TDataStd_TreeNode) Node;
827 if ( ! L.FindAttribute(XCAFDoc::ShapeRefGUID(), Node) ||
828 ! Node->HasFirst() ) return Standard_True;
830 return Standard_False;
833 //=======================================================================
834 //function : GetUsers
835 //purpose : Returns number of users (0 if shape is free)
836 //=======================================================================
838 Standard_Integer XCAFDoc_ShapeTool::GetUsers (const TDF_Label& L,
839 TDF_LabelSequence& Labels,
840 const Standard_Boolean getsubchilds)
842 Standard_Integer NbUsers=0;
843 Handle(TDataStd_TreeNode) Node ;
845 if ( ! L.FindAttribute(XCAFDoc::ShapeRefGUID(), Node) ) return NbUsers;
847 Node = Node->First();
848 while ( ! Node.IsNull() ) {
850 if ( getsubchilds ) {
851 TDF_Label underL = Node->Label().Father();
852 NbUsers += GetUsers ( underL, Labels, getsubchilds );
855 Labels.Append(Node->Label());
862 //=======================================================================
863 //function : NbComponents
865 //=======================================================================
867 Standard_Integer XCAFDoc_ShapeTool::NbComponents (const TDF_Label& L,
868 const Standard_Boolean getsubchilds)
870 TDF_LabelSequence subLabels;
871 GetComponents (L, subLabels, getsubchilds);
872 return subLabels.Length();
875 //=======================================================================
876 //function : GetComponents
878 //=======================================================================
880 Standard_Boolean XCAFDoc_ShapeTool::GetComponents (const TDF_Label& L, TDF_LabelSequence& Labels,
881 const Standard_Boolean getsubchilds)
883 if ( ! IsAssembly(L) ) return Standard_False;
885 TDF_ChildIterator It(L);
886 for (; It.More(); It.Next() ) {
887 TDF_Label comp = It.Value();
888 if ( IsComponent ( comp ) ) {
889 if ( getsubchilds ) {
891 if ( GetReferredShape ( comp, underL ) )
892 GetComponents ( underL, Labels, getsubchilds);
894 Labels.Append ( comp );
897 return Standard_True;
900 //=======================================================================
901 //function : GetLocation
903 //=======================================================================
905 TopLoc_Location XCAFDoc_ShapeTool::GetLocation (const TDF_Label& L)
907 Handle(XCAFDoc_Location) LocationAttribute;
908 if (L.FindAttribute(XCAFDoc_Location::GetID(), LocationAttribute))
909 return LocationAttribute->Get();
911 Handle(TNaming_NamedShape) NS;
913 if ( L.FindAttribute ( TNaming_NamedShape::GetID(), NS ) ) {
914 S = TNaming_Tool::GetShape(NS);
919 //=======================================================================
920 //function : GetReferredShape
922 //=======================================================================
924 Standard_Boolean XCAFDoc_ShapeTool::GetReferredShape (const TDF_Label& L,
927 if ( ! IsReference(L) ) return Standard_False;
929 Handle (TDataStd_TreeNode) Node;
930 L.FindAttribute(XCAFDoc::ShapeRefGUID(), Node);
931 Label = Node->Father()->Label();
932 return Standard_True;
935 //=======================================================================
936 //function : AddComponent
938 //=======================================================================
940 TDF_Label XCAFDoc_ShapeTool::AddComponent (const TDF_Label& assembly,
941 const TDF_Label& compL,
942 const TopLoc_Location &Loc)
946 // check that shape is assembly
947 if ( ! IsAssembly(assembly) ) {
948 // if it is simple shape, make it assembly
949 if ( IsSimpleShape(assembly) )
950 TDataStd_UAttribute::Set ( assembly, XCAFDoc::AssemblyGUID() );
954 // add a component as reference
956 L = aTag.NewChild(assembly);
957 MakeReference ( L, compL, Loc );
959 // map shape to label
961 if (GetShape(L, aShape))
963 if (!myShapeLabels.IsBound(aShape))
964 myShapeLabels.Bind(aShape, L);
970 //=======================================================================
971 //function : AddComponent
973 //=======================================================================
975 TDF_Label XCAFDoc_ShapeTool::AddComponent (const TDF_Label& assembly,
976 const TopoDS_Shape& comp,
977 const Standard_Boolean expand)
979 // get label for component`s shape
980 TopoDS_Shape S0 = comp;
984 compL = AddShape ( S0, expand );
986 // add component by its label
987 return AddComponent ( assembly, compL, comp.Location() );
990 //=======================================================================
991 //function : RemoveComponent
993 //=======================================================================
995 void XCAFDoc_ShapeTool::RemoveComponent (const TDF_Label& comp) const
997 if ( IsComponent(comp) )
999 comp.ForgetAllAttributes();
1003 //=======================================================================
1004 //function : UpdateAssemblies
1006 //=======================================================================
1008 void XCAFDoc_ShapeTool::UpdateAssemblies()
1010 // We start from the free shapes (roots in the assembly structure)
1011 TDF_LabelSequence aRootLabels;
1012 GetFreeShapes(aRootLabels);
1014 // Iterate over the free shapes
1015 for ( TDF_LabelSequence::Iterator anIt(aRootLabels); anIt.More(); anIt.Next() )
1017 TDF_Label aRefLabel = anIt.Value();
1018 if (IsReference(aRefLabel))
1020 GetReferredShape(aRefLabel, aRefLabel);
1022 const TDF_Label& aRootLab = aRefLabel;
1023 TopoDS_Shape anAssemblyShape;
1024 updateComponent(aRootLab, anAssemblyShape);
1028 //=======================================================================
1029 //function : IsSubShape
1031 //=======================================================================
1033 //static Standard_Boolean CheckSubShape (const TopoDS_Shape &S, const TopoDS_Shape &sub)
1035 // if ( S.IsSame ( sub ) ) return Standard_True;
1037 // if ( S.ShapeType() >= sub.ShapeType() ) return Standard_False;
1039 // for ( TopoDS_Iterator it(S); it.More(); it.Next() ) {
1040 // if ( CheckSubShape ( it.Value(), sub ) ) return Standard_True;
1042 // return Standard_False;
1045 //=======================================================================
1046 //function : IsSubShape
1048 //=======================================================================
1050 Standard_Boolean XCAFDoc_ShapeTool::IsSubShape (const TDF_Label &shapeL,
1051 const TopoDS_Shape &sub) const
1053 Handle(XCAFDoc_ShapeMapTool) A;
1054 if (!shapeL.FindAttribute(XCAFDoc_ShapeMapTool::GetID(), A))
1056 TopoDS_Shape aShape = GetShape(shapeL);
1057 if (aShape.IsNull())
1058 return Standard_False;
1059 A = XCAFDoc_ShapeMapTool::Set(shapeL);
1060 A->SetShape(aShape);
1063 return A->IsSubShape(sub);
1066 //=======================================================================
1067 //function : FindSubShape
1069 //=======================================================================
1071 Standard_Boolean XCAFDoc_ShapeTool::FindSubShape (const TDF_Label &shapeL,
1072 const TopoDS_Shape &sub,
1076 return Standard_False;
1078 if (TNaming_Tool::HasLabel(Label(), sub)) {
1080 L = TNaming_Tool::Label(Label(), sub, TransDef);
1082 return Standard_False;
1083 if (L.Father() == shapeL)
1084 return Standard_True;
1088 return Standard_False;
1091 // if subshape was found wrong, try to do it manually
1092 // it can be possible if several part shapes has the same subshapes
1094 TDF_ChildIterator aChldLabIt(shapeL);
1095 for (; aChldLabIt.More(); aChldLabIt.Next() ) {
1096 TDF_Label aSubLabel = aChldLabIt.Value();
1097 TopoDS_Shape aSubShape;
1098 if (GetShape(aSubLabel, aSubShape) && aSubShape.IsSame(sub)) {
1100 return Standard_True;
1103 return Standard_False;
1106 //=======================================================================
1107 //function : AddSubShape
1109 //=======================================================================
1111 TDF_Label XCAFDoc_ShapeTool::AddSubShape (const TDF_Label &shapeL,
1112 const TopoDS_Shape &sub) const
1115 if (!IsSimpleShape(shapeL) || !IsTopLevel(shapeL))
1118 if ( FindSubShape ( shapeL, sub, L ) ) return L;
1120 if (!IsSubShape(shapeL, sub))
1124 L = aTag.NewChild(shapeL);
1126 TNaming_Builder tnBuild(L);
1127 tnBuild.Generated(sub);
1129 // if(!mySubShapes.IsBound(sub))
1130 // mySubShapes.Bind(sub,L);
1136 //=======================================================================
1137 //function : FindMainShapeUsingMap
1139 //=======================================================================
1141 TDF_Label XCAFDoc_ShapeTool::FindMainShapeUsingMap(const TopoDS_Shape &sub) const
1143 //for(Standard_Integer i=1; i<=myNotAssemblies.Length(); i++) {
1144 // TDF_Label L = myNotAssemblies.Value(i);
1145 // if(IsSubShape(L,sub)) return L;
1147 if(mySubShapes.IsBound(sub))
1148 return mySubShapes.Find(sub);
1154 //=======================================================================
1155 //function : FindMainShape
1157 //=======================================================================
1159 TDF_Label XCAFDoc_ShapeTool::FindMainShape (const TopoDS_Shape &sub) const
1161 TDF_ChildIterator it(Label());
1162 for (; it.More(); it.Next()) {
1163 TDF_Label L = it.Value();
1165 if ( IsSimpleShape( L ) && IsSubShape ( L, sub ) ) return L;
1172 //=======================================================================
1173 //function : GetSubShapes
1175 //=======================================================================
1177 Standard_Boolean XCAFDoc_ShapeTool::GetSubShapes (const TDF_Label &L,
1178 TDF_LabelSequence& Labels)
1180 TDF_ChildIterator It(L);
1181 for (; It.More(); It.Next() ) {
1182 TDF_Label sub = It.Value();
1183 if ( IsSubShape ( sub ) ) Labels.Append ( sub );
1185 return Labels.Length() >0;
1188 //=======================================================================
1189 //function : BaseLabel
1191 //=======================================================================
1193 TDF_Label XCAFDoc_ShapeTool::BaseLabel () const
1198 //=======================================================================
1199 //function : DumpAssembly
1200 //purpose : recursive part of Dump()
1201 //=======================================================================
1203 static void DumpAssembly(Standard_OStream& theDumpLog,
1205 const Standard_Integer level,
1206 const Standard_Boolean deep)
1209 XCAFDoc_ShapeTool::GetShape(L, S);
1212 for (Standard_Integer i=0; i<level; i++)
1215 TCollection_AsciiString Entry;
1216 TDF_Tool::Entry(L, Entry);
1218 if(XCAFDoc_ShapeTool::IsAssembly(L))
1220 theDumpLog<<"ASSEMBLY ";
1222 else if (XCAFDoc_ShapeTool::IsSimpleShape(L))
1224 if(L.Father().Father().Father().IsRoot())
1225 theDumpLog<<"PART ";
1229 theDumpLog<<"INSTANCE ";
1231 TopAbs::Print(S.ShapeType(), theDumpLog);
1233 theDumpLog<<" "<<Entry;
1234 if(XCAFDoc_ShapeTool::IsReference(L))
1236 Handle(TDataStd_TreeNode) aRef;
1237 L.FindAttribute(XCAFDoc::ShapeRefGUID(), aRef);
1238 TDF_Tool::Entry(aRef->Father()->Label(), Entry);
1239 theDumpLog<<" (refers to "<<Entry<<")";
1241 Handle(TDataStd_Name) Name;
1242 if (L.FindAttribute(TDataStd_Name::GetID(), Name))
1243 theDumpLog<<" \""<<Name->Get()<<"\" ";
1246 theDumpLog<<"("<<*(void**)&S.TShape();
1247 if (! S.Location().IsIdentity())
1248 theDumpLog<<", "<< *(void**)&S.Location();
1253 Handle(TDataStd_TreeNode) Node;
1254 TDF_ChildIterator NodeIterator(L);
1255 for (; NodeIterator.More(); NodeIterator.Next()) {
1256 DumpAssembly(theDumpLog, NodeIterator.Value(), level+1, deep);
1262 //=======================================================================
1265 //=======================================================================
1267 Standard_OStream& XCAFDoc_ShapeTool::Dump(Standard_OStream& theDumpLog, const Standard_Boolean deep) const
1269 Standard_Integer level = 0;
1270 // TopTools_SequenceOfShape SeqShapes;
1271 TDF_LabelSequence SeqLabels;
1272 GetShapes( SeqLabels);
1274 if (SeqLabels.Length()>0) theDumpLog<<endl;
1276 for (i=1; i<=SeqLabels.Length(); i++) {
1277 DumpAssembly(theDumpLog, SeqLabels.Value(i), level, deep);
1281 GetFreeShapes(SeqLabels);
1282 theDumpLog<<endl<<"Free Shapes: "<<SeqLabels.Length()<<endl;
1283 for (i = 1; i<=SeqLabels.Length(); i++) {
1284 DumpShape(theDumpLog, SeqLabels.Value(i), level, deep);
1290 //=======================================================================
1292 //purpose : override
1293 //=======================================================================
1295 Standard_OStream& XCAFDoc_ShapeTool::Dump(Standard_OStream& theDumpLog) const
1297 TDF_Attribute::Dump (theDumpLog);
1298 Dump (theDumpLog, Standard_False);
1302 //=======================================================================
1303 //function : DumpShape
1305 //=======================================================================
1307 void XCAFDoc_ShapeTool::DumpShape(Standard_OStream& theDumpLog, const TDF_Label& L,const Standard_Integer level,const Standard_Boolean deep)
1310 if(! XCAFDoc_ShapeTool::GetShape(L, S) ) return;
1311 for (Standard_Integer i=0; i<level; i++)
1314 if(XCAFDoc_ShapeTool::IsAssembly(L))
1316 theDumpLog<<"ASSEMBLY ";
1318 else if (XCAFDoc_ShapeTool::IsSimpleShape(L))
1320 if(L.Father().Father().Father().IsRoot())
1321 theDumpLog<<"PART ";
1325 theDumpLog<<"INSTANCE ";
1327 TopAbs::Print(S.ShapeType(), theDumpLog);
1329 TCollection_AsciiString Entry;
1330 TDF_Tool::Entry(L, Entry);
1331 theDumpLog<<" "<<Entry;
1332 if(XCAFDoc_ShapeTool::IsReference(L))
1334 Handle(TDataStd_TreeNode) aRef;
1335 L.FindAttribute(XCAFDoc::ShapeRefGUID(), aRef);
1336 TDF_Tool::Entry(aRef->Father()->Label(), Entry);
1337 theDumpLog<<" (refers to "<<Entry<<")";
1340 Handle(TDataStd_Name) Name;
1341 if (L.FindAttribute(TDataStd_Name::GetID(),Name))
1342 theDumpLog<<" \""<<Name->Get()<<"\" ";
1345 theDumpLog<<"("<<*(void**)&S.TShape();
1346 if (! S.Location().IsIdentity())
1347 theDumpLog<<", "<< *(void**)&S.Location();
1352 //=======================================================================
1353 //function : IsExternRef
1355 //=======================================================================
1357 Standard_Boolean XCAFDoc_ShapeTool::IsExternRef(const TDF_Label& L)
1359 Handle(TDataStd_UAttribute) Uattr;
1360 return L.FindAttribute(XCAFDoc::ExternRefGUID(), Uattr);
1363 //=======================================================================
1364 //function : SetExternRefs
1366 //=======================================================================
1368 void XCAFDoc_ShapeTool::SetExternRefs(const TDF_Label& L,
1369 const TColStd_SequenceOfHAsciiString& SHAS) const
1371 TDF_Label ShapeLabel = L.NewChild();
1372 TDataStd_UAttribute::Set(ShapeLabel,XCAFDoc::ExternRefGUID());
1373 for(Standard_Integer i=1; i<=SHAS.Length(); i++) {
1374 TDF_Label tmplbl = ShapeLabel.FindChild(i,Standard_True);
1375 Handle(TCollection_HAsciiString) str = SHAS(i);
1376 TCollection_ExtendedString extstr(str->String());
1377 TDataStd_Name::Set(tmplbl,extstr);
1381 //=======================================================================
1382 //function : SetExternRefs
1384 //=======================================================================
1386 TDF_Label XCAFDoc_ShapeTool::SetExternRefs(const TColStd_SequenceOfHAsciiString& SHAS) const
1388 TDF_Label ShapeLabel;
1391 ShapeLabel = aTag.NewChild(Label());
1392 TDataStd_UAttribute::Set(ShapeLabel,XCAFDoc::ExternRefGUID());
1393 for(Standard_Integer i=1; i<=SHAS.Length(); i++) {
1394 TDF_Label tmplbl = ShapeLabel.FindChild(i,Standard_True);
1395 Handle(TCollection_HAsciiString) str = SHAS(i);
1396 TCollection_ExtendedString extstr(str->String());
1397 TDataStd_Name::Set(tmplbl,extstr);
1402 //=======================================================================
1403 //function : GetExternRefs
1405 //=======================================================================
1407 void XCAFDoc_ShapeTool::GetExternRefs(const TDF_Label& L,
1408 TColStd_SequenceOfHAsciiString& SHAS)
1410 Handle(TDataStd_Name) TDN;
1412 for(Standard_Integer i=1; i<=L.NbChildren(); i++) {
1413 tmplbl = L.FindChild(i);
1414 if(tmplbl.FindAttribute(TDataStd_Name::GetID(),TDN)) {
1415 TCollection_ExtendedString extstr = TDN->Get();
1416 Handle(TCollection_HAsciiString) str =
1417 new TCollection_HAsciiString(TCollection_AsciiString(extstr, '?'));
1423 // API: API work with SHUO (Specified Higher Usage Occurrance) structure
1425 //=======================================================================
1426 //function : GetSHUO
1428 //=======================================================================
1430 Standard_Boolean XCAFDoc_ShapeTool::GetSHUO (const TDF_Label& SHUOLabel,
1431 Handle(XCAFDoc_GraphNode)& aSHUOAttr)
1433 if ( !SHUOLabel.FindAttribute( XCAFDoc::SHUORefGUID(), aSHUOAttr ) )
1434 return Standard_False;
1435 return Standard_True;
1438 //=======================================================================
1439 //function : GetAllComponentSHUO
1441 //=======================================================================
1443 Standard_Boolean XCAFDoc_ShapeTool::GetAllComponentSHUO (const TDF_Label& theCompLabel,
1444 TDF_AttributeSequence& theSHUOAttrs)
1446 TDF_ChildIterator it(theCompLabel);
1447 for (; it.More(); it.Next()) {
1448 TDF_Label L = it.Value();
1449 Handle(XCAFDoc_GraphNode) aSHUOAttr;
1450 if ( GetSHUO( L, aSHUOAttr ) )
1451 theSHUOAttrs.Append( aSHUOAttr );
1453 return (theSHUOAttrs.Length() > 0);
1456 //=======================================================================
1457 //function : SetSHUO
1459 //=======================================================================
1461 Standard_Boolean XCAFDoc_ShapeTool::SetSHUO (const TDF_LabelSequence& labels,
1462 Handle(XCAFDoc_GraphNode)& MainSHUOAttr) const
1464 MainSHUOAttr.Nullify();
1465 // check number of labels
1466 if (labels.Length() < 2)
1467 return Standard_False;
1468 // check is all labels contains components of any assemblyies
1470 for (i = 1; i <= labels.Length(); i++)
1471 if ( !IsComponent(labels.Value(i)) )
1472 return Standard_False;
1475 TDF_Label UpperSubL = aTag.NewChild( labels( 1 ) );
1476 if (theAutoNaming) {
1477 TCollection_ExtendedString Entry("SHUO");
1478 TDataStd_Name::Set(UpperSubL, TCollection_ExtendedString( Entry ));
1480 Handle(XCAFDoc_GraphNode) aUpperSHUO;
1481 aUpperSHUO = XCAFDoc_GraphNode::Set( UpperSubL, XCAFDoc::SHUORefGUID() );
1482 // init out argument by main upper usage SHUO
1483 MainSHUOAttr = aUpperSHUO;
1484 // add other next_usage occurrences.
1485 for (i = 2; i <= labels.Length(); i++) {
1486 TDF_Label NextSubL = aTag.NewChild( labels( i ) );
1487 if (theAutoNaming) {
1488 TCollection_ExtendedString EntrySub("SHUO-");
1490 TDataStd_Name::Set(NextSubL, TCollection_ExtendedString( EntrySub ));
1492 Handle(XCAFDoc_GraphNode) aNextSHUO;
1493 aNextSHUO = XCAFDoc_GraphNode::Set( NextSubL, XCAFDoc::SHUORefGUID() );
1495 aUpperSHUO->SetChild( aNextSHUO );
1496 aNextSHUO->SetFather( aUpperSHUO );
1497 // now lets next_usage become upper_usage for next level of SHUO
1498 aUpperSHUO = aNextSHUO;
1499 UpperSubL = NextSubL;
1502 return Standard_True;
1505 //=======================================================================
1506 //function : GetSHUOUpperUsage
1508 //=======================================================================
1510 Standard_Boolean XCAFDoc_ShapeTool::GetSHUOUpperUsage (const TDF_Label& NextUsageL,
1511 TDF_LabelSequence& aLabels)
1513 Handle(XCAFDoc_GraphNode) aNextSHUO;
1514 if( !GetSHUO( NextUsageL, aNextSHUO ) || aNextSHUO->NbFathers()<1 )
1515 return Standard_False;
1517 // get upper_usage SHAO
1518 for (Standard_Integer i = 1; i <= aNextSHUO->NbFathers(); i++)
1519 aLabels.Append( aNextSHUO->GetFather(i)->Label() );
1520 return Standard_True;
1523 //=======================================================================
1524 //function : GetSHUONextUsage
1526 //=======================================================================
1528 Standard_Boolean XCAFDoc_ShapeTool::GetSHUONextUsage (const TDF_Label& UpperUsageL,
1529 TDF_LabelSequence& aLabels)
1531 Handle(XCAFDoc_GraphNode) aUpperSHUO;
1532 if ( !GetSHUO( UpperUsageL, aUpperSHUO ) || aUpperSHUO->NbChildren()<1 )
1533 return Standard_False;
1534 // get upper_usage SHAO
1535 for (Standard_Integer i = 1; i <= aUpperSHUO->NbChildren(); i++)
1536 aLabels.Append( aUpperSHUO->GetChild(i)->Label() );
1537 return Standard_True;
1540 //=======================================================================
1541 //function : RemoveSHUO
1543 //=======================================================================
1545 Standard_Boolean XCAFDoc_ShapeTool::RemoveSHUO (const TDF_Label& L) const
1547 L.ForgetAllAttributes (Standard_True);
1548 return Standard_True;
1551 //=======================================================================
1552 //function : checkForShape
1553 //purpose : auxilary
1554 //=======================================================================
1556 static Standard_Boolean checkForShape (const TopoDS_Shape& theShape,
1557 const TopoDS_Shape& theCurSh,
1558 const TDF_Label& theUserL,
1559 TDF_LabelSequence& theLabels)
1561 // the label of an assembly which contains this component
1562 TDF_Label aSuperUserL = theUserL.Father();
1563 TopLoc_Location aSupLoc, aCompLoc;
1564 aSupLoc = ::XCAFDoc_ShapeTool::GetLocation ( aSuperUserL );
1565 aCompLoc = ::XCAFDoc_ShapeTool::GetLocation ( theUserL );
1566 TopoDS_Shape aCopySh = theCurSh;
1567 aCompLoc = aCompLoc.Multiplied( theCurSh.Location() );
1568 aSupLoc = aSupLoc.Multiplied( aCompLoc );
1569 aCopySh.Location( aSupLoc );
1570 if ( aCopySh.IsSame( theShape ) ) {
1571 theLabels.Prepend( theUserL );
1572 return Standard_True;
1574 // try to search deeply (upper by assmebly structure)
1575 TDF_LabelSequence aNewLabels;
1576 for (Standard_Integer j = 1; j <= theLabels.Length(); j++)
1577 aNewLabels.Append( theLabels.Value( j ) );
1578 aNewLabels.Prepend( theUserL );
1579 TDF_LabelSequence aUsers;
1580 ::XCAFDoc_ShapeTool::GetUsers( aSuperUserL, aUsers );
1581 for (Standard_Integer i = 1; i <= aUsers.Length(); i++)
1582 if ( checkForShape( theShape, aCopySh, aUsers.Value( i ), aNewLabels ) ) {
1584 theLabels = aNewLabels;
1585 return Standard_True;
1587 return Standard_False;
1590 //=======================================================================
1591 //function : FindComponent
1593 //=======================================================================
1595 Standard_Boolean XCAFDoc_ShapeTool::FindComponent (const TopoDS_Shape& theShape,
1596 TDF_LabelSequence& theLabels) const
1599 // search for a top-level shape that corresponds to this component
1600 TopoDS_Shape S0 = theShape;
1601 TopLoc_Location loc;
1602 S0.Location ( loc );
1603 TDF_Label aRefL = FindShape( S0 );
1605 return Standard_False; // cannot find top-level shape.
1607 TDF_LabelSequence aUsers;
1608 ::XCAFDoc_ShapeTool::GetUsers( aRefL, aUsers );
1609 for (Standard_Integer i = 1; i <= aUsers.Length(); i++)
1610 if ( checkForShape( theShape, S0, aUsers.Value( i ), theLabels ) )
1613 return (theLabels.Length() > 0);
1616 //=======================================================================
1617 //function : getShapesOfSHUO
1618 //purpose : auxilary
1619 //=======================================================================
1621 static Standard_Boolean getShapesOfSHUO (TopLoc_IndexedMapOfLocation& theaPrevLocMap,
1622 const Handle(XCAFDoc_ShapeTool)& theSTool,
1623 const TDF_Label& theSHUOlab,
1624 TopoDS_Shape& theShape)
1626 Handle(XCAFDoc_GraphNode) SHUO;
1627 TDF_LabelSequence aLabSeq;
1628 theSTool->GetSHUONextUsage( theSHUOlab, aLabSeq );
1629 if (aLabSeq.Length() >= 1)
1630 for (Standard_Integer i = 1; i <= aLabSeq.Length(); i++) {
1631 TDF_Label aSubCompL = aLabSeq.Value( i );
1632 TopLoc_Location compLoc = XCAFDoc_ShapeTool::GetLocation ( aSubCompL.Father() );
1633 // create new map of laocation (to not merge locations from different shapes)
1634 TopLoc_IndexedMapOfLocation aNewPrevLocMap;
1635 for (Standard_Integer m = 1; m <= theaPrevLocMap.Extent(); m++)
1636 aNewPrevLocMap.Add( theaPrevLocMap.FindKey( m ) );
1637 aNewPrevLocMap.Add( compLoc );
1638 // got for the new sublocations and corresponding shape
1639 getShapesOfSHUO( aNewPrevLocMap, theSTool, aSubCompL, theShape );
1642 TopoDS_Shape aSHUO_NUSh = theSTool->GetShape ( theSHUOlab.Father() );
1643 if ( aSHUO_NUSh.IsNull() ) return Standard_False;
1644 // cause got shape with location already.
1645 TopLoc_Location nullLoc;
1646 aSHUO_NUSh.Location ( nullLoc );
1647 // multiply the locations
1648 Standard_Integer intMapLenght = theaPrevLocMap.Extent();
1649 if ( intMapLenght < 1 )
1650 return Standard_False; // should not be, but to avoid exception...?
1651 TopLoc_Location SupcompLoc;
1652 SupcompLoc = theaPrevLocMap.FindKey( intMapLenght );
1653 if (intMapLenght > 1) {
1654 Standard_Integer l = intMapLenght - 1;
1656 SupcompLoc = theaPrevLocMap.FindKey( l ).Multiplied( SupcompLoc );
1660 aSHUO_NUSh.Location( SupcompLoc );
1661 theShape = aSHUO_NUSh;
1663 return (!theShape.IsNull());
1666 //=======================================================================
1667 //function : GetSHUOInstance
1669 //=======================================================================
1671 TopoDS_Shape XCAFDoc_ShapeTool::GetSHUOInstance (const Handle(XCAFDoc_GraphNode)& theSHUO) const
1673 TopoDS_Shape aShape;
1674 if (theSHUO.IsNull())
1677 TDF_Label aSHUOlab = theSHUO->Label();
1678 // get location of the assembly
1679 TopLoc_Location loc = XCAFDoc_ShapeTool::GetLocation ( aSHUOlab.Father().Father() );
1680 // get location of the component
1681 TopLoc_Location compLoc = XCAFDoc_ShapeTool::GetLocation ( aSHUOlab.Father() );
1682 TopLoc_IndexedMapOfLocation aPrevLocMap;
1683 // get previous setted location
1684 if ( !loc.IsIdentity() )
1685 aPrevLocMap.Add( loc );
1686 aPrevLocMap.Add( compLoc );
1687 // get shape by recurse method
1688 const Handle(XCAFDoc_ShapeTool)& STool = this;
1689 getShapesOfSHUO( aPrevLocMap, STool, aSHUOlab, aShape );
1694 //=======================================================================
1695 //function : getUsersShapesOfSHUO
1696 //purpose : auxilary
1697 //=======================================================================
1699 static Standard_Boolean getUsersShapesOfSHUO (TopLoc_IndexedMapOfLocation& aPrevLocMap,
1700 const Handle(XCAFDoc_ShapeTool)& STool,
1701 const TDF_Label& aSHUOlab,
1702 const TDF_Label& theUserL,
1703 TopTools_SequenceOfShape& theSHUOShapeSeq)
1705 TopLoc_IndexedMapOfLocation aNewPrevLocMap;
1706 // get location of the assembly
1707 TopLoc_Location loc = XCAFDoc_ShapeTool::GetLocation ( theUserL.Father() );
1708 // get location of the component
1709 TopLoc_Location compLoc = XCAFDoc_ShapeTool::GetLocation ( theUserL );
1710 // get previous setted location
1711 aNewPrevLocMap.Add( loc );
1712 aNewPrevLocMap.Add( compLoc );
1714 for (i = 1; i <= aPrevLocMap.Extent(); i++)
1715 aNewPrevLocMap.Add( aPrevLocMap.FindKey(i) );
1716 TDF_Label L = theUserL.Father();
1717 TDF_LabelSequence usersLab;
1718 ::XCAFDoc_ShapeTool::GetUsers( L, usersLab );
1719 if (usersLab.Length() == 0) {
1720 TopoDS_Shape aShape;
1721 getShapesOfSHUO( aNewPrevLocMap, STool, aSHUOlab, aShape );
1722 if (!aShape.IsNull()) {
1723 theSHUOShapeSeq.Append(aShape);
1724 return Standard_True;
1727 // now iterates on users of this assembly as component
1728 for ( i = 1; i <= usersLab.Length(); i++ ) {
1729 TDF_Label aNewUserL = usersLab.Value(i);
1730 getUsersShapesOfSHUO( aNewPrevLocMap, STool, aSHUOlab, aNewUserL, theSHUOShapeSeq );
1733 return (theSHUOShapeSeq.Length() > 1);
1736 //=======================================================================
1737 //function : GetAllSHUOInstances
1738 //purpose : auxilary
1739 //=======================================================================
1741 Standard_Boolean XCAFDoc_ShapeTool::GetAllSHUOInstances (const Handle(XCAFDoc_GraphNode)& theSHUO,
1742 TopTools_SequenceOfShape& theSHUOShapeSeq) const
1744 if (theSHUO.IsNull())
1745 return Standard_False;
1747 TDF_Label aSHUOlab = theSHUO->Label();
1748 TopLoc_IndexedMapOfLocation aPrevLocMap;
1749 // get location of the assembly
1750 TopLoc_Location loc = XCAFDoc_ShapeTool::GetLocation ( aSHUOlab.Father().Father() );
1751 // get location of the component
1752 TopLoc_Location compLoc = XCAFDoc_ShapeTool::GetLocation ( aSHUOlab.Father() );
1753 // get previous setted location
1754 if ( !loc.IsIdentity() )
1755 aPrevLocMap.Add( loc );
1756 aPrevLocMap.Add( compLoc );
1757 // get label of assembly
1758 TDF_Label L = aSHUOlab.Father().Father();
1759 TDF_LabelSequence usersLab;
1760 ::XCAFDoc_ShapeTool::GetUsers( L, usersLab );
1761 TopoDS_Shape aShape;
1762 const Handle(XCAFDoc_ShapeTool)& STool = this;
1763 if (usersLab.Length() == 0) {
1764 getShapesOfSHUO( aPrevLocMap, STool, aSHUOlab, aShape );
1765 if (!aShape.IsNull()) {
1766 theSHUOShapeSeq.Append(aShape);
1767 return Standard_True;
1770 // now iterates on users of this assembly as component
1771 for (Standard_Integer i = 1; i <= usersLab.Length(); i++) {
1772 TDF_Label aUserL = usersLab.Value(i);
1773 getUsersShapesOfSHUO( aPrevLocMap, STool, aSHUOlab, aUserL, theSHUOShapeSeq );
1776 return (theSHUOShapeSeq.Length() > 1);
1779 //=======================================================================
1780 //function : SetInstanceSHUO
1782 //=======================================================================
1784 Handle(XCAFDoc_GraphNode) XCAFDoc_ShapeTool::SetInstanceSHUO (const TopoDS_Shape& theShape) const
1786 Handle(XCAFDoc_GraphNode) SHUO;
1787 TDF_LabelSequence aLabels;
1788 if ( FindComponent( theShape, aLabels ) )
1789 // set shuo structure on labels of component-assembly structure
1790 SetSHUO( aLabels, SHUO );
1794 //=======================================================================
1795 //function : FindSHUO
1797 //=======================================================================
1799 Standard_Boolean XCAFDoc_ShapeTool::FindSHUO (const TDF_LabelSequence& theLabels,
1800 Handle(XCAFDoc_GraphNode)& theSHUOAttr)
1802 TDF_AttributeSequence SHUOAttrs;
1803 TDF_Label aCompLabel = theLabels.Value(1);
1804 if (! ::XCAFDoc_ShapeTool::GetAllComponentSHUO( aCompLabel, SHUOAttrs ) )
1805 return Standard_False;
1806 // WARNING: manage that each SHUO upper_usage have only one SHUO next_usage
1807 for (Standard_Integer i = 1; i <= SHUOAttrs.Length(); i++) {
1808 TDF_LabelSequence aCondidate;
1809 Handle(XCAFDoc_GraphNode) anSHUO = Handle(XCAFDoc_GraphNode)::DownCast(SHUOAttrs.Value(i));
1810 aCondidate.Append( anSHUO->Label().Father() );
1811 while (anSHUO->NbChildren()) {
1812 anSHUO = anSHUO->GetChild( 1 );
1813 aCondidate.Append( anSHUO->Label().Father() );
1815 // check the label sequences
1816 Standard_Boolean isEqual = Standard_True;
1817 if (theLabels.Length() != aCondidate.Length())
1818 isEqual = Standard_False;
1820 for (Standard_Integer li = 1; li <= theLabels.Length(); li++)
1821 if ( theLabels.Value(li) != aCondidate.Value(li) ) {
1822 isEqual = Standard_False;
1828 theSHUOAttr = Handle(XCAFDoc_GraphNode)::DownCast(SHUOAttrs.Value(i));
1831 return ( !theSHUOAttr.IsNull() );
1834 //=======================================================================
1837 //=======================================================================
1838 Standard_Boolean XCAFDoc_ShapeTool::Expand (const TDF_Label& theShapeL)
1840 if (theShapeL.IsNull() || IsAssembly(theShapeL))
1841 return Standard_False;
1843 TopoDS_Shape aShape = GetShape(theShapeL);
1844 if (aShape.IsNull())
1845 return Standard_False;
1847 TopAbs_ShapeEnum aShapeType = aShape.ShapeType();
1848 Standard_Boolean isExpandedType = aShapeType == TopAbs_COMPOUND || aShapeType == TopAbs_COMPSOLID ||
1849 aShapeType == TopAbs_SHELL || aShapeType == TopAbs_WIRE;
1852 TopoDS_Iterator anIter(aShape);
1853 for(; anIter.More(); anIter.Next())
1855 const TopoDS_Shape& aChildShape = anIter.Value();
1856 TDF_Label aChild, aPart;
1858 // Find child shape as subshape of expanded shape
1859 FindSubShape(theShapeL, aChildShape, aChild);
1860 Handle(TDataStd_Name) anAttr;
1861 //make child (if color isn't set or if it is compound)
1862 if (aChild.IsNull()) {
1863 aChild = AddSubShape(theShapeL, aChildShape);
1867 aChild.FindAttribute(TDataStd_Name::GetID(), anAttr);
1870 // Try to find child shape as already existed part
1871 aPart = FindShape(aChildShape.Located(TopLoc_Location()));
1872 if (aPart.IsNull()) {
1873 // Create new part to link child shape
1874 aPart = AddShape(aChildShape.Located(TopLoc_Location()), Standard_False, Standard_False);
1876 // Add shape manually, if already existed subshape found instead of creation of new part
1877 if (!aPart.IsNull() && !IsTopLevel(aPart)) {
1878 if (!GetReferredShape(aPart, aPart)) {
1880 aPart = aTag.NewChild(Label());
1881 SetShape(aPart, aChildShape.Located(TopLoc_Location()));
1886 if (!anAttr.IsNull()) {
1887 TDataStd_Name::Set(aPart, anAttr->Get());
1890 Standard_SStream Stream;
1891 TopAbs::Print(aChildShape.ShapeType(), Stream);
1892 TCollection_AsciiString aName(Stream.str().c_str());
1893 TDataStd_Name::Set(aPart, TCollection_ExtendedString(aName));
1895 MakeReference(aChild, aPart, aChildShape.Location());
1896 makeSubShape(theShapeL, aPart, aChildShape, aChildShape.Location());
1898 //set assembly attribute
1899 TDataStd_UAttribute::Set(theShapeL, XCAFDoc::AssemblyGUID());
1900 return Standard_True;
1902 return Standard_False;
1905 //=======================================================================
1906 //function : makeSubShape
1908 //=======================================================================
1910 void XCAFDoc_ShapeTool::makeSubShape (const TDF_Label& theMainShapeL,
1911 const TDF_Label& thePart,
1912 const TopoDS_Shape& theShape,
1913 const TopLoc_Location& theLoc)
1915 TopoDS_Iterator anIter(theShape);
1916 Standard_Boolean isCompoundPart = (GetShape(thePart).ShapeType() == TopAbs_COMPOUND);
1917 Standard_Boolean isAssembly = IsAssembly(thePart);
1918 for(; anIter.More(); anIter.Next()) {
1919 const TopoDS_Shape& aChildShape = anIter.Value();
1920 TDF_Label aChildLabel;
1921 FindSubShape(theMainShapeL, aChildShape, aChildLabel);
1922 if(!aChildLabel.IsNull()) {
1924 aChildLabel.ForgetAllAttributes();
1925 makeSubShape(theMainShapeL, thePart, aChildShape, theLoc);
1930 Handle(TDataStd_Name) anAttr;
1931 aChildLabel.FindAttribute(TDataStd_Name::GetID(), anAttr);
1932 TopLoc_Location aSubLoc;
1933 // Calculate location for subshapes of compound parts
1935 aSubLoc = theLoc.Inverted() * aChildShape.Location();
1937 TDF_Label aSubLabel;
1938 if (!FindSubShape(thePart, aChildShape.Located(aSubLoc), aSubLabel)) {
1939 aSubLabel = AddSubShape(thePart, aChildShape.Located(aSubLoc));
1940 //set name to sub shape
1941 if (!anAttr.IsNull()) {
1942 TDataStd_Name::Set(aSubLabel, anAttr->Get());
1945 Standard_SStream Stream;
1946 TopAbs::Print(aChildShape.ShapeType(), Stream);
1947 TCollection_AsciiString aName(Stream.str().c_str());
1948 TDataStd_Name::Set(aSubLabel, TCollection_ExtendedString(aName));
1950 // Create auxiliary link, it will be removed during moving attributes
1951 MakeReference(aSubLabel, aChildLabel, aChildShape.Location());
1954 aChildLabel.ForgetAllAttributes();
1957 makeSubShape(theMainShapeL, thePart, aChildShape, theLoc);
1961 //=======================================================================
1962 //function : updateComponent
1964 //=======================================================================
1966 Standard_Boolean XCAFDoc_ShapeTool::updateComponent(const TDF_Label& theItemLabel,
1967 TopoDS_Shape& theUpdatedShape) const
1969 if ( !IsAssembly(theItemLabel) )
1970 return Standard_False; // Do nothing for non-assemblies
1972 // Get the currently stored compound for the assembly
1973 TopoDS_Shape aCurrentRootShape;
1974 GetShape(theItemLabel, aCurrentRootShape);
1975 TopTools_MapOfOrientedShape aCurrentRootShapeMap (aCurrentRootShape.NbChildren());
1977 // Get components of the assembly
1978 TDF_LabelSequence aComponentLabs;
1979 GetComponents(theItemLabel, aComponentLabs);
1981 // This flag indicates whether to update the compound of the assembly
1982 Standard_Boolean isModified = Standard_False;
1984 // Compare the number of components in XDE structure with the number of
1985 // components in topological structure. A component may happen to be removed,
1986 // so we have to update the assembly compound
1987 const Standard_Integer aNumTopoComponents = aCurrentRootShape.NbChildren();
1989 if ( aNumTopoComponents != aComponentLabs.Length() )
1990 isModified = Standard_True;
1992 // Iterate over the assembly components. If at least one component is
1993 // modified (this is the recursive check), then the actually stored
1994 // compound has to be updated
1995 TopTools_ListOfShape aComponentShapes;
1997 for ( TDF_LabelSequence::Iterator aCompIt(aComponentLabs); aCompIt.More(); aCompIt.Next() )
1999 const TDF_Label& aComponentLab = aCompIt.Value();
2001 // Take the referred assembly item (ultimately, a part for an instance)
2002 TDF_Label aComponentRefLab;
2003 GetReferredShape(aComponentLab, aComponentRefLab);
2005 // Shape comes with some placement transformation here
2006 TopoDS_Shape aComponentShape;
2007 GetShape(aComponentLab, aComponentShape);
2008 TopLoc_Location aComponentLoc = aComponentShape.Location();
2010 // If the component is a sub-assembly, then its associated compound
2011 // has to be processed in the same manner
2012 if ( IsAssembly(aComponentRefLab) )
2015 if ( updateComponent(aComponentRefLab, aComponentShape) )
2018 isModified = Standard_True;
2020 aComponentShape.Location(aComponentLoc); // Apply placement
2025 // Search for a part in the actual compound of the ultimate assembly.
2026 // If the part is there, then the compound is up-to-date, so it does not require rebuilding
2029 if (aCurrentRootShapeMap.IsEmpty())
2031 // optimize search for next labels in aComponentLabs
2032 for (TopoDS_Iterator aTopoIt(aCurrentRootShape); aTopoIt.More(); aTopoIt.Next())
2034 aCurrentRootShapeMap.Add (aTopoIt.Value());
2037 if (!aCurrentRootShapeMap.Contains (aComponentShape))
2039 // Part has been modified somewhere, so the compound has to be rebuilt
2040 isModified = Standard_True;
2045 // Fill the list of shapes composing a new compound for the assembly
2046 aComponentShapes.Append(aComponentShape);
2049 // If any component is modified, we update the currently stored shape
2052 TopoDS_Compound anUpdatedCompound;
2054 aBB.MakeCompound(anUpdatedCompound);
2056 // Compose new compound
2057 for ( TopTools_ListIteratorOfListOfShape aShapeIt(aComponentShapes); aShapeIt.More(); aShapeIt.Next() )
2059 aBB.Add( anUpdatedCompound, aShapeIt.Value() );
2062 // Store the updated shape as an output
2063 theUpdatedShape = anUpdatedCompound;
2065 // Use topological naming services to store the updated shape in XDE
2066 TNaming_Builder NB(theItemLabel);
2067 NB.Generated(theUpdatedShape);