Salome HOME
bos #29482 Export of colors and names to STEP.
[modules/shaper.git] / src / GeomAlgoAPI / GeomAlgoAPI_STEPExport.cpp
index 052a43ed8fae6de02626e8745f652e10f7ec78a9..224840ec50b989f833cfc5dadecd8ac266c5fd1e 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2020  CEA/DEN, EDF R&D
+// Copyright (C) 2014-2022  CEA/DEN, EDF R&D
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 
 #include "GeomAlgoAPI_Tools.h"
 
-#include <TopoDS_Shape.hxx>
+#include <GeomAPI_Shape.h>
+#include <ModelAPI_ResultBody.h>
+#include <ModelAPI_AttributeIntArray.h>
 
-// OOCT includes
-#include <IFSelect_ReturnStatus.hxx>
-#include <STEPControl_Writer.hxx>
+#include <TDocStd_Document.hxx>
+#include <TDataStd_Name.hxx>
+#include <XCAFDoc_DocumentTool.hxx>
+#include <XCAFDoc_ShapeTool.hxx>
+#include <XCAFDoc_ColorTool.hxx>
+#include <STEPCAFControl_Writer.hxx>
 #include <Interface_Static.hxx>
+#include <Quantity_Color.hxx>
 
-bool STEPExport(const std::string& theFileName,
-                const std::string& /*theFormatName*/,
-                const std::shared_ptr<GeomAPI_Shape>& theShape,
-                std::string& theError)
+// a structure to manage step document exported attributes
+struct GeomAlgoAPI_STEPAttributes {
+  bool myHasColor; ///< true if color is defined
+  Quantity_Color myColor;
+  std::wstring myName;
+  Handle(XCAFDoc_ShapeTool) myShapeTool;
+  Handle(XCAFDoc_ColorTool) myColorTool;
+
+  GeomAlgoAPI_STEPAttributes(const TDF_Label& theMain) : myHasColor(false)
+  {
+    myShapeTool = XCAFDoc_DocumentTool::ShapeTool(theMain);
+    myShapeTool->SetAutoNaming(Standard_False);
+    myColorTool = XCAFDoc_DocumentTool::ColorTool(theMain);
+  }
+};
+
+static TDF_Label exportShape(const GeomShapePtr theShape, GeomAlgoAPI_STEPAttributes& theAttrs,
+  const GeomShapePtr theFatherShape, TDF_Label& theFaterID) {
+  TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();
+  TDF_Label aShapeLab;
+  if (!theFaterID.IsNull()) { // make sub-component of father's assembly
+    gp_Trsf aFatherTrsf;
+    if (theFatherShape.get())
+      aFatherTrsf = theFatherShape->implPtr<TopoDS_Shape>()->Location().Transformation();
+    TopLoc_Location aLocation = aFatherTrsf.Inverted() * aShape.Location();
+    static const TopLoc_Location anEmptyLoc;
+    aShape.Location(anEmptyLoc);
+    aShapeLab = theAttrs.myShapeTool->AddShape(aShape, Standard_False);
+    TDF_Label aRetLabel = theAttrs.myShapeTool->AddComponent(theFaterID, aShapeLab, aLocation);
+    if (!aRetLabel.IsNull())
+      aRetLabel.ForgetAttribute(TDataStd_Name::GetID());
+  }
+  else { // make a single shape
+    aShapeLab = theAttrs.myShapeTool->AddShape(aShape, Standard_False);
+    TDF_Label aRefShapeLab;
+    if (theAttrs.myShapeTool->GetReferredShape(aShapeLab, aRefShapeLab))
+      aShapeLab = aRefShapeLab;
+  }
+  TDataStd_Name::Set(aShapeLab, TCollection_ExtendedString(theAttrs.myName.c_str()));
+  if (theAttrs.myHasColor) {
+    TDF_Label aColorLab = theAttrs.myColorTool->AddColor(theAttrs.myColor);
+    theAttrs.myColorTool->SetColor(aShapeLab, aColorLab, XCAFDoc_ColorGen);
+  }
+  return aShapeLab;
+}
+
+/// Returns the attributes of the result: names and color
+static void getAttributes(const ResultPtr& theResult, GeomAlgoAPI_STEPAttributes& theAttrs)
 {
-  #ifdef _DEBUG
-  std::cout << "Export STEP into file " << theFileName << std::endl;
-  #endif
+  theAttrs.myName = theResult->data()->name();
+  AttributeIntArrayPtr aColorAttr = theResult->data()->intArray(ModelAPI_Result::COLOR_ID());
+  if (aColorAttr.get() && aColorAttr->size() > 2) {
+    theAttrs.myHasColor = true;
+    theAttrs.myColor.SetValues(aColorAttr->value(0) / 255., aColorAttr->value(1) / 255.,
+                               aColorAttr->value(2) / 255., Quantity_TOC_RGB);
+  }
+  else
+    theAttrs.myHasColor = false;
+}
 
-  if (!theShape.get()) {
-    theError = "STEP Export failed: An invalid argument";
-    return false;
+/// Performs the whole result export: as an assembly or a single one, but with results attributes.
+static void putResult(const ResultPtr& theResult, const GeomShapePtr theFatherShape,
+  TDF_Label& theFaterID, GeomAlgoAPI_STEPAttributes& theAttrs)
+{
+  GeomShapePtr aShape = theResult->shape();
+  if (!aShape.get() || aShape->isNull())
+    return;
+  ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theResult);
+  if (aBody.get() && aBody->numberOfSubs()) { // make an assembly
+    getAttributes(theResult, theAttrs);
+    TDF_Label aBodyID = exportShape(aShape, theAttrs, theFatherShape, theFaterID);
+    int aNumSubs = aBody->numberOfSubs();
+    for (int a = 0; a < aNumSubs; a++) {
+      ResultBodyPtr aSub = aBody->subResult(a);
+      if (!aSub->isDisabled())
+        putResult(aSub, aShape, aBodyID, theAttrs);
+    }
+  }
+  else { // a simple shape-body
+    getAttributes(theResult, theAttrs);
+    exportShape(aShape, theAttrs, theFatherShape, theFaterID);
   }
+}
 
-  try
-  {
-    // Set "C" numeric locale to save numbers correctly
-    GeomAlgoAPI_Tools::Localizer loc;
+bool STEPExport(const std::string& theFileName,
+                const std::list<std::shared_ptr<GeomAPI_Shape> >& theShapes,
+                const std::list<std::shared_ptr<ModelAPI_Result> >& theResults,
+                std::string& theError)
+{
+  theError = "";
+  // prepare XCAF document to store the whole data structure there
+  Handle(TDocStd_Document) aDoc = new TDocStd_Document("BinXCAF");
+
+  GeomAlgoAPI_STEPAttributes anAttrs(aDoc->Main());
 
-    IFSelect_ReturnStatus status ;
-    //VRV: OCC 4.0 migration
-    STEPControl_Writer aWriter;
-    Interface_Static::SetCVal("xstep.cascade.unit","M");
+  std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator aShape = theShapes.cbegin();
+  std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aResult = theResults.cbegin();
+  for (; aShape != theShapes.cend(); aShape++, aResult++) {
+    TDF_Label aNullLab;
+    if (aResult->get() && !(*aShape)->isSame((*aResult)->shape()))
+    { // simple sub-shape
+      getAttributes(*aResult, anAttrs);
+      exportShape(*aShape, anAttrs, GeomShapePtr(), aNullLab);
+    }
+    else { // whole result selection
+      putResult(*aResult, GeomShapePtr(), aNullLab, anAttrs);
+    }
+  }
+  // store the XCAF document to STEP file
+  try {
+    GeomAlgoAPI_Tools::Localizer aLocalizer; // Set "C" numeric locale to save numbers correctly
+    STEPCAFControl_Writer aWriter;
+    Interface_Static::SetCVal("xstep.cascade.unit", "M");
+    Interface_Static::SetIVal("write.step.nonmanifold", 0); // 1 don't allow to export assemly tree
     Interface_Static::SetCVal("write.step.unit", "M");
-    Interface_Static::SetIVal("write.step.nonmanifold", 1);
-    status = aWriter.Transfer(theShape->impl<TopoDS_Shape>(), STEPControl_AsIs);
-    //VRV: OCC 4.0 migration
-    if( status == IFSelect_RetDone )
-      status = aWriter.Write(theFileName.c_str());
 
-    // Return previous locale
-    if( status == IFSelect_RetDone )
-      return true;
+    auto aStatus = aWriter.Transfer(aDoc, STEPControl_AsIs);
+    if (aStatus == IFSelect_RetDone)
+      aStatus = aWriter.Write(theFileName.c_str());
+    if (aStatus != IFSelect_RetDone)
+      theError = "STEP Export failed";
   }
-  catch (Standard_Failure)
-  {
+  catch (Standard_Failure exception) {
     theError = "Exception catched in STEPExport";
   }
-  return false;
+  return theError.empty();
 }