STEP - custom attributes #627
-
|
Hi, I want to add custom properties to a step file. But none of the attributes are seen in a typical viewer. Code that is able to read a step file, copy the geometry and write to step. #include "compas.h"
#include <nanobind/stl/string.h>
// STEP I/O includes
#include <STEPControl_Reader.hxx>
#include <STEPCAFControl_Writer.hxx>
#include <STEPCAFControl_Reader.hxx>
#include <TopoDS_Shape.hxx>
#include <IFSelect_ReturnStatus.hxx>
// XDE includes for assemblies and attributes
#include <TDocStd_Document.hxx>
#include <XCAFApp_Application.hxx>
#include <XCAFDoc_ShapeTool.hxx>
#include <XCAFDoc_ColorTool.hxx>
#include <XCAFDoc_DocumentTool.hxx>
#include <TDataStd_Name.hxx>
#include <TDataStd_Comment.hxx>
#include <TDataStd_NamedData.hxx>
#include <TDF_Label.hxx>
#include <TDF_LabelSequence.hxx>
// Transformation includes
#include <gp_Trsf.hxx>
#include <gp_Vec.hxx>
#include <BRepBuilderAPI_Transform.hxx>
#include <TopoDS_Compound.hxx>
#include <BRep_Builder.hxx>
// Color includes
#include <Quantity_Color.hxx>
#include <Quantity_NameOfColor.hxx>
// Validation properties
#include <GProp_GProps.hxx>
#include <BRepGProp.hxx>
// Shape exploration
#include <TopExp_Explorer.hxx>
#include <TopAbs_ShapeEnum.hxx>
void assemble(const std::string& input_path, const std::string& output_path) {
// Create XDE document for assembly with attributes
Handle(XCAFApp_Application) app = XCAFApp_Application::GetApplication();
Handle(TDocStd_Document) doc;
app->NewDocument("MDTV-XCAF", doc);
// Get shape and color tools
Handle(XCAFDoc_ShapeTool) shapeTool = XCAFDoc_DocumentTool::ShapeTool(doc->Main());
Handle(XCAFDoc_ColorTool) colorTool = XCAFDoc_DocumentTool::ColorTool(doc->Main());
// Read original STEP file
STEPControl_Reader reader;
IFSelect_ReturnStatus status = reader.ReadFile(input_path.c_str());
if (status != IFSelect_RetDone) return;
reader.TransferRoots();
TopoDS_Shape original = reader.Shape(1);
if (original.IsNull()) return;
// No assembly compound - use individual components only to avoid duplicates
// Define positions and properties for 4 components with ingredient names
double positions[4][3] = {{0, 0, 0}, {10, 0, 0}, {0, 10, 0}, {10, 10, 0}};
std::string ingredientNames[4] = {"Carrot", "Pepper", "Onion", "Celery"};
Quantity_NameOfColor colors[4] = {Quantity_NOC_ORANGE, Quantity_NOC_RED, Quantity_NOC_PURPLE, Quantity_NOC_GREEN};
std::vector<TopoDS_Shape> transformedShapes;
// Add the original shape as a reference shape (to be reused)
TDF_Label originalShapeLabel = shapeTool->AddShape(original, Standard_False);
// Create main assembly with a compound to ensure it has geometry
TopoDS_Compound assemblyCompound;
BRep_Builder builder;
builder.MakeCompound(assemblyCompound);
// Create assembly label and add the compound
TDF_Label assemblyLabel = shapeTool->AddShape(assemblyCompound, Standard_True);
TDataStd_Name::Set(assemblyLabel, "Chicken Soup Assembly");
TDataStd_Comment::Set(assemblyLabel, "COMPAS OCCT Example by Petras Vestartas - 19-07-2025");
// Create transformed instances and add them as assembly components with properties
std::vector<TDF_Label> componentLabels;
for (int i = 0; i < 4; i++) {
gp_Trsf transform; // Create transformation for this instance
transform.SetTranslation(gp_Vec(positions[i][0], positions[i][1], positions[i][2]));
// Create transformed shape and add to compound
BRepBuilderAPI_Transform transformer(original, transform);
TopoDS_Shape transformed = transformer.Shape();
builder.Add(assemblyCompound, transformed);
transformedShapes.push_back(transformed);
// Add component with transformation
TDF_Label componentLabel = shapeTool->AddComponent(assemblyLabel, originalShapeLabel, transform);
componentLabels.push_back(componentLabel);
// Set ingredient name for each component
std::string componentName = ingredientNames[i] + " - Soup Ingredient";
TDataStd_Name::Set(componentLabel, componentName.c_str());
// Add custom properties using TDataStd_NamedData (OCCT 7.9+ custom property sets)
Handle(TDataStd_NamedData) namedData = TDataStd_NamedData::Set(componentLabel);
// Set ingredient properties as key-value pairs
namedData->SetString("ingredient_type", ingredientNames[i].c_str());
namedData->SetString("category", "soup_ingredient");
namedData->SetString("freshness", "fresh");
namedData->SetString("origin", "local_market");
namedData->SetReal("position_x", positions[i][0]);
namedData->SetReal("position_y", positions[i][1]);
namedData->SetReal("position_z", positions[i][2]);
namedData->SetInteger("ingredient_id", i + 1);
namedData->SetString("recipe", "chicken_soup_classic");
// Also add as comment for guaranteed STEP export compatibility
std::string fallbackComment = "Type: " + ingredientNames[i] + ", Category: soup_ingredient, Fresh: Yes, Origin: local_market, Recipe: chicken_soup_classic";
// Add cooking-specific properties
if (ingredientNames[i] == "Carrot") {
namedData->SetString("cooking_time", "15_minutes");
namedData->SetString("preparation", "diced");
fallbackComment += ", Cooking: 15min diced";
} else if (ingredientNames[i] == "Pepper") {
namedData->SetString("cooking_time", "5_minutes");
namedData->SetString("preparation", "ground");
fallbackComment += ", Cooking: 5min ground";
} else if (ingredientNames[i] == "Onion") {
namedData->SetString("cooking_time", "10_minutes");
namedData->SetString("preparation", "chopped");
fallbackComment += ", Cooking: 10min chopped";
} else if (ingredientNames[i] == "Celery") {
namedData->SetString("cooking_time", "12_minutes");
namedData->SetString("preparation", "sliced");
fallbackComment += ", Cooking: 12min sliced";
}
// Set the fallback comment for guaranteed STEP export
TDataStd_Comment::Set(componentLabel, fallbackComment.c_str());
// Assign color to the component
Quantity_Color color(colors[i]);
colorTool->SetColor(componentLabel, color, XCAFDoc_ColorSurf);
}
// Write STEP file with XDE (preserves assembly structure and attributes)
STEPCAFControl_Writer writer;
writer.SetColorMode(Standard_True); // Export colors
writer.SetNameMode(Standard_True); // Export names
if (writer.Transfer(doc, STEPControl_AsIs)) {
writer.Write(output_path.c_str());
}
}
NB_MODULE(_step, m) {
m.doc() = "STEP file I/O functions";
m.def("assemble", &assemble, "Read STEP file, create assembly with 4 translated copies including attributes (names, colors, validation properties)", "input_path"_a, "output_path"_a);
} |
Beta Was this translation helpful? Give feedback.
Answered by
dpasukhi
Jul 19, 2025
Replies: 1 comment 13 replies
-
|
Export of metadata is not supported by current version of OCCT. That is not possible at the moment. |
Beta Was this translation helpful? Give feedback.
13 replies
Answer selected by
dpasukhi
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment

Export of metadata is not supported by current version of OCCT. That is not possible at the moment.