three-slicer 0.1.0 → 0.1.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.
Files changed (58) hide show
  1. package/README.md +342 -24
  2. package/components/README.md +1 -1
  3. package/components/dist/SettingsPanel.js +3 -4
  4. package/engine/index.d.ts +3 -1
  5. package/engine/src/data.js +12 -0
  6. package/engine/src/settings.js +1 -1
  7. package/engine/src/slicer.worker.js +2 -1
  8. package/engine/src/slicer_core.js +0 -0
  9. package/engine/src/slicer_core.mt.js +0 -0
  10. package/engine/src/toggle_eval.js +1 -2
  11. package/package.json +54 -26
  12. package/types/components.d.ts +19 -0
  13. package/types/data/config-schema.json.d.ts +55 -0
  14. package/types/data/invalidation-map.json.d.ts +15 -0
  15. package/types/data/toggle-rules.json.d.ts +20 -0
  16. package/types/data/ui-tree.json.d.ts +19 -0
  17. package/types/data.d.ts +17 -0
  18. package/types/gen_settings_types.mjs +70 -0
  19. package/types/settings-keys.d.ts +1704 -0
  20. package/types/settings.d.ts +19 -0
  21. package/types/toggle.d.ts +22 -0
  22. package/types/viewer-loaders.d.ts +33 -0
  23. package/types/viewer-toolpath.d.ts +105 -0
  24. package/types/viewer.d.ts +15 -0
  25. package/types/wasm.d.ts +5 -0
  26. package/types/worker.d.ts +3 -0
  27. package/viewer/README.md +1 -1
  28. package/viewer/dist/Viewport.js +674 -617
  29. package/viewer/dist/model_loaders.js +220 -108
  30. package/viewer/styles.css +2 -0
  31. package/data/config-schema-builddump.json +0 -12921
  32. package/viewer/src/Viewport.jsx +0 -1353
  33. package/viewer/src/assets/add.svg +0 -1
  34. package/viewer/src/assets/arrange.svg +0 -1
  35. package/viewer/src/assets/boolean.svg +0 -1
  36. package/viewer/src/assets/cut.svg +0 -1
  37. package/viewer/src/assets/delete.svg +0 -1
  38. package/viewer/src/assets/deleteall.svg +0 -1
  39. package/viewer/src/assets/duplicate.svg +0 -1
  40. package/viewer/src/assets/measure.svg +0 -1
  41. package/viewer/src/assets/mmu.svg +0 -1
  42. package/viewer/src/assets/move.svg +0 -1
  43. package/viewer/src/assets/negative.svg +0 -1
  44. package/viewer/src/assets/onbed.svg +0 -1
  45. package/viewer/src/assets/open.svg +0 -1
  46. package/viewer/src/assets/orient.svg +0 -1
  47. package/viewer/src/assets/paint.svg +0 -1
  48. package/viewer/src/assets/rotate.svg +0 -1
  49. package/viewer/src/assets/scale.svg +0 -1
  50. package/viewer/src/assets/seam.svg +0 -1
  51. package/viewer/src/assets/split.svg +0 -1
  52. package/viewer/src/assets/textmark.svg +0 -1
  53. package/viewer/src/assets/varlayer.svg +0 -1
  54. package/viewer/src/icons.js +0 -23
  55. package/viewer/src/make_worker.js +0 -9
  56. package/viewer/src/model_loaders.js +0 -178
  57. package/viewer/src/shadow_host.jsx +0 -30
  58. package/viewer/src/toolpath_gpu.js +0 -430
@@ -1,144 +1,256 @@
1
- import * as T from "three";
2
- import { OBJLoader as E } from "three/examples/jsm/loaders/OBJLoader.js";
3
- import { PLYLoader as F } from "three/examples/jsm/loaders/PLYLoader.js";
4
- import { ThreeMFLoader as x } from "three/examples/jsm/loaders/3MFLoader.js";
5
- import { AMFLoader as L } from "three/examples/jsm/loaders/AMFLoader.js";
6
- const O = ["stl", "obj", "3mf", "amf", "ply"];
7
- function A(e) {
8
- const o = e.lastIndexOf(".");
9
- return o < 0 ? "" : e.slice(o + 1).toLowerCase();
1
+ import * as C from "three";
2
+ import { OBJLoader as U } from "three/examples/jsm/loaders/OBJLoader.js";
3
+ import { PLYLoader as V } from "three/examples/jsm/loaders/PLYLoader.js";
4
+ import { AMFLoader as W } from "three/examples/jsm/loaders/AMFLoader.js";
5
+ import { unzipSync as X } from "three/examples/jsm/libs/fflate.module.js";
6
+ const x = [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0];
7
+ function J(t, e) {
8
+ const s = new Array(12);
9
+ for (let n = 0; n < 4; n++)
10
+ for (let o = 0; o < 3; o++)
11
+ s[n * 3 + o] = t[n * 3] * e[o] + t[n * 3 + 1] * e[3 + o] + t[n * 3 + 2] * e[6 + o] + (n === 3 ? e[9 + o] : 0);
12
+ return s;
10
13
  }
11
- function v(e) {
12
- const o = new DataView(e);
13
- if (e.byteLength >= 84) {
14
- const u = o.getUint32(80, !0);
15
- if (e.byteLength === 84 + u * 50) {
16
- const c = new Float32Array(u * 9);
17
- let a = 84, p = 0;
18
- for (let d = 0; d < u; d++) {
19
- a += 12;
20
- for (let t = 0; t < 3; t++)
21
- c[p++] = o.getFloat32(a, !0), c[p++] = o.getFloat32(a + 4, !0), c[p++] = o.getFloat32(a + 8, !0), a += 12;
22
- a += 2;
14
+ function R(t) {
15
+ if (!t) return x;
16
+ const e = t.trim().split(/\s+/).map(Number);
17
+ return e.length === 12 && e.every(Number.isFinite) ? e : x;
18
+ }
19
+ const k = {};
20
+ function w(t, e) {
21
+ const n = (k[e] || (k[e] = new RegExp(`\\b${e}\\s*=\\s*"([^"]*)"`))).exec(t);
22
+ return n ? n[1] : null;
23
+ }
24
+ const z = /<vertex\s+x="([^"]*)"\s+y="([^"]*)"\s+z="([^"]*)"/g, I = /<triangle\s+v1="([^"]*)"\s+v2="([^"]*)"\s+v3="([^"]*)"/g;
25
+ function Y(t) {
26
+ const e = [];
27
+ z.lastIndex = 0;
28
+ let s;
29
+ for (; s = z.exec(t); ) e.push(+s[1], +s[2], +s[3]);
30
+ if (!e.length)
31
+ for (const o of t.match(/<vertex\b[^>]*>/g) || []) e.push(+w(o, "x"), +w(o, "y"), +w(o, "z"));
32
+ if (e.length < 9) return null;
33
+ const n = [];
34
+ for (I.lastIndex = 0; s = I.exec(t); ) n.push(+s[1], +s[2], +s[3]);
35
+ if (!n.length)
36
+ for (const o of t.match(/<triangle\b[^>]*>/g) || []) n.push(+w(o, "v1"), +w(o, "v2"), +w(o, "v3"));
37
+ return n.length ? { verts: e, tris: n } : null;
38
+ }
39
+ function H(t) {
40
+ const e = /* @__PURE__ */ new Map(), s = /<object\b([^>]*)>([\s\S]*?)<\/object>/g;
41
+ let n;
42
+ for (; n = s.exec(t); ) {
43
+ const i = w(n[1], "id");
44
+ if (!i) continue;
45
+ const c = n[2], p = [];
46
+ for (const d of c.match(/<component\b[^>]*>/g) || []) {
47
+ const h = w(d, "objectid");
48
+ h && p.push({ objectid: h, path: w(d, "p:path") || w(d, "path"), transform: R(w(d, "transform")) });
49
+ }
50
+ e.set(i, p.length ? { components: p } : { mesh: Y(c) });
51
+ }
52
+ const o = [], u = /<build\b[^>]*>([\s\S]*?)<\/build>/.exec(t);
53
+ if (u)
54
+ for (const i of u[1].match(/<item\b[^>]*>/g) || []) {
55
+ const c = w(i, "objectid");
56
+ c && o.push({ objectid: c, path: w(i, "p:path") || w(i, "path"), transform: R(w(i, "transform")) });
57
+ }
58
+ return { objects: e, items: o };
59
+ }
60
+ function L(t) {
61
+ const e = String(t).replace(/^\/+/, "");
62
+ return e.includes("%") ? decodeURIComponent(e) : e;
63
+ }
64
+ function Q(t, e = "model") {
65
+ const s = ArrayBuffer.isView(t) ? new Uint8Array(t.buffer, t.byteOffset, t.byteLength) : new Uint8Array(t), n = X(s), o = /* @__PURE__ */ new Map();
66
+ for (const a of Object.keys(n)) o.set(L(a), n[a]);
67
+ const u = new TextDecoder(), i = /* @__PURE__ */ new Map(), c = (a) => {
68
+ const m = L(a);
69
+ if (i.has(m)) return i.get(m);
70
+ const l = o.get(m), M = l ? H(u.decode(l)) : null;
71
+ return i.set(m, M), M;
72
+ };
73
+ let p = "3D/3dmodel.model";
74
+ const d = o.get("_rels/.rels");
75
+ if (d) {
76
+ for (const a of u.decode(d).match(/<Relationship\b[^>]*>/g) || [])
77
+ if ((w(a, "Type") || "").endsWith("/3dmodel")) {
78
+ p = L(w(a, "Target"));
79
+ break;
80
+ }
81
+ }
82
+ const h = c(p);
83
+ if (!h) throw new Error(`3MF 루트 모델 없음: ${p}`);
84
+ const r = [], f = (a, m, l, M, $) => {
85
+ if ($ > 16) return;
86
+ const T = c(m), E = T == null ? void 0 : T.objects.get(a);
87
+ if (!E) return;
88
+ if (E.components) {
89
+ for (const y of E.components) f(y.objectid, y.path || m, J(y.transform, l), M, $ + 1);
90
+ return;
91
+ }
92
+ if (!E.mesh) return;
93
+ const { verts: v, tris: S } = E.mesh;
94
+ for (let y = 0; y < S.length; y++) {
95
+ const A = S[y] * 3, b = v[A], j = v[A + 1], F = v[A + 2];
96
+ M.push(
97
+ b * l[0] + j * l[3] + F * l[6] + l[9],
98
+ b * l[1] + j * l[4] + F * l[7] + l[10],
99
+ b * l[2] + j * l[5] + F * l[8] + l[11]
100
+ );
101
+ }
102
+ }, g = h.items.length ? h.items : [...h.objects.keys()].filter((a) => h.objects.get(a).mesh).map((a) => ({ objectid: a, path: p, transform: x }));
103
+ return g.forEach((a, m) => {
104
+ const l = [];
105
+ f(a.objectid, a.path || p, a.transform, l, 0), l.length >= 9 && r.push({ name: g.length > 1 ? `${e}#${m + 1}` : e, tris: new Float32Array(l) });
106
+ }), r;
107
+ }
108
+ const P = ["stl", "obj", "3mf", "amf", "ply"], _ = /* @__PURE__ */ new Map();
109
+ function et(t, e) {
110
+ for (const s of (Array.isArray(t) ? t : String(t).split(",")).map((n) => n.trim().toLowerCase()))
111
+ _.set(s, e), P.includes(s) || P.push(s);
112
+ }
113
+ function q(t) {
114
+ const e = t.lastIndexOf(".");
115
+ return e < 0 ? "" : t.slice(e + 1).toLowerCase();
116
+ }
117
+ function G(t) {
118
+ const e = new DataView(t);
119
+ if (t.byteLength >= 84) {
120
+ const i = e.getUint32(80, !0);
121
+ if (t.byteLength === 84 + i * 50) {
122
+ const c = new Float32Array(i * 9);
123
+ let p = 84, d = 0;
124
+ for (let h = 0; h < i; h++) {
125
+ p += 12;
126
+ for (let r = 0; r < 3; r++)
127
+ c[d++] = e.getFloat32(p, !0), c[d++] = e.getFloat32(p + 4, !0), c[d++] = e.getFloat32(p + 8, !0), p += 12;
128
+ p += 2;
23
129
  }
24
130
  return c;
25
131
  }
26
132
  }
27
- const l = new TextDecoder().decode(e), n = /vertex\s+([-\d.eE+]+)\s+([-\d.eE+]+)\s+([-\d.eE+]+)/g, r = [];
28
- let i;
29
- for (; i = n.exec(l); ) r.push(+i[1], +i[2], +i[3]);
30
- return r.length < 9 ? null : new Float32Array(r);
133
+ const s = new TextDecoder().decode(t), n = /vertex\s+([-\d.eE+]+)\s+([-\d.eE+]+)\s+([-\d.eE+]+)/g, o = [];
134
+ let u;
135
+ for (; u = n.exec(s); ) o.push(+u[1], +u[2], +u[3]);
136
+ return o.length < 9 ? null : new Float32Array(o);
31
137
  }
32
- function y(e, o) {
33
- var p;
34
- const l = (p = e == null ? void 0 : e.attributes) == null ? void 0 : p.position;
35
- if (!l || l.count < 3) return null;
36
- const n = e.index, r = new T.Vector3(), i = Math.floor((n ? n.count : l.count) / 3), u = new Float32Array(i * 9);
138
+ function B(t, e) {
139
+ var d;
140
+ const s = (d = t == null ? void 0 : t.attributes) == null ? void 0 : d.position;
141
+ if (!s || s.count < 3) return null;
142
+ const n = t.index, o = new C.Vector3(), u = Math.floor((n ? n.count : s.count) / 3), i = new Float32Array(u * 9);
37
143
  let c = 0;
38
- const a = (d) => {
39
- r.fromBufferAttribute(l, d), o && r.applyMatrix4(o), u[c++] = r.x, u[c++] = r.y, u[c++] = r.z;
144
+ const p = (h) => {
145
+ o.fromBufferAttribute(s, h), e && o.applyMatrix4(e), i[c++] = o.x, i[c++] = o.y, i[c++] = o.z;
40
146
  };
41
147
  if (n)
42
- for (let d = 0; d < i * 3; d++) a(n.getX(d));
148
+ for (let h = 0; h < u * 3; h++) p(n.getX(h));
43
149
  else
44
- for (let d = 0; d < i * 3; d++) a(d);
45
- return u;
150
+ for (let h = 0; h < u * 3; h++) p(h);
151
+ return i;
46
152
  }
47
- function m(e) {
48
- e.updateMatrixWorld(!0);
49
- const o = [];
50
- return e.traverse((l) => {
51
- l.isMesh && l.geometry && o.push({ geometry: l.geometry, matrix: l.matrixWorld });
52
- }), o;
153
+ function D(t) {
154
+ t.updateMatrixWorld(!0);
155
+ const e = [];
156
+ return t.traverse((s) => {
157
+ s.isMesh && s.geometry && e.push({ geometry: s.geometry, matrix: s.matrixWorld });
158
+ }), e;
53
159
  }
54
- function M(e, o, l) {
55
- const n = o.map((c) => y(c.geometry, c.matrix)).filter(Boolean);
160
+ function O(t, e, s) {
161
+ const n = e.map((c) => B(c.geometry, c.matrix)).filter(Boolean);
56
162
  if (!n.length) return [];
57
- if (l && n.length > 1)
58
- return n.map((c, a) => ({ name: `${e}#${a + 1}`, modelPos: c }));
59
- if (n.length === 1) return [{ name: e, modelPos: n[0] }];
60
- let r = 0;
61
- for (const c of n) r += c.length;
62
- const i = new Float32Array(r);
63
- let u = 0;
163
+ if (s && n.length > 1)
164
+ return n.map((c, p) => ({ name: `${t}#${p + 1}`, modelPos: c }));
165
+ if (n.length === 1) return [{ name: t, modelPos: n[0] }];
166
+ let o = 0;
167
+ for (const c of n) o += c.length;
168
+ const u = new Float32Array(o);
169
+ let i = 0;
64
170
  for (const c of n)
65
- i.set(c, u), u += c.length;
66
- return [{ name: e, modelPos: i }];
171
+ u.set(c, i), i += c.length;
172
+ return [{ name: t, modelPos: u }];
67
173
  }
68
- async function k(e, o) {
69
- const l = A(e);
70
- switch (l) {
174
+ async function nt(t, e) {
175
+ const s = q(t);
176
+ switch (s) {
71
177
  case "stl": {
72
- const n = v(o);
178
+ const n = G(e);
73
179
  if (!n) throw new Error("STL 파싱 실패");
74
- return [{ name: e, modelPos: n }];
180
+ return [{ name: t, modelPos: n }];
75
181
  }
76
182
  case "obj": {
77
- const n = new E().parse(new TextDecoder().decode(o));
78
- return M(e, m(n), !1);
183
+ const n = new U().parse(new TextDecoder().decode(e));
184
+ return O(t, D(n), !1);
79
185
  }
80
186
  case "ply": {
81
- const n = new F().parse(o), r = y(n, null);
82
- if (!r) throw new Error("PLY 지오메트리 없음");
83
- return [{ name: e, modelPos: r }];
187
+ const n = new V().parse(e), o = B(n, null);
188
+ if (!o) throw new Error("PLY 지오메트리 없음");
189
+ return [{ name: t, modelPos: o }];
84
190
  }
85
191
  case "3mf": {
86
- const n = new x().parse(o), r = M(e, m(n), !0);
87
- if (!r.length) throw new Error("3MF 메시 없음");
88
- return r;
192
+ const n = Q(e, t).map((o) => ({ name: o.name, modelPos: o.tris }));
193
+ if (!n.length) throw new Error("3MF 메시 없음");
194
+ return n;
89
195
  }
90
196
  case "amf": {
91
- const n = new L().parse(o), r = M(e, m(n), !0);
92
- if (!r.length) throw new Error("AMF 메시 없음");
93
- return r;
197
+ const n = new W().parse(e), o = O(t, D(n), !0);
198
+ if (!o.length) throw new Error("AMF 메시 없음");
199
+ return o;
200
+ }
201
+ default: {
202
+ const n = _.get(s);
203
+ if (!n) throw new Error(`지원하지 않는 포맷: .${s}`);
204
+ const o = await n(e, t);
205
+ if (!(o != null && o.length)) throw new Error(`.${s} 메시 없음`);
206
+ return o;
94
207
  }
95
- default:
96
- throw new Error(`지원하지 않는 포맷: .${l} (STEP 은 범위 외 — OCCT 필요)`);
97
208
  }
98
209
  }
99
- function D(e) {
100
- const o = Math.floor(e.length / 9);
101
- if (o < 2) return null;
102
- const l = 1e4, n = /* @__PURE__ */ new Map(), r = new Int32Array(o * 3);
103
- for (let t = 0; t < o; t++)
104
- for (let s = 0; s < 3; s++) {
105
- const f = t * 9 + s * 3, w = `${Math.round(e[f] * l)},${Math.round(e[f + 1] * l)},${Math.round(e[f + 2] * l)}`;
106
- let h = n.get(w);
107
- h === void 0 && (h = n.size, n.set(w, h)), r[t * 3 + s] = h;
210
+ function ot(t) {
211
+ const e = Math.floor(t.length / 9);
212
+ if (e < 2) return null;
213
+ const s = 1e4, n = /* @__PURE__ */ new Map(), o = new Int32Array(e * 3);
214
+ for (let r = 0; r < e; r++)
215
+ for (let f = 0; f < 3; f++) {
216
+ const g = r * 9 + f * 3, a = `${Math.round(t[g] * s)},${Math.round(t[g + 1] * s)},${Math.round(t[g + 2] * s)}`;
217
+ let m = n.get(a);
218
+ m === void 0 && (m = n.size, n.set(a, m)), o[r * 3 + f] = m;
108
219
  }
109
- const i = new Int32Array(o);
110
- for (let t = 0; t < o; t++) i[t] = t;
111
- const u = (t) => {
112
- for (; i[t] !== t; )
113
- i[t] = i[i[t]], t = i[t];
114
- return t;
115
- }, c = (t, s) => {
116
- t = u(t), s = u(s), t !== s && (i[s] = t);
117
- }, a = /* @__PURE__ */ new Map();
118
- for (let t = 0; t < o; t++)
119
- for (let s = 0; s < 3; s++) {
120
- const f = r[t * 3 + s], w = r[t * 3 + (s + 1) % 3], h = f < w ? f * 4294967296 + w : w * 4294967296 + f, g = a.get(h);
121
- g === void 0 ? a.set(h, t) : c(t, g);
220
+ const u = new Int32Array(e);
221
+ for (let r = 0; r < e; r++) u[r] = r;
222
+ const i = (r) => {
223
+ for (; u[r] !== r; )
224
+ u[r] = u[u[r]], r = u[r];
225
+ return r;
226
+ }, c = (r, f) => {
227
+ r = i(r), f = i(f), r !== f && (u[f] = r);
228
+ }, p = /* @__PURE__ */ new Map();
229
+ for (let r = 0; r < e; r++)
230
+ for (let f = 0; f < 3; f++) {
231
+ const g = o[r * 3 + f], a = o[r * 3 + (f + 1) % 3], m = g < a ? g * 4294967296 + a : a * 4294967296 + g, l = p.get(m);
232
+ l === void 0 ? p.set(m, r) : c(r, l);
122
233
  }
123
- const p = /* @__PURE__ */ new Map();
124
- for (let t = 0; t < o; t++) {
125
- const s = u(t);
126
- let f = p.get(s);
127
- f || (f = [], p.set(s, f)), f.push(t);
234
+ const d = /* @__PURE__ */ new Map();
235
+ for (let r = 0; r < e; r++) {
236
+ const f = i(r);
237
+ let g = d.get(f);
238
+ g || (g = [], d.set(f, g)), g.push(r);
128
239
  }
129
- return p.size < 2 ? null : [...p.values()].sort((t, s) => s.length - t.length).map((t) => {
130
- const s = new Float32Array(t.length * 9);
131
- let f = 0;
132
- for (const w of t) {
133
- const h = w * 9;
134
- for (let g = 0; g < 9; g++) s[f++] = e[h + g];
240
+ return d.size < 2 ? null : [...d.values()].sort((r, f) => f.length - r.length).map((r) => {
241
+ const f = new Float32Array(r.length * 9);
242
+ let g = 0;
243
+ for (const a of r) {
244
+ const m = a * 9;
245
+ for (let l = 0; l < 9; l++) f[g++] = t[m + l];
135
246
  }
136
- return s;
247
+ return f;
137
248
  });
138
249
  }
139
250
  export {
140
- O as SUPPORTED_EXT,
141
- A as fileExt,
142
- k as loadModel,
143
- D as splitConnectedComponents
251
+ P as SUPPORTED_EXT,
252
+ q as fileExt,
253
+ nt as loadModel,
254
+ et as registerLoader,
255
+ ot as splitConnectedComponents
144
256
  };
package/viewer/styles.css CHANGED
@@ -131,6 +131,8 @@
131
131
  /* ⑤ 하단 고정 버튼 바 */
132
132
  .side-bottom { flex: 0 0 auto; display: flex; gap: 8px; padding: 10px; border-top: 1px solid #dcdfe3; background: #e6e9ec; }
133
133
  .side-bottom .slice-btn { flex: 1.4; margin: 0; }
134
+ .auto-slice { display: flex; align-items: center; gap: 5px; font-size: 12px; color: #444; cursor: pointer; white-space: nowrap; user-select: none; }
135
+ .auto-slice input { margin: 0; }
134
136
  .export-btn { flex: 1; text-align: center; padding: 9px; border-radius: 8px; background: #dfe6ea; color: #1f6feb;
135
137
  border: 1px solid #c7d2da; text-decoration: none; font-weight: 600; cursor: pointer; font-size: 13px; }
136
138
  .export-btn:hover { background: #d3dee4; }