0029599: Data Exchange - Incorrect expand compound method in XDE
[occt.git] / src / XCAFDoc / XCAFDoc_ShapeTool.cxx
index 5be7fe6..b39e3b0 100644 (file)
@@ -329,8 +329,9 @@ TDF_Label XCAFDoc_ShapeTool::FindShape (const TopoDS_Shape& S,
                                     const Standard_Boolean findInstance) const
 {
   TDF_Label L;
-  FindShape ( S, L, findInstance );
-  return L;
+  if (FindShape(S, L, findInstance))
+    return L;
+  return TDF_Label();
 }
 
 //=======================================================================
@@ -1035,11 +1036,12 @@ Standard_Boolean XCAFDoc_ShapeTool::IsSubShape (const TDF_Label &shapeL,
                                             const TopoDS_Shape &sub) const
 {
   Handle(XCAFDoc_ShapeMapTool) A;
-  if ( ! shapeL.FindAttribute(XCAFDoc_ShapeMapTool::GetID(), A) )
-    return Standard_False;
-  
-  //TopoDS_Shape S = GetShape ( shapeL );
-  //return ! S.IsNull() && CheckSubShape ( S, sub );
+  if (!shapeL.FindAttribute(XCAFDoc_ShapeMapTool::GetID(), A))
+  {
+    A = XCAFDoc_ShapeMapTool::Set(shapeL);
+    TopoDS_Shape aShape = GetShape(shapeL);
+    A->SetShape(aShape);
+  }
   
   return A->IsSubShape(sub);
 }
@@ -1085,7 +1087,8 @@ TDF_Label XCAFDoc_ShapeTool::AddSubShape (const TDF_Label &shapeL,
   TDF_Label L;
   if ( FindSubShape ( shapeL, sub, L ) ) return L;
   
-  if ( ! IsSubShape ( shapeL, sub ) ) return L;
+  if (!IsSubShape(shapeL, sub))
+    return TDF_Label();
   
   TDF_TagSource aTag;
   L = aTag.NewChild(shapeL);
@@ -1801,13 +1804,12 @@ Standard_Boolean XCAFDoc_ShapeTool::FindSHUO (const TDF_LabelSequence& theLabels
 //function : Expand
 //purpose  : 
 //=======================================================================
-
-Standard_Boolean XCAFDoc_ShapeTool::Expand (const TDF_Label& Shape)
+Standard_Boolean XCAFDoc_ShapeTool::Expand (const TDF_Label& theShapeL)
 {
-  if (Shape.IsNull() || IsAssembly(Shape))
+  if (theShapeL.IsNull() || IsAssembly(theShapeL))
     return Standard_False;
 
-  TopoDS_Shape aShape = GetShape(Shape);
+  TopoDS_Shape aShape = GetShape(theShapeL);
   if (aShape.IsNull())
     return Standard_False;
 
@@ -1817,48 +1819,64 @@ Standard_Boolean XCAFDoc_ShapeTool::Expand (const TDF_Label& Shape)
   if (isExpandedType)
   {
     //set assembly attribute
-    TDataStd_UAttribute::Set ( Shape, XCAFDoc::AssemblyGUID() );
-
+    TDataStd_UAttribute::Set(theShapeL, XCAFDoc::AssemblyGUID());
     TopoDS_Iterator anIter(aShape);
     for(; anIter.More(); anIter.Next())
     {
       TopoDS_Shape aChildShape = anIter.Value();
-      TDF_Label aChild = FindShape(aChildShape, Standard_True);
-      TDF_TagSource aTag;
+      TDF_Label aChild, aPart;
+
+      // Find child shape as subshape of expanded shape
+      if (!FindSubShape(theShapeL, aChildShape, aChild)) {
+        // Fast searchig using FindSubShape() can find only the first apparation, try to find manually
+        TDF_ChildIterator anIt(theShapeL);
+        for (; anIt.More(); anIt.Next()) {
+          TDF_Label aSubLabel = anIt.Value();
+          TopoDS_Shape aSubS;
+          if (GetShape(aSubLabel, aSubS) && aSubS.IsSame(aChildShape)) {
+            aChild = aSubLabel;
+            break;
+          }
+        }
+      }
       Handle(TDataStd_Name) anAttr;
-      //make part for child
-      TDF_Label aPart = aTag.NewChild(Label());
       //make child (if color isn't set or if it is compound)
-      if(aChild.IsNull())
-      {
-        TopLoc_Location nulloc;
-        aChild = aTag.NewChild(Shape);
-        SetShape(aChild, aChildShape);
-        SetShape(aPart, aChildShape.Located(nulloc));
+      if (aChild.IsNull()) {
+        aChild = AddSubShape(theShapeL, aChildShape);
       }
-      else
-      {
+      else {
         //get name
         aChild.FindAttribute(TDataStd_Name::GetID(), anAttr);
-        TopLoc_Location nulloc;
-        SetShape(aPart, aChildShape.Located(nulloc));
       }
-      //set name to part
-      if(!anAttr.IsNull())
-      {
+
+      // Try to find child shape as already existed part
+      aPart = FindShape(aChildShape.Located(TopLoc_Location()));
+      if (aPart.IsNull()) {
+        // Create new part to link child shape
+        aPart = AddShape(aChildShape.Located(TopLoc_Location()), Standard_False, Standard_False);
+      }
+
+      // Add shape manually, if already existed subshape found instead of creation of new part
+      if (!aPart.IsNull() && !IsTopLevel(aPart)) {
+        if (!GetReferredShape(aPart, aPart)) {
+          TDF_TagSource aTag;
+          aPart = aTag.NewChild(Label());
+          SetShape(aPart, aChildShape.Located(TopLoc_Location()));
+        }
+      }
+
+      // set name to part
+      if (!anAttr.IsNull()) {
         TDataStd_Name::Set(aPart, anAttr->Get());
       }
-      else
-      {
+      else {
         Standard_SStream Stream;
         TopAbs::Print(aChildShape.ShapeType(), Stream);
-        TCollection_AsciiString aName (Stream.str().c_str());
+        TCollection_AsciiString aName(Stream.str().c_str());
         TDataStd_Name::Set(aPart, TCollection_ExtendedString(aName));
       }
-
       MakeReference(aChild, aPart, aChildShape.Location());
-      
-      makeSubShape(aPart, aChildShape);
+      makeSubShape(aPart, aChildShape, aChildShape.Location());
     }
     return Standard_True;
   }
@@ -1870,39 +1888,46 @@ Standard_Boolean XCAFDoc_ShapeTool::Expand (const TDF_Label& Shape)
 //purpose  : 
 //=======================================================================
 
-void XCAFDoc_ShapeTool::makeSubShape (const TDF_Label& Part, const TopoDS_Shape& Shape)
+void XCAFDoc_ShapeTool::makeSubShape (const TDF_Label& thePart,
+                                      const TopoDS_Shape& theShape,
+                                      const TopLoc_Location& theLoc)
 {
-  TDF_TagSource aTag;
-  TopoDS_Iterator anIter(Shape);
-  for(; anIter.More(); anIter.Next())
-  {
+  TopoDS_Iterator anIter(theShape);
+  Standard_Boolean isCompoundPart = (GetShape(thePart).ShapeType() == TopAbs_COMPOUND);
+
+  for(; anIter.More(); anIter.Next()) {
     TopoDS_Shape aChildShape = anIter.Value();
     TDF_Label aChildLabel = FindShape(aChildShape,Standard_True);
-    if(!aChildLabel.IsNull())
-    { 
+    if(!aChildLabel.IsNull()) { 
       //get name
       Handle(TDataStd_Name) anAttr;
       aChildLabel.FindAttribute(TDataStd_Name::GetID(), anAttr);
-      TopLoc_Location nulloc;
+      TopLoc_Location aSubLoc;
+      // Calculate location for subshapes of compound parts
+      if (isCompoundPart) 
+        aSubLoc = theLoc.Inverted() * aChildShape.Location();
       //make subshape
-      TDF_Label aSubLabel = aTag.NewChild(Part);
-      SetShape(aSubLabel, aChildShape.Located(nulloc));
-      //set name to sub shape
-      if(!anAttr.IsNull())
-      {
-        TDataStd_Name::Set(aSubLabel, anAttr->Get());
+      TDF_Label aSubLabel;
+      if (!FindSubShape(thePart, aChildShape.Located(aSubLoc), aSubLabel)) {
+        aSubLabel = AddSubShape(thePart, aChildShape.Located(aSubLoc));
+        //set name to sub shape
+        if (!anAttr.IsNull()) {
+          TDataStd_Name::Set(aSubLabel, anAttr->Get());
+        }
+        else {
+          Standard_SStream Stream;
+          TopAbs::Print(aChildShape.ShapeType(), Stream);
+          TCollection_AsciiString aName(Stream.str().c_str());
+          TDataStd_Name::Set(aSubLabel, TCollection_ExtendedString(aName));
+        }
+        // Create auxiliary link, it will be removed during moving attributes
+        MakeReference(aSubLabel, aChildLabel, aChildShape.Location());
       }
-      else
-      {
-        Standard_SStream Stream;
-        TopAbs::Print(aChildShape.ShapeType(), Stream);
-        TCollection_AsciiString aName (Stream.str().c_str());
-        TDataStd_Name::Set(aSubLabel, TCollection_ExtendedString(aName));
+      else {
+        aChildLabel.ForgetAllAttributes();
       }
-      // Create auxiliary link, it will be removed during moving attributes
-      MakeReference(aSubLabel, aChildLabel, aChildShape.Location());
     }
-    makeSubShape(Part, aChildShape);
+    makeSubShape(thePart, aChildShape, theLoc);
   }
 }