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.
16 #include <XCAFDoc_ShapeTool.hxx>
18 #include <BRep_Builder.hxx>
20 #include <gp_Trsf.hxx>
21 #include <Standard_GUID.hxx>
22 #include <Standard_Type.hxx>
23 #include <TCollection_AsciiString.hxx>
24 #include <TCollection_ExtendedString.hxx>
25 #include <TCollection_HAsciiString.hxx>
26 #include <TColStd_SequenceOfHAsciiString.hxx>
27 #include <TDataStd_ChildNodeIterator.hxx>
28 #include <TDataStd_Name.hxx>
29 #include <TDataStd_TreeNode.hxx>
30 #include <TDataStd_UAttribute.hxx>
31 #include <TDF_Attribute.hxx>
32 #include <TDF_ChildIDIterator.hxx>
33 #include <TDF_ChildIterator.hxx>
34 #include <TDF_Label.hxx>
35 #include <TDF_LabelMap.hxx>
36 #include <TDF_LabelSequence.hxx>
37 #include <TDF_MapIteratorOfLabelMap.hxx>
38 #include <TDF_RelocationTable.hxx>
39 #include <TDF_Tool.hxx>
40 #include <TDocStd_Document.hxx>
41 #include <TNaming_Builder.hxx>
42 #include <TNaming_NamedShape.hxx>
43 #include <TNaming_Tool.hxx>
44 #include <TopLoc_IndexedMapOfLocation.hxx>
45 #include <TopLoc_Location.hxx>
46 #include <TopoDS_Compound.hxx>
47 #include <TopoDS_Iterator.hxx>
48 #include <TopoDS_Shape.hxx>
49 #include <TopTools_ListOfShape.hxx>
50 #include <TopTools_MapOfOrientedShape.hxx>
51 #include <XCAFDoc.hxx>
52 #include <XCAFDoc_GraphNode.hxx>
53 #include <XCAFDoc_Location.hxx>
54 #include <XCAFDoc_ShapeMapTool.hxx>
56 IMPLEMENT_DERIVED_ATTRIBUTE_WITH_TYPE(XCAFDoc_ShapeTool,TDataStd_GenericEmpty,"xcaf","ShapeTool")
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 // Auxiliary methods //////////////////////////////////////////////////
114 //=======================================================================
115 //function : SetLabelNameByLink
117 //=======================================================================
118 static void SetLabelNameByLink(const TDF_Label L)
120 Handle(TDataStd_TreeNode) Node;
121 if (! L.FindAttribute(XCAFDoc::ShapeRefGUID(), Node) ||
122 ! Node->HasFather()) {
124 std::cout<<"Error: XCAFDoc_ShapeTool, SetLabelNameByLink(): NO NODE"<<std::endl;
128 TCollection_AsciiString Entry;
129 TDF_Tool::Entry ( Node->Father()->Label(), Entry );
130 Entry.Insert(1, "=>[");
133 TDataStd_Name::Set(L, TCollection_ExtendedString( Entry ));
137 //=======================================================================
138 //function : SetLabelNameByShape
140 //=======================================================================
141 static void SetLabelNameByShape(const TDF_Label L)
144 if (XCAFDoc_ShapeTool::GetShape(L, S) &&
145 ! L.IsAttribute(TDataStd_Name::GetID()) ) {
146 Standard_SStream Stream;
147 // TopAbs_ShapeEnum Type = S.ShapeType();
148 // if (Type == TopAbs_COMPOUND) Stream<<"ASSEMBLY";
150 TopAbs::Print(S.ShapeType(), Stream);
151 TCollection_AsciiString aName (Stream.str().c_str());
152 TDataStd_Name::Set(L, TCollection_ExtendedString(aName));
157 //=======================================================================
158 //function : SearchUsingMap
160 //=======================================================================
162 Standard_Boolean XCAFDoc_ShapeTool::SearchUsingMap(const TopoDS_Shape &S, TDF_Label &L,
163 const Standard_Boolean findWithoutLoc,
164 const Standard_Boolean findSubShape) const
167 if(myShapeLabels.IsBound(S)) {
168 L = myShapeLabels.Find(S);
169 return Standard_True;
174 if(myShapeLabels.IsBound(S0)) {
175 TDF_Label L1 = myShapeLabels.Find(S0);
176 TDF_LabelSequence Labels;
177 if(GetUsers(L1, Labels, Standard_True)) {
178 for(Standard_Integer i=1; i<=Labels.Length(); i++) {
179 TopoDS_Shape c = GetShape(Labels.Value(i));
182 return Standard_True;
188 return Standard_True;
192 if(hasSimpleShapes) {
193 if(mySimpleShapes.IsBound(S)) {
194 L = mySimpleShapes.Find(S);
195 return Standard_True;
197 if(mySimpleShapes.IsBound(S0)) {
198 L = mySimpleShapes.Find(S0);
199 return Standard_True;
203 if(!findSubShape) return Standard_False;
204 TDF_Label mainL = FindMainShapeUsingMap(S);
205 if(mainL.IsNull()) return Standard_False;
206 L = AddSubShape(mainL,S);
207 return !L.IsNull();//Standard_True;
211 //=======================================================================
214 //=======================================================================
216 Standard_Boolean XCAFDoc_ShapeTool::Search (const TopoDS_Shape &S,
218 const Standard_Boolean findInstance,
219 const Standard_Boolean findComponent,
220 const Standard_Boolean findSubShape) const
222 // search among shapes
223 Standard_Boolean isLocated = ! S.Location().IsIdentity();
226 // try to find top-level instance
227 if ( findInstance && FindShape ( S, L, Standard_True ) )
228 return Standard_True;
229 // try to find component of assembly
230 if ( findComponent ) {
231 TDF_LabelSequence labels;
232 GetShapes ( labels );
233 for ( Standard_Integer i=1; i <= labels.Length(); i++ ) {
234 if ( ! IsAssembly ( labels.Value(i) ) ) continue;
235 TDF_LabelSequence comp;
236 GetComponents ( labels.Value(i), comp );
237 for ( Standard_Integer j=1; j <= comp.Length(); j++ ) {
238 TopoDS_Shape c = GetShape ( comp.Value(j) );
239 if ( c.IsSame ( S ) ) {
241 return Standard_True;
247 // try to find top-level simple shape
248 if ( FindShape ( S, L, Standard_False ) ) return Standard_True;
251 if ( ! findSubShape ) return Standard_False;
252 TDF_Label mainL = FindMainShape ( S );
253 if ( mainL.IsNull() ) return Standard_False;
254 L = AddSubShape ( mainL, S );
255 return !L.IsNull();//Standard_True;
258 //=======================================================================
259 //function : FindShape
261 //=======================================================================
263 Standard_Boolean XCAFDoc_ShapeTool::FindShape (const TopoDS_Shape& S,
265 const Standard_Boolean findInstance) const
267 // search for null-located shape
269 if ( ! findInstance ) {
274 // this code is used instead of the following for performance reasons
275 if (TNaming_Tool::HasLabel(Label(), S0)) {
277 L = TNaming_Tool::Label(Label(), S0, TransDef);
280 return Standard_False;
283 return Standard_True;
285 // Try to find shape manually
286 TDF_ChildIDIterator it(Label(), TNaming_NamedShape::GetID());
287 for (; it.More(); it.Next()) {
288 TDF_Label aLabel = it.Value()->Label();
289 Handle(TNaming_NamedShape) NS;
290 if ( aLabel.FindAttribute(TNaming_NamedShape::GetID(), NS) &&
291 S0.IsSame ( TNaming_Tool::GetShape(NS) ) ) {
293 return Standard_True;
298 return Standard_False;
301 //=======================================================================
302 //function : FindShape
304 //=======================================================================
306 TDF_Label XCAFDoc_ShapeTool::FindShape (const TopoDS_Shape& S,
307 const Standard_Boolean findInstance) const
310 if (FindShape(S, L, findInstance))
315 //=======================================================================
316 //function : GetShape
318 //=======================================================================
320 Standard_Boolean XCAFDoc_ShapeTool::GetShape (const TDF_Label& L, TopoDS_Shape& S)
322 Handle(XCAFDoc_Location) LocationAttribute;
325 TopoDS_Compound EmptyComp;
327 B.MakeCompound(EmptyComp);
331 // for instance, get referred shape
332 Handle(TDataStd_TreeNode) Node;
333 if ( L.FindAttribute(XCAFDoc::ShapeRefGUID(), Node) && Node->HasFather() &&
334 L.FindAttribute(XCAFDoc_Location::GetID(), LocationAttribute)) {
335 if ( ! GetShape(Node->Father()->Label(), S) ) return Standard_False;
336 S.Move ( LocationAttribute->Get() );
337 return Standard_True;
340 // else just return shape on this label
341 Handle(TNaming_NamedShape) NS;
342 if ( ! L.FindAttribute(TNaming_NamedShape::GetID(), NS) ) return Standard_False;
343 S = TNaming_Tool::GetShape(NS);
344 return Standard_True;
347 //=======================================================================
348 //function : GetShape
350 //=======================================================================
352 TopoDS_Shape XCAFDoc_ShapeTool::GetShape(const TDF_Label& L)
359 //=======================================================================
360 //function : NewShape
362 //=======================================================================
364 TDF_Label XCAFDoc_ShapeTool::NewShape() const
366 TopoDS_Compound aShape;
368 tdsB.MakeCompound ( aShape );
371 TDF_Label aLabel = aTag.NewChild(Label());
373 TNaming_Builder tnBuild(aLabel);
374 tnBuild.Generated(aShape);
379 //=======================================================================
380 //function : SetShape
382 //=======================================================================
384 void XCAFDoc_ShapeTool::SetShape (const TDF_Label& L, const TopoDS_Shape& S)
386 TNaming_Builder tnBuild(L);
387 tnBuild.Generated(S);
388 Handle(XCAFDoc_ShapeMapTool) A = XCAFDoc_ShapeMapTool::Set(L);
389 // if ( ! L.FindAttribute(XCAFDoc_ShapeMapTool::GetID(), A) ) {
390 // A = XCAFDoc_ShapeMapTool::Set(L);
391 // L.AddAttribute(A);
395 if(!myShapeLabels.IsBound(S)) {
396 myShapeLabels.Bind(S,L);
400 //=======================================================================
401 //function : MakeReference
403 //=======================================================================
405 void XCAFDoc_ShapeTool::MakeReference (const TDF_Label &L,
406 const TDF_Label &refL,
407 const TopLoc_Location &loc)
410 XCAFDoc_Location::Set(L, loc);
413 Handle(TDataStd_TreeNode) refNode, mainNode;
414 mainNode = TDataStd_TreeNode::Set ( refL, XCAFDoc::ShapeRefGUID() );
415 refNode = TDataStd_TreeNode::Set ( L, XCAFDoc::ShapeRefGUID() );
416 refNode->Remove(); // abv: fix against bug in TreeNode::Append()
417 mainNode->Append(refNode);
420 SetLabelNameByLink(L);
423 //=======================================================================
424 //function : addShape
426 //=======================================================================
428 TDF_Label XCAFDoc_ShapeTool::addShape (const TopoDS_Shape& S, const Standard_Boolean makeAssembly)
430 TDF_Label ShapeLabel;
433 // search if the shape already exists (with the same location)
434 if ( S.IsNull() || FindShape ( S, ShapeLabel, Standard_True ) ) return ShapeLabel;
436 // else add a new label
437 ShapeLabel = aTag.NewChild(Label());
439 // if shape has location, make a reference to the same shape without location
440 if ( ! S.Location().IsIdentity() /*&& FindShape ( S, L )*/ ) {
444 TDF_Label L = addShape ( S0, makeAssembly );
445 MakeReference ( ShapeLabel, L, S.Location() );
449 // else add a shape to a label
450 TNaming_Builder tnBuild(ShapeLabel);
451 tnBuild.Generated(S);
453 Handle(XCAFDoc_ShapeMapTool) A = XCAFDoc_ShapeMapTool::Set(ShapeLabel);
454 // if ( ! ShapeLabel.FindAttribute(XCAFDoc_ShapeMapTool::GetID(), A) ) {
455 // A = XCAFDoc_ShapeMapTool::Set(ShapeLabel);
456 // ShapeLabel.AddAttribute(A);
461 SetLabelNameByShape(ShapeLabel);
463 // if shape is Compound and flag is set, create assembly
464 if ( makeAssembly && S.ShapeType() == TopAbs_COMPOUND ) {
465 // mark assembly by assigning UAttribute
466 Handle(TDataStd_UAttribute) Uattr;
467 Uattr = TDataStd_UAttribute::Set ( ShapeLabel, XCAFDoc::AssemblyGUID() );
469 TDataStd_Name::Set(ShapeLabel, TCollection_ExtendedString("ASSEMBLY"));
471 // iterate on components
472 TopoDS_Iterator Iterator(S);
473 for (; Iterator.More(); Iterator.Next()) {
474 // get label for component`s shape
475 TopoDS_Shape Scomp = Iterator.Value(), S0 = Scomp;
478 TDF_Label compL = addShape ( S0, makeAssembly );
480 // add a component as reference
481 TDF_Label RefLabel = aTag.NewChild(ShapeLabel);
482 MakeReference ( RefLabel, compL, Scomp.Location() );
486 if(!IsAssembly(ShapeLabel)) {
487 //const TopTools_IndexedMapOfShape tmpMap = A->GetMap();
488 //for(Standard_Integer i=1; i<=tmpMap.Extent(); i++)
489 //mySubShapes.Bind(tmpMap.FindKey(i),ShapeLabel);
490 for(Standard_Integer i=1; i<=A->GetMap().Extent(); i++)
492 TopoDS_Shape aSh = A->GetMap().FindKey(i);
493 mySubShapes.Bind(aSh,ShapeLabel);
495 //mySubShapes.Bind(ShapeLabel,A->GetMap());
502 //=======================================================================
503 //function : prepareAssembly
505 //=======================================================================
506 static Standard_Boolean prepareAssembly (const TopoDS_Shape& theShape,
507 TopoDS_Shape& theOUTShape)
509 // iterate on components
510 theOUTShape = theShape;
511 if (theShape.ShapeType() == TopAbs_COMPOUND) {
513 // check if shape if frosen
514 if (!theOUTShape.Free())
515 theOUTShape.Free(Standard_True);
517 TopTools_SequenceOfShape aSubShapeSeq;
518 TopoDS_Iterator Iterator(theShape);
519 for (; Iterator.More(); Iterator.Next())
520 aSubShapeSeq.Append(Iterator.Value());
521 for (Standard_Integer i = 1; i <= aSubShapeSeq.Length(); i++) {
522 TopoDS_Shape Scomp = aSubShapeSeq.Value(i);
523 TopoDS_Shape aNewScomp;
524 B.Remove(theOUTShape, Scomp);
525 prepareAssembly( Scomp, aNewScomp );
526 TopLoc_Location aLoc;
527 aLoc = aNewScomp.Location();
528 if ( aLoc.IsIdentity() ) {
529 // create an "empty" location
531 aTrsf.SetScale(gp_Pnt(0,0,0), 1);
532 aLoc = TopLoc_Location( aTrsf );
533 aNewScomp.Location( aLoc );
535 B.Add(theOUTShape, aNewScomp);
538 return Standard_True;
542 //=======================================================================
543 //function : AddShape
545 //=======================================================================
547 TDF_Label XCAFDoc_ShapeTool::AddShape (const TopoDS_Shape& theShape,
548 const Standard_Boolean makeAssembly,
549 const Standard_Boolean makePrepare)
551 // PTV 17.02.2003 to avoid components without location.
552 TopoDS_Shape S = theShape;
553 if ( makePrepare && makeAssembly && S.ShapeType() == TopAbs_COMPOUND )
554 prepareAssembly( theShape, S ); // OCC1669
556 TDF_Label L = addShape(S,makeAssembly);
558 if(!myShapeLabels.IsBound(S)) {
559 myShapeLabels.Bind(S,L);
564 //return addShape( S, makeAssembly );
567 //=======================================================================
568 //function : RemoveShape
570 //=======================================================================
572 Standard_Boolean XCAFDoc_ShapeTool::RemoveShape (const TDF_Label& L,
573 const Standard_Boolean removeCompletely) const
575 if ( ! IsTopLevel ( L ) || ! IsFree ( L ) ) return Standard_False;
577 Handle(TDataStd_TreeNode) aNode;
579 if (removeCompletely &&
580 L.FindAttribute (XCAFDoc::ShapeRefGUID(), aNode) &&
581 aNode->HasFather() &&
582 L.IsAttribute (XCAFDoc_Location::GetID()))
584 aLabel = aNode->Father()->Label();
587 L.ForgetAllAttributes (Standard_True);
589 if (removeCompletely && !aLabel.IsNull())
591 return RemoveShape(aLabel);
593 return Standard_True;
597 //=======================================================================
600 //=======================================================================
602 void XCAFDoc_ShapeTool::Init()
604 hasSimpleShapes = Standard_False;
608 //=======================================================================
609 //function : SetAutoNaming
611 //=======================================================================
613 void XCAFDoc_ShapeTool::SetAutoNaming (const Standard_Boolean V)
619 //=======================================================================
620 //function : AutoNaming
622 //=======================================================================
624 Standard_Boolean XCAFDoc_ShapeTool::AutoNaming()
626 return theAutoNaming;
630 //=======================================================================
631 //function : ComputeShapes
633 //=======================================================================
635 void XCAFDoc_ShapeTool::ComputeShapes(const TDF_Label& L)
637 TDF_ChildIterator it(L);
638 for(; it.More(); it.Next()) {
639 TDF_Label L1 = it.Value();
642 if(!myShapeLabels.IsBound(S)) {
643 mySimpleShapes.Bind(S,L1);
651 //=======================================================================
652 //function : ComputeSimpleShapes
654 //=======================================================================
656 void XCAFDoc_ShapeTool::ComputeSimpleShapes()
658 ComputeShapes(Label());
659 hasSimpleShapes = Standard_True;
663 //=======================================================================
664 //function : GetShapes
666 //=======================================================================
668 void XCAFDoc_ShapeTool::GetShapes(TDF_LabelSequence& Labels) const
672 TDF_ChildIterator it(Label());
673 for (; it.More(); it.Next()) {
674 TDF_Label L = it.Value();
676 if ( GetShape ( L, S ) ) Labels.Append ( L );
681 //=======================================================================
682 //function : GetFreeShapes
684 //=======================================================================
686 void XCAFDoc_ShapeTool::GetFreeShapes (TDF_LabelSequence& FreeLabels) const
690 TDF_ChildIterator it(Label());
691 for (; it.More(); it.Next()) {
692 TDF_Label L = it.Value();
694 if ( GetShape ( L, S ) && IsFree ( L ) ) FreeLabels.Append ( L );
698 //=======================================================================
699 //function : IsTopLevel
701 //=======================================================================
703 Standard_Boolean XCAFDoc_ShapeTool::IsTopLevel (const TDF_Label& L) const
705 return L.Father() == Label();
708 //=======================================================================
711 //=======================================================================
713 Standard_Boolean XCAFDoc_ShapeTool::IsShape (const TDF_Label& L)
715 return IsSimpleShape ( L ) || IsAssembly ( L ) || IsReference ( L );
718 //=======================================================================
719 //function : IsSimpleShape
721 //=======================================================================
723 Standard_Boolean XCAFDoc_ShapeTool::IsSimpleShape (const TDF_Label& L)
725 Handle(TNaming_NamedShape) NS;
726 return L.FindAttribute ( TNaming_NamedShape::GetID(), NS ) &&
727 ! IsAssembly ( L ) && ! IsReference ( L );
730 //=======================================================================
731 //function : IsReference
733 //=======================================================================
735 Standard_Boolean XCAFDoc_ShapeTool::IsReference (const TDF_Label& L)
737 Handle(TDataStd_TreeNode) Node;
738 return L.FindAttribute(XCAFDoc::ShapeRefGUID(), Node) && Node->HasFather();
741 //=======================================================================
742 //function : IsAssembly
744 //=======================================================================
746 Standard_Boolean XCAFDoc_ShapeTool::IsAssembly (const TDF_Label& L)
748 Handle(TDataStd_UAttribute) Uattr;
749 return L.FindAttribute(XCAFDoc::AssemblyGUID(), Uattr);
752 //=======================================================================
753 //function : IsComponent
755 //=======================================================================
757 Standard_Boolean XCAFDoc_ShapeTool::IsComponent (const TDF_Label& L)
759 return IsReference ( L ) && IsAssembly ( L.Father() );
762 //=======================================================================
763 //function : IsCompound
765 //=======================================================================
767 Standard_Boolean XCAFDoc_ShapeTool::IsCompound (const TDF_Label& L)
769 Handle(TDataStd_Name) Name;
770 if (L.FindAttribute(TDataStd_Name::GetID(),Name)) {
771 TCollection_ExtendedString estr1 = Name->Get();
772 TCollection_ExtendedString estr2("COMPOUND");
774 return Standard_True;
777 return Standard_False;
780 //=======================================================================
781 //function : IsSubShape
783 //=======================================================================
785 Standard_Boolean XCAFDoc_ShapeTool::IsSubShape (const TDF_Label& L)
787 return IsSimpleShape ( L ) && IsShape ( L.Father() );
790 //=======================================================================
793 //=======================================================================
795 Standard_Boolean XCAFDoc_ShapeTool::IsFree (const TDF_Label& L)
797 Handle(TDataStd_TreeNode) Node;
798 if ( ! L.FindAttribute(XCAFDoc::ShapeRefGUID(), Node) ||
799 ! Node->HasFirst() ) return Standard_True;
801 return Standard_False;
804 //=======================================================================
805 //function : GetUsers
806 //purpose : Returns number of users (0 if shape is free)
807 //=======================================================================
809 Standard_Integer XCAFDoc_ShapeTool::GetUsers (const TDF_Label& L,
810 TDF_LabelSequence& Labels,
811 const Standard_Boolean getsubchilds)
813 Standard_Integer NbUsers=0;
814 Handle(TDataStd_TreeNode) Node ;
816 if ( ! L.FindAttribute(XCAFDoc::ShapeRefGUID(), Node) ) return NbUsers;
818 Node = Node->First();
819 while ( ! Node.IsNull() ) {
821 if ( getsubchilds ) {
822 TDF_Label underL = Node->Label().Father();
823 NbUsers += GetUsers ( underL, Labels, getsubchilds );
826 Labels.Append(Node->Label());
833 //=======================================================================
834 //function : NbComponents
836 //=======================================================================
838 Standard_Integer XCAFDoc_ShapeTool::NbComponents (const TDF_Label& L,
839 const Standard_Boolean getsubchilds)
841 TDF_LabelSequence subLabels;
842 GetComponents (L, subLabels, getsubchilds);
843 return subLabels.Length();
846 //=======================================================================
847 //function : GetComponents
849 //=======================================================================
851 Standard_Boolean XCAFDoc_ShapeTool::GetComponents (const TDF_Label& L, TDF_LabelSequence& Labels,
852 const Standard_Boolean getsubchilds)
854 if ( ! IsAssembly(L) ) return Standard_False;
856 TDF_ChildIterator It(L);
857 for (; It.More(); It.Next() ) {
858 TDF_Label comp = It.Value();
859 if ( IsComponent ( comp ) ) {
860 if ( getsubchilds ) {
862 if ( GetReferredShape ( comp, underL ) )
863 GetComponents ( underL, Labels, getsubchilds);
865 Labels.Append ( comp );
868 return Standard_True;
871 //=======================================================================
872 //function : GetLocation
874 //=======================================================================
876 TopLoc_Location XCAFDoc_ShapeTool::GetLocation (const TDF_Label& L)
878 Handle(XCAFDoc_Location) LocationAttribute;
879 if (L.FindAttribute(XCAFDoc_Location::GetID(), LocationAttribute))
880 return LocationAttribute->Get();
882 Handle(TNaming_NamedShape) NS;
884 if ( L.FindAttribute ( TNaming_NamedShape::GetID(), NS ) ) {
885 S = TNaming_Tool::GetShape(NS);
890 //=======================================================================
891 //function : GetReferredShape
893 //=======================================================================
895 Standard_Boolean XCAFDoc_ShapeTool::GetReferredShape (const TDF_Label& L,
898 if ( ! IsReference(L) ) return Standard_False;
900 Handle (TDataStd_TreeNode) Node;
901 L.FindAttribute(XCAFDoc::ShapeRefGUID(), Node);
902 Label = Node->Father()->Label();
903 return Standard_True;
906 //=======================================================================
907 //function : AddComponent
909 //=======================================================================
911 TDF_Label XCAFDoc_ShapeTool::AddComponent (const TDF_Label& assembly,
912 const TDF_Label& compL,
913 const TopLoc_Location &Loc)
917 // check that shape is assembly
918 if ( ! IsAssembly(assembly) ) {
919 // if it is simple shape, make it assembly
920 if ( IsSimpleShape(assembly) )
921 TDataStd_UAttribute::Set ( assembly, XCAFDoc::AssemblyGUID() );
925 // add a component as reference
927 L = aTag.NewChild(assembly);
928 MakeReference ( L, compL, Loc );
930 // map shape to label
932 if (GetShape(L, aShape))
934 if (!myShapeLabels.IsBound(aShape))
935 myShapeLabels.Bind(aShape, L);
941 //=======================================================================
942 //function : AddComponent
944 //=======================================================================
946 TDF_Label XCAFDoc_ShapeTool::AddComponent (const TDF_Label& assembly,
947 const TopoDS_Shape& comp,
948 const Standard_Boolean expand)
950 // get label for component`s shape
951 TopoDS_Shape S0 = comp;
955 compL = AddShape ( S0, expand );
957 // add component by its label
958 return AddComponent ( assembly, compL, comp.Location() );
961 //=======================================================================
962 //function : RemoveComponent
964 //=======================================================================
966 void XCAFDoc_ShapeTool::RemoveComponent (const TDF_Label& comp) const
968 if ( IsComponent(comp) )
970 comp.ForgetAllAttributes();
974 //=======================================================================
975 //function : UpdateAssemblies
977 //=======================================================================
979 void XCAFDoc_ShapeTool::UpdateAssemblies()
981 // We start from the free shapes (roots in the assembly structure)
982 TDF_LabelSequence aRootLabels;
983 GetFreeShapes(aRootLabels);
985 // Iterate over the free shapes
986 TDF_LabelMap anUpdated;
987 for ( TDF_LabelSequence::Iterator anIt(aRootLabels); anIt.More(); anIt.Next() )
989 TDF_Label aRefLabel = anIt.Value();
990 if (IsReference(aRefLabel))
992 GetReferredShape(aRefLabel, aRefLabel);
994 const TDF_Label& aRootLab = aRefLabel;
995 TopoDS_Shape anAssemblyShape;
996 updateComponent(aRootLab, anAssemblyShape, anUpdated);
1000 //=======================================================================
1001 //function : IsSubShape
1003 //=======================================================================
1005 //static Standard_Boolean CheckSubShape (const TopoDS_Shape &S, const TopoDS_Shape &sub)
1007 // if ( S.IsSame ( sub ) ) return Standard_True;
1009 // if ( S.ShapeType() >= sub.ShapeType() ) return Standard_False;
1011 // for ( TopoDS_Iterator it(S); it.More(); it.Next() ) {
1012 // if ( CheckSubShape ( it.Value(), sub ) ) return Standard_True;
1014 // return Standard_False;
1017 //=======================================================================
1018 //function : IsSubShape
1020 //=======================================================================
1022 Standard_Boolean XCAFDoc_ShapeTool::IsSubShape (const TDF_Label &shapeL,
1023 const TopoDS_Shape &sub) const
1025 Handle(XCAFDoc_ShapeMapTool) A;
1026 if (!shapeL.FindAttribute(XCAFDoc_ShapeMapTool::GetID(), A))
1028 TopoDS_Shape aShape = GetShape(shapeL);
1029 if (aShape.IsNull())
1030 return Standard_False;
1031 A = XCAFDoc_ShapeMapTool::Set(shapeL);
1032 A->SetShape(aShape);
1035 return A->IsSubShape(sub);
1038 //=======================================================================
1039 //function : FindSubShape
1041 //=======================================================================
1043 Standard_Boolean XCAFDoc_ShapeTool::FindSubShape (const TDF_Label &shapeL,
1044 const TopoDS_Shape &sub,
1048 return Standard_False;
1050 if (TNaming_Tool::HasLabel(Label(), sub)) {
1052 L = TNaming_Tool::Label(Label(), sub, TransDef);
1054 return Standard_False;
1055 if (L.Father() == shapeL)
1056 return Standard_True;
1060 return Standard_False;
1063 // if subshape was found wrong, try to do it manually
1064 // it can be possible if several part shapes has the same subshapes
1066 TDF_ChildIterator aChldLabIt(shapeL);
1067 for (; aChldLabIt.More(); aChldLabIt.Next() ) {
1068 TDF_Label aSubLabel = aChldLabIt.Value();
1069 Handle(TNaming_NamedShape) NS;
1070 if (!aSubLabel.FindAttribute(TNaming_NamedShape::GetID(), NS))
1072 TopoDS_Shape aSubShape = TNaming_Tool::GetShape(NS);
1073 if (!aSubShape.IsNull() && aSubShape.IsSame(sub)) {
1075 return Standard_True;
1079 return Standard_False;
1082 //=======================================================================
1083 //function : AddSubShape
1085 //=======================================================================
1087 TDF_Label XCAFDoc_ShapeTool::AddSubShape (const TDF_Label &shapeL,
1088 const TopoDS_Shape &sub) const
1091 if (!IsSimpleShape(shapeL) || !IsTopLevel(shapeL))
1094 if ( FindSubShape ( shapeL, sub, L ) ) return L;
1096 if (!IsSubShape(shapeL, sub))
1100 L = aTag.NewChild(shapeL);
1102 TNaming_Builder tnBuild(L);
1103 tnBuild.Generated(sub);
1108 //=======================================================================
1109 //function : AddSubShape
1111 //=======================================================================
1113 Standard_Boolean XCAFDoc_ShapeTool::AddSubShape(const TDF_Label &shapeL,
1114 const TopoDS_Shape &sub,
1115 TDF_Label &addedSubShapeL) const
1117 addedSubShapeL = TDF_Label();
1118 // Check if adding subshape is possible
1119 if (!IsSimpleShape(shapeL) || !IsTopLevel(shapeL))
1120 return Standard_False;
1122 // Try to find already existed subshape
1123 if (FindSubShape(shapeL, sub, addedSubShapeL))
1124 return Standard_False;
1126 if (!IsSubShape(shapeL, sub))
1127 return Standard_False;
1130 addedSubShapeL = aTag.NewChild(shapeL);
1131 TNaming_Builder tnBuild(addedSubShapeL);
1132 tnBuild.Generated(sub);
1134 return Standard_True;
1138 //=======================================================================
1139 //function : FindMainShapeUsingMap
1141 //=======================================================================
1143 TDF_Label XCAFDoc_ShapeTool::FindMainShapeUsingMap(const TopoDS_Shape &sub) const
1145 //for(Standard_Integer i=1; i<=myNotAssemblies.Length(); i++) {
1146 // TDF_Label L = myNotAssemblies.Value(i);
1147 // if(IsSubShape(L,sub)) return L;
1149 if(mySubShapes.IsBound(sub))
1150 return mySubShapes.Find(sub);
1156 //=======================================================================
1157 //function : FindMainShape
1159 //=======================================================================
1161 TDF_Label XCAFDoc_ShapeTool::FindMainShape (const TopoDS_Shape &sub) const
1163 TDF_ChildIterator it(Label());
1164 for (; it.More(); it.Next()) {
1165 TDF_Label L = it.Value();
1167 if ( IsSimpleShape( L ) && IsSubShape ( L, sub ) ) return L;
1174 //=======================================================================
1175 //function : GetSubShapes
1177 //=======================================================================
1179 Standard_Boolean XCAFDoc_ShapeTool::GetSubShapes (const TDF_Label &L,
1180 TDF_LabelSequence& Labels)
1182 TDF_ChildIterator It(L);
1183 for (; It.More(); It.Next() ) {
1184 TDF_Label sub = It.Value();
1185 if ( IsSubShape ( sub ) ) Labels.Append ( sub );
1187 return Labels.Length() >0;
1190 //=======================================================================
1191 //function : BaseLabel
1193 //=======================================================================
1195 TDF_Label XCAFDoc_ShapeTool::BaseLabel () const
1200 //=======================================================================
1201 //function : DumpAssembly
1202 //purpose : recursive part of Dump()
1203 //=======================================================================
1205 static void DumpAssembly(Standard_OStream& theDumpLog,
1207 const Standard_Integer level,
1208 const Standard_Boolean deep)
1211 XCAFDoc_ShapeTool::GetShape(L, S);
1214 for (Standard_Integer i=0; i<level; i++)
1217 TCollection_AsciiString Entry;
1218 TDF_Tool::Entry(L, Entry);
1220 if(XCAFDoc_ShapeTool::IsAssembly(L))
1222 theDumpLog<<"ASSEMBLY ";
1224 else if (XCAFDoc_ShapeTool::IsSimpleShape(L))
1226 if(L.Father().Father().Father().IsRoot())
1227 theDumpLog<<"PART ";
1231 theDumpLog<<"INSTANCE ";
1233 TopAbs::Print(S.ShapeType(), theDumpLog);
1235 theDumpLog<<" "<<Entry;
1236 if(XCAFDoc_ShapeTool::IsReference(L))
1238 Handle(TDataStd_TreeNode) aRef;
1239 L.FindAttribute(XCAFDoc::ShapeRefGUID(), aRef);
1240 TDF_Tool::Entry(aRef->Father()->Label(), Entry);
1241 theDumpLog<<" (refers to "<<Entry<<")";
1243 Handle(TDataStd_Name) Name;
1244 if (L.FindAttribute(TDataStd_Name::GetID(), Name))
1245 theDumpLog<<" \""<<Name->Get()<<"\" ";
1248 theDumpLog<<"("<<*(void**)&S.TShape();
1249 if (! S.Location().IsIdentity())
1250 theDumpLog<<", "<< *(void**)&S.Location();
1253 theDumpLog<<std::endl;
1255 Handle(TDataStd_TreeNode) Node;
1256 TDF_ChildIterator NodeIterator(L);
1257 for (; NodeIterator.More(); NodeIterator.Next()) {
1258 DumpAssembly(theDumpLog, NodeIterator.Value(), level+1, deep);
1261 theDumpLog<<std::endl;
1264 //=======================================================================
1267 //=======================================================================
1269 Standard_OStream& XCAFDoc_ShapeTool::Dump(Standard_OStream& theDumpLog, const Standard_Boolean deep) const
1271 Standard_Integer level = 0;
1272 // TopTools_SequenceOfShape SeqShapes;
1273 TDF_LabelSequence SeqLabels;
1274 GetShapes( SeqLabels);
1276 if (SeqLabels.Length()>0) theDumpLog<<std::endl;
1278 for (i=1; i<=SeqLabels.Length(); i++) {
1279 DumpAssembly(theDumpLog, SeqLabels.Value(i), level, deep);
1283 GetFreeShapes(SeqLabels);
1284 theDumpLog<<std::endl<<"Free Shapes: "<<SeqLabels.Length()<<std::endl;
1285 for (i = 1; i<=SeqLabels.Length(); i++) {
1286 DumpShape(theDumpLog, SeqLabels.Value(i), level, deep);
1287 theDumpLog<<std::endl;
1292 //=======================================================================
1294 //purpose : override
1295 //=======================================================================
1297 Standard_OStream& XCAFDoc_ShapeTool::Dump(Standard_OStream& theDumpLog) const
1299 TDF_Attribute::Dump (theDumpLog);
1300 Dump (theDumpLog, Standard_False);
1304 //=======================================================================
1305 //function : DumpShape
1307 //=======================================================================
1309 void XCAFDoc_ShapeTool::DumpShape(Standard_OStream& theDumpLog, const TDF_Label& L,const Standard_Integer level,const Standard_Boolean deep)
1312 if(! XCAFDoc_ShapeTool::GetShape(L, S) ) return;
1313 for (Standard_Integer i=0; i<level; i++)
1316 if(XCAFDoc_ShapeTool::IsAssembly(L))
1318 theDumpLog<<"ASSEMBLY ";
1320 else if (XCAFDoc_ShapeTool::IsSimpleShape(L))
1322 if(L.Father().Father().Father().IsRoot())
1323 theDumpLog<<"PART ";
1327 theDumpLog<<"INSTANCE ";
1329 TopAbs::Print(S.ShapeType(), theDumpLog);
1331 TCollection_AsciiString Entry;
1332 TDF_Tool::Entry(L, Entry);
1333 theDumpLog<<" "<<Entry;
1334 if(XCAFDoc_ShapeTool::IsReference(L))
1336 Handle(TDataStd_TreeNode) aRef;
1337 L.FindAttribute(XCAFDoc::ShapeRefGUID(), aRef);
1338 TDF_Tool::Entry(aRef->Father()->Label(), Entry);
1339 theDumpLog<<" (refers to "<<Entry<<")";
1341 //std::cout<<std::endl;
1342 Handle(TDataStd_Name) Name;
1343 if (L.FindAttribute(TDataStd_Name::GetID(),Name))
1344 theDumpLog<<" \""<<Name->Get()<<"\" ";
1347 theDumpLog<<"("<<*(void**)&S.TShape();
1348 if (! S.Location().IsIdentity())
1349 theDumpLog<<", "<< *(void**)&S.Location();
1354 //=======================================================================
1355 //function : IsExternRef
1357 //=======================================================================
1359 Standard_Boolean XCAFDoc_ShapeTool::IsExternRef(const TDF_Label& L)
1361 Handle(TDataStd_UAttribute) Uattr;
1362 return L.FindAttribute(XCAFDoc::ExternRefGUID(), Uattr);
1365 //=======================================================================
1366 //function : SetExternRefs
1368 //=======================================================================
1370 void XCAFDoc_ShapeTool::SetExternRefs(const TDF_Label& L,
1371 const TColStd_SequenceOfHAsciiString& SHAS) const
1373 TDF_Label ShapeLabel = L.NewChild();
1374 TDataStd_UAttribute::Set(ShapeLabel,XCAFDoc::ExternRefGUID());
1375 for(Standard_Integer i=1; i<=SHAS.Length(); i++) {
1376 TDF_Label tmplbl = ShapeLabel.FindChild(i,Standard_True);
1377 Handle(TCollection_HAsciiString) str = SHAS(i);
1378 TCollection_ExtendedString extstr(str->String());
1379 TDataStd_Name::Set(tmplbl,extstr);
1383 //=======================================================================
1384 //function : SetExternRefs
1386 //=======================================================================
1388 TDF_Label XCAFDoc_ShapeTool::SetExternRefs(const TColStd_SequenceOfHAsciiString& SHAS) const
1390 TDF_Label ShapeLabel;
1393 ShapeLabel = aTag.NewChild(Label());
1394 TDataStd_UAttribute::Set(ShapeLabel,XCAFDoc::ExternRefGUID());
1395 for(Standard_Integer i=1; i<=SHAS.Length(); i++) {
1396 TDF_Label tmplbl = ShapeLabel.FindChild(i,Standard_True);
1397 Handle(TCollection_HAsciiString) str = SHAS(i);
1398 TCollection_ExtendedString extstr(str->String());
1399 TDataStd_Name::Set(tmplbl,extstr);
1404 //=======================================================================
1405 //function : GetExternRefs
1407 //=======================================================================
1409 void XCAFDoc_ShapeTool::GetExternRefs(const TDF_Label& L,
1410 TColStd_SequenceOfHAsciiString& SHAS)
1412 Handle(TDataStd_Name) TDN;
1414 for(Standard_Integer i=1; i<=L.NbChildren(); i++) {
1415 tmplbl = L.FindChild(i);
1416 if(tmplbl.FindAttribute(TDataStd_Name::GetID(),TDN)) {
1417 TCollection_ExtendedString extstr = TDN->Get();
1418 Handle(TCollection_HAsciiString) str =
1419 new TCollection_HAsciiString(TCollection_AsciiString(extstr));
1425 // API: API work with SHUO (Specified Higher Usage Occurrance) structure
1427 //=======================================================================
1428 //function : GetSHUO
1430 //=======================================================================
1432 Standard_Boolean XCAFDoc_ShapeTool::GetSHUO (const TDF_Label& SHUOLabel,
1433 Handle(XCAFDoc_GraphNode)& aSHUOAttr)
1435 if ( !SHUOLabel.FindAttribute( XCAFDoc::SHUORefGUID(), aSHUOAttr ) )
1436 return Standard_False;
1437 return Standard_True;
1440 //=======================================================================
1441 //function : GetAllComponentSHUO
1443 //=======================================================================
1445 Standard_Boolean XCAFDoc_ShapeTool::GetAllComponentSHUO (const TDF_Label& theCompLabel,
1446 TDF_AttributeSequence& theSHUOAttrs)
1448 TDF_ChildIterator it(theCompLabel);
1449 for (; it.More(); it.Next()) {
1450 TDF_Label L = it.Value();
1451 Handle(XCAFDoc_GraphNode) aSHUOAttr;
1452 if ( GetSHUO( L, aSHUOAttr ) )
1453 theSHUOAttrs.Append( aSHUOAttr );
1455 return (theSHUOAttrs.Length() > 0);
1458 //=======================================================================
1459 //function : SetSHUO
1461 //=======================================================================
1463 Standard_Boolean XCAFDoc_ShapeTool::SetSHUO (const TDF_LabelSequence& labels,
1464 Handle(XCAFDoc_GraphNode)& MainSHUOAttr) const
1466 MainSHUOAttr.Nullify();
1467 // check number of labels
1468 if (labels.Length() < 2)
1469 return Standard_False;
1470 // check is all labels contains components of any assemblyies
1472 for (i = 1; i <= labels.Length(); i++)
1473 if ( !IsComponent(labels.Value(i)) )
1474 return Standard_False;
1477 TDF_Label UpperSubL = aTag.NewChild( labels( 1 ) );
1478 if (theAutoNaming) {
1479 TCollection_ExtendedString Entry("SHUO");
1480 TDataStd_Name::Set(UpperSubL, TCollection_ExtendedString( Entry ));
1482 Handle(XCAFDoc_GraphNode) aUpperSHUO;
1483 aUpperSHUO = XCAFDoc_GraphNode::Set( UpperSubL, XCAFDoc::SHUORefGUID() );
1484 // init out argument by main upper usage SHUO
1485 MainSHUOAttr = aUpperSHUO;
1486 // add other next_usage occurrences.
1487 for (i = 2; i <= labels.Length(); i++) {
1488 TDF_Label NextSubL = aTag.NewChild( labels( i ) );
1489 if (theAutoNaming) {
1490 TCollection_ExtendedString EntrySub("SHUO-");
1492 TDataStd_Name::Set(NextSubL, TCollection_ExtendedString( EntrySub ));
1494 Handle(XCAFDoc_GraphNode) aNextSHUO;
1495 aNextSHUO = XCAFDoc_GraphNode::Set( NextSubL, XCAFDoc::SHUORefGUID() );
1497 aUpperSHUO->SetChild( aNextSHUO );
1498 aNextSHUO->SetFather( aUpperSHUO );
1499 // now lets next_usage become upper_usage for next level of SHUO
1500 aUpperSHUO = aNextSHUO;
1501 UpperSubL = NextSubL;
1504 return Standard_True;
1507 //=======================================================================
1508 //function : GetSHUOUpperUsage
1510 //=======================================================================
1512 Standard_Boolean XCAFDoc_ShapeTool::GetSHUOUpperUsage (const TDF_Label& NextUsageL,
1513 TDF_LabelSequence& aLabels)
1515 Handle(XCAFDoc_GraphNode) aNextSHUO;
1516 if( !GetSHUO( NextUsageL, aNextSHUO ) || aNextSHUO->NbFathers()<1 )
1517 return Standard_False;
1519 // get upper_usage SHAO
1520 for (Standard_Integer i = 1; i <= aNextSHUO->NbFathers(); i++)
1521 aLabels.Append( aNextSHUO->GetFather(i)->Label() );
1522 return Standard_True;
1525 //=======================================================================
1526 //function : GetSHUONextUsage
1528 //=======================================================================
1530 Standard_Boolean XCAFDoc_ShapeTool::GetSHUONextUsage (const TDF_Label& UpperUsageL,
1531 TDF_LabelSequence& aLabels)
1533 Handle(XCAFDoc_GraphNode) aUpperSHUO;
1534 if ( !GetSHUO( UpperUsageL, aUpperSHUO ) || aUpperSHUO->NbChildren()<1 )
1535 return Standard_False;
1536 // get upper_usage SHAO
1537 for (Standard_Integer i = 1; i <= aUpperSHUO->NbChildren(); i++)
1538 aLabels.Append( aUpperSHUO->GetChild(i)->Label() );
1539 return Standard_True;
1542 //=======================================================================
1543 //function : RemoveSHUO
1545 //=======================================================================
1547 Standard_Boolean XCAFDoc_ShapeTool::RemoveSHUO (const TDF_Label& L) const
1549 L.ForgetAllAttributes (Standard_True);
1550 return Standard_True;
1553 //=======================================================================
1554 //function : checkForShape
1555 //purpose : auxilary
1556 //=======================================================================
1558 static Standard_Boolean checkForShape (const TopoDS_Shape& theShape,
1559 const TopoDS_Shape& theCurSh,
1560 const TDF_Label& theUserL,
1561 TDF_LabelSequence& theLabels)
1563 // the label of an assembly which contains this component
1564 TDF_Label aSuperUserL = theUserL.Father();
1565 TopLoc_Location aSupLoc, aCompLoc;
1566 aSupLoc = ::XCAFDoc_ShapeTool::GetLocation ( aSuperUserL );
1567 aCompLoc = ::XCAFDoc_ShapeTool::GetLocation ( theUserL );
1568 TopoDS_Shape aCopySh = theCurSh;
1569 aCompLoc = aCompLoc.Multiplied( theCurSh.Location() );
1570 aSupLoc = aSupLoc.Multiplied( aCompLoc );
1571 aCopySh.Location( aSupLoc );
1572 if ( aCopySh.IsSame( theShape ) ) {
1573 theLabels.Prepend( theUserL );
1574 return Standard_True;
1576 // try to search deeply (upper by assmebly structure)
1577 TDF_LabelSequence aNewLabels;
1578 for (Standard_Integer j = 1; j <= theLabels.Length(); j++)
1579 aNewLabels.Append( theLabels.Value( j ) );
1580 aNewLabels.Prepend( theUserL );
1581 TDF_LabelSequence aUsers;
1582 ::XCAFDoc_ShapeTool::GetUsers( aSuperUserL, aUsers );
1583 for (Standard_Integer i = 1; i <= aUsers.Length(); i++)
1584 if ( checkForShape( theShape, aCopySh, aUsers.Value( i ), aNewLabels ) ) {
1586 theLabels = aNewLabels;
1587 return Standard_True;
1589 return Standard_False;
1592 //=======================================================================
1593 //function : FindComponent
1595 //=======================================================================
1597 Standard_Boolean XCAFDoc_ShapeTool::FindComponent (const TopoDS_Shape& theShape,
1598 TDF_LabelSequence& theLabels) const
1601 // search for a top-level shape that corresponds to this component
1602 TopoDS_Shape S0 = theShape;
1603 TopLoc_Location loc;
1604 S0.Location ( loc );
1605 TDF_Label aRefL = FindShape( S0 );
1607 return Standard_False; // cannot find top-level shape.
1609 TDF_LabelSequence aUsers;
1610 ::XCAFDoc_ShapeTool::GetUsers( aRefL, aUsers );
1611 for (Standard_Integer i = 1; i <= aUsers.Length(); i++)
1612 if ( checkForShape( theShape, S0, aUsers.Value( i ), theLabels ) )
1615 return (theLabels.Length() > 0);
1618 //=======================================================================
1619 //function : getShapesOfSHUO
1620 //purpose : auxilary
1621 //=======================================================================
1623 static Standard_Boolean getShapesOfSHUO (TopLoc_IndexedMapOfLocation& theaPrevLocMap,
1624 const Handle(XCAFDoc_ShapeTool)& theSTool,
1625 const TDF_Label& theSHUOlab,
1626 TopoDS_Shape& theShape)
1628 Handle(XCAFDoc_GraphNode) SHUO;
1629 TDF_LabelSequence aLabSeq;
1630 theSTool->GetSHUONextUsage( theSHUOlab, aLabSeq );
1631 if (aLabSeq.Length() >= 1)
1632 for (Standard_Integer i = 1; i <= aLabSeq.Length(); i++) {
1633 TDF_Label aSubCompL = aLabSeq.Value( i );
1634 TopLoc_Location compLoc = XCAFDoc_ShapeTool::GetLocation ( aSubCompL.Father() );
1635 // create new map of laocation (to not merge locations from different shapes)
1636 TopLoc_IndexedMapOfLocation aNewPrevLocMap;
1637 for (Standard_Integer m = 1; m <= theaPrevLocMap.Extent(); m++)
1638 aNewPrevLocMap.Add( theaPrevLocMap.FindKey( m ) );
1639 aNewPrevLocMap.Add( compLoc );
1640 // got for the new sublocations and corresponding shape
1641 getShapesOfSHUO( aNewPrevLocMap, theSTool, aSubCompL, theShape );
1644 TopoDS_Shape aSHUO_NUSh = theSTool->GetShape ( theSHUOlab.Father() );
1645 if ( aSHUO_NUSh.IsNull() ) return Standard_False;
1646 // cause got shape with location already.
1647 TopLoc_Location nullLoc;
1648 aSHUO_NUSh.Location ( nullLoc );
1649 // multiply the locations
1650 Standard_Integer intMapLenght = theaPrevLocMap.Extent();
1651 if ( intMapLenght < 1 )
1652 return Standard_False; // should not be, but to avoid exception...?
1653 TopLoc_Location SupcompLoc;
1654 SupcompLoc = theaPrevLocMap.FindKey( intMapLenght );
1655 if (intMapLenght > 1) {
1656 Standard_Integer l = intMapLenght - 1;
1658 SupcompLoc = theaPrevLocMap.FindKey( l ).Multiplied( SupcompLoc );
1662 aSHUO_NUSh.Location( SupcompLoc );
1663 theShape = aSHUO_NUSh;
1665 return (!theShape.IsNull());
1668 //=======================================================================
1669 //function : GetSHUOInstance
1671 //=======================================================================
1673 TopoDS_Shape XCAFDoc_ShapeTool::GetSHUOInstance (const Handle(XCAFDoc_GraphNode)& theSHUO) const
1675 TopoDS_Shape aShape;
1676 if (theSHUO.IsNull())
1679 TDF_Label aSHUOlab = theSHUO->Label();
1680 // get location of the assembly
1681 TopLoc_Location loc = XCAFDoc_ShapeTool::GetLocation ( aSHUOlab.Father().Father() );
1682 // get location of the component
1683 TopLoc_Location compLoc = XCAFDoc_ShapeTool::GetLocation ( aSHUOlab.Father() );
1684 TopLoc_IndexedMapOfLocation aPrevLocMap;
1685 // get previous setted location
1686 if ( !loc.IsIdentity() )
1687 aPrevLocMap.Add( loc );
1688 aPrevLocMap.Add( compLoc );
1689 // get shape by recurse method
1690 const Handle(XCAFDoc_ShapeTool)& STool = this;
1691 getShapesOfSHUO( aPrevLocMap, STool, aSHUOlab, aShape );
1696 //=======================================================================
1697 //function : getUsersShapesOfSHUO
1698 //purpose : auxilary
1699 //=======================================================================
1701 static Standard_Boolean getUsersShapesOfSHUO (TopLoc_IndexedMapOfLocation& aPrevLocMap,
1702 const Handle(XCAFDoc_ShapeTool)& STool,
1703 const TDF_Label& aSHUOlab,
1704 const TDF_Label& theUserL,
1705 TopTools_SequenceOfShape& theSHUOShapeSeq)
1707 TopLoc_IndexedMapOfLocation aNewPrevLocMap;
1708 // get location of the assembly
1709 TopLoc_Location loc = XCAFDoc_ShapeTool::GetLocation ( theUserL.Father() );
1710 // get location of the component
1711 TopLoc_Location compLoc = XCAFDoc_ShapeTool::GetLocation ( theUserL );
1712 // get previous setted location
1713 aNewPrevLocMap.Add( loc );
1714 aNewPrevLocMap.Add( compLoc );
1716 for (i = 1; i <= aPrevLocMap.Extent(); i++)
1717 aNewPrevLocMap.Add( aPrevLocMap.FindKey(i) );
1718 TDF_Label L = theUserL.Father();
1719 TDF_LabelSequence usersLab;
1720 ::XCAFDoc_ShapeTool::GetUsers( L, usersLab );
1721 if (usersLab.Length() == 0) {
1722 TopoDS_Shape aShape;
1723 getShapesOfSHUO( aNewPrevLocMap, STool, aSHUOlab, aShape );
1724 if (!aShape.IsNull()) {
1725 theSHUOShapeSeq.Append(aShape);
1726 return Standard_True;
1729 // now iterates on users of this assembly as component
1730 for ( i = 1; i <= usersLab.Length(); i++ ) {
1731 TDF_Label aNewUserL = usersLab.Value(i);
1732 getUsersShapesOfSHUO( aNewPrevLocMap, STool, aSHUOlab, aNewUserL, theSHUOShapeSeq );
1735 return (theSHUOShapeSeq.Length() > 1);
1738 //=======================================================================
1739 //function : GetAllSHUOInstances
1740 //purpose : auxilary
1741 //=======================================================================
1743 Standard_Boolean XCAFDoc_ShapeTool::GetAllSHUOInstances (const Handle(XCAFDoc_GraphNode)& theSHUO,
1744 TopTools_SequenceOfShape& theSHUOShapeSeq) const
1746 if (theSHUO.IsNull())
1747 return Standard_False;
1749 TDF_Label aSHUOlab = theSHUO->Label();
1750 TopLoc_IndexedMapOfLocation aPrevLocMap;
1751 // get location of the assembly
1752 TopLoc_Location loc = XCAFDoc_ShapeTool::GetLocation ( aSHUOlab.Father().Father() );
1753 // get location of the component
1754 TopLoc_Location compLoc = XCAFDoc_ShapeTool::GetLocation ( aSHUOlab.Father() );
1755 // get previous setted location
1756 if ( !loc.IsIdentity() )
1757 aPrevLocMap.Add( loc );
1758 aPrevLocMap.Add( compLoc );
1759 // get label of assembly
1760 TDF_Label L = aSHUOlab.Father().Father();
1761 TDF_LabelSequence usersLab;
1762 ::XCAFDoc_ShapeTool::GetUsers( L, usersLab );
1763 TopoDS_Shape aShape;
1764 const Handle(XCAFDoc_ShapeTool)& STool = this;
1765 if (usersLab.Length() == 0) {
1766 getShapesOfSHUO( aPrevLocMap, STool, aSHUOlab, aShape );
1767 if (!aShape.IsNull()) {
1768 theSHUOShapeSeq.Append(aShape);
1769 return Standard_True;
1772 // now iterates on users of this assembly as component
1773 for (Standard_Integer i = 1; i <= usersLab.Length(); i++) {
1774 TDF_Label aUserL = usersLab.Value(i);
1775 getUsersShapesOfSHUO( aPrevLocMap, STool, aSHUOlab, aUserL, theSHUOShapeSeq );
1778 return (theSHUOShapeSeq.Length() > 1);
1781 //=======================================================================
1782 //function : SetInstanceSHUO
1784 //=======================================================================
1786 Handle(XCAFDoc_GraphNode) XCAFDoc_ShapeTool::SetInstanceSHUO (const TopoDS_Shape& theShape) const
1788 Handle(XCAFDoc_GraphNode) SHUO;
1789 TDF_LabelSequence aLabels;
1790 if ( FindComponent( theShape, aLabels ) )
1791 // set shuo structure on labels of component-assembly structure
1792 SetSHUO( aLabels, SHUO );
1796 //=======================================================================
1797 //function : FindSHUO
1799 //=======================================================================
1801 Standard_Boolean XCAFDoc_ShapeTool::FindSHUO (const TDF_LabelSequence& theLabels,
1802 Handle(XCAFDoc_GraphNode)& theSHUOAttr)
1804 TDF_AttributeSequence SHUOAttrs;
1805 TDF_Label aCompLabel = theLabels.Value(1);
1806 if (! ::XCAFDoc_ShapeTool::GetAllComponentSHUO( aCompLabel, SHUOAttrs ) )
1807 return Standard_False;
1808 // WARNING: manage that each SHUO upper_usage have only one SHUO next_usage
1809 for (Standard_Integer i = 1; i <= SHUOAttrs.Length(); i++) {
1810 TDF_LabelSequence aCondidate;
1811 Handle(XCAFDoc_GraphNode) anSHUO = Handle(XCAFDoc_GraphNode)::DownCast(SHUOAttrs.Value(i));
1812 aCondidate.Append( anSHUO->Label().Father() );
1813 while (anSHUO->NbChildren()) {
1814 anSHUO = anSHUO->GetChild( 1 );
1815 aCondidate.Append( anSHUO->Label().Father() );
1817 // check the label sequences
1818 Standard_Boolean isEqual = Standard_True;
1819 if (theLabels.Length() != aCondidate.Length())
1820 isEqual = Standard_False;
1822 for (Standard_Integer li = 1; li <= theLabels.Length(); li++)
1823 if ( theLabels.Value(li) != aCondidate.Value(li) ) {
1824 isEqual = Standard_False;
1830 theSHUOAttr = Handle(XCAFDoc_GraphNode)::DownCast(SHUOAttrs.Value(i));
1833 return ( !theSHUOAttr.IsNull() );
1836 //=======================================================================
1839 //=======================================================================
1840 Standard_Boolean XCAFDoc_ShapeTool::Expand (const TDF_Label& theShapeL)
1842 if (theShapeL.IsNull() || IsAssembly(theShapeL))
1843 return Standard_False;
1845 TopoDS_Shape aShape = GetShape(theShapeL);
1846 if (aShape.IsNull())
1847 return Standard_False;
1849 TopAbs_ShapeEnum aShapeType = aShape.ShapeType();
1850 Standard_Boolean isExpandedType = aShapeType == TopAbs_COMPOUND || aShapeType == TopAbs_COMPSOLID ||
1851 aShapeType == TopAbs_SHELL || aShapeType == TopAbs_WIRE;
1854 TopoDS_Iterator anIter(aShape);
1855 for(; anIter.More(); anIter.Next())
1857 const TopoDS_Shape& aChildShape = anIter.Value();
1858 TDF_Label aChild, aPart;
1860 // Find child shape as subshape of expanded shape
1861 FindSubShape(theShapeL, aChildShape, aChild);
1862 Handle(TDataStd_Name) anAttr;
1863 //make child (if color isn't set or if it is compound)
1864 if (aChild.IsNull()) {
1865 aChild = AddSubShape(theShapeL, aChildShape);
1869 aChild.FindAttribute(TDataStd_Name::GetID(), anAttr);
1872 // Try to find child shape as already existed part
1873 aPart = FindShape(aChildShape.Located(TopLoc_Location()));
1874 if (aPart.IsNull()) {
1875 // Create new part to link child shape
1876 aPart = AddShape(aChildShape.Located(TopLoc_Location()), Standard_False, Standard_False);
1878 // Add shape manually, if already existed subshape found instead of creation of new part
1879 if (!aPart.IsNull() && !IsTopLevel(aPart)) {
1880 if (!GetReferredShape(aPart, aPart)) {
1882 aPart = aTag.NewChild(Label());
1883 SetShape(aPart, aChildShape.Located(TopLoc_Location()));
1888 if (!anAttr.IsNull()) {
1889 TDataStd_Name::Set(aPart, anAttr->Get());
1892 Standard_SStream Stream;
1893 TopAbs::Print(aChildShape.ShapeType(), Stream);
1894 TCollection_AsciiString aName(Stream.str().c_str());
1895 TDataStd_Name::Set(aPart, TCollection_ExtendedString(aName));
1897 MakeReference(aChild, aPart, aChildShape.Location());
1898 makeSubShape(theShapeL, aPart, aChildShape, aChildShape.Location());
1900 //set assembly attribute
1901 TDataStd_UAttribute::Set(theShapeL, XCAFDoc::AssemblyGUID());
1902 return Standard_True;
1904 return Standard_False;
1907 //=======================================================================
1908 //function : makeSubShape
1910 //=======================================================================
1912 void XCAFDoc_ShapeTool::makeSubShape (const TDF_Label& theMainShapeL,
1913 const TDF_Label& thePart,
1914 const TopoDS_Shape& theShape,
1915 const TopLoc_Location& theLoc)
1917 TopoDS_Iterator anIter(theShape);
1918 Standard_Boolean isCompoundPart = (GetShape(thePart).ShapeType() == TopAbs_COMPOUND);
1919 Standard_Boolean isAssembly = IsAssembly(thePart);
1921 for(; anIter.More(); anIter.Next()) {
1922 const TopoDS_Shape& aChildShape = anIter.Value();
1923 TDF_Label aChildLabel;
1924 FindSubShape(theMainShapeL, aChildShape, aChildLabel);
1925 if(!aChildLabel.IsNull()) {
1927 aChildLabel.ForgetAllAttributes();
1928 makeSubShape(theMainShapeL, thePart, aChildShape, theLoc);
1932 Handle(TDataStd_Name) anAttr;
1933 aChildLabel.FindAttribute(TDataStd_Name::GetID(), anAttr);
1934 TopLoc_Location aSubLoc;
1935 // Calculate location for subshapes of compound parts
1936 aSubLoc = aChildShape.Location();
1938 aSubLoc = theLoc.Inverted() * aSubLoc;
1940 TDF_Label aSubLabel;
1941 // Identical location and empty location are not the same for ShapeTool, so try to process both
1942 // in case of aSubLoc is not identical, the second Add try will not affect algorithm.
1943 Standard_Boolean isNewSubL;
1944 isNewSubL = AddSubShape(thePart, aChildShape.Located(aSubLoc), aSubLabel);
1945 if (aSubLabel.IsNull())
1947 isNewSubL = AddSubShape(thePart, aChildShape.Located(TopLoc_Location()), aSubLabel);
1950 //set name to sub shape
1951 if (!anAttr.IsNull()) {
1952 TDataStd_Name::Set(aSubLabel, anAttr->Get());
1955 Standard_SStream Stream;
1956 TopAbs::Print(aChildShape.ShapeType(), Stream);
1957 TCollection_AsciiString aName(Stream.str().c_str());
1958 TDataStd_Name::Set(aSubLabel, TCollection_ExtendedString(aName));
1960 // Create auxiliary link, it will be removed during moving attributes
1961 MakeReference(aSubLabel, aChildLabel, aChildShape.Location());
1964 aChildLabel.ForgetAllAttributes();
1968 makeSubShape(theMainShapeL, thePart, aChildShape, theLoc);
1972 //=======================================================================
1973 //function : updateComponent
1975 //=======================================================================
1977 Standard_Boolean XCAFDoc_ShapeTool::updateComponent(const TDF_Label& theItemLabel,
1978 TopoDS_Shape& theUpdatedShape,
1979 TDF_LabelMap& theUpdated) const
1981 if ( !IsAssembly(theItemLabel) )
1982 return Standard_False; // Do nothing for non-assemblies
1984 // Get the currently stored compound for the assembly
1985 TopoDS_Shape aCurrentRootShape;
1986 GetShape(theItemLabel, aCurrentRootShape);
1988 // Check if the given assembly is already updated
1989 if (theUpdated.Contains(theItemLabel)) {
1990 theUpdatedShape = aCurrentRootShape;
1991 return Standard_True;
1994 TopTools_MapOfOrientedShape aCurrentRootShapeMap (aCurrentRootShape.NbChildren());
1996 // Get components of the assembly
1997 TDF_LabelSequence aComponentLabs;
1998 GetComponents(theItemLabel, aComponentLabs);
2000 // This flag indicates whether to update the compound of the assembly
2001 Standard_Boolean isModified = Standard_False;
2003 // Compare the number of components in XDE structure with the number of
2004 // components in topological structure. A component may happen to be removed,
2005 // so we have to update the assembly compound
2006 const Standard_Integer aNumTopoComponents = aCurrentRootShape.NbChildren();
2008 if ( aNumTopoComponents != aComponentLabs.Length() )
2009 isModified = Standard_True;
2011 // Iterate over the assembly components. If at least one component is
2012 // modified (this is the recursive check), then the actually stored
2013 // compound has to be updated
2014 TopTools_ListOfShape aComponentShapes;
2016 for ( TDF_LabelSequence::Iterator aCompIt(aComponentLabs); aCompIt.More(); aCompIt.Next() )
2018 const TDF_Label& aComponentLab = aCompIt.Value();
2020 // Take the referred assembly item (ultimately, a part for an instance)
2021 TDF_Label aComponentRefLab;
2022 GetReferredShape(aComponentLab, aComponentRefLab);
2024 // Shape comes with some placement transformation here
2025 TopoDS_Shape aComponentShape;
2026 GetShape(aComponentLab, aComponentShape);
2027 TopLoc_Location aComponentLoc = aComponentShape.Location();
2029 // If the component is a sub-assembly, then its associated compound
2030 // has to be processed in the same manner
2031 if ( IsAssembly(aComponentRefLab) )
2034 if ( updateComponent(aComponentRefLab, aComponentShape, theUpdated) )
2036 isModified = Standard_True;
2037 aComponentShape.Location(aComponentLoc); // Apply placement
2042 // Search for a part in the actual compound of the ultimate assembly.
2043 // If the part is there, then the compound is up-to-date, so it does not require rebuilding
2046 if (aCurrentRootShapeMap.IsEmpty())
2048 // optimize search for next labels in aComponentLabs
2049 for (TopoDS_Iterator aTopoIt(aCurrentRootShape); aTopoIt.More(); aTopoIt.Next())
2051 aCurrentRootShapeMap.Add (aTopoIt.Value());
2054 if (!aCurrentRootShapeMap.Contains (aComponentShape))
2056 // Part has been modified somewhere, so the compound has to be rebuilt
2057 isModified = Standard_True;
2062 // Fill the list of shapes composing a new compound for the assembly
2063 aComponentShapes.Append(aComponentShape);
2066 // If any component is modified, we update the currently stored shape
2069 TopoDS_Compound anUpdatedCompound;
2071 aBB.MakeCompound(anUpdatedCompound);
2073 // Compose new compound
2074 for ( TopTools_ListIteratorOfListOfShape aShapeIt(aComponentShapes); aShapeIt.More(); aShapeIt.Next() )
2076 aBB.Add( anUpdatedCompound, aShapeIt.Value() );
2079 // Store the updated shape as an output
2080 theUpdatedShape = anUpdatedCompound;
2082 // Use topological naming services to store the updated shape in XDE
2083 TNaming_Builder NB(theItemLabel);
2084 NB.Generated(theUpdatedShape);
2088 theUpdated.Add(theItemLabel);
2093 //=======================================================================
2094 //function : GetNamedProperties
2096 //=======================================================================
2098 Handle(TDataStd_NamedData) XCAFDoc_ShapeTool::GetNamedProperties (const TDF_Label& theLabel,
2099 const Standard_Boolean theToCreate) const
2101 Handle(TDataStd_NamedData) aNamedProperty;
2102 if (!theLabel.FindAttribute(TDataStd_NamedData::GetID(), aNamedProperty) && theToCreate)
2104 aNamedProperty = TDataStd_NamedData::Set(theLabel);
2107 return aNamedProperty;
2110 //=======================================================================
2111 //function : GetNamedProperties
2113 //=======================================================================
2115 Handle(TDataStd_NamedData) XCAFDoc_ShapeTool::GetNamedProperties (const TopoDS_Shape& theShape,
2116 const Standard_Boolean theToCreate) const
2118 Handle(TDataStd_NamedData) aNamedProperty;
2120 if (!Search (theShape, aLabel))
2121 return aNamedProperty;
2123 aNamedProperty = GetNamedProperties (aLabel, theToCreate);
2125 return aNamedProperty;
2128 //=======================================================================
2129 //function : DumpJson
2131 //=======================================================================
2132 void XCAFDoc_ShapeTool::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
2134 OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
2136 OCCT_DUMP_BASE_CLASS (theOStream, theDepth, TDF_Attribute)
2138 for (XCAFDoc_DataMapOfShapeLabel::Iterator aShapeLabelIt (myShapeLabels); aShapeLabelIt.More(); aShapeLabelIt.Next())
2140 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &aShapeLabelIt.Key())
2142 TCollection_AsciiString aShapeLabel;
2143 TDF_Tool::Entry (aShapeLabelIt.Value(), aShapeLabel);
2144 OCCT_DUMP_FIELD_VALUE_STRING (theOStream, aShapeLabel)
2147 for (XCAFDoc_DataMapOfShapeLabel::Iterator aSubShapeIt (mySubShapes); aSubShapeIt.More(); aSubShapeIt.Next())
2149 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &aSubShapeIt.Key())
2151 TCollection_AsciiString aSubShape;
2152 TDF_Tool::Entry (aSubShapeIt.Value(), aSubShape);
2153 OCCT_DUMP_FIELD_VALUE_STRING (theOStream, aSubShape)
2156 for (XCAFDoc_DataMapOfShapeLabel::Iterator aSimpleShapeIt (mySimpleShapes); aSimpleShapeIt.More(); aSimpleShapeIt.Next())
2158 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &aSimpleShapeIt.Key())
2160 TCollection_AsciiString aSimpleShape;
2161 TDF_Tool::Entry (aSimpleShapeIt.Value(), aSimpleShape);
2162 OCCT_DUMP_FIELD_VALUE_STRING (theOStream, aSimpleShape)
2165 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, hasSimpleShapes)