partforge 0.143.0 → 0.143.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -51,6 +51,29 @@ function makeProbe(onCall) {
|
|
|
51
51
|
toSTL: () => new ArrayBuffer(0),
|
|
52
52
|
toIndexedMesh: () => ({ positions: new Float32Array(9), indices: new Uint32Array(3) }),
|
|
53
53
|
};
|
|
54
|
+
// Solid's optional mesh-topology queries return numbers/booleans, not a handle.
|
|
55
|
+
Object.assign(solidQueries, { genus: () => 0, isEmpty: () => false });
|
|
56
|
+
// Shape2D ops that return DATA rather than another Shape2D. Without an entry here an
|
|
57
|
+
// op falls through to the chaining branch and hands back the Shape2D handle itself,
|
|
58
|
+
// so ordinary array/number use of the result (`.corners().map(…)`, `.area() * 2`)
|
|
59
|
+
// was recorded as an unknown Shape2D op and failed lint as `unknown-solid-op`.
|
|
60
|
+
// `regions()` returns live Shape2Ds, so its dummy is an array holding the handle.
|
|
61
|
+
// The dummy region is a unit square in the contour IR (closed: last point = first).
|
|
62
|
+
const square = [[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]];
|
|
63
|
+
const shape2dQueries = {
|
|
64
|
+
...solidQueries,
|
|
65
|
+
isEmpty: () => false,
|
|
66
|
+
area: () => 1,
|
|
67
|
+
boundingBox: () => ({ min: [0, 0], max: [1, 1], center: [0.5, 0.5], size: [1, 1] }),
|
|
68
|
+
toRegions: () => [{ outer: square.map((p) => [...p]), holes: [] }],
|
|
69
|
+
simple: () => ({ outer: square.map((p) => [...p]), holes: [] }),
|
|
70
|
+
toContours: () => [{ outer: { start: [0, 0], segments: square.slice(1).map((p) => ({ to: [...p] })) }, holes: [] }],
|
|
71
|
+
corners: () => [0, 1, 2, 3].map((i) => ({
|
|
72
|
+
index: i, position: i, point: [...square[i]], interiorAngleDeg: 90, convex: true, segTypes: ["line", "line"],
|
|
73
|
+
})),
|
|
74
|
+
contains: () => false,
|
|
75
|
+
regions: () => [shape2d],
|
|
76
|
+
};
|
|
54
77
|
const kernelQueries = {
|
|
55
78
|
toSTEP: () => Promise.resolve(new ArrayBuffer(0)),
|
|
56
79
|
cleanup: () => {},
|
|
@@ -82,10 +105,8 @@ function makeProbe(onCall) {
|
|
|
82
105
|
},
|
|
83
106
|
});
|
|
84
107
|
|
|
85
|
-
// Shape2D handles reuse solidQueries: boundingBox/volume/… dummies chain the same
|
|
86
|
-
// either way, and a 3-component bbox is as good a dummy as a 2-component one.
|
|
87
108
|
const proxy = opProxy(solidQueries, "solid", () => proxy); // a solid handle: every op chains back to itself
|
|
88
|
-
const shape2d = opProxy(
|
|
109
|
+
const shape2d = opProxy(shape2dQueries, "shape2d",
|
|
89
110
|
(key) => (SOLID_YIELDING_SHAPE2D_OPS.has(key) ? proxy : shape2d));
|
|
90
111
|
const kernel = opProxy(kernelQueries, "kernel", // factory ops (cylinder/box/prism/…) return a solid
|
|
91
112
|
(key) => (SHAPE2D_YIELDING_KERNEL_OPS.has(key) ? shape2d : proxy));
|
package/src/framework/imports.js
CHANGED
|
@@ -10,11 +10,21 @@ import { parse3MF } from "./geometry/threemf-parse.js";
|
|
|
10
10
|
|
|
11
11
|
const EXT = { step: "step", stp: "step", stl: "stl", "3mf": "3mf" };
|
|
12
12
|
|
|
13
|
+
// Font files declared as an import. Without this a TTF fell through to the STL
|
|
14
|
+
// fallback below and failed as "binary STL truncated: header says 3848966777
|
|
15
|
+
// triangles" — an error about a mesh the author never meant (cloud feedback #148).
|
|
16
|
+
const FONT_EXT = new Set(["ttf", "otf", "woff", "woff2"]);
|
|
17
|
+
const FONT_MAGIC = ["\x00\x01\x00\x00", "OTTO", "true", "ttcf", "wOFF", "wOF2"];
|
|
18
|
+
|
|
13
19
|
export function detectFormat(source, bytes) {
|
|
14
20
|
const path = source instanceof URL ? source.pathname : typeof source === "string" ? source.split("?")[0] : null;
|
|
15
21
|
const ext = path?.match(/\.([A-Za-z0-9]+)$/)?.[1]?.toLowerCase();
|
|
16
|
-
if (ext && EXT[ext]) return EXT[ext];
|
|
17
22
|
const u8 = bytes instanceof ArrayBuffer ? new Uint8Array(bytes) : bytes;
|
|
23
|
+
const magic = u8 && u8.length >= 4 ? String.fromCharCode(...u8.slice(0, 4)) : "";
|
|
24
|
+
if ((ext && FONT_EXT.has(ext)) || FONT_MAGIC.includes(magic)) {
|
|
25
|
+
throw new Error(`a font file${path ? ` ("${path}")` : ""} is declared under \`imports\` — declare it under \`fonts\` and use it with text2d`);
|
|
26
|
+
}
|
|
27
|
+
if (ext && EXT[ext]) return EXT[ext];
|
|
18
28
|
if (u8 && u8.length > 0) {
|
|
19
29
|
const head = String.fromCharCode(...u8.slice(0, 64));
|
|
20
30
|
if (head.startsWith("ISO-10303-21")) return "step";
|