0028104: Data Exchange - Extract sub-assembly (XDE)
authordpasukhi <dpasukhi@opencascade.com>
Tue, 26 Oct 2021 20:45:42 +0000 (23:45 +0300)
committersmoskvin <smoskvin@opencascade.com>
Thu, 28 Oct 2021 19:04:04 +0000 (22:04 +0300)
- Added getting and setting Material, VisMaterial and Props to XCAFDoc_Editor::Expand.
- Added XCAFDoc_Editor::Extract to transfer part to a new location
  - XCAFDoc_Editor::Extract allows to extract a part as a component or simply extract to an empty label with attached colors, layers, materials, vismaterials and props
- Added XCAFDoc_Editor::CloneMetaData to clone shape's attributes to new location
- Added XCAFDoc_Editor::CloneShapeLabel to clone shape to new document
- Added XCAFDoc_DocumentTool::Check*Tool methods to check an existing of an any tool
- Protected against creating a new label for non-existent tools via extract or expand process

src/XCAFDoc/XCAFDoc_DocumentTool.cxx
src/XCAFDoc/XCAFDoc_DocumentTool.hxx
src/XCAFDoc/XCAFDoc_Editor.cxx
src/XCAFDoc/XCAFDoc_Editor.hxx
src/XDEDRAW/XDEDRAW_Common.cxx
tests/bugs/xde/bug28104 [new file with mode: 0644]
tests/bugs/xde/bug28104_1 [new file with mode: 0644]

index 02c6fb0f3148959055d8fac836cd3ac58f6d9080..cc4eba53b0523987baf2f2be7d699511065d3aea 100644 (file)
@@ -249,6 +249,19 @@ TDF_Label XCAFDoc_DocumentTool::VisMaterialLabel (const TDF_Label& theLabel)
   return XCAFDoc_ShapeTool::Set(ShapesLabel(acces));
 }
 
+ //=======================================================================
+//function : CheckShapeTool
+//purpose  :
+//=======================================================================
+Standard_Boolean XCAFDoc_DocumentTool::CheckShapeTool(const TDF_Label& theAcces)
+{
+  TDF_Label aLabel = DocLabel(theAcces).FindChild(1, Standard_False);
+  if (aLabel.IsNull())
+  {
+    return Standard_False;
+  }
+  return aLabel.IsAttribute(XCAFDoc_ShapeTool::GetID());
+}
 
 //=======================================================================
 //function : ColorTool
@@ -260,6 +273,20 @@ Handle(XCAFDoc_ColorTool) XCAFDoc_DocumentTool::ColorTool (const TDF_Label& acce
   return XCAFDoc_ColorTool::Set(ColorsLabel(acces));
 }
 
+ //=======================================================================
+ //function : CheckColorTool
+ //purpose  :
+ //=======================================================================
+Standard_Boolean XCAFDoc_DocumentTool::CheckColorTool(const TDF_Label& theAcces)
+{
+  TDF_Label aLabel = DocLabel(theAcces).FindChild(2, Standard_False);
+  if (aLabel.IsNull())
+  {
+    return Standard_False;
+  }
+  return aLabel.IsAttribute(XCAFDoc_ColorTool::GetID());
+}
+
 //=======================================================================
 //function : VisMaterialTool
 //purpose  :
@@ -269,6 +296,20 @@ Handle(XCAFDoc_VisMaterialTool) XCAFDoc_DocumentTool::VisMaterialTool (const TDF
   return XCAFDoc_VisMaterialTool::Set (VisMaterialLabel (theLabel));
 }
 
+//=======================================================================
+//function : CheckVisMaterialTool
+//purpose  :
+//=======================================================================
+Standard_Boolean XCAFDoc_DocumentTool::CheckVisMaterialTool(const TDF_Label& theAcces)
+{
+  TDF_Label aLabel = DocLabel(theAcces).FindChild(10, Standard_False);
+  if (aLabel.IsNull())
+  {
+    return Standard_False;
+  }
+  return aLabel.IsAttribute(XCAFDoc_VisMaterialTool::GetID());
+}
+
 //=======================================================================
 //function : LayerTool
 //purpose  : 
@@ -279,6 +320,19 @@ Handle(XCAFDoc_LayerTool) XCAFDoc_DocumentTool::LayerTool (const TDF_Label& acce
   return XCAFDoc_LayerTool::Set(LayersLabel(acces));
 }
 
+//=======================================================================
+//function : CheckLayerTool
+//purpose  :
+//=======================================================================
+Standard_Boolean XCAFDoc_DocumentTool::CheckLayerTool(const TDF_Label& theAcces)
+{
+  TDF_Label aLabel = DocLabel(theAcces).FindChild(3, Standard_False);
+  if (aLabel.IsNull())
+  {
+    return Standard_False;
+  }
+  return aLabel.IsAttribute(XCAFDoc_LayerTool::GetID());
+}
 
 //=======================================================================
 //function : DimTolTool
@@ -290,6 +344,19 @@ Handle(XCAFDoc_DimTolTool) XCAFDoc_DocumentTool::DimTolTool(const TDF_Label& acc
   return XCAFDoc_DimTolTool::Set(DGTsLabel(acces));
 }
 
+//=======================================================================
+//function : CheckDimTolTool
+//purpose  :
+//=======================================================================
+Standard_Boolean XCAFDoc_DocumentTool::CheckDimTolTool(const TDF_Label& theAcces)
+{
+  TDF_Label aLabel = DocLabel(theAcces).FindChild(4, Standard_False);
+  if (aLabel.IsNull())
+  {
+    return Standard_False;
+  }
+  return aLabel.IsAttribute(XCAFDoc_DimTolTool::GetID());
+}
 
 //=======================================================================
 //function : MaterialTool
@@ -301,6 +368,20 @@ Handle(XCAFDoc_MaterialTool) XCAFDoc_DocumentTool::MaterialTool(const TDF_Label&
   return XCAFDoc_MaterialTool::Set(MaterialsLabel(acces));
 }
 
+//=======================================================================
+//function : CheckMaterialTool
+//purpose  :
+//=======================================================================
+Standard_Boolean XCAFDoc_DocumentTool::CheckMaterialTool(const TDF_Label& theAcces)
+{
+  TDF_Label aLabel = DocLabel(theAcces).FindChild(5, Standard_False);
+  if (aLabel.IsNull())
+  {
+    return Standard_False;
+  }
+  return aLabel.IsAttribute(XCAFDoc_MaterialTool::GetID());
+}
+
 //=======================================================================
 //function : ViewTool
 //purpose  : 
@@ -311,6 +392,20 @@ Handle(XCAFDoc_ViewTool) XCAFDoc_DocumentTool::ViewTool(const TDF_Label& acces)
   return XCAFDoc_ViewTool::Set(ViewsLabel(acces));
 }
 
+//=======================================================================
+//function : CheckViewTool
+//purpose  :
+//=======================================================================
+Standard_Boolean XCAFDoc_DocumentTool::CheckViewTool(const TDF_Label& theAcces)
+{
+  TDF_Label aLabel = DocLabel(theAcces).FindChild(7, Standard_False);
+  if (aLabel.IsNull())
+  {
+    return Standard_False;
+  }
+  return aLabel.IsAttribute(XCAFDoc_ViewTool::GetID());
+}
+
 //=======================================================================
 //function : ClippingPlaneTool
 //purpose  : 
@@ -322,15 +417,42 @@ Handle(XCAFDoc_ClippingPlaneTool) XCAFDoc_DocumentTool::ClippingPlaneTool(const
 }
 
 //=======================================================================
-//function : ClippingPlaneTool
-//purpose  : 
+//function : CheckClippingPlaneTool
+//purpose  :
 //=======================================================================
+Standard_Boolean XCAFDoc_DocumentTool::CheckClippingPlaneTool(const TDF_Label& theAcces)
+{
+  TDF_Label aLabel = DocLabel(theAcces).FindChild(8, Standard_False);
+  if (aLabel.IsNull())
+  {
+    return Standard_False;
+  }
+  return aLabel.IsAttribute(XCAFDoc_ClippingPlaneTool::GetID());
+}
 
+//=======================================================================
+//function : NotesTool
+//purpose  :
+//=======================================================================
 Handle(XCAFDoc_NotesTool) XCAFDoc_DocumentTool::NotesTool(const TDF_Label& acces)
 {
   return XCAFDoc_NotesTool::Set(NotesLabel(acces));
 }
 
+//=======================================================================
+//function : CheckNotesTool
+//purpose  :
+//=======================================================================
+Standard_Boolean XCAFDoc_DocumentTool::CheckNotesTool(const TDF_Label& theAcces)
+{
+  TDF_Label aLabel = DocLabel(theAcces).FindChild(9, Standard_False);
+  if (aLabel.IsNull())
+  {
+    return Standard_False;
+  }
+  return aLabel.IsAttribute(XCAFDoc_NotesTool::GetID());
+}
+
 //=======================================================================
 //function : GetLengthUnit
 //purpose  :
index ac9fe2b110be785034fab77e6124d4da86750d31..cc9551364c9035750b88c52492f12657809c54be 100644 (file)
@@ -96,32 +96,68 @@ public:
 
   //! Creates (if it does not exist) ShapeTool attribute on ShapesLabel().
   Standard_EXPORT static Handle(XCAFDoc_ShapeTool) ShapeTool (const TDF_Label& acces);
+
+  //! Checks for the ShapeTool attribute on the label's document
+  //! Returns TRUE if Tool exists, ELSE if it has not been created
+  Standard_EXPORT static Standard_Boolean CheckShapeTool(const TDF_Label& theAcces);
   
   //! Creates (if it does not exist) ColorTool attribute on ColorsLabel().
   Standard_EXPORT static Handle(XCAFDoc_ColorTool) ColorTool (const TDF_Label& acces);
 
+  //! Checks for the ColorTool attribute on the label's document
+  //! Returns TRUE if Tool exists, ELSE if it has not been created
+  Standard_EXPORT static Standard_Boolean CheckColorTool(const TDF_Label& theAcces);
+
   //! Creates (if it does not exist) XCAFDoc_VisMaterialTool attribute on VisMaterialLabel().
   //! Should not be confused with MaterialTool() defining physical/manufacturing materials.
   Standard_EXPORT static Handle(XCAFDoc_VisMaterialTool) VisMaterialTool (const TDF_Label& theLabel);
 
+  //! Checks for the VisMaterialTool attribute on the label's document
+  //! Returns TRUE if Tool exists, ELSE if it has not been created
+  Standard_EXPORT static Standard_Boolean CheckVisMaterialTool(const TDF_Label& theAcces);
+
   //! Creates (if it does not exist) LayerTool attribute on LayersLabel().
   Standard_EXPORT static Handle(XCAFDoc_LayerTool) LayerTool (const TDF_Label& acces);
   
+  //! Checks for the LayerTool attribute on the label's document
+  //! Returns TRUE if Tool exists, ELSE if it has not been created
+  Standard_EXPORT static Standard_Boolean CheckLayerTool(const TDF_Label& theAcces);
+
   //! Creates (if it does not exist) DimTolTool attribute on DGTsLabel().
   Standard_EXPORT static Handle(XCAFDoc_DimTolTool) DimTolTool (const TDF_Label& acces);
+
+  //! Checks for the DimTolTool attribute on the label's document
+  //! Returns TRUE if Tool exists, ELSE if it has not been created
+  Standard_EXPORT static Standard_Boolean CheckDimTolTool(const TDF_Label& theAcces);
   
   //! Creates (if it does not exist) DimTolTool attribute on DGTsLabel().
   Standard_EXPORT static Handle(XCAFDoc_MaterialTool) MaterialTool (const TDF_Label& acces);
 
+  //! Checks for the MaterialTool attribute on the label's document
+  //! Returns TRUE if Tool exists, ELSE if it has not been created
+  Standard_EXPORT static Standard_Boolean CheckMaterialTool(const TDF_Label& theAcces);
+
   //! Creates (if it does not exist) ViewTool attribute on ViewsLabel().
   Standard_EXPORT static Handle(XCAFDoc_ViewTool) ViewTool(const TDF_Label& acces);
+
+  //! Checks for the ViewTool attribute on the label's document
+  //! Returns TRUE if Tool exists, ELSE if it has not been created
+  Standard_EXPORT static Standard_Boolean CheckViewTool(const TDF_Label& theAcces);
   
   //! Creates (if it does not exist) ClippingPlaneTool attribute on ClippingPlanesLabel().
   Standard_EXPORT static Handle(XCAFDoc_ClippingPlaneTool) ClippingPlaneTool(const TDF_Label& acces);
 
+  //! Checks for the ClippingPlaneTool attribute on the label's document
+  //! Returns TRUE if Tool exists, ELSE if it has not been created
+  Standard_EXPORT static Standard_Boolean CheckClippingPlaneTool(const TDF_Label& theAcces);
+
   //! Creates (if it does not exist) NotesTool attribute on NotesLabel().
   Standard_EXPORT static Handle(XCAFDoc_NotesTool) NotesTool(const TDF_Label& acces);
 
+  //! Checks for the NotesTool attribute on the label's document
+  //! Returns TRUE if Tool exists, ELSE if it has not been created
+  Standard_EXPORT static Standard_Boolean CheckNotesTool(const TDF_Label& theAcces);
+
   //! Returns value of current internal unit for the document
   //! converted to base unit type.
   Standard_EXPORT static Standard_Boolean GetLengthUnit(const Handle(TDocStd_Document)& theDoc,
index 37f07e0f2764c5e4802f304ee20be56ac0d942db..dd92a88cfe2ef0592a7006ddb34572978e993eaa 100644 (file)
 // commercial license or contractual agreement.
 
 #include <XCAFDoc_Editor.hxx>
-#include <XCAFDoc.hxx>
-
-#include <TDF_Label.hxx>
-#include <TDF_LabelSequence.hxx>
-#include <TDF_ChildIterator.hxx>
-#include <TDataStd_Name.hxx>
-#include <TDataStd_UAttribute.hxx>
-#include <TopLoc_Location.hxx>
-#include <TopoDS_Shape.hxx>
 
-#include <XCAFDoc_DocumentTool.hxx>
+#include <BRep_Builder.hxx>
+#include <XCAFDoc.hxx>
 #include <XCAFDoc_ColorTool.hxx>
+#include <XCAFDoc_DocumentTool.hxx>
+#include <XCAFDoc_GraphNode.hxx>
+#include <XCAFDoc_Location.hxx>
 #include <XCAFDoc_LayerTool.hxx>
-#include <XCAFDoc_ShapeTool.hxx>
+#include <XCAFDoc_MaterialTool.hxx>
 #include <XCAFDoc_ShapeMapTool.hxx>
-#include <XCAFDoc_Location.hxx>
+#include <XCAFDoc_ShapeTool.hxx>
+#include <XCAFDoc_VisMaterial.hxx>
+#include <XCAFDoc_VisMaterialTool.hxx>
+#include <TDF_AttributeIterator.hxx>
+#include <TDF_ChildIterator.hxx>
+#include <TDF_RelocationTable.hxx>
+#include <TDF_Tool.hxx>
+#include <TDataStd_TreeNode.hxx>
+#include <TopLoc_Location.hxx>
+#include <TopoDS_Compound.hxx>
 #include <TNaming_NamedShape.hxx>
 
 //=======================================================================
 //function : Expand
 //purpose  : Convert Shape to assembly
 //=======================================================================
-
-Standard_Boolean XCAFDoc_Editor::Expand (const TDF_Label& Doc, const TDF_Label& Shape,
-  const Standard_Boolean recursively)
+Standard_Boolean XCAFDoc_Editor::Expand (const TDF_Label& theDoc,
+                                         const TDF_Label& theShape,
+                                         const Standard_Boolean theRecursively)
 {
-  if(Doc.IsNull() || Shape.IsNull())
+  if (theDoc.IsNull() || theShape.IsNull())
+  {
     return Standard_False;
-
-  Handle(XCAFDoc_ColorTool) aColorTool = XCAFDoc_DocumentTool::ColorTool(Doc);
-  Handle(XCAFDoc_LayerTool) aLayerTool = XCAFDoc_DocumentTool::LayerTool(Doc);
-  Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(Doc);
+  }
+  Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(theDoc);
   Standard_Boolean isAutoNaming = aShapeTool->AutoNaming();
   aShapeTool->SetAutoNaming(Standard_False);
 
-  TDF_Label aCompoundPartL = Shape;
-  if (aShapeTool->IsReference(Shape))
+  TDF_Label aCompoundPartL = theShape;
+  if (aShapeTool->IsReference(theShape))
     aShapeTool->GetReferredShape(aCompoundPartL, aCompoundPartL);
 
   TopoDS_Shape aS = aShapeTool->GetShape(aCompoundPartL);
   if (aShapeTool->Expand(aCompoundPartL))
   {
     //move attributes
-    TDF_ChildIterator anIter(aCompoundPartL, Standard_True);
-    for(; anIter.More(); anIter.Next())
+    for(TDF_ChildIterator aPartIter(aCompoundPartL, Standard_True);
+      aPartIter.More(); aPartIter.Next())
     {
-      TDF_Label aChild = anIter.Value();
-      TDF_LabelSequence aLayers;
-      TDF_LabelSequence aColors;
-      Handle(TDataStd_Name) aName;
-      getParams(Doc, aChild, aColors, aLayers, aName);
+      TDF_Label aChild = aPartIter.Value();
       //get part
       TDF_Label aPart;
       if(aShapeTool->GetReferredShape(aChild, aPart))
       {
-        setParams(Doc, aPart, aColors, aLayers, aName);
+        CloneMetaData(aChild, aPart, NULL);
         //remove unnecessary links
         TopoDS_Shape aShape = aShapeTool->GetShape(aChild);
         if(!aShapeTool->GetShape(aPart.Father()).IsNull())
         {
-          TopLoc_Location nulloc;
           aPart.ForgetAttribute(XCAFDoc::ShapeRefGUID());
           if (aShapeTool->GetShape(aPart.Father()).ShapeType() == TopAbs_COMPOUND)
           {
@@ -93,31 +91,30 @@ Standard_Boolean XCAFDoc_Editor::Expand (const TDF_Label& Doc, const TDF_Label&
         TDF_LabelSequence aUsers;
         if (aShapeTool->GetUsers(aChild, aUsers) > 0)
         {
-          for (Standard_Integer i = 1; i <= aUsers.Length(); i++)
+          for (TDF_LabelSequence::Iterator anIter(aUsers);
+            anIter.More(); anIter.Next())
           {
-            TDF_Label aSubLabel = aUsers.Value(i);
+            TDF_Label aSubLabel = anIter.Value();
             //remove unnecessary links
             aSubLabel.ForgetAttribute(XCAFDoc::ShapeRefGUID());
             aSubLabel.ForgetAttribute(XCAFDoc_ShapeMapTool::GetID());
-            setParams(Doc, aSubLabel, aColors, aLayers, aName);
+            CloneMetaData(aChild, aSubLabel, NULL);
           }
           aChild.ForgetAllAttributes(Standard_False);
         }
       }
     }
-    //if assembly contains compound, expand it recursively(if flag recursively is true)
-    if(recursively)
+    //if assembly contains compound, expand it recursively(if flag theRecursively is true)
+    if(theRecursively)
     {
-      anIter.Initialize(aCompoundPartL);
-      for(; anIter.More(); anIter.Next())
+      for(TDF_ChildIterator aPartIter(aCompoundPartL); aPartIter.More(); aPartIter.Next())
       {
-        TDF_Label aChild = anIter.Value();
-        TDF_Label aPart;
-        if(aShapeTool->GetReferredShape(aChild, aPart))
+        TDF_Label aPart = aPartIter.Value();
+        if(aShapeTool->GetReferredShape(aPart, aPart))
         {
           TopoDS_Shape aPartShape = aShapeTool->GetShape(aPart);
           if (!aPartShape.IsNull() && aPartShape.ShapeType() == TopAbs_COMPOUND)
-            Expand(Doc, aPart, recursively);
+            Expand(theDoc, aPart, theRecursively);
         }
       }
     }
@@ -132,108 +129,357 @@ Standard_Boolean XCAFDoc_Editor::Expand (const TDF_Label& Doc, const TDF_Label&
 //function : Expand
 //purpose  : Convert all compounds in Doc to assembly
 //=======================================================================
-
-Standard_Boolean XCAFDoc_Editor::Expand (const TDF_Label& Doc, const Standard_Boolean recursively)
+Standard_Boolean XCAFDoc_Editor::Expand (const TDF_Label& theDoc,
+                                         const Standard_Boolean theRecursively)
 {
-  Standard_Boolean result = Standard_False;
+  if (theDoc.IsNull())
+  {
+    return Standard_False;
+  }
+  Standard_Boolean aResult = Standard_False;
   TDF_LabelSequence aLabels;
-  Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(Doc);
+  Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(theDoc);
   aShapeTool->GetFreeShapes(aLabels);
-  for(Standard_Integer i = 1; i <= aLabels.Length(); i++)
+  for(TDF_LabelSequence::Iterator anIter(aLabels); anIter.More(); anIter.Next())
   {
-    TopoDS_Shape aS = aShapeTool->GetShape(aLabels(i));
-    if (!aS.IsNull() && aS.ShapeType() == TopAbs_COMPOUND && !aShapeTool->IsAssembly(aLabels(i)))
-      if (Expand(Doc, aLabels(i), recursively))
+    const TDF_Label aLabel = anIter.Value();
+    const TopoDS_Shape aS = aShapeTool->GetShape(aLabel);
+    if (!aS.IsNull() && aS.ShapeType() == TopAbs_COMPOUND && !aShapeTool->IsAssembly(aLabel))
+    {
+      if (Expand(theDoc, aLabel, theRecursively))
       {
-        result = Standard_True;
+        aResult = Standard_True;
       }
+    }
   }
-  return result;
+  return aResult;
 }
 
 //=======================================================================
-//function : getParams
-//purpose  : Get colors layers and name
+//function : Extract
+//purpose  :
 //=======================================================================
-
-Standard_Boolean XCAFDoc_Editor::getParams (const TDF_Label& Doc, const TDF_Label& Label,
-                                            TDF_LabelSequence& Colors, TDF_LabelSequence& Layers,
-                                            Handle(TDataStd_Name)& Name)
+Standard_Boolean XCAFDoc_Editor::Extract(const TDF_LabelSequence& theSrcLabels,
+                                         const TDF_Label& theDstLabel,
+                                         const Standard_Boolean theIsNoVisMat)
 {
-  if(Doc.IsNull() || Label.IsNull())
+  if (theDstLabel.IsNull())
+  {
     return Standard_False;
+  }
 
-  Handle(XCAFDoc_ColorTool) aColorTool = XCAFDoc_DocumentTool::ColorTool(Doc);
-  Handle(XCAFDoc_LayerTool) aLayerTool = XCAFDoc_DocumentTool::LayerTool(Doc);
-
-  //get colors
-  XCAFDoc_ColorType aTypeColor = XCAFDoc_ColorGen;
-  for(;;)
+  Handle(XCAFDoc_ShapeTool) aDstShapeTool = XCAFDoc_DocumentTool::ShapeTool(theDstLabel);
+  NCollection_DataMap<Handle(XCAFDoc_VisMaterial), Handle(XCAFDoc_VisMaterial)> aVisMatMap;
+  for (TDF_LabelSequence::Iterator aNewRootIter(theSrcLabels);
+    aNewRootIter.More(); aNewRootIter.Next())
   {
-    TDF_Label aColor;
-    aColorTool->GetColor(Label, aTypeColor, aColor);
-    Colors.Append(aColor);
-    if(aTypeColor == XCAFDoc_ColorCurv)
-      break;
-    aTypeColor = (XCAFDoc_ColorType)(aTypeColor + 1);
+    // Shape
+    TopLoc_Location aLoc;
+    TDF_LabelDataMap aMap;
+    const TDF_Label aSrcLabel = aNewRootIter.Value();
+    Handle(XCAFDoc_ShapeTool) aSrcShapeTool = XCAFDoc_DocumentTool::ShapeTool(aSrcLabel);
+    Handle(XCAFDoc_Location) aLocationAttr;
+    if (aSrcLabel.FindAttribute(XCAFDoc_Location::GetID(), aLocationAttr))
+    {
+      aLoc = aLocationAttr->Get();
+    }
+    TDF_Label aCompLabel = aSrcLabel;
+    aSrcShapeTool->GetReferredShape(aSrcLabel, aCompLabel);
+    TDF_Label aResLabel = CloneShapeLabel(aCompLabel, aSrcShapeTool, aDstShapeTool, aMap);
+    TDF_Label aNewCompLabel = aDstShapeTool->AddComponent(theDstLabel, aResLabel, aLoc);
+    if (aNewCompLabel.IsNull())
+    {
+      TopoDS_Shape aNewShape = aDstShapeTool->GetShape(aResLabel);
+      aNewShape.Move(aLoc);
+      aNewCompLabel = aDstShapeTool->AddShape(aNewShape, false);
+    }
+    aMap.Bind(aSrcLabel, aNewCompLabel);
+    aMap.Bind(aCompLabel, aResLabel);
+    aDstShapeTool->UpdateAssemblies();
+    // Attributes
+    for (TDF_LabelDataMap::Iterator aLabelIter(aMap); aLabelIter.More(); aLabelIter.Next())
+    {
+      CloneMetaData(aLabelIter.Key(), aLabelIter.Value(), &aVisMatMap, true, true, true, !theIsNoVisMat);
+    }
   }
-
-  //get layers
-  aLayerTool->GetLayers(Label, Layers);
-
-  //get name
-  Label.FindAttribute(TDataStd_Name::GetID(), Name);
   return Standard_True;
 }
 
 //=======================================================================
-//function : setParams
-//purpose  : set colors layers and name
+//function : Extract
+//purpose  :
 //=======================================================================
+Standard_Boolean XCAFDoc_Editor::Extract(const TDF_Label& theSrcLabel,
+                                         const TDF_Label& theDstLabel,
+                                         const Standard_Boolean theIsNoVisMat)
+{
+  TDF_LabelSequence aSeq;
+  aSeq.Append(theSrcLabel);
+  return Extract(aSeq, theDstLabel, theIsNoVisMat);
+}
 
-Standard_Boolean XCAFDoc_Editor::setParams (const TDF_Label& Doc, const TDF_Label& Label,
-                                            const TDF_LabelSequence& Colors, const TDF_LabelSequence& Layers,
-                                            const Handle(TDataStd_Name)& Name)
+// =======================================================================
+// function : CloneShapeLebel
+// purpose  :
+// =======================================================================
+TDF_Label XCAFDoc_Editor::CloneShapeLabel(const TDF_Label& theSrcLabel,
+                                          const Handle(XCAFDoc_ShapeTool)& theSrcShapeTool,
+                                          const Handle(XCAFDoc_ShapeTool)& theDstShapeTool,
+                                          TDF_LabelDataMap& theMap)
 {
-  if(Doc.IsNull() || Label.IsNull())
-    return Standard_False;
+  TDF_Label aNewShL;
+  if (theMap.Find(theSrcLabel, aNewShL))
+  {
+    return aNewShL;
+  }
 
-  Handle(XCAFDoc_ColorTool) aColorTool = XCAFDoc_DocumentTool::ColorTool(Doc);
-  Handle(XCAFDoc_LayerTool) aLayerTool = XCAFDoc_DocumentTool::LayerTool(Doc);
-  Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(Doc);
+  // Location for main assembly
+  if (theSrcShapeTool->IsAssembly(theSrcLabel))
+  {
+    // add assembly and iterate all its components
+    TopoDS_Compound aComp;
+    BRep_Builder().MakeCompound(aComp);
+    aNewShL = theDstShapeTool->AddShape(aComp);
+    theMap.Bind(theSrcLabel, aNewShL);
 
-  //set layers
-  if(!Layers.IsEmpty())
+    TDF_LabelSequence aComponents;
+    theSrcShapeTool->GetComponents(theSrcLabel, aComponents);
+    for (TDF_LabelSequence::Iterator aCompIter(aComponents); aCompIter.More(); aCompIter.Next())
+    {
+      TDF_Label aCompL = aCompIter.Value();
+      TDF_Label aRefL;
+      theSrcShapeTool->GetReferredShape(aCompL, aRefL);
+      TDF_Label aCompOriginalL = CloneShapeLabel(aRefL, theSrcShapeTool, theDstShapeTool, theMap);
+      Handle(XCAFDoc_Location) aLocationAttr;
+      aCompL.FindAttribute(XCAFDoc_Location::GetID(), aLocationAttr);
+      TDF_Label aNewCompL = theDstShapeTool->AddComponent(aNewShL, aCompOriginalL, aLocationAttr->Get());
+      theMap.Bind(aCompIter.Value(), aNewCompL);
+    }
+    return aNewShL;
+  }
+
+  // add part
+  TopoDS_Shape aShape = theSrcShapeTool->GetShape(theSrcLabel);
+  aNewShL = theDstShapeTool->AddShape(aShape, false);
+  theMap.Bind(theSrcLabel, aNewShL);
+
+  // get original instead of auxiliary instance
+  TDF_Label anOldOriginalL = theSrcLabel;
+  if (theSrcShapeTool->IsReference(theSrcLabel))
+  {
+    theSrcShapeTool->GetReferredShape(theSrcLabel, anOldOriginalL);
+    theDstShapeTool->GetReferredShape(aNewShL, aNewShL);
+    theMap.Bind(anOldOriginalL, aNewShL);
+  }
+  // copy subshapes
+  TDF_LabelSequence anOldSubShapes;
+  theSrcShapeTool->GetSubShapes(anOldOriginalL, anOldSubShapes);
+  for (TDF_LabelSequence::Iterator aSubIter(anOldSubShapes); aSubIter.More(); aSubIter.Next())
+  {
+    TopoDS_Shape aSubShape = theSrcShapeTool->GetShape(aSubIter.Value());
+    TDF_Label aNewSubShapeL = theDstShapeTool->AddSubShape(aNewShL, aSubShape);
+    theMap.Bind(aSubIter.Value(), aNewSubShapeL);
+  }
+  return aNewShL;
+}
+
+//=======================================================================
+//function : CloneMetaData
+//purpose  :
+//=======================================================================
+void XCAFDoc_Editor::CloneMetaData(const TDF_Label& theSrcLabel,
+  const TDF_Label& theDstLabel,
+  NCollection_DataMap<Handle(XCAFDoc_VisMaterial), Handle(XCAFDoc_VisMaterial)>* theVisMatMap,
+  const Standard_Boolean theToCopyColor,
+  const Standard_Boolean theToCopyLayer,
+  const Standard_Boolean theToCopyMaterial,
+  const Standard_Boolean theToCopyVisMaterial,
+  const Standard_Boolean theToCopyAttribute)
+{
+  if (theSrcLabel == theDstLabel || theSrcLabel.IsNull() || theDstLabel.IsNull())
   {
-    for(Standard_Integer i = 1; i <= Layers.Length(); i++)
+    return;
+  }
+  const Standard_Boolean toCopyColor = theToCopyColor & XCAFDoc_DocumentTool::CheckColorTool(theSrcLabel);
+  const Standard_Boolean toCopyLayer = theToCopyLayer & XCAFDoc_DocumentTool::CheckLayerTool(theSrcLabel);
+  const Standard_Boolean toCopyMaterial = theToCopyMaterial & XCAFDoc_DocumentTool::CheckMaterialTool(theSrcLabel);
+  const Standard_Boolean toCopyVisMaterial = XCAFDoc_DocumentTool::CheckVisMaterialTool(theSrcLabel);
+  // Colors
+  if (toCopyColor)
+  {
+    Handle(XCAFDoc_ColorTool) aSrcColorTool = XCAFDoc_DocumentTool::ColorTool(theSrcLabel);
+    Handle(XCAFDoc_ColorTool) aDstColorTool = XCAFDoc_DocumentTool::ColorTool(theDstLabel);
+    const XCAFDoc_ColorType aTypes[] = { XCAFDoc_ColorGen , XCAFDoc_ColorSurf , XCAFDoc_ColorCurv };
+    for (int anInd = 0; anInd < 3; anInd++)
+    {
+      TDF_Label aColorL;
+      aSrcColorTool->GetColor(theSrcLabel, aTypes[anInd], aColorL);
+      if (!aColorL.IsNull())
+      {
+        Quantity_ColorRGBA aColor;
+        aSrcColorTool->GetColor(aColorL, aColor);
+        aDstColorTool->SetColor(theDstLabel, aColor, aTypes[anInd]);
+      }
+    }
+    aDstColorTool->SetVisibility(theDstLabel, aSrcColorTool->IsVisible(theSrcLabel));
+  }
+  // Layers
+  if (toCopyLayer)
+  {
+    Handle(XCAFDoc_LayerTool) aSrcLayerTool = XCAFDoc_DocumentTool::LayerTool(theSrcLabel);
+    Handle(XCAFDoc_LayerTool) aDstLayerTool = XCAFDoc_DocumentTool::LayerTool(theDstLabel);
+    TDF_LabelSequence aLayers;
+    aSrcLayerTool->GetLayers(theSrcLabel, aLayers);
+    for (TDF_LabelSequence::Iterator aLayerIter(aLayers); aLayerIter.More(); aLayerIter.Next())
     {
-      aLayerTool->SetLayer(Label, Layers.Value(i));
+      TCollection_ExtendedString aLayerName;
+      aSrcLayerTool->GetLayer(aLayerIter.Value(), aLayerName);
+      aDstLayerTool->SetLayer(theDstLabel, aLayerName);
+    }
+  }
+  // Materials
+  if (toCopyMaterial)
+  {
+    Handle(TDataStd_TreeNode) aMatNode;
+    if (theSrcLabel.FindAttribute(XCAFDoc::MaterialRefGUID(), aMatNode) && aMatNode->HasFather())
+    {
+      TDF_Label aMaterialL = aMatNode->Father()->Label();
+      if (!aMaterialL.IsNull())
+      {
+        Handle(XCAFDoc_MaterialTool) aSrcMaterialTool = XCAFDoc_DocumentTool::MaterialTool(theSrcLabel);
+        Handle(XCAFDoc_MaterialTool) aDstMaterialTool = XCAFDoc_DocumentTool::MaterialTool(theDstLabel);
+        double aDensity = 0.0;
+        Handle(TCollection_HAsciiString) aName, aDescription, aDensName, aDensValType;
+        if (aSrcMaterialTool->GetMaterial(aMaterialL, aName, aDescription, aDensity, aDensName, aDensValType)
+          && !aName.IsNull()
+          && aName->Length() != 0)
+        {
+          aDstMaterialTool->SetMaterial(theDstLabel, aName, aDescription, aDensity, aDensName, aDensValType);
+        }
+      }
+    }
+  }
+  // Visual Materials
+  if (toCopyVisMaterial && (theToCopyVisMaterial || toCopyColor))
+  {
+    Handle(XCAFDoc_VisMaterialTool) aSrcVisMatTool = XCAFDoc_DocumentTool::VisMaterialTool(theSrcLabel);
+    TDF_Label aVisMaterialL;
+    aSrcVisMatTool->GetShapeMaterial(theSrcLabel, aVisMaterialL);
+    if (!aVisMaterialL.IsNull())
+    {
+      Handle(XCAFDoc_VisMaterialTool) aDstVisMatTool;
+      Handle(XCAFDoc_ColorTool) aDstColorTool;
+      if (theToCopyVisMaterial)
+      {
+        aDstVisMatTool = XCAFDoc_DocumentTool::VisMaterialTool(theDstLabel);
+      }
+      else
+      {
+        aDstColorTool = XCAFDoc_DocumentTool::ColorTool(theDstLabel);
+      }
+      Handle(XCAFDoc_VisMaterial) aVisMatSrc = aSrcVisMatTool->GetMaterial(aVisMaterialL);
+      if(theToCopyVisMaterial)
+      {
+        Handle(XCAFDoc_VisMaterial) aVisMatDst;
+        if (theVisMatMap != NULL)
+        {
+          if (!theVisMatMap->Find(aVisMatSrc, aVisMatDst))
+          {
+            aVisMatDst = new XCAFDoc_VisMaterial();
+            aVisMatDst->SetCommonMaterial(aVisMatSrc->CommonMaterial());
+            aVisMatDst->SetPbrMaterial(aVisMatSrc->PbrMaterial());
+            aVisMatDst->SetAlphaMode(aVisMatSrc->AlphaMode(), aVisMatSrc->AlphaCutOff());
+            aVisMatDst->SetFaceCulling(aVisMatSrc->FaceCulling());
+            TCollection_AsciiString aName;
+            Handle(TDataStd_Name) aNodeName;
+            if (aVisMatSrc->Label().FindAttribute(TDataStd_Name::GetID(), aNodeName))
+            {
+              aName = aNodeName->Get();
+            }
+            aDstVisMatTool->AddMaterial(aVisMatDst, aName);
+            theVisMatMap->Bind(aVisMatSrc, aVisMatDst);
+          }
+        }
+        else
+        {
+          aVisMatDst = aVisMatSrc; // consider the same document
+        }
+        aDstVisMatTool->SetShapeMaterial(theDstLabel, aVisMatDst->Label());
+      }
+      else
+      {
+        aDstColorTool->SetColor(theDstLabel, aVisMatSrc->BaseColor(), XCAFDoc_ColorGen);
+      }
     }
   }
-  //set colors
-  if(!Colors.IsEmpty())
+  // Other attributes
+  if (theToCopyAttribute)
   {
-    XCAFDoc_ColorType aTypeColor = XCAFDoc_ColorGen;
-    for(Standard_Integer i = 1; i <= Colors.Length(); i++)
+    // Finds the target attributes or creates them empty
+    for (TDF_AttributeIterator anAttIter(theSrcLabel); anAttIter.More(); anAttIter.Next())
     {
-      if(!Colors.Value(i).IsNull())
-        aColorTool->SetColor(Label, Colors.Value(i), aTypeColor);
-      aTypeColor = (XCAFDoc_ColorType)(aTypeColor + 1);
+      const Handle(TDF_Attribute) anAttSrc = anAttIter.Value();
+      // protect against color and layer coping without link to colors and layers
+      if (const TDataStd_TreeNode* aTreeNode = dynamic_cast<const TDataStd_TreeNode*> (anAttSrc.get()))
+      {
+        (void)aTreeNode;
+        continue;
+      }
+      else if (const XCAFDoc_GraphNode* aGraphNode = dynamic_cast<const XCAFDoc_GraphNode*> (anAttSrc.get()))
+      {
+        (void)aGraphNode;
+        continue;
+      }
+      else if (const TNaming_NamedShape* aShapeAttr = dynamic_cast<const TNaming_NamedShape*> (anAttSrc.get()))
+      {
+        (void)aShapeAttr;
+        continue;
+      }
+      else if (const XCAFDoc_ShapeMapTool* aShMapTool = dynamic_cast<const XCAFDoc_ShapeMapTool*> (anAttSrc.get()))
+      {
+        (void)aShMapTool;
+        continue;
+      }
+      else if (const XCAFDoc_Location* aLocAttr = dynamic_cast<const XCAFDoc_Location*> (anAttSrc.get()))
+      {
+        (void)aLocAttr;
+        continue;
+      }
+      Handle(TDF_Attribute) anAttDst;
+      if (!theDstLabel.FindAttribute(anAttSrc->ID(), anAttDst))
+      {
+        anAttDst = anAttSrc->NewEmpty();
+        theDstLabel.AddAttribute(anAttDst);
+      }
+      Handle(TDF_RelocationTable) aRT = new TDF_RelocationTable();
+      anAttSrc->Paste(anAttDst, aRT);
     }
   }
-  //set name
-  if(!Name.IsNull())
+  // Name
+  Handle(TDataStd_Name) aNameAttr;
+  theSrcLabel.FindAttribute(TDataStd_Name::GetID(), aNameAttr);
+  Handle(XCAFDoc_ShapeTool) aDstShapeTool = XCAFDoc_DocumentTool::ShapeTool(theDstLabel);
+  if (!aNameAttr.IsNull())
   {
-    if(Name->Get().Search("=>") < 0)
-      TDataStd_Name::Set(Label, Name->Get());
+    TDF_Label aRefLabel;
+    if (aNameAttr->Get().Search("=>") < 0)
+    {
+      TDataStd_Name::Set(theDstLabel, aNameAttr->Get());
+    }
+    else if (aDstShapeTool->GetReferredShape(theDstLabel, aRefLabel))
+    {
+      TCollection_AsciiString aRefName;
+      TDF_Tool::Entry(aRefLabel, aRefName);
+      aRefName.Insert(1, "=>");
+      TDataStd_Name::Set(theDstLabel, aRefName);
+    }
   }
   else
   {
     Standard_SStream Stream;
-    TopoDS_Shape aShape = aShapeTool->GetShape(Label);
+    TopoDS_Shape aShape = aDstShapeTool->GetShape(theDstLabel);
     TopAbs::Print(aShape.ShapeType(), Stream);
-    TCollection_AsciiString aName (Stream.str().c_str());
-    TDataStd_Name::Set(Label, TCollection_ExtendedString(aName));
+    TCollection_AsciiString aName(Stream.str().c_str());
+    TDataStd_Name::Set(theDstLabel, TCollection_ExtendedString(aName));
   }
-  return Standard_True;
-}
\ No newline at end of file
+}
index 2f9c78df2c01e8ce389855fa26e559d39cc19ef8..89ac8ac7cf0c92a3f097f6cf59efcd50aaa49c55 100644 (file)
 #ifndef _XCAFDoc_Editor_HeaderFile
 #define _XCAFDoc_Editor_HeaderFile
 
-#include <Standard.hxx>
 #include <Standard_DefineAlloc.hxx>
-#include <Standard_Macro.hxx>
-
-#include <Standard_Boolean.hxx>
 #include <TDataStd_Name.hxx>
+#include <TDF_AttributeMap.hxx>
 #include <TDF_Label.hxx>
+#include <TDF_LabelDataMap.hxx>
 #include <TDF_LabelSequence.hxx>
 
-
+class XCAFDoc_VisMaterial;
+class XCAFDoc_ShapeTool;
 
 //! Tool for edit structure of document.
-class XCAFDoc_Editor 
+class XCAFDoc_Editor
 {
 public:
 
   DEFINE_STANDARD_ALLOC
 
-  
-  //! Convert Shape (compound/compsolid/shell/wire) to assembly.
-  //! Only compounds expanded recursively
-  Standard_EXPORT static   Standard_Boolean Expand (const TDF_Label& Doc, const TDF_Label& Shape, const Standard_Boolean recursively = Standard_True) ;
-  
-  //! Convert all compounds in Doc to assembly
-  Standard_EXPORT static   Standard_Boolean Expand (const TDF_Label& Doc, const Standard_Boolean recursively = Standard_True) ;
-
-
-
-
-protected:
-
-
-
-
-
-private:
-
-  
-  //! Get colors, layers and name from Label
-  Standard_EXPORT static   Standard_Boolean getParams (const TDF_Label& Doc, const TDF_Label& Label, TDF_LabelSequence& Colors, TDF_LabelSequence& Layers, Handle(TDataStd_Name)& Name) ;
-  
-  //! Set colors, layers and name from Label
-  Standard_EXPORT static   Standard_Boolean setParams (const TDF_Label& Doc, const TDF_Label& Label, const TDF_LabelSequence& Colors, const TDF_LabelSequence& Layers, const Handle(TDataStd_Name)& Name) ;
-
-
-
+  //! Converts shape (compound/compsolid/shell/wire) to assembly.
+  //! @param[in] theDoc input document
+  //! @param[in] theShape input shape label
+  //! @param[in] theRecursively recursively expand a compound subshape
+  //! @return True if shape successfully expanded
+  Standard_EXPORT static Standard_Boolean Expand(const TDF_Label& theDoc,
+                                                 const TDF_Label& theShape,
+                                                 const Standard_Boolean theRecursively = Standard_True);
+
+  //! Converts all compounds shapes in the document to assembly
+  //! @param[in] theDoc input document
+  //! @param[in] theShape input shape label
+  //! @param[in] theRecursively recursively expand a compound subshape
+  //! @return True if shape successfully expanded
+  Standard_EXPORT static Standard_Boolean Expand(const TDF_Label& theDoc,
+                                                 const Standard_Boolean theRecursively = Standard_True);
+
+  //! Clones all labels to a new position, keeping the structure with all the attributes
+  //! @param[in] theSrcLabels original labels to copy from
+  //! @param[in] theDstLabel label to set result as a component of or a main document's label to simply set new shape
+  //! @param[in] theIsNoVisMat get a VisMaterial attributes as is or convert to color
+  //! @return True if shape successfully extracted
+  Standard_EXPORT static Standard_Boolean Extract(const TDF_LabelSequence& theSrcLabels,
+                                                  const TDF_Label& theDstLabel,
+                                                  const Standard_Boolean theIsNoVisMat = Standard_False);
+
+  //! Clones the label to a new position, keeping the structure with all the attributes
+  //! @param[in] theSrcLabel original label to copy from
+  //! @param[in] theDstLabel label to set result as a component of or a main document's label to simply set new shape
+  //! @param[in] theIsNoVisMat get a VisMaterial attributes as is or convert to color
+  //! @return True if shape successfully extracted
+  Standard_EXPORT static Standard_Boolean Extract(const TDF_Label& theSrcLabel,
+                                                  const TDF_Label& theDstLabel,
+                                                  const Standard_Boolean theIsNoVisMat = Standard_False);
+
+  //! Copies shapes label with keeping of shape structure (recursively)
+  //! @param[in] theSrcLabel original label to copy from
+  //! @param[in] theSrcShapeTool shape tool to get
+  //! @param[in] theDstShapeTool shape tool to set
+  //! @param[out] theMap relating map of the original shapes label and labels created from them
+  //! @return result shape label
+  Standard_EXPORT static TDF_Label CloneShapeLabel(const TDF_Label& theSrcLabel,
+                                                   const Handle(XCAFDoc_ShapeTool)& theSrcShapeTool,
+                                                   const Handle(XCAFDoc_ShapeTool)& theDstShapeTool,
+                                                   TDF_LabelDataMap& theMap);
+
+  //! Copies metadata contains from the source label to the destination label.
+  //! Protected against creating a new label for non-existent tools
+  //! @param[in] theSrcLabel original label to copy from
+  //! @param[in] theDstLabel destination shape label to set attributes
+  //! @param[in] theVisMatMap relating map of the original VisMaterial and created. Can be NULL for the same document
+  //! @param[in] theToCopyColor copying visible value and shape color (handled all color type)
+  //! @param[in] theToCopyLayer copying layer
+  //! @param[in] theToCopyMaterial copying  material
+  //! @param[in] theToCopyVisMaterial copying visual material
+  //! @param[in] theToCopyAttributes copying of other node attributes, for example, a shape's property
+  Standard_EXPORT static void CloneMetaData(const TDF_Label& theSrcLabel,
+                                            const TDF_Label& theDstLabel,
+                                            NCollection_DataMap<Handle(XCAFDoc_VisMaterial), Handle(XCAFDoc_VisMaterial)>* theVisMatMap,
+                                            const Standard_Boolean theToCopyColor = Standard_True,
+                                            const Standard_Boolean theToCopyLayer = Standard_True,
+                                            const Standard_Boolean theToCopyMaterial = Standard_True,
+                                            const Standard_Boolean theToCopyVisMaterial = Standard_True,
+                                            const Standard_Boolean theToCopyAttributes = Standard_True);
 
 };
 
-
-
-
-
-
-
 #endif // _XCAFDoc_Editor_HeaderFile
index 55a900499a1fa6766c7e28b2b9492498bd82ddc8..a0697110e3e4f6d83c73e203995c00e68178cdb2 100644 (file)
@@ -579,6 +579,10 @@ static Standard_Integer WriteStep (Draw_Interpretor& di, Standard_Integer argc,
   return 0;
 }
 
+//=======================================================================
+//function : Expand
+//purpose  :
+//=======================================================================
 static Standard_Integer Expand (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
 {
   if (argc < 3) {
@@ -626,6 +630,68 @@ static Standard_Integer Expand (Draw_Interpretor& di, Standard_Integer argc, con
   return 0;
 }
 
+//=======================================================================
+//function : Extract
+//purpose  :
+//=======================================================================
+static Standard_Integer Extract(Draw_Interpretor& di,
+                                Standard_Integer argc,
+                                const char** argv)
+{
+  if (argc < 4)
+  {
+    di << "Use: " << argv[0] << "dstDoc [dstAssmblSh] srcDoc srcLabel1 srcLabel2 ...\n";
+    return 1;
+  }
+
+  Handle(TDocStd_Document) aSrcDoc, aDstDoc;
+  DDocStd::GetDocument(argv[1], aDstDoc);
+  if (aDstDoc.IsNull())
+  {
+    di << "Error " << argv[1] << " is not a document\n";
+    return 1;
+  }
+  TDF_Label aDstLabel;
+  Standard_Integer anArgInd = 3;
+  TDF_Tool::Label(aDstDoc->GetData(), argv[2], aDstLabel);
+  Handle(XCAFDoc_ShapeTool) aDstShapeTool = XCAFDoc_DocumentTool::ShapeTool(aDstDoc->Main());
+  if (aDstLabel.IsNull())
+  {
+    aDstLabel = aDstShapeTool->Label();
+    anArgInd = 2; // to get Src Doc
+  }
+  DDocStd::GetDocument(argv[anArgInd++], aSrcDoc);
+  if (aSrcDoc.IsNull())
+  {
+    di << "Error " << argv[anArgInd] << " is not a document\n";
+    return 1;
+  }
+
+  TDF_LabelSequence aSrcShapes;
+  for (; anArgInd < argc; anArgInd++)
+  {
+    TDF_Label aSrcLabel;
+    TDF_Tool::Label(aSrcDoc->GetData(), argv[anArgInd], aSrcLabel);
+    if (aSrcLabel.IsNull())
+    {
+      di << "[" << argv[anArgInd] << "] is not valid Src label\n";
+      return 1;
+    }
+    aSrcShapes.Append(aSrcLabel);
+  }
+  if (aSrcShapes.IsEmpty())
+  {
+    di << "Error: No Shapes to extract\n";
+    return 1;
+  }
+
+  if (!XCAFDoc_Editor::Extract(aSrcShapes, aDstLabel))
+  {
+    di << "Error: Cannot extract labels\n";
+    return 1;
+  }
+  return 0;
+}
 
 //=======================================================================
 //function : WriteVrml
@@ -695,6 +761,9 @@ void XDEDRAW_Common::InitCommands(Draw_Interpretor& di)
 
   di.Add("XExpand", "XExpand Doc recursively(0/1) or XExpand Doc recursively(0/1) label1 label2 ..."  
           "or XExpand Doc recursively(0/1) shape1 shape2 ...",__FILE__, Expand, g);
+  di.Add("XExtract", "XExtract dstDoc [dstAssmblSh] srcDoc srcLabel1 srcLabel2 ...\t"
+    "Extracts given srcLabel1 srcLabel2 ... from srcDoc into given Doc or assembly shape",
+    __FILE__, Extract, g);
 
   di.Add("WriteVrml", "Doc filename [version VRML#1.0/VRML#2.0 (1/2): 2 by default] [representation shaded/wireframe/both (0/1/2): 0 by default]", __FILE__, WriteVrml, g);
 
diff --git a/tests/bugs/xde/bug28104 b/tests/bugs/xde/bug28104
new file mode 100644 (file)
index 0000000..fc1d423
--- /dev/null
@@ -0,0 +1,154 @@
+puts "============================================================================"
+puts "0028104: Data Exchange - Extract sub-assembly (XDE)"
+puts "============================================================================"
+puts ""
+
+pload DCAF
+
+Close D0 -silent
+Close D1 -silent
+Close D2 -silent
+Close D3 -silent
+Close D4 -silent
+Close D5 -silent
+Close D6 -silent
+
+box b1 0 0 0 10 10 10
+box b2 0 0 0 10 10 10 
+box b3 0 0 0 10 10 10 
+compound b1 b2 b3 c 
+
+XOpen [locate_data_file bug30189.xbf] D0
+
+XNewDoc D2
+XAddShape D2 c
+XNewDoc D3
+XAddShape D3 c
+XNewDoc D4
+XAddShape D4 c
+XNewDoc D5
+XAddShape D5 c
+XNewDoc D6
+XAddShape D6 c
+
+# All copy
+XNewDoc D1
+XExtract D1 D0 0:1:1:1
+# Exctact part
+XExtract D2 D0 0:1:1:3
+# Exctact component
+XExtract D3 D0 0:1:1:2:1
+# Exctact part as a component
+XExtract D4 0:1:1:1 D0 0:1:1:3
+# Exctact compontnt as a component
+XExtract D5 0:1:1:1 D0 0:1:1:2:1
+# Exctact compontnt as a component
+XExtract D6 0:1:1:1 D0 0:1:1:2:1 0:1:1:2:2 0:1:1:2:3 0:1:1:3
+
+# checking labels structure and number of colors and shape
+set err_compare_ref ""
+set statD0 [XStat D0]
+set statD1 [XStat D1]
+set cur_list [split $statD0 \n]
+set ref_list [split $statD1 \n]
+set nb_ref [llength $ref_list]
+set nb_cur [llength $cur_list]
+set ref_Compare 0
+set isNextLayer 0; set isNextColor 0
+for { set i 0 } { $i < $nb_cur } { incr i } {
+  set refstr [lindex $ref_list $i]
+  set curstr [lindex $cur_list $i]
+  set isOK 1
+  if {[regexp "Number of colors" $refstr]} {
+    set isNextColor 1
+  } elseif {[regexp "Number of layers" $refstr]} {
+    set isNextLayer 1
+  } elseif {$isNextLayer || $isNextColor} {
+    set refProp [split $refstr " "]
+  set curProp [split $curstr " "]
+  if {[llength $refProp] != [llength $curProp]} {
+    set isOK 0
+  } else {
+    for { set j 0 } { $j < [llength $refProp] && $isOK} { incr j } {
+      set isFind 0
+      for { set k 0 } { $k < [llength $refProp] && $isOK} { incr k } {
+        if {[lindex $refProp  $j] == [lindex $curProp  $k]} {
+          set isFind 1
+        break
+        }
+      }
+      set isOK $isFind
+    }
+  }
+  set isNextLayer 0;  set isNextColor 0
+  } elseif {$refstr != $curstr} {
+    set isOK 0
+  }
+  if {!$isOK} {
+    incr ref_Compare
+  append err_compare_ref " Reference data - $refstr\n"
+  append err_compare_ref " Current data   - $curstr\n"
+  append err_compare_ref "----------------------------------------------\n"
+  }
+}
+
+if { $ref_Compare > 0} {
+  puts "Error : $ref_Compare differences with reference data found :\n$err_compare_ref"
+} else {
+  puts "Comparison of current result with reference data - OK\n"
+}
+
+XGetOneShape res0 D0
+XGetOneShape res1 D1
+compare res0 res1
+
+set propsD2 [XCheckProps D2]
+if { ![regexp "0:1:1:5  +\"nut" $propsD2] } {
+  puts "Error: Incorrectly extracted shapes from D0 0:1:1:3 to D2"
+}
+if { ![regexp "RED" [XGetAllColors D2]] } {
+  puts "Error: Incorrectly extracted attributes from D0 0:1:1:3 to D2"
+}
+
+set propsD3 [XCheckProps D3]
+if { ![regexp "0:1:1:5  +\"nut" $propsD3] && ![regexp "0:1:1:6  +\"nut_1" $propsD3] } {
+  puts "Error: Incorrectly extracted shapes from D0 0:1:1:2:1 to D3"
+}
+if { ![regexp "RED" [XGetAllColors D3]] } {
+  puts "Error: Incorrectly extracted attributes from D0 0:1:1:2:1 to D3"
+}
+
+set dumpD4 [Xdump D4]
+if { ![regexp "PART SOLID 0:1:1:5  +\"nut" $dumpD4] && ![regexp "refers to 0:1:1:5" $dumpD4] } {
+  puts "Error: Incorrectly extracted shapes from D0 0:1:1:3 to D4 0:1:1:1"
+}
+if { ![regexp "RED" [XGetAllColors D4]] } {
+  puts "Error: Incorrectly extracted attributes from D0 0:1:1:3 to D4 0:1:1:1"
+}
+
+set dumpD5 [Xdump D5]
+if { ![regexp "PART SOLID 0:1:1:5 \"nut" $dumpD5] && ![regexp "refers to 0:1:1:5')' \"nut_1" $dumpD5] } {
+  puts "Error: Incorrectly extracted shapes from D0 0:1:1:2:1 to D5 0:1:1:1"
+}
+if { ![regexp "RED" [XGetAllColors D5]] } {
+  puts "Error: Incorrect XExtract D0 0:1:1:2:1 D5 0:1:1:1"
+}
+
+set dumpD6 [Xdump D6]
+if { ![regexp "nut_1" $dumpD6] && ![regexp "nut_2" $dumpD6] && ![regexp "rod_1'" $dumpD6] && ![regexp "refers to 0:1:1:5" $dumpD6]} {
+  puts "Error: Incorrectly extracted shapes from D0 0:1:1:2:1 0:1:1:2:2 0:1:1:2:3 0:1:1:3 to D6 0:1:1:1"
+}
+set colorD6 [XGetAllColors D6]
+if { ![regexp "RED" $colorD6] && ![regexp "DARKGOLDENROD1" $colorD6]} {
+  puts "Error: Incorrectly extracted attributes from D0 0:1:1:2:1 0:1:1:2:2 0:1:1:2:3 0:1:1:3 to D6 0:1:1:1"
+}
+
+checkprops res0 -equal res1
+
+Close D0 -silent
+Close D1 -silent
+Close D2 -silent
+Close D3 -silent
+Close D4 -silent
+Close D5 -silent
+Close D6 -silent
diff --git a/tests/bugs/xde/bug28104_1 b/tests/bugs/xde/bug28104_1
new file mode 100644 (file)
index 0000000..b6f5247
--- /dev/null
@@ -0,0 +1,81 @@
+puts "============================================================================"
+puts "0028104: Data Exchange - Extract sub-assembly (XDE)"
+puts "============================================================================"
+puts ""
+
+pload DCAF
+
+Close D0 -silent
+Close D1 -silent
+
+# Reading step file
+ReadStep D0 [locate_data_file as1-oc-214-mat.stp]
+
+# All copy
+XNewDoc D1
+XExtract D1 D0 0:1:1:1
+
+# checking Props, labels structure and number of colors and shape
+set err_compare_ref ""
+set statD0 [XStat D0]
+set statD1 [XStat D1]
+set cur_list [split $statD0 \n]
+set ref_list [split $statD1 \n]
+set nb_ref [llength $ref_list]
+set nb_cur [llength $cur_list]
+set ref_Compare 0
+set isNextLayer 0; set isNextColor 0
+for { set i 0 } { $i < $nb_cur } { incr i } {
+  set refstr [lindex $ref_list $i]
+  set curstr [lindex $cur_list $i]
+  set isOK 1
+  if {[regexp "Number of colors" $refstr]} {
+    set isNextColor 1
+  } elseif {[regexp "Number of layers" $refstr]} {
+    set isNextLayer 1
+  } elseif {$isNextLayer || $isNextColor} {
+    set refProp [split $refstr " "]
+  set curProp [split $curstr " "]
+  if {[llength $refProp] != [llength $curProp]} {
+    set isOK 0
+  } else {
+    for { set j 0 } { $j < [llength $refProp] && $isOK} { incr j } {
+      set isFind 0
+      for { set k 0 } { $k < [llength $refProp] && $isOK} { incr k } {
+        if {[lindex $refProp  $j] == [lindex $curProp  $k]} {
+          set isFind 1
+        break
+        }
+      }
+      set isOK $isFind
+    }
+  }
+  set isNextLayer 0;  set isNextColor 0
+  } elseif {$refstr != $curstr} {
+    set isOK 0
+  }
+  if {!$isOK} {
+    incr ref_Compare
+  append err_compare_ref " Reference data - $refstr\n"
+  append err_compare_ref " Current data   - $curstr\n"
+  append err_compare_ref "----------------------------------------------\n"
+  }
+}
+
+if { $ref_Compare > 0} {
+  puts "Error : $ref_Compare differences with reference data found :\n$err_compare_ref"
+} else {
+  puts "Comparison of current result with reference data - OK\n"
+}
+
+XGetOneShape res0 D0
+XGetOneShape res1 D1
+set propsD0 [XCheckProps D0]
+set propsD1 [XCheckProps D1]
+if { $propsD0 != $propsD1 } {
+  puts "Error: Incorrect extraction of shape properties"
+}
+checkprops res0 -equal res1
+
+Close D0 -silent
+Close D1 -silent