3
TCollection_ExtendedString,
5
} from "replicad-opencascadejs";
6
import { uuidv } from "../utils/uuid";
7
import { getOC } from "../oclib";
8
import { AnyShape } from "../shapes";
9
import { GCWithScope, WrappingObj } from "../register";
11
const wrapString = (str: string): TCollection_ExtendedString => {
13
return new oc.TCollection_ExtendedString_2(str, true);
16
function parseSlice(hex: string, index: number): number {
17
return parseInt(hex.slice(index * 2, (index + 1) * 2), 16);
19
function colorFromHex(hex: string): [number, number, number] {
21
if (color.indexOf("#") === 0) color = color.slice(1);
23
if (color.length === 3) {
24
color = color.replace(/([0-9a-f])/gi, "$1$1");
27
return [parseSlice(color, 0), parseSlice(color, 1), parseSlice(color, 2)];
30
const wrapColor = (hex: string, alpha = 1): Quantity_ColorRGBA => {
32
const [r, g, b] = colorFromHex(hex);
34
return new oc.Quantity_ColorRGBA_5(r / 255, g / 255, b / 255, alpha);
37
export class AssemblyExporter extends WrappingObj<TDocStd_Document> {}
46
export function createAssembly(shapes: ShapeConfig[] = []): AssemblyExporter {
49
const doc = new oc.TDocStd_Document(wrapString("XmlOcaf"));
51
oc.XCAFDoc_ShapeTool.SetAutoNaming(false);
53
const mainLabel = doc.Main();
55
const tool = oc.XCAFDoc_DocumentTool.ShapeTool(mainLabel).get();
56
const ctool = oc.XCAFDoc_DocumentTool.ColorTool(mainLabel).get();
58
for (const { shape, name, color, alpha } of shapes) {
59
const shapeNode = tool.NewShape();
61
tool.SetShape(shapeNode, shape.wrapped);
63
oc.TDataStd_Name.Set_1(shapeNode, wrapString(name || uuidv()));
67
wrapColor(color || "#f00", alpha ?? 1),
68
// @ts-expect-error the type system does not work for these
69
oc.XCAFDoc_ColorType.XCAFDoc_ColorSurf
73
tool.UpdateAssemblies();
75
return new AssemblyExporter(doc);
78
export type SupportedUnit =
90
export function exportSTEP(
91
shapes: ShapeConfig[] = [],
92
{ unit, modelUnit }: { unit?: SupportedUnit; modelUnit?: SupportedUnit } = {}
95
const r = GCWithScope();
97
const doc = createAssembly(shapes);
99
if (unit || modelUnit) {
100
// eslint-disable-next-line @typescript-eslint/no-unused-vars
101
const dummy = r(new oc.STEPCAFControl_Writer_1());
103
oc.Interface_Static.SetCVal(
104
"xstep.cascade.unit",
105
(modelUnit || unit || "MM").toUpperCase()
107
oc.Interface_Static.SetCVal(
109
(unit || modelUnit || "MM").toUpperCase()
113
const session = r(new oc.XSControl_WorkSession());
115
new oc.STEPCAFControl_Writer_2(
116
r(new oc.Handle_XSControl_WorkSession_2(session)),
120
writer.SetColorMode(true);
121
writer.SetLayerMode(true);
122
writer.SetNameMode(true);
123
oc.Interface_Static.SetIVal("write.surfacecurve.mode", true);
124
oc.Interface_Static.SetIVal("write.precision.mode", 0);
125
oc.Interface_Static.SetIVal("write.step.assembly", 2);
126
oc.Interface_Static.SetIVal("write.step.schema", 5);
128
const progress = r(new oc.Message_ProgressRange_1());
130
new oc.Handle_TDocStd_Document_2(doc.wrapped),
131
// @ts-expect-error the type system does not work for these
132
oc.STEPControl_StepModelType.STEPControl_AsIs,
137
const filename = "export.step";
138
const done = writer.Write(filename);
140
if (done === oc.IFSelect_ReturnStatus.IFSelect_RetDone) {
141
// Read the STEP File from the filesystem and clean up
142
const file = oc.FS.readFile("/" + filename);
143
oc.FS.unlink("/" + filename);
145
// Return the contents of the STEP File
146
const blob = new Blob([file], { type: "application/STEP" });
149
throw new Error("WRITE STEP FILE FAILED.");