UNPKG

@bitbybit-dev/occt

Version:

Bit By Bit Developers CAD algorithms using OpenCascade Technology kernel. Run in Node and in Browser.

216 lines (215 loc) 9.31 kB
export class OCCTIO { constructor(occ, och) { this.occ = occ; this.och = och; } saveShapeSTEP(inputs) { const shapeToUse = inputs.shape; let adjustedShape; if (inputs.adjustYtoZ) { const rotatedShape = this.och.transformsService.rotate({ shape: inputs.shape, axis: [1, 0, 0], angle: -90 }); if (inputs.fromRightHanded) { adjustedShape = rotatedShape; } else { adjustedShape = this.och.transformsService.mirrorAlongNormal({ shape: rotatedShape, origin: [0, 0, 0], normal: [0, 0, 1] }); rotatedShape.delete(); } } const fileName = "x"; const writer = new this.occ.STEPControl_Writer_1(); let transferShape; if (adjustedShape) { transferShape = adjustedShape; } else { transferShape = shapeToUse; } // Convert to a .STEP File const messageProgress = new this.occ.Message_ProgressRange_1(); let transferResult; try { transferResult = writer.Transfer(transferShape, this.occ.STEPControl_StepModelType.STEPControl_AsIs, true, messageProgress); } catch (ex) { throw (new Error("Failed when calling writer.Transfer.")); } let result; if (transferResult === this.occ.IFSelect_ReturnStatus.IFSelect_RetDone) { // Write the STEP File to the virtual Emscripten Filesystem Temporarily const writeResult = writer.Write(fileName); if (writeResult === this.occ.IFSelect_ReturnStatus.IFSelect_RetDone) { // Read the STEP File from the filesystem and clean up const stepFileText = this.occ.FS.readFile("/" + fileName, { encoding: "utf8" }); this.occ.FS.unlink("/" + fileName); // Return the contents of the STEP File result = stepFileText; } else { throw (new Error("Failed when writing step file.")); } } else { throw (new Error("Failed when transfering to step writer.")); } if (adjustedShape) { adjustedShape.delete(); } messageProgress.delete(); return result; } saveShapeStl(inputs) { const shapeToUse = inputs.shape; // This could be made optional... // Clean cached triangulation data for the shape. // This allows to get lower res models out of higher res that was once computed and cached. this.occ.BRepTools.Clean(shapeToUse, true); let adjustedShape; if (inputs.adjustYtoZ) { const rotatedShape = this.och.transformsService.rotate({ shape: inputs.shape, axis: [1, 0, 0], angle: -90 }); adjustedShape = this.och.transformsService.mirrorAlongNormal({ shape: rotatedShape, origin: [0, 0, 0], normal: [0, 0, 1] }); rotatedShape.delete(); } const fileName = "x"; const writer = new this.occ.StlAPI_Writer(); let transferShape; if (adjustedShape) { transferShape = adjustedShape; } else { transferShape = shapeToUse; } const messageProgress = new this.occ.Message_ProgressRange_1(); let result; const incrementalMeshBuilder = new this.occ.BRepMesh_IncrementalMesh_2(transferShape, inputs.precision, false, 0.5, false); // Write the STL File to the virtual Emscripten Filesystem Temporarily const writeResult = writer.Write(transferShape, fileName, messageProgress); if (writeResult) { // Read the STL File from the filesystem and clean up const stlFile = this.occ.FS.readFile("/" + fileName, { encoding: "utf8" }); this.occ.FS.unlink("/" + fileName); // Return the contents of the STL File result = stlFile; } else { throw (new Error("Failed when writing stl file.")); } if (adjustedShape) { adjustedShape.delete(); } messageProgress.delete(); if (incrementalMeshBuilder) { incrementalMeshBuilder.Delete(); } return result; } /** This function parses the ASCII contents of a `.STEP` or `.IGES` * File as a Shape into the `externalShapes` dictionary. */ loadSTEPorIGES(inputs) { const fileName = inputs.fileName; const fileText = inputs.filetext; const fileType = (() => { switch (fileName.toLowerCase().split(".").pop()) { case "step": case "stp": return "step"; case "iges": case "igs": return "iges"; default: return undefined; } })(); // Writes the uploaded file to Emscripten's Virtual Filesystem this.occ.FS.createDataFile("/", `file.${fileType}`, fileText, true, true, true); // Choose the correct OpenCascade file parsers to read the CAD file let reader; if (fileType === "step") { reader = new this.occ.STEPControl_Reader_1(); } else if (fileType === "iges") { reader = new this.occ.IGESControl_Reader_1(); } else { console.error("opencascade can't parse this extension! (yet)"); return undefined; } const readResult = reader.ReadFile(`file.${fileType}`); // Read the file if (readResult === this.occ.IFSelect_ReturnStatus.IFSelect_RetDone) { // Translate all transferable roots to OpenCascade const messageProgress = new this.occ.Message_ProgressRange_1(); reader.TransferRoots(messageProgress); messageProgress.delete(); let stepShape = reader.OneShape(); let adjustedShape; if (inputs.adjustZtoY) { const mirroredShape = this.och.transformsService.mirrorAlongNormal({ shape: stepShape, origin: [0, 0, 0], normal: [0, 0, 1] }); adjustedShape = this.och.transformsService.rotate({ shape: mirroredShape, axis: [1, 0, 0], angle: 90 }); mirroredShape.delete(); } // Out with the old, in with the new! // Remove the file when we're done (otherwise we run into errors on reupload) this.occ.FS.unlink(`/file.${fileType}`); if (adjustedShape) { stepShape.delete(); stepShape = adjustedShape; } return stepShape; } else { console.error("Something in OCCT went wrong trying to read " + fileName); } return undefined; } // TODO WIP! This function parses the contents of a `.STEP` file as an assembly // and returns the assembly structure. It's not finished yet and needs a lot of work. parseStepAssembly(inputs) { const fileName = inputs.fileName; const fileText = inputs.filetext; // Write file to virtual filesystem this.occ.FS.createDataFile("/", "step_file.step", fileText, true, true, true); try { // Create XCAF application and document const app = this.occ.XCAFApp_Application.GetApplication(); const format = new this.occ.TCollection_ExtendedString_2("MDTV-XCAF", true); const docHandle = new this.occ.Handle_TDocStd_Document_1(); app.get().NewDocument_2(format, docHandle); const doc = docHandle.get(); // Use STEPCAFControl_Reader to read with full XCAF support const reader = new this.occ.STEPCAFControl_Reader_1(); reader.SetColorMode(true); // Enable color reading reader.SetNameMode(true); // Enable name reading reader.SetLayerMode(true); // Enable layer reading reader.SetPropsMode(true); // Enable properties reading // Read the file const readResult = reader.ReadFile("step_file.step"); if (readResult === this.occ.IFSelect_ReturnStatus.IFSelect_RetDone) { // Transfer to XCAF document const messageProgress = new this.occ.Message_ProgressRange_1(); const transferResult = reader.Transfer_1(docHandle, messageProgress); messageProgress.delete(); if (transferResult) { // Parse using the improved assembly parser // const assemblyStructure = this.ioAssembly.parseXCAFDocument(doc); // Clean up reader.delete(); format.delete(); docHandle.delete(); this.occ.FS.unlink("/step_file.step"); return {}; } else { throw new Error("Failed to transfer STEP data to XCAF document"); } } else { throw new Error("Failed to read STEP file"); } } catch (error) { this.occ.FS.unlink("/step_file.step"); throw error; } } }