UNPKG

@bitbybit-dev/occt-worker

Version:

Bit By Bit Developers CAD algorithms using OpenCascade Technology kernel adapted for WebWorker

125 lines (124 loc) 5.06 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { Subject } from "rxjs"; import { OccStateEnum } from "./occ-state.enum"; /** * This is a manager of OpenCascade worker. Promisified API allows to deal with the worker in a more natural way * and because all those CAD algorithms are quite heavy this does make a lot of sense at this time. */ export class OCCTWorkerManager { constructor() { this.occWorkerState$ = new Subject(); this.promisesMade = []; } occWorkerAlreadyInitialised() { return this.occWorker ? true : false; } /** * Convert File/Blob to Uint8Array if needed, before sending to worker. * File/Blob objects cannot be cloned for postMessage, so we convert them first. * ArrayBuffer is also converted to Uint8Array for WASM compatibility. */ prepareStepData(data) { return __awaiter(this, void 0, void 0, function* () { if (typeof File !== "undefined" && data instanceof File) { return new Uint8Array(yield data.arrayBuffer()); } if (typeof Blob !== "undefined" && data instanceof Blob) { return new Uint8Array(yield data.arrayBuffer()); } if (data instanceof ArrayBuffer) { return new Uint8Array(data); } return data; }); } setOccWorker(worker) { this.occWorker = worker; this.occWorker.onmessage = ({ data }) => { if (data === "occ-initialised") { this.occWorkerState$.next({ state: OccStateEnum.initialised, }); } else if (data === "busy") { this.occWorkerState$.next({ state: OccStateEnum.computing, }); } else { const promise = this.promisesMade.find(made => made.uid === data.uid); if (promise && data.result !== undefined && !data.error) { promise.resolve(data.result); } else if (data.error) { if (this.errorCallback) { try { this.errorCallback(data.error); } catch (cbErr) { console.error("OCCT errorCallback threw:", cbErr); } } if (promise) { promise.reject(data.error); } } this.promisesMade = this.promisesMade.filter(i => i.uid !== data.uid); if (this.promisesMade.length === 0) { this.occWorkerState$.next({ state: OccStateEnum.loaded, }); } else { this.occWorkerState$.next({ state: OccStateEnum.computing, }); } } }; } cleanPromisesMade() { this.promisesMade = []; } genericCallToWorkerPromise(functionName, inputs) { const uid = `call${Math.random()}${Date.now()}`; const obj = { uid }; const prom = new Promise((resolve, reject) => { obj.resolve = resolve; obj.reject = reject; }); obj.promise = prom; this.promisesMade.push(obj); this.occWorker.postMessage({ action: { functionName, inputs }, uid, }); return prom; } /** * This needs to be done before every run and the promise needs to be awaited before run executes again * This makes sure that cache keeps the objects and hashes from the previous run and the rest is deleted * In this way it is possible to hace the cache of manageable size */ startedTheRun() { return this.genericCallToWorkerPromise("startedTheRun", {}); } /** * This needs to be done before every run and the promise needs to be awaited before run executes again * This makes sure that cache keeps the objects and hashes from the previous run and the rest is deleted * In this way it is possible to hace the cache of manageable size */ cleanAllCache() { return this.genericCallToWorkerPromise("cleanAllCache", {}); } }