@bitbybit-dev/occt
Version:
Bit By Bit Developers CAD algorithms using OpenCascade Technology kernel. Run in Node and in Browser.
760 lines (759 loc) • 32.2 kB
JavaScript
export class OCCTIOAssembly {
constructor(occ, och) {
this.occ = occ;
this.och = och;
// Add a property to cache color assignments
this.colorAssignments = new Map();
}
parseComponentWithXCAF(shape, label, shapeTool, colorTool, name, level) {
const id = this.generateId();
const isAssembly = this.occ.XCAFDoc_ShapeTool.IsAssembly(label);
const component = {
id,
name: this.extractNameFromLabel(label) || name || `${isAssembly ? "Assembly" : "Part"}_${id}`,
type: isAssembly ? "assembly" : "part",
shape: shape,
children: [],
transformation: this.extractTransformation(shape),
properties: this.extractProperties(shape),
attributes: this.extractAttributesFromXCAF(label),
color: this.extractColorFromXCAF(shape, label, colorTool),
pmi: this.extractPMI(shape)
};
if (isAssembly) {
component.children = this.extractChildrenWithXCAF(label, shapeTool, colorTool, level + 1);
}
return component;
}
extractChildrenWithXCAF(assemblyLabel, shapeTool, colorTool, level) {
const children = [];
// Get components of the assembly
const components = new this.occ.TDF_LabelSequence_1();
this.occ.XCAFDoc_ShapeTool.GetComponents(assemblyLabel, components, false);
for (let i = 1; i <= components.Length(); i++) {
const componentLabel = components.Value(i);
// Get the referenced shape
const referredLabel = new this.occ.TDF_Label();
if (this.occ.XCAFDoc_ShapeTool.GetReferredShape(componentLabel, referredLabel)) {
const componentShape = new this.occ.TopoDS_Shape();
if (this.occ.XCAFDoc_ShapeTool.GetShape_1(referredLabel, componentShape)) {
// Get the location/transformation for this component instance
const location = this.occ.XCAFDoc_ShapeTool.GetLocation(componentLabel);
if (location && !location.IsIdentity()) {
// Apply the location to the shape
const locatedShape = componentShape.Located(location, false);
const childComponent = this.parseComponentWithXCAF(locatedShape, referredLabel, shapeTool, colorTool, `Component_${level}_${i - 1}`, level);
children.push(childComponent);
// Clean up
locatedShape.delete();
}
else {
// No specific location, use shape as-is
const childComponent = this.parseComponentWithXCAF(componentShape, referredLabel, shapeTool, colorTool, `Component_${level}_${i - 1}`, level);
children.push(childComponent);
}
componentShape.delete();
}
referredLabel.delete();
}
componentLabel.delete();
}
components.delete();
return children;
}
extractColorFromXCAF(shape, label, colorTool) {
try {
const color = new this.occ.Quantity_Color_1();
if (colorTool.GetColor_1(label, color)) {
const result = this.convertQuantityColorToRgba(color);
color.delete();
return result;
}
if (colorTool.GetColor_1(label, color)) {
const result = this.convertQuantityColorToRgba(color);
color.delete();
return result;
}
if (colorTool.GetColor_7(shape, this.occ.XCAFDoc_ColorType.XCAFDoc_ColorSurf, color)) {
const result = this.convertQuantityColorToRgba(color);
color.delete();
return result;
}
if (colorTool.GetColor_7(shape, this.occ.XCAFDoc_ColorType.XCAFDoc_ColorCurv, color)) {
const result = this.convertQuantityColorToRgba(color);
color.delete();
return result;
}
if (colorTool.GetColor_7(shape, this.occ.XCAFDoc_ColorType.XCAFDoc_ColorGen, color)) {
const result = this.convertQuantityColorToRgba(color);
color.delete();
return result;
}
const subShapeColor = this.extractSubShapeColor(shape, colorTool);
if (subShapeColor) {
color.delete();
return subShapeColor;
}
color.delete();
}
catch (error) {
console.warn("Error extracting XCAF color:", error);
}
return undefined;
}
convertQuantityColorToRgba(color) {
return {
r: Math.round(color.Red() * 255) / 255,
g: Math.round(color.Green() * 255) / 255,
b: Math.round(color.Blue() * 255) / 255,
a: 1.0
};
}
extractSubShapeColor(shape, colorTool) {
try {
const faceExplorer = new this.occ.TopExp_Explorer_2(shape, this.occ.TopAbs_ShapeEnum.TopAbs_FACE, this.occ.TopAbs_ShapeEnum.TopAbs_SHAPE);
while (faceExplorer.More()) {
const face = this.occ.TopoDS.Face_1(faceExplorer.Current());
const color = new this.occ.Quantity_Color_1();
if (colorTool.GetColor_7(face, this.occ.XCAFDoc_ColorType.XCAFDoc_ColorSurf, color)) {
const result = this.convertQuantityColorToRgba(color);
color.delete();
face.delete();
faceExplorer.delete();
return result;
}
color.delete();
face.delete();
faceExplorer.Next();
}
faceExplorer.delete();
}
catch (error) {
console.warn("Error extracting sub-shape color:", error);
}
return undefined;
}
extractNameFromLabel(label) {
try {
// Try to get name attribute from the label using correct API
const nameAttrHandle = new this.occ.Handle_TDF_Attribute_1();
const nameID = this.occ.TDataStd_Name.GetID();
if (label.FindAttribute_1(nameID, nameAttrHandle)) {
try {
const TCollection_ExtendedString = nameAttrHandle.get().Get();
const nameString = new this.occ.TCollection_AsciiString_13(TCollection_ExtendedString, 0).ToCString();
nameAttrHandle.delete();
return nameString && nameString.trim() !== "" ? nameString.trim() : undefined;
}
catch (convertError) {
console.warn("Error converting TCollection_ExtendedString:", convertError);
}
}
nameAttrHandle.delete();
}
catch (error) {
console.warn("Error extracting name:", error);
}
return undefined;
}
extractAttributesFromXCAF(label) {
const attributes = {};
try {
// Try to extract various attributes from the label
// This is where you would extract material properties, custom attributes, etc.
// Example: Extract density if available using the correct FindAttribute method
const realAttrHandle = new this.occ.Handle_TDF_Attribute_1();
const realID = new this.occ.TDataStd_Real().ID();
if (label.FindAttribute_1(realID, realAttrHandle)) {
const realData = this.occ.TDataStd_Real.DownCast(realAttrHandle);
// Cast the attribute to the correct type
if (realData && !realData.IsNull()) {
attributes.density = realData.Get();
realData.delete();
}
}
realAttrHandle.delete();
}
catch (error) {
console.warn("Error extracting attributes:", error);
}
return attributes;
}
extractProperties(shape) {
const properties = {};
try {
// Calculate volume
const gprops = new this.occ.GProp_GProps_1();
this.occ.BRepGProp.VolumeProperties_1(shape, gprops, false, false, false);
properties.volume = gprops.Mass();
// Calculate center of mass
const centerOfMass = gprops.CentreOfMass();
properties.centerOfMass = [
centerOfMass.X(),
centerOfMass.Y(),
centerOfMass.Z()
];
gprops.delete();
centerOfMass.delete();
// Calculate surface area
const surfaceGprops = new this.occ.GProp_GProps_1();
this.occ.BRepGProp.SurfaceProperties_1(shape, surfaceGprops, false, false);
properties.surfaceArea = surfaceGprops.Mass();
surfaceGprops.delete();
// Calculate bounding box
const bbox = new this.occ.Bnd_Box_1();
this.occ.BRepBndLib.Add(shape, bbox, false);
const corner1 = bbox.CornerMin();
const corner2 = bbox.CornerMax();
properties.boundingBox = {
min: [corner1.X(), corner1.Y(), corner1.Z()],
max: [corner2.X(), corner2.Y(), corner2.Z()]
};
bbox.delete();
corner1.delete();
corner2.delete();
}
catch (error) {
console.warn("Error extracting properties:", error);
}
return properties;
}
extractPMI(shape) {
const pmiData = [];
try {
// Try to extract PMI data using XCAF dimension and tolerance tools
// Note: This requires access to XCAFDoc_DimTolTool which may not be available in all OCCT builds
// Extract annotations if available
this.extractAnnotationsFromShape(shape, pmiData);
}
catch (error) {
console.warn("Error extracting PMI data:", error);
}
return pmiData;
}
extractAnnotationsFromShape(shape, pmiData) {
try {
// This would require access to annotation tools in XCAF
// For now, we'll add placeholder logic for common annotations
// Check if shape has cylindrical features (holes, pins)
this.extractCylindricalFeatures(shape, pmiData);
}
catch (error) {
console.warn("Error extracting annotations:", error);
}
}
extractCylindricalFeatures(shape, pmiData) {
try {
const faceExplorer = new this.occ.TopExp_Explorer_2(shape, this.occ.TopAbs_ShapeEnum.TopAbs_FACE, this.occ.TopAbs_ShapeEnum.TopAbs_SHAPE);
while (faceExplorer.More()) {
const face = this.occ.TopoDS.Face_1(faceExplorer.Current());
// Check if face is cylindrical
const surface = this.occ.BRep_Tool.Surface_2(face);
const surfaceType = surface.get().DynamicType().Name();
if (surfaceType.includes("Cylinder")) {
// Extract cylinder properties
const cylinderSurf = surface.get();
// Get cylinder axis and radius information
const props = new this.occ.GProp_GProps_1();
this.occ.BRepGProp.SurfaceProperties_1(face, props, false, false);
const centerOfMass = props.CentreOfMass();
pmiData.push({
type: "feature",
text: "Cylindrical Feature",
position: [centerOfMass.X(), centerOfMass.Y(), centerOfMass.Z()],
direction: [0, 0, 1],
properties: {
type: "cylinder",
surfaceArea: props.Mass()
}
});
props.delete();
centerOfMass.delete();
}
surface.delete();
face.delete();
faceExplorer.Next();
}
faceExplorer.delete();
}
catch (error) {
console.warn("Error extracting cylindrical features:", error);
}
}
extractTransformation(shape) {
// Extract transformation matrix from shape location
const location = shape.Location_1();
const transformation = location.Transformation();
// Get translation
const translation = transformation.TranslationPart();
const translationArray = [
translation.X(),
translation.Y(),
translation.Z()
];
// Get rotation matrix and convert to quaternion
const rotationMatrix = transformation.HVectorialPart();
const quaternion = this.matrixToQuaternion(rotationMatrix);
// Get scale (OCCT doesn't typically store non-uniform scale)
const scale = [
transformation.ScaleFactor(),
transformation.ScaleFactor(),
transformation.ScaleFactor()
];
// Get full 4x4 matrix
const matrix = this.extractTransformationMatrix(transformation);
location.delete();
transformation.delete();
translation.delete();
rotationMatrix.delete();
return {
translation: translationArray,
rotation: quaternion,
scale,
matrix
};
}
extractTransformationMatrix(transformation) {
// Extract 4x4 transformation matrix from gp_Trsf
const matrix = new Array(16).fill(0);
try {
// Get the 3x4 transformation matrix values
const values = [
[transformation.Value(1, 1), transformation.Value(1, 2), transformation.Value(1, 3), transformation.Value(1, 4)],
[transformation.Value(2, 1), transformation.Value(2, 2), transformation.Value(2, 3), transformation.Value(2, 4)],
[transformation.Value(3, 1), transformation.Value(3, 2), transformation.Value(3, 3), transformation.Value(3, 4)],
[0, 0, 0, 1]
];
// Flatten to 16-element array (column-major order)
for (let row = 0; row < 4; row++) {
for (let col = 0; col < 4; col++) {
matrix[col * 4 + row] = values[row][col];
}
}
}
catch (error) {
console.warn("Error extracting transformation matrix:", error);
// Return identity matrix as fallback
matrix[0] = matrix[5] = matrix[10] = matrix[15] = 1;
}
return matrix;
}
matrixToQuaternion(rotMatrix) {
try {
// Extract quaternion from 3x3 rotation matrix
const m11 = rotMatrix.Value(1, 1);
const m12 = rotMatrix.Value(1, 2);
const m13 = rotMatrix.Value(1, 3);
const m21 = rotMatrix.Value(2, 1);
const m22 = rotMatrix.Value(2, 2);
const m23 = rotMatrix.Value(2, 3);
const m31 = rotMatrix.Value(3, 1);
const m32 = rotMatrix.Value(3, 2);
const m33 = rotMatrix.Value(3, 3);
// Convert rotation matrix to quaternion
const trace = m11 + m22 + m33;
let x, y, z, w;
if (trace > 0) {
const s = Math.sqrt(trace + 1.0) * 2;
w = 0.25 * s;
x = (m32 - m23) / s;
y = (m13 - m31) / s;
z = (m21 - m12) / s;
}
else if (m11 > m22 && m11 > m33) {
const s = Math.sqrt(1.0 + m11 - m22 - m33) * 2;
w = (m32 - m23) / s;
x = 0.25 * s;
y = (m12 + m21) / s;
z = (m13 + m31) / s;
}
else if (m22 > m33) {
const s = Math.sqrt(1.0 + m22 - m11 - m33) * 2;
w = (m13 - m31) / s;
x = (m12 + m21) / s;
y = 0.25 * s;
z = (m23 + m32) / s;
}
else {
const s = Math.sqrt(1.0 + m33 - m11 - m22) * 2;
w = (m21 - m12) / s;
x = (m13 + m31) / s;
y = (m23 + m32) / s;
z = 0.25 * s;
}
return [x, y, z, w];
}
catch (error) {
console.warn("Error converting matrix to quaternion:", error);
return [0, 0, 0, 1]; // Identity quaternion
}
}
generateId() {
return Math.random().toString(36).substr(2, 9);
}
countComponents(component, callback) {
callback(component);
component.children.forEach(child => this.countComponents(child, callback));
}
// Utility method to serialize the assembly structure to JSON string
serializeAssembly(assembly) {
// Remove OCCT shape objects before serialization
const cleanAssembly = this.cleanAssemblyForSerialization(assembly);
return JSON.stringify(cleanAssembly, null, 2);
}
cleanAssemblyForSerialization(assembly) {
const clean = JSON.parse(JSON.stringify(assembly));
const removeShapes = (component) => {
delete component.shape;
if (component.children) {
component.children = component.children.map(removeShapes);
}
return component;
};
clean.root = removeShapes(clean.root);
return clean;
}
// New method for parsing XCAF documents with full metadata
parseXCAFDocument(doc) {
const mainLabel = doc.Main();
const shapeTool = this.occ.XCAFDoc_DocumentTool.ShapeTool(mainLabel).get();
const colorTool = this.occ.XCAFDoc_DocumentTool.ColorTool(mainLabel).get();
const materialTool = this.occ.XCAFDoc_DocumentTool.MaterialTool(mainLabel).get();
// Build color assignment map
this.buildColorAssignments(colorTool);
// Get all free shapes (top-level assembly components)
const freeShapes = new this.occ.TDF_LabelSequence_1();
shapeTool.GetFreeShapes(freeShapes);
let totalParts = 0;
let totalAssemblies = 0;
let rootComponent;
if (freeShapes.Length() === 1) {
// Single root assembly
const rootLabel = freeShapes.Value(1);
const rootShape = new this.occ.TopoDS_Shape();
if (this.occ.XCAFDoc_ShapeTool.GetShape_1(rootLabel, rootShape)) {
rootComponent = this.parseXCAFComponent(rootShape, rootLabel, shapeTool, colorTool, materialTool, "root", 0);
rootShape.delete();
}
else {
// Fallback
rootComponent = this.createEmptyRootComponent();
}
}
else if (freeShapes.Length() > 1) {
// Multiple top-level components - create virtual root
rootComponent = this.createEmptyRootComponent();
for (let i = 1; i <= freeShapes.Length(); i++) {
const label = freeShapes.Value(i);
const shape = new this.occ.TopoDS_Shape();
if (this.occ.XCAFDoc_ShapeTool.GetShape_1(label, shape)) {
const component = this.parseXCAFComponent(shape, label, shapeTool, colorTool, materialTool, `Component_0_${i - 1}`, 1);
rootComponent.children.push(component);
shape.delete();
}
}
}
else {
// No free shapes - create empty root
rootComponent = this.createEmptyRootComponent();
}
this.countComponents(rootComponent, (component) => {
if (component.type === "part")
totalParts++;
else
totalAssemblies++;
});
// Clean up
freeShapes.delete();
return {
version: "1.0.0",
units: "mm",
root: rootComponent,
metadata: {
totalParts,
totalAssemblies,
createdAt: new Date().toISOString(),
source: "STEP/XCAF"
}
};
}
createEmptyRootComponent() {
return {
id: this.generateId(),
name: "root",
type: "assembly",
children: [],
transformation: {
translation: [0, 0, 0],
rotation: [0, 0, 0, 1],
scale: [1, 1, 1],
matrix: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]
},
properties: {},
attributes: {},
pmi: []
};
}
parseXCAFComponent(shape, label, shapeTool, colorTool, materialTool, name, level) {
const id = this.generateId();
const isAssembly = this.occ.XCAFDoc_ShapeTool.IsAssembly(label);
const component = {
id,
name: this.extractNameFromXCAFLabel(label) || name || `${isAssembly ? "Assembly" : "Part"}_${id}`,
type: isAssembly ? "assembly" : "part",
shape: shape,
children: [],
transformation: this.extractTransformation(shape),
properties: this.extractProperties(shape),
attributes: this.extractXCAFAttributes(label, materialTool),
color: this.extractXCAFColor(shape, label, colorTool),
pmi: this.extractPMI(shape)
};
if (isAssembly) {
component.children = this.extractXCAFChildren(label, shapeTool, colorTool, materialTool, level + 1);
}
return component;
}
extractXCAFChildren(assemblyLabel, shapeTool, colorTool, materialTool, level) {
const children = [];
// Get components of the assembly
const components = new this.occ.TDF_LabelSequence_1();
this.occ.XCAFDoc_ShapeTool.GetComponents(assemblyLabel, components, false);
for (let i = 1; i <= components.Length(); i++) {
const componentLabel = components.Value(i);
// Get the referenced shape
const referredLabel = new this.occ.TDF_Label();
if (this.occ.XCAFDoc_ShapeTool.GetReferredShape(componentLabel, referredLabel)) {
const componentShape = new this.occ.TopoDS_Shape();
if (this.occ.XCAFDoc_ShapeTool.GetShape_1(referredLabel, componentShape)) {
// Get the location/transformation for this component instance
const location = this.occ.XCAFDoc_ShapeTool.GetLocation(componentLabel);
let finalShape = componentShape;
if (location && !location.IsIdentity()) {
finalShape = componentShape.Located(location, false);
}
const childComponent = this.parseXCAFComponent(finalShape, referredLabel, shapeTool, colorTool, materialTool, `Component_${level}_${i - 1}`, level);
children.push(childComponent);
// Clean up
if (finalShape !== componentShape) {
finalShape.delete();
}
componentShape.delete();
if (location) {
location.delete();
}
}
referredLabel.delete();
}
componentLabel.delete();
}
components.delete();
return children;
}
extractNameFromXCAFLabel(label) {
try {
const nameID = this.occ.TDataStd_Name.GetID();
const nameAttrHandle = new this.occ.Handle_TDF_Attribute_1();
if (label.FindAttribute_1(nameID, nameAttrHandle)) {
try {
const TCollection_ExtendedString = nameAttrHandle.get().Get();
const nameString = new this.occ.TCollection_AsciiString_13(TCollection_ExtendedString, 0).ToCString();
nameAttrHandle.delete();
if (nameString && nameString.trim() !== "") {
return nameString.trim();
}
}
catch (convertError) {
console.warn("Error converting TCollection_ExtendedString:", convertError);
}
}
nameAttrHandle.delete();
}
catch (error) {
console.warn("Error extracting XCAF name:", error);
}
return undefined;
}
extractXCAFColor(shape, label, colorTool) {
try {
let color = new this.occ.Quantity_Color_1();
const colorRGB = new this.occ.Quantity_ColorRGBA_1();
if (colorTool.GetColor_1(label, color)) {
const result = this.convertQuantityColorToRgba(color);
color.delete();
return result;
}
if (colorTool.GetColor_2(label, colorRGB)) {
color = colorRGB.GetRGB();
const result = this.convertQuantityColorToRgba(color);
color.delete();
colorRGB.delete();
return result;
}
if (colorTool.GetColor_7(shape, this.occ.XCAFDoc_ColorType.XCAFDoc_ColorSurf, color)) {
const result = this.convertQuantityColorToRgba(color);
color.delete();
return result;
}
if (colorTool.GetColor_8(shape, this.occ.XCAFDoc_ColorType.XCAFDoc_ColorSurf, colorRGB)) {
color = colorRGB.GetRGB();
const result = this.convertQuantityColorToRgba(color);
color.delete();
colorRGB.delete();
return result;
}
if (colorTool.GetColor_7(shape, this.occ.XCAFDoc_ColorType.XCAFDoc_ColorCurv, color)) {
const result = this.convertQuantityColorToRgba(color);
color.delete();
return result;
}
if (colorTool.GetColor_8(shape, this.occ.XCAFDoc_ColorType.XCAFDoc_ColorCurv, colorRGB)) {
color = colorRGB.GetRGB();
const result = this.convertQuantityColorToRgba(color);
color.delete();
colorRGB.delete();
return result;
}
if (colorTool.GetColor_7(shape, this.occ.XCAFDoc_ColorType.XCAFDoc_ColorGen, color)) {
const result = this.convertQuantityColorToRgba(color);
color.delete();
return result;
}
if (colorTool.GetColor_8(shape, this.occ.XCAFDoc_ColorType.XCAFDoc_ColorGen, colorRGB)) {
color = colorRGB.GetRGB();
const result = this.convertQuantityColorToRgba(color);
colorRGB.delete();
color.delete();
return result;
}
const labelTag = String(label.Tag());
if (this.colorAssignments.has(labelTag)) {
return this.colorAssignments.get(labelTag);
}
const subShapeColor = this.extractSubShapeColor(shape, colorTool);
if (subShapeColor) {
color.delete();
return subShapeColor;
}
color.delete();
}
catch (error) {
console.warn("Error extracting XCAF color:", error);
}
return undefined;
}
extractXCAFAttributes(label, materialTool) {
const attributes = {};
try {
this.extractMaterialFromLabel(label, attributes);
this.extractAdditionalMaterialProperties(label, attributes);
}
catch (error) {
console.warn("Error extracting XCAF attributes:", error);
}
return attributes;
}
extractMaterialFromLabel(label, attributes) {
try {
const materialName = this.extractMaterialName(label);
if (materialName) {
attributes.material = materialName;
}
const density = this.extractMaterialDensity(label);
if (density > 0) {
attributes.density = density;
}
this.extractAdditionalMaterialProperties(label, attributes);
}
catch (error) {
console.warn("Error extracting material from label:", error);
}
}
extractMaterialName(materialLabel) {
try {
const nameAttrHandle = new this.occ.Handle_TDF_Attribute_1();
if (materialLabel.FindAttribute_1(this.occ.TDataStd_Name.GetID(), nameAttrHandle)) {
try {
const TCollection_ExtendedString = nameAttrHandle.get().Get();
const nameString = new this.occ.TCollection_AsciiString_13(TCollection_ExtendedString, 0).ToCString();
nameAttrHandle.delete();
if (nameString && nameString.trim() !== "") {
return nameString.trim();
}
}
catch (convertError) {
console.warn("Error converting material name:", convertError);
}
}
nameAttrHandle.delete();
}
catch (error) {
console.warn("Error extracting material name:", error);
}
return undefined;
}
extractMaterialDensity(materialLabel) {
try {
// Try to get density value from real attributes
const realAttrHandle = new this.occ.Handle_TDF_Attribute_1();
const realID = new this.occ.TDataStd_Real().ID();
if (materialLabel.FindAttribute_1(realID, realAttrHandle)) {
const attr = realAttrHandle.get();
if (attr) {
try {
const density = attr.Get();
realAttrHandle.delete();
return density;
}
catch (accessError) {
console.warn("Error accessing density value:", accessError);
}
}
}
realAttrHandle.delete();
}
catch (error) {
console.warn("Error extracting material density:", error);
}
return 0;
}
extractAdditionalMaterialProperties(label, attributes) {
try {
const intAttrHandle = new this.occ.Handle_TDF_Attribute_1();
const intID = new this.occ.TDataStd_Integer().ID();
if (label.FindAttribute_1(intID, intAttrHandle)) {
const attr = intAttrHandle.get();
if (attr) {
try {
const materialId = attr.Get();
attributes.materialId = materialId;
}
catch (accessError) {
console.warn("Error accessing material ID:", accessError);
}
}
}
intAttrHandle.delete();
}
catch (error) {
console.warn("Error extracting additional material properties:", error);
}
}
buildColorAssignments(colorTool) {
this.colorAssignments.clear();
// Get all color labels
const colorLabels = new this.occ.TDF_LabelSequence_1();
colorTool.GetColors(colorLabels);
for (let i = 1; i <= colorLabels.Length(); i++) {
const colorLabel = colorLabels.Value(i);
const color = new this.occ.Quantity_Color_1();
if (colorTool.GetColor_1(colorLabel, color)) {
this.colorAssignments.set(String(colorLabel.Tag()), this.convertQuantityColorToRgba(color));
}
color.delete();
colorLabel.delete();
}
console.log(this.colorAssignments);
colorLabels.delete();
}
}