
Mon, 03/31/2025 - 08:50
Hi.
When making a sphere and coloring it, and then performing transformations (such as translation), the color will be lost.
I have written a complete and executable minimal example program to reproduce this problem:
#include <TDocStd_Document.hxx>
#include <STEPCAFControl_Writer.hxx>
#include <Interface_Static.hxx>
#include <TDocStd_Application.hxx>
#include <XCAFApp_Application.hxx>
#include <TCollection_ExtendedString.hxx>
#include <XCAFDoc_DocumentTool.hxx>
#include <XCAFDoc_ShapeTool.hxx>
#include <XCAFDoc_ColorTool.hxx>
#include <gp_Pnt.hxx>
#include <BRepPrimAPI_MakeSphere.hxx>
#include <TopoDS_Shape.hxx>
#include <BRepBuilderAPI_Transform.hxx>
#include <TDataStd_Name.hxx>
#include <Quantity_Color.hxx>
#include <filesystem> // compile using C++17 or higher standard
bool write_step_with_color(const Handle(TDocStd_Document)& doc, std::filesystem::path file_name) {
STEPCAFControl_Writer step_writer;
Interface_Static::SetIVal("write.stepcaf.subshapes.name", 1);
if (!step_writer.Transfer(doc, STEPControl_AsIs)) { return false; }
if (
IFSelect_ReturnStatus ret = step_writer.Write(file_name.string().c_str());
ret != IFSelect_RetDone
) {
return false;
}
return true;
}
int main(const int argc, const char** argv) {
Handle(TDocStd_Document) doc;
Handle(TDocStd_Application) app = XCAFApp_Application::GetApplication();
app->NewDocument(TCollection_ExtendedString("BinXCAF"), doc);
Handle(XCAFDoc_ShapeTool) shape_tool = XCAFDoc_DocumentTool::ShapeTool(doc->Main());
Handle(XCAFDoc_ColorTool) color_tool = XCAFDoc_DocumentTool::ColorTool(doc->Main());
// shape1
const TopoDS_Shape shape1 = BRepPrimAPI_MakeSphere(gp_Pnt(-30.0, 0.0, 0.0), 1.0);
TDF_Label label1 = shape_tool->AddShape(shape1);
TDataStd_Name::Set(label1, TCollection_ExtendedString("shape1"));
color_tool->SetColor(label1, Quantity_Color(1.0, 0.5, 0.5, Quantity_TOC_RGB), XCAFDoc_ColorGen);
// shape2
const TopoDS_Shape shape2 = BRepPrimAPI_MakeSphere(gp_Pnt(0.0, 0.0, 0.0), 3.0);
TDF_Label label2 = shape_tool->AddShape(shape2);
TDataStd_Name::Set(label2, TCollection_ExtendedString("shape2"));
color_tool->SetColor(label2, Quantity_Color(0.0, 0.5, 0.5, Quantity_TOC_RGB), XCAFDoc_ColorGen);
gp_Trsf trsf;
trsf.SetTranslation(gp_Vec(30.0, 0.0, 0.0));
BRepBuilderAPI_Transform shape_transformer = BRepBuilderAPI_Transform(shape2, trsf, Standard_False);
shape_tool->SetShape(label2, shape_transformer);
// shape3
{
// shape3-1
const TopoDS_Shape shape31 = BRepPrimAPI_MakeSphere(gp_Pnt(-20.0, 0.0, 0.0), 5.0);
TDF_Label label31 = shape_tool->AddShape(shape31);
TDataStd_Name::Set(label31, TCollection_ExtendedString("shape3-1"));
color_tool->SetColor(label31, Quantity_Color(1.0, 0.5, 0.5, Quantity_TOC_RGB), XCAFDoc_ColorGen);
// shape3-2
const TopoDS_Shape shape32 = BRepPrimAPI_MakeSphere(gp_Pnt(0.0, 0.0, 0.0), 7.0);
TDF_Label label32 = shape_tool->AddShape(shape32);
TDataStd_Name::Set(label32, TCollection_ExtendedString("shape3-2"));
color_tool->SetColor(label32, Quantity_Color(0.0, 0.5, 0.5, Quantity_TOC_RGB), XCAFDoc_ColorGen);
// if the transformation operation and SetShape are removed, everything will be normal
gp_Trsf trsf;
trsf.SetTranslation(gp_Vec(20.0, 0.0, 0.0));
BRepBuilderAPI_Transform shape_transformer = BRepBuilderAPI_Transform(shape32, trsf, Standard_False);
shape_tool->SetShape(label32, shape_transformer);
TopoDS_Compound shape3;
BRep_Builder builder;
builder.MakeCompound(shape3);
builder.Add(shape3, shape31);
builder.Add(shape3, shape32);
TDF_Label label3 = shape_tool->AddShape(shape3);
TDataStd_Name::Set(label3, TCollection_ExtendedString("shape3"));
}
auto step_file_name = std::filesystem::path(argv[1]);
write_step_with_color(doc, step_file_name);
return 0;
}
I just want to use some of the basic shapes provided by OCCT (such as spheres, rectangles) and some basic transformations (such as translation, rotation, scaling) to assemble more complex shapes. As seen in the above code, in FreeCAD, shape1
and shape2
can be displayed normally, but the name of shape3-2
in shape3
has changed to "SOLID
", losing color, and worse, the translation operation has failed.
If the transformation operation and SetShape are removed, everything will be normal. So, how can I balance shape transformation, coloring, and MakeCompound
.
I have carefully studied the relevant documents provided by the official, but still cannot find any errors. Please give me some guidance and express my blessings in advance.
Wed, 04/02/2025 - 06:00
Oh, although I don't know why the code above went wrong, I have found another solution:
Mon, 03/31/2025 - 12:53
The reason of modification - when you call BRepAPI you modify geometry of your Shape but not shape inside document. Need to use the XCAFDoc_Editor to modify transformations of the shape nodes or apply transformation as an attirbute.
Tue, 04/01/2025 - 06:39
Thank you very much for your patient reply.
If I understand correctly, "apply transformation as an attribute" means to use
Location()
to modify themyLocation
private member variable ofTopoDS_Shape
. However, I find the disadvantage of this method. SinceTopoDS_Shape
can only use move construction or reference, I can't copy the same geometry in aTDocStd_Document
: imagine a scene where spheres are arranged in a column. They are just different in color andmyLocation
, and the data of the geometry is identical. If I create them one by one, it is good, but there is a lot of data redundancy. A good approach for such scenarios is to create only one set of geometric data (forTopoDS_Shape
, it should refer to its private member variableHandle(TopoDS_TShape) myTShape
), and then create instances with different colors andmyLocation
according to the actual situation, which reference the same set of geometric data.I tried the
Extract
method provided byXCAFDoc_Editor
and indeed copied a copy of the data, but my modification ofmyLocation
inTopoDS_Shape
doesn't seem to work. Here is some of my code: