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)