mirror of
https://github.com/gittrahan/support-fins.git
synced 2026-10-22 03:42:40 -05:00
84 lines
3.9 KiB
JavaScript
84 lines
3.9 KiB
JavaScript
// Bridge between a plugin's Python and the fin engine.
|
|
//
|
|
// Python plugins (Orca today) run this bundle, built by plugins/shared/bundle.py,
|
|
// inside an embedded V8 (mini-racer). Plain V8 has no atob/btoa/TextDecoder, so
|
|
// geometry crosses the boundary as base64 of raw little-endian bytes, decoded here
|
|
// by hand. That is ~20x smaller and much faster than a JSON number array for a
|
|
// 100k-triangle part.
|
|
//
|
|
// in : base64 float64 triangle soup (posed, mm) + JSON options
|
|
// out: JSON { triangles: base64 float32 soup (seated frame), offset, pieces,
|
|
// overFaces, smallFaces, stats }
|
|
// drawWallB64 does the same for Draw mode (draw_entry.js): one wall between two points.
|
|
import { computeFins, ENGINE_DEFAULTS, optionsFromDialog, optionVisible, OPTIONS_SCHEMA } from './fins_entry.js';
|
|
import { drawWall } from './draw_entry.js';
|
|
import { reportLine } from './report.js';
|
|
|
|
const B64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
|
const LOOKUP = new Uint8Array(256);
|
|
for (let i = 0; i < B64.length; i++) LOOKUP[B64.charCodeAt(i)] = i;
|
|
|
|
export function b64ToBytes(s) {
|
|
let pad = 0;
|
|
if (s.endsWith('==')) pad = 2; else if (s.endsWith('=')) pad = 1;
|
|
const n = (s.length / 4) * 3 - pad;
|
|
const out = new Uint8Array(n);
|
|
let o = 0;
|
|
for (let i = 0; i < s.length; i += 4) {
|
|
const a = LOOKUP[s.charCodeAt(i)], b = LOOKUP[s.charCodeAt(i + 1)];
|
|
const c = LOOKUP[s.charCodeAt(i + 2)], d = LOOKUP[s.charCodeAt(i + 3)];
|
|
const v = (a << 18) | (b << 12) | (c << 6) | d;
|
|
if (o < n) out[o++] = (v >> 16) & 255;
|
|
if (o < n) out[o++] = (v >> 8) & 255;
|
|
if (o < n) out[o++] = v & 255;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
export function bytesToB64(bytes) {
|
|
const parts = [];
|
|
let chunk = '';
|
|
for (let i = 0; i < bytes.length; i += 3) {
|
|
const a = bytes[i], b = i + 1 < bytes.length ? bytes[i + 1] : 0, c = i + 2 < bytes.length ? bytes[i + 2] : 0;
|
|
const v = (a << 16) | (b << 8) | c;
|
|
chunk += B64[(v >> 18) & 63] + B64[(v >> 12) & 63]
|
|
+ (i + 1 < bytes.length ? B64[(v >> 6) & 63] : '=')
|
|
+ (i + 2 < bytes.length ? B64[v & 63] : '=');
|
|
if (chunk.length > 65536) { parts.push(chunk); chunk = ''; }
|
|
}
|
|
parts.push(chunk);
|
|
return parts.join('');
|
|
}
|
|
|
|
const soupOf = (b64) => {
|
|
const bytes = b64ToBytes(b64);
|
|
return new Float64Array(bytes.buffer, bytes.byteOffset, bytes.byteLength / 8);
|
|
};
|
|
const trianglesB64 = (t) => bytesToB64(new Uint8Array(t.buffer, t.byteOffset, t.byteLength));
|
|
|
|
export function computeFinsB64(soupB64, optionsJson) {
|
|
const options = optionsJson ? JSON.parse(optionsJson) : {};
|
|
const res = computeFins(soupOf(soupB64), options);
|
|
return JSON.stringify({ triangles: trianglesB64(res.triangles), offset: res.offset,
|
|
pieces: res.pieces, overFaces: Array.from(res.overFaces),
|
|
smallFaces: Array.from(res.smallFaces), stats: res.stats });
|
|
}
|
|
|
|
// a, b: JSON [x, y, z] in the soup's frame.
|
|
export function drawWallB64(soupB64, aJson, bJson, optionsJson) {
|
|
const options = optionsJson ? JSON.parse(optionsJson) : {};
|
|
const res = drawWall(soupOf(soupB64), JSON.parse(aJson), JSON.parse(bJson), options);
|
|
if (!res.ok) return JSON.stringify(res);
|
|
return JSON.stringify({ ok: true, triangles: trianglesB64(res.triangles), offset: res.offset, stats: res.stats });
|
|
}
|
|
|
|
// A Python host's settings dialog, as JSON strings like computeFinsB64 (supportfins_host
|
|
// host_schema / host_options / host_visible).
|
|
export const optionsSchemaJson = () => JSON.stringify(OPTIONS_SCHEMA);
|
|
export const optionsFromDialogJson = (valuesJson) => JSON.stringify(optionsFromDialog(JSON.parse(valuesJson)));
|
|
export const optionVisibleJson = (key, valuesJson) => optionVisible(key, JSON.parse(valuesJson));
|
|
|
|
// optionsFromDialog / optionVisible / OPTIONS_SCHEMA: what a host's settings dialog needs;
|
|
// reportLine: the one-line result, for a host whose dialog is a web page (SolidWorks)
|
|
export { computeFins, drawWall, ENGINE_DEFAULTS, optionsFromDialog, optionVisible, OPTIONS_SCHEMA, reportLine };
|