
Mon, 04/28/2025 - 19:30
Hello,
I'm trying to load a step file, print its structure and show each componet / solids name and depth in the structure tree, along with the RGB value of any solids.
https://unlimited3d.wordpress.com/2022/09/09/colored-step-model-in-occt-...
Using this turorial which explaines things well. This tutorial shows they can print names for compounds and shapes.
I can use an XCAFPrs_DocumentExplorer to get CAF components as nodes, and print the structure tree but it only shows the nodes which are TopAbs_COMPOUNDS. I can then access the sub shapes, which are the TopAbs_SOLIDS, and retrieve the RGB values of these using a ShapeTool and ColourTool, but I can't get the name os TopAbs_SOLIDS via the attribute access.
I can see the solid names in the STEP file, "#89=MANIFOLD_SOLID_BREP('sphere_black',#166);".
Some other posts suggest similar issues, and that they had to use alternate methods (https://dev.opencascade.org/content/how-get-manifoldsolidbrep-entity-nam...). But i've not had much luck accessing the solids this way as I get segfaults.
Could anyone see what I'm doing wrong, or suggest altername methods, please? I'm using Open Cascade 7.8 on Rocky Linux 8.6.
Thanks in advance
#include <iostream>
#include <string>
#include <vector>
#include <OSD.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Compound.hxx>
#include <BRep_Builder.hxx>
#include <BRepAlgoAPI_Algo.hxx>
#include <BRepAlgoAPI_Cut.hxx>
#include <BRepAlgoAPI_Common.hxx>
#include <BOPAlgo_Splitter.hxx>
#include <BRepPrimAPI_MakeHalfSpace.hxx>
#include <STEPCAFControl_Controller.hxx>
#include <STEPCAFControl_Reader.hxx>
#include <STEPCAFControl_Writer.hxx>
#include <TDocStd_Document.hxx>
#include <XCAFApp_Application.hxx>
#include <XCAFPrs_DocumentExplorer.hxx>
#include <XCAFDoc_DocumentTool.hxx>
#include <XCAFDoc_ShapeTool.hxx>
#include <XCAFDoc_ColorTool.hxx>
#include <XCAFDoc_ColorType.hxx>
#include <XCAFPrs.hxx>
#include <XCAFPrs_AISObject.hxx>
#include <BinXCAFDrivers.hxx>
#include <TDataStd_Name.hxx>
#include <TopExp_Explorer.hxx>
#include <TDataStd_Name.hxx>
#include <Interface_EntityIterator.hxx>
#include <StepData_StepModel.hxx>
bool loadStepFile(std::string fileName, Handle(TDocStd_Document) doc) {
// set up bool flag to return
bool fileRead, fileTransfered;
// initialise step caf controller
STEPCAFControl_Controller::Init();
// set up the step file reader
STEPCAFControl_Reader stepReader;
stepReader.SetColorMode(true);
stepReader.SetNameMode(true);
stepReader.SetMatMode(true);
stepReader.SetGDTMode(true);
stepReader.SetLayerMode(true);
stepReader.SetPropsMode(true);
stepReader.SetSHUOMode(true);
stepReader.SetViewMode(true);
// IFSelect_ReturnStatus readFileStatus = ;
if (stepReader.ReadFile(fileName.c_str()) == IFSelect_RetDone){
std::cout << "[OK] file loaded" << std::endl;
fileRead = true;
}
else{
std::cout << "[ERROR] file failed to load" << std::endl;
fileRead = false;
}
// transfer model to document
if (stepReader.Transfer(doc)) {
std::cout << "[OK] model transfered to documnet" << std::endl;
fileTransfered = true;
}
else{
std::cout << "[ERROR] model transfer failed" << std::endl;
fileTransfered = false;
}
return true;
}
TCollection_AsciiString shapeTypeAsString(TopoDS_Shape shape) {
if (shape.ShapeType() == TopAbs_COMPOUND) {
// std::cout << "shape type = TopAbs_COMPOUND" << std::endl;
return " (TopAbs_COMPOUND)";
}
else if (shape.ShapeType() == TopAbs_SOLID) {
return " (TopAbs_SOLID)";
}
else {
// std::cout << "shape type nor TopAbs_COMPOUND or TopAbs_SOLID" << std::endl;
return " (not TopAbs_COMPOUND or TopAbs_SOLID)";
}
}
std::vector<int> getColour(TopoDS_Shape shape, TDF_Label label, Handle(XCAFDoc_ColorTool) colourTool) {
Quantity_ColorRGBA colourSurf;
Quantity_ColorRGBA colourGen;
Quantity_ColorRGBA colourCurv;
bool hasColourSurf = colourTool->GetColor(label, XCAFDoc_ColorSurf, colourSurf);
bool hasColourGen = colourTool->GetColor(label, XCAFDoc_ColorSurf, colourGen);
bool hasColourCurv = colourTool->GetColor(label, XCAFDoc_ColorSurf, colourCurv);
std::vector<int> coloursRGB = {-1, -1, -1};
double red, green, blue;
if (!hasColourSurf && !hasColourGen && !hasColourCurv) {
// use default colours -1, -1, -1
}
else if (hasColourSurf) {
// std::cout << "surf" << std::endl;
colourSurf.GetRGB().Values(red, green, blue, Quantity_TOC_sRGB);
}
else if (hasColourGen) {
// std::cout << "gen" << std::endl;
colourGen.GetRGB().Values(red, green, blue, Quantity_TOC_sRGB);
}
else if (hasColourCurv) {
// std::cout << "curv" << std::endl;
colourSurf.GetRGB().Values(red, green, blue, Quantity_TOC_sRGB);
}
int redInt = static_cast<int>(Round(red * 255));
int greenInt = static_cast<int>(Round(green * 255));
int blueInt = static_cast<int>(Round(blue * 255));
coloursRGB = {redInt, greenInt, blueInt};
return coloursRGB;
}
void printStructure(Handle(TDocStd_Document) doc, Handle(XCAFDoc_ShapeTool) shapeTool, Handle(XCAFDoc_ColorTool) colourTool) {
for (XCAFPrs_DocumentExplorer docExplorer (doc, XCAFPrs_DocumentExplorerFlags_None); docExplorer.More(); docExplorer.Next()) {
// get the current node
const XCAFPrs_DocumentNode& node = docExplorer.Current();
// get shape
TopoDS_Shape nodeShape = XCAFPrs_DocumentExplorer::FindShapeFromPathId(doc, node.Id);
// get node shape type
TCollection_AsciiString nodeTypeString = shapeTypeAsString(nodeShape);
// case for compound found
if (nodeShape.ShapeType() == TopAbs_COMPOUND) {
// get node name and location in tree
TCollection_AsciiString nameWithDepth ((docExplorer.CurrentDepth()), '-');
// get name in structure
Handle(TDataStd_Name) nodeName;
if (node.RefLabel.FindAttribute (TDataStd_Name::GetID(), nodeName) || node.Label.FindAttribute (TDataStd_Name::GetID(), nodeName))
{
nameWithDepth += nodeName->Get();
}
nameWithDepth += nodeTypeString;
std::cout << nameWithDepth << " [id: " << node.Id << "]" << std::endl;
// get list of sub shapes in compound
TDF_LabelSequence subShapeLabels;
if (shapeTool->GetSubShapes(node.RefLabel, subShapeLabels) || shapeTool->GetSubShapes(node.Label, subShapeLabels)) {
for (Standard_Integer i = 1; i <= subShapeLabels.Length(); ++i) {
// get the label of the sub shape
TDF_Label subShapeLabel = subShapeLabels.Value(i);
// get the shape of the sub shape
TopoDS_Shape subShape = shapeTool->GetShape(subShapeLabel);
// get node shape type
TCollection_AsciiString subShapeTypeAsString = shapeTypeAsString(subShape);
// check if subshape label is a referred label
TDF_Label subShapeRefferedLabel;
if (XCAFDoc_ShapeTool::GetReferredShape(subShapeLabel, subShapeRefferedLabel)) {
subShapeLabel = subShapeRefferedLabel;
}
// get sub shape name and location in tree
TCollection_AsciiString subShapeNameWithDepth ((docExplorer.CurrentDepth() + 1), '-');
// get name in structure
Handle(TDataStd_Name) subShapeName;
if (subShapeLabel.FindAttribute (TDataStd_Name::GetID(), subShapeName) || subShapeLabel.FindAttribute (TDataStd_Name::GetID(), subShapeName))
{
subShapeNameWithDepth += subShapeName->Get();
}
else {
subShapeNameWithDepth += "name_not_found";
}
subShapeNameWithDepth += subShapeTypeAsString;
std::vector<int> subShapeColour = getColour(subShape, subShapeLabel, colourTool);
std::cout << subShapeNameWithDepth << "RGB = " << subShapeColour[0] << " " << subShapeColour[1] << " " << subShapeColour[2] << std::endl;
}
}
else{
// std::cout << "no sub shape labels" << std::endl;
}
}
else {
std::cout << "Unknown shape found" << std::endl;
}
}
}
cmake_minimum_required(VERSION 3.16)
# set the project name
project(Structure)
# add include directories for header files
include_directories(include)
# find open cascade package
find_package(OpenCASCADE COMPONENTS FoundationClasses REQUIRED)
find_package(OpenCASCADE COMPONENTS ModelingAlgorithms REQUIRED)
find_package(OpenCASCADE COMPONENTS ModelingData REQUIRED)
find_package(OpenCASCADE COMPONENTS DataExchange REQUIRED)
include_directories(${OpenCASCADE_INCLUDE_DIR})
link_directories(${OpenCASCADE_LIBRARY_DIR})
MESSAGE("================================")
MESSAGE(${OpenCASCADE_LIBRARY_DIR})
add_executable(Structure src/structure.cpp)
target_link_libraries(${PROJECT_NAME} PRIVATE TKBO TKBin TKCAF TKCDF TKMath
TKernel TKGeomAlgo TKTopAlgo TKDESTEP
TKLCAF TKXCAF TKBRep TKPrim TKShHealing
TKGeomBase TKG3d TKG2d TKBinL TKDE
TKXSBase TKVCAF TKV3d TKService
TKMesh TKHLR TKBinXCAF)
Wed, 04/30/2025 - 15:49
I think the STEPCAFControl_Reader will group solids into compounds be default, which can be switched off using the following code. This seems to fix my issues. Could this lead me to other problems, such as slower code or loss of other onformation I'm not yet seeing?