three-slicer 0.1.0
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/LICENSE.txt +661 -0
- package/README.md +44 -0
- package/components/README.md +39 -0
- package/components/dist/SettingsPanel.js +180 -0
- package/components/styles.css +84 -0
- package/data/README.md +22 -0
- package/data/config-schema-builddump.json +12921 -0
- package/data/config-schema.json +12685 -0
- package/data/invalidation-map.json +631 -0
- package/data/toggle-rules.json +2277 -0
- package/data/ui-tree.json +1586 -0
- package/engine/README.md +52 -0
- package/engine/examples/headless.mjs +37 -0
- package/engine/index.d.ts +29 -0
- package/engine/index.js +45 -0
- package/engine/src/settings.js +130 -0
- package/engine/src/slicer.worker.js +73 -0
- package/engine/src/slicer_core.js +0 -0
- package/engine/src/slicer_core.mt.js +0 -0
- package/engine/src/toggle_eval.js +78 -0
- package/package.json +74 -0
- package/viewer/README.md +68 -0
- package/viewer/dist/Viewport.js +1108 -0
- package/viewer/dist/make_worker.js +9 -0
- package/viewer/dist/model_loaders.js +144 -0
- package/viewer/dist/toolpath_gpu.js +386 -0
- package/viewer/src/Viewport.jsx +1353 -0
- package/viewer/src/assets/add.svg +1 -0
- package/viewer/src/assets/arrange.svg +1 -0
- package/viewer/src/assets/boolean.svg +1 -0
- package/viewer/src/assets/cut.svg +1 -0
- package/viewer/src/assets/delete.svg +1 -0
- package/viewer/src/assets/deleteall.svg +1 -0
- package/viewer/src/assets/duplicate.svg +1 -0
- package/viewer/src/assets/measure.svg +1 -0
- package/viewer/src/assets/mmu.svg +1 -0
- package/viewer/src/assets/move.svg +1 -0
- package/viewer/src/assets/negative.svg +1 -0
- package/viewer/src/assets/onbed.svg +1 -0
- package/viewer/src/assets/open.svg +1 -0
- package/viewer/src/assets/orient.svg +1 -0
- package/viewer/src/assets/paint.svg +1 -0
- package/viewer/src/assets/rotate.svg +1 -0
- package/viewer/src/assets/scale.svg +1 -0
- package/viewer/src/assets/seam.svg +1 -0
- package/viewer/src/assets/split.svg +1 -0
- package/viewer/src/assets/textmark.svg +1 -0
- package/viewer/src/assets/varlayer.svg +1 -0
- package/viewer/src/icons.js +23 -0
- package/viewer/src/make_worker.js +9 -0
- package/viewer/src/model_loaders.js +178 -0
- package/viewer/src/shadow_host.jsx +30 -0
- package/viewer/src/toolpath_gpu.js +430 -0
- package/viewer/styles.css +231 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M.5,13.5V1.5a1,1,0,0,1,1-1h12a1,1,0,0,1,1,1v12a1,1,0,0,1-1,1H1.5A1,1,0,0,1,.5,13.5Zm3-6h3m2,0h3m-4-4v8" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40"><path d="M33.5,35H5.5A1.5,1.5,0,0,1,4,33.5V5.5A1.5,1.5,0,0,1,5.5,4h28A1.5,1.5,0,0,1,35,5.5v28A1.5,1.5,0,0,1,33.5,35ZM5.5,5a.5.5,0,0,0-.5.5v28a.5.5,0,0,0,.5.5h28a.5.5,0,0,0,.5-.5V5.5a.5.5,0,0,0-.5-.5Z" style="fill:#b6b6b6"/><path d="M30.5,32H8.5A1.5,1.5,0,0,1,7,30.5v-6A1.5,1.5,0,0,1,8.5,23h22A1.5,1.5,0,0,1,32,24.5v6A1.5,1.5,0,0,1,30.5,32Zm-22-8a.5.5,0,0,0-.5.5v6a.5.5,0,0,0,.5.5h22a.5.5,0,0,0,.5-.5v-6a.5.5,0,0,0-.5-.5Zm22-2h-6A1.5,1.5,0,0,1,23,20.5V8.5A1.5,1.5,0,0,1,24.5,7h6A1.5,1.5,0,0,1,32,8.5v12A1.5,1.5,0,0,1,30.5,22Zm-6-14a.5.5,0,0,0-.5.5v12a.5.5,0,0,0,.5.5h6a.5.5,0,0,0,.5-.5V8.5a.5.5,0,0,0-.5-.5Zm-6,6h-8a3.5,3.5,0,0,1,0-7h8a3.5,3.5,0,0,1,0,7Zm-8-6a2.5,2.5,0,0,0,0,5h8a2.5,2.5,0,0,0,0-5Zm8,14A3.5,3.5,0,1,1,22,18.5,3.5,3.5,0,0,1,18.5,22Zm0-6A2.5,2.5,0,1,0,21,18.5,2.5,2.5,0,0,0,18.5,16Zm-8,6A3.5,3.5,0,1,1,14,18.5,3.5,3.5,0,0,1,10.5,22Zm0-6A2.5,2.5,0,1,0,13,18.5,2.5,2.5,0,0,0,10.5,16Z" style="fill:#009688"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M6.2,8a2.6,2.6,0,1,0,5.2,0a2.6,2.6,0,1,0,-5.2,0" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M4.6,8a2.6,2.6,0,1,0,5.2,0a2.6,2.6,0,1,0,-5.2,0" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M.5,13.5V1.5a1,1,0,0,1,1-1h12a1,1,0,0,1,1,1v12a1,1,0,0,1-1,1H1.5A1,1,0,0,1,.5,13.5Z" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M3.5,9h2m2,0h2m2,0h2" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M8,3.5l1.8,3h-3.6z" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M.5,13.5V1.5a1,1,0,0,1,1-1h12a1,1,0,0,1,1,1v12a1,1,0,0,1-1,1H1.5A1,1,0,0,1,.5,13.5Zm3-6h8" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M.5,13.5V1.5a1,1,0,0,1,1-1h12a1,1,0,0,1,1,1v12a1,1,0,0,1-1,1H1.5A1,1,0,0,1,.5,13.5Z" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M5,5l6,6" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M11,5l-6,6" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M4,4h5v5H4z" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M7,7h5v5H7z" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M2.5,8h11" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M2.5,6v4" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M13.5,6v4" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M6,7v2" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M10,7v2" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M4,8a4,4,0,1,0,8,0a4,4,0,1,0,-8,0" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M8,4a4,4,0,0,1,0,8z" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1;fill:#949494;stroke:none"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40"><path d="M34.854,19.146l-4-4a.5.5,0,0,0-.708.708L33.293,19H28.5a.5.5,0,0,0,0,1h4.793l-3.147,3.146a.5.5,0,0,0,.708.708l4-4A.5.5,0,0,0,34.854,19.146Z" style="fill:#009688"/><path d="M19.854,4.146a.5.5,0,0,0-.708,0l-4,4a.5.5,0,0,0,.708.708L19,5.707V10.5a.5.5,0,0,0,1,0V5.707l3.146,3.147a.5.5,0,0,0,.708-.708Z" style="fill:#009688"/><path d="M23.146,30.146,20,33.293V28.5a.5.5,0,0,0-1,0v4.793l-3.146-3.147a.5.5,0,0,0-.708.708l4,4a.5.5,0,0,0,.708,0l4-4a.5.5,0,0,0-.708-.708Z" style="fill:#009688"/><path d="M10.5,19H5.707l3.147-3.146a.5.5,0,0,0-.708-.708l-4,4a.5.5,0,0,0,0,.708l4,4a.5.5,0,0,0,.708-.708L5.707,20H10.5a.5.5,0,0,0,0-1Z" style="fill:#009688"/><path d="M24.5,26h-10A1.5,1.5,0,0,1,13,24.5v-10A1.5,1.5,0,0,1,14.5,13h10A1.5,1.5,0,0,1,26,14.5v10A1.5,1.5,0,0,1,24.5,26Zm-10-12a.5.5,0,0,0-.5.5v10a.5.5,0,0,0,.5.5h10a.5.5,0,0,0,.5-.5v-10a.5.5,0,0,0-.5-.5Z" style="fill:#b6b6b6"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M.5,13.5V1.5a1,1,0,0,1,1-1h12a1,1,0,0,1,1,1v12a1,1,0,0,1-1,1H1.5A1,1,0,0,1,.5,13.5Z" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M5,5h6v6H5z" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1;stroke-dasharray:2 1.5"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M.5,13.5V1.5a1,1,0,0,1,1-1h12a1,1,0,0,1,1,1v12a1,1,0,0,1-1,1H1.5A1,1,0,0,1,.5,13.5Z" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M8,3.5v5m-2-2 2,2 2-2" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M4,11.5h8" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40"><path d="M34.923,10.25a.392.392,0,0,0-.033-.05.5.5,0,0,0-.2-.162l0,0-15-6a.5.5,0,0,0-.372,0l-15,6,0,0a.5.5,0,0,0-.2.162.392.392,0,0,0-.033.05A.478.478,0,0,0,4,10.5v18a.464.464,0,0,0,.028.138.429.429,0,0,0,.011.054l.01.015a.51.51,0,0,0,.1.144l.008,0a.5.5,0,0,0,.156.1l0,0,14.989,6,0,0,.006,0a.5.5,0,0,0,.372,0l.006,0,0,0,1.989-.8a.5.5,0,0,0-.372-.928L20,33.762V16.839l14-5.6V21.5a.5.5,0,0,0,1,0v-11A.481.481,0,0,0,34.923,10.25ZM19,33.762l-14-5.6V11.239l14,5.6Zm.5-17.8L5.846,10.5,19.5,5.039,33.153,10.5Z" style="fill:#b6b6b6"/><path d="M33.5,24h-8A1.5,1.5,0,0,0,24,25.5v8A1.5,1.5,0,0,0,25.5,35h8A1.5,1.5,0,0,0,35,33.5v-8A1.5,1.5,0,0,0,33.5,24Zm.5,9.5a.5.5,0,0,1-.5.5h-8a.5.5,0,0,1-.5-.5v-8a.5.5,0,0,1,.5-.5h8a.5.5,0,0,1,.5.5Z" style="fill:#009688"/><path d="M32.5,29H30V26.5a.5.5,0,0,0-1,0V29H26.5a.5.5,0,0,0,0,1H29v2.5a.5.5,0,0,0,1,0V30h2.5a.5.5,0,0,0,0-1Z" style="fill:#009688"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40"><path d="M25.5,22a.5.5,0,0,1-.5-.5V18H18v3.5a.5.5,0,0,1-1,0v-6a.5.5,0,0,1,.084-.277l2-3A.5.5,0,0,1,19.5,12h4a.5.5,0,0,1,.416.223l2,3A.5.5,0,0,1,26,15.5v6A.5.5,0,0,1,25.5,22ZM18,17h7V15.651L23.232,13H19.768L18,15.651Z" style="fill:#009688"/><path d="M11.964,29.314a.5.5,0,0,0-.65-.278L7.152,30.7a17.321,17.321,0,0,1,3.739-6.888.5.5,0,1,0-.782-.624A19.312,19.312,0,0,0,6.359,29.8L4.964,26.314a.5.5,0,1,0-.928.372l2,5c0,.01.016.015.021.025a.475.475,0,0,0,.15.185c.009.007.016.017.025.023a.5.5,0,0,0,.2.076A.367.367,0,0,0,6.5,32h0a.475.475,0,0,0,.181-.036h0l5-2A.5.5,0,0,0,11.964,29.314Z" style="fill:#009688"/><rect x="4" y="34" width="31" height="1" style="fill:#009688"/><path d="M34.854,17.146l-13-13a.5.5,0,0,0-.708,0l-13,13a.5.5,0,0,0,.708.708L21.5,5.207,33.793,17.5,21.146,30.146a.5.5,0,0,0,.708.708l13-13A.5.5,0,0,0,34.854,17.146Z" style="fill:#b6b6b6"/><path d="M21.5,31a.5.5,0,0,1-.354-.146l-13-13a.5.5,0,0,1,.708-.708l13,13A.5.5,0,0,1,21.5,31Z" style="fill:#009688"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40"><path d="M27.878,34.926h-4.4c-.509,0-.845,0-.955-.394a.593.593,0,0,1,.36-.67,2.3,2.3,0,0,0,1.2-2.189,3.253,3.253,0,1,1,3.8,3.206Zm-3.538-1h2.988a2.253,2.253,0,1,0-2.253-2.253A3.445,3.445,0,0,1,24.34,33.926Z" style="fill:#009688"/><path d="M30.5,30.289l-.846-.535,4.364-6.9a.222.222,0,0,0-.36-.258l-5.4,6.644-.776-.631,5.4-6.644a1.222,1.222,0,0,1,1.982,1.423Z" style="fill:#009688"/><path d="M33.5,35h-1a.5.5,0,0,1,0-1h1a.5.5,0,0,0,.5-.5v-5a.5.5,0,0,1,1,0v5A1.5,1.5,0,0,1,33.5,35Z" style="fill:#b6b6b6"/><path d="M7.5,35a.5.5,0,0,1-.5-.5v-20a.5.5,0,0,1,1,0v20A.5.5,0,0,1,7.5,35Z" style="fill:#009688"/><path d="M10.5,35a.5.5,0,0,1-.5-.5v-20a.5.5,0,0,1,1,0v20A.5.5,0,0,1,10.5,35Z" style="fill:#009688"/><path d="M13.5,35h-9a.5.5,0,0,1-.5-.5v-20a.5.5,0,0,1,.5-.5h9a.5.5,0,0,1,.5.5v20A.5.5,0,0,1,13.5,35ZM5,34h8V15H5Z" style="fill:#009688"/><path d="M22.5,29a.5.5,0,0,1-.5-.5V15H4.5a.5.5,0,0,1-.5-.5v-9A1.5,1.5,0,0,1,5.5,4h28A1.5,1.5,0,0,1,35,5.5v13a.5.5,0,0,1-1,0V5.5a.5.5,0,0,0-.5-.5H5.5a.5.5,0,0,0-.5.5V14H22.5a.5.5,0,0,1,.5.5v14A.5.5,0,0,1,22.5,29Z" style="fill:#b6b6b6"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40"><path d="M24.5,26h-10A1.5,1.5,0,0,1,13,24.5v-10A1.5,1.5,0,0,1,14.5,13h10A1.5,1.5,0,0,1,26,14.5v10A1.5,1.5,0,0,1,24.5,26Zm-10-12a.5.5,0,0,0-.5.5v10a.5.5,0,0,0,.5.5h10a.5.5,0,0,0,.5-.5v-10a.5.5,0,0,0-.5-.5Z" style="fill:#b6b6b6"/><path d="M35,19.5A15.517,15.517,0,0,1,19.5,35a15.767,15.767,0,0,1-2.063-.136.5.5,0,0,1-.43-.562.507.507,0,0,1,.562-.43A14.5,14.5,0,1,0,19.5,5,14.43,14.43,0,0,0,7.751,11H11.5a.5.5,0,0,1,0,1h-5a.5.5,0,0,1-.5-.5v-5a.5.5,0,0,1,1,0v3.836A15.5,15.5,0,0,1,35,19.5ZM5.943,24.66a.5.5,0,1,0-.933.356A15.426,15.426,0,0,0,7.354,29.13a.5.5,0,0,0,.783-.621A14.533,14.533,0,0,1,5.943,24.66Zm8.4,8.4a14.523,14.523,0,0,1-3.85-2.194.5.5,0,0,0-.621.784,15.455,15.455,0,0,0,4.115,2.343.487.487,0,0,0,.178.033.5.5,0,0,0,.178-.966ZM5.128,21.431A14.621,14.621,0,0,1,5,19.5a.5.5,0,0,0-1,0,15.729,15.729,0,0,0,.136,2.062.5.5,0,0,0,.992-.131Z" style="fill:#009688"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40"><path d="M25.5,5h-2a.5.5,0,0,1,0-1h2a.5.5,0,0,1,0,1ZM21,4.5a.5.5,0,0,0-.5-.5h-2a.5.5,0,0,0,0,1h2A.5.5,0,0,0,21,4.5Zm-5,0a.5.5,0,0,0-.5-.5h-2a.5.5,0,0,0,0,1h2A.5.5,0,0,0,16,4.5Zm10,30a.5.5,0,0,0-.5-.5h-2a.5.5,0,0,0,0,1h2A.5.5,0,0,0,26,34.5Zm-5,0a.5.5,0,0,0-.5-.5h-2a.5.5,0,0,0,0,1h2A.5.5,0,0,0,21,34.5Zm-5,0a.5.5,0,0,0-.5-.5h-2a.5.5,0,0,0,0,1h2A.5.5,0,0,0,16,34.5ZM5,15.5v-2a.5.5,0,0,0-1,0v2a.5.5,0,0,0,1,0Zm0,5v-2a.5.5,0,0,0-1,0v2a.5.5,0,0,0,1,0Zm0,5v-2a.5.5,0,0,0-1,0v2a.5.5,0,0,0,1,0Zm30-10v-2a.5.5,0,0,0-1,0v2a.5.5,0,0,0,1,0Zm0,5v-2a.5.5,0,0,0-1,0v2a.5.5,0,0,0,1,0Zm0,5v-2a.5.5,0,0,0-1,0v2a.5.5,0,0,0,1,0Zm-9-1v-10A1.5,1.5,0,0,0,24.5,13h-10A1.5,1.5,0,0,0,13,14.5v10A1.5,1.5,0,0,0,14.5,26h10A1.5,1.5,0,0,0,26,24.5ZM24.5,14a.5.5,0,0,1,.5.5v10a.5.5,0,0,1-.5.5h-10a.5.5,0,0,1-.5-.5v-10a.5.5,0,0,1,.5-.5Z" style="fill:#b6b6b6"/><path d="M34.962,4.309A.5.5,0,0,0,34.5,4h-5a.5.5,0,0,0,0,1h3.793l-6.147,6.146a.5.5,0,0,0,.708.708L34,5.707V9.5a.5.5,0,0,0,1,0v-5A.5.5,0,0,0,34.962,4.309Z" style="fill:#009688"/><path d="M5.707,5H9.5a.5.5,0,0,0,0-1h-5a.5.5,0,0,0-.5.5v5a.5.5,0,0,0,1,0V5.707l6.146,6.147a.5.5,0,0,0,.708-.708Z" style="fill:#009688"/><path d="M34.5,29a.5.5,0,0,0-.5.5v3.793l-6.146-6.147a.5.5,0,0,0-.708.708L33.293,34H29.5a.5.5,0,0,0,0,1h5a.5.5,0,0,0,.5-.5v-5A.5.5,0,0,0,34.5,29Z" style="fill:#009688"/><path d="M11.146,27.146,5,33.293V29.5a.5.5,0,0,0-1,0v5a.5.5,0,0,0,.5.5h5a.5.5,0,0,0,0-1H5.707l6.147-6.146a.5.5,0,0,0-.708-.708Z" style="fill:#009688"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M.5,13.5V1.5a1,1,0,0,1,1-1h12a1,1,0,0,1,1,1v12a1,1,0,0,1-1,1H1.5A1,1,0,0,1,.5,13.5Z" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M8,3.5v2m0,2v2m0,2v2" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M.5,13.5V1.5a1,1,0,0,1,1-1h12a1,1,0,0,1,1,1v12a1,1,0,0,1-1,1H1.5A1,1,0,0,1,.5,13.5Z" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M8,3.5v9" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M6,6.5,4,8l2,1.5" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M10,6.5,12,8l-2,1.5" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M.5,13.5V1.5a1,1,0,0,1,1-1h12a1,1,0,0,1,1,1v12a1,1,0,0,1-1,1H1.5A1,1,0,0,1,.5,13.5Z" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M4.5,5h7" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M8,5v6.5" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M3,4.5h10" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M3,7h10" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M3,9h10" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M3,10.5h10" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M3,11.6h10" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/></svg>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// 아이콘 데이터 URI — assets/*.svg 를 인라인(번들러 svg 로더 의존 제거).
|
|
2
|
+
// 재생성: node -e 로 assets 를 순회해 이 파일을 다시 쓴다(수동 편집 금지).
|
|
3
|
+
export const addIcon = 'data:image/svg+xml;utf8,' + encodeURIComponent("<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><path d=\"M.5,13.5V1.5a1,1,0,0,1,1-1h12a1,1,0,0,1,1,1v12a1,1,0,0,1-1,1H1.5A1,1,0,0,1,.5,13.5Zm3-6h3m2,0h3m-4-4v8\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/></svg>")
|
|
4
|
+
export const arrangeIcon = 'data:image/svg+xml;utf8,' + encodeURIComponent("<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"40\" height=\"40\" viewBox=\"0 0 40 40\"><path d=\"M33.5,35H5.5A1.5,1.5,0,0,1,4,33.5V5.5A1.5,1.5,0,0,1,5.5,4h28A1.5,1.5,0,0,1,35,5.5v28A1.5,1.5,0,0,1,33.5,35ZM5.5,5a.5.5,0,0,0-.5.5v28a.5.5,0,0,0,.5.5h28a.5.5,0,0,0,.5-.5V5.5a.5.5,0,0,0-.5-.5Z\" style=\"fill:#b6b6b6\"/><path d=\"M30.5,32H8.5A1.5,1.5,0,0,1,7,30.5v-6A1.5,1.5,0,0,1,8.5,23h22A1.5,1.5,0,0,1,32,24.5v6A1.5,1.5,0,0,1,30.5,32Zm-22-8a.5.5,0,0,0-.5.5v6a.5.5,0,0,0,.5.5h22a.5.5,0,0,0,.5-.5v-6a.5.5,0,0,0-.5-.5Zm22-2h-6A1.5,1.5,0,0,1,23,20.5V8.5A1.5,1.5,0,0,1,24.5,7h6A1.5,1.5,0,0,1,32,8.5v12A1.5,1.5,0,0,1,30.5,22Zm-6-14a.5.5,0,0,0-.5.5v12a.5.5,0,0,0,.5.5h6a.5.5,0,0,0,.5-.5V8.5a.5.5,0,0,0-.5-.5Zm-6,6h-8a3.5,3.5,0,0,1,0-7h8a3.5,3.5,0,0,1,0,7Zm-8-6a2.5,2.5,0,0,0,0,5h8a2.5,2.5,0,0,0,0-5Zm8,14A3.5,3.5,0,1,1,22,18.5,3.5,3.5,0,0,1,18.5,22Zm0-6A2.5,2.5,0,1,0,21,18.5,2.5,2.5,0,0,0,18.5,16Zm-8,6A3.5,3.5,0,1,1,14,18.5,3.5,3.5,0,0,1,10.5,22Zm0-6A2.5,2.5,0,1,0,13,18.5,2.5,2.5,0,0,0,10.5,16Z\" style=\"fill:#009688\"/></svg>")
|
|
5
|
+
export const booleanIcon = 'data:image/svg+xml;utf8,' + encodeURIComponent("<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><path d=\"M6.2,8a2.6,2.6,0,1,0,5.2,0a2.6,2.6,0,1,0,-5.2,0\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/><path d=\"M4.6,8a2.6,2.6,0,1,0,5.2,0a2.6,2.6,0,1,0,-5.2,0\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/></svg>")
|
|
6
|
+
export const cutIcon = 'data:image/svg+xml;utf8,' + encodeURIComponent("<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><path d=\"M.5,13.5V1.5a1,1,0,0,1,1-1h12a1,1,0,0,1,1,1v12a1,1,0,0,1-1,1H1.5A1,1,0,0,1,.5,13.5Z\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/><path d=\"M3.5,9h2m2,0h2m2,0h2\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/><path d=\"M8,3.5l1.8,3h-3.6z\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/></svg>")
|
|
7
|
+
export const deleteIcon = 'data:image/svg+xml;utf8,' + encodeURIComponent("<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><path d=\"M.5,13.5V1.5a1,1,0,0,1,1-1h12a1,1,0,0,1,1,1v12a1,1,0,0,1-1,1H1.5A1,1,0,0,1,.5,13.5Zm3-6h8\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/></svg>")
|
|
8
|
+
export const deleteallIcon = 'data:image/svg+xml;utf8,' + encodeURIComponent("<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><path d=\"M.5,13.5V1.5a1,1,0,0,1,1-1h12a1,1,0,0,1,1,1v12a1,1,0,0,1-1,1H1.5A1,1,0,0,1,.5,13.5Z\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/><path d=\"M5,5l6,6\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/><path d=\"M11,5l-6,6\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/></svg>")
|
|
9
|
+
export const duplicateIcon = 'data:image/svg+xml;utf8,' + encodeURIComponent("<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><path d=\"M4,4h5v5H4z\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/><path d=\"M7,7h5v5H7z\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/></svg>")
|
|
10
|
+
export const measureIcon = 'data:image/svg+xml;utf8,' + encodeURIComponent("<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><path d=\"M2.5,8h11\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/><path d=\"M2.5,6v4\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/><path d=\"M13.5,6v4\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/><path d=\"M6,7v2\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/><path d=\"M10,7v2\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/></svg>")
|
|
11
|
+
export const mmuIcon = 'data:image/svg+xml;utf8,' + encodeURIComponent("<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><path d=\"M4,8a4,4,0,1,0,8,0a4,4,0,1,0,-8,0\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/><path d=\"M8,4a4,4,0,0,1,0,8z\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1;fill:#949494;stroke:none\"/></svg>")
|
|
12
|
+
export const moveIcon = 'data:image/svg+xml;utf8,' + encodeURIComponent("<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"40\" height=\"40\" viewBox=\"0 0 40 40\"><path d=\"M34.854,19.146l-4-4a.5.5,0,0,0-.708.708L33.293,19H28.5a.5.5,0,0,0,0,1h4.793l-3.147,3.146a.5.5,0,0,0,.708.708l4-4A.5.5,0,0,0,34.854,19.146Z\" style=\"fill:#009688\"/><path d=\"M19.854,4.146a.5.5,0,0,0-.708,0l-4,4a.5.5,0,0,0,.708.708L19,5.707V10.5a.5.5,0,0,0,1,0V5.707l3.146,3.147a.5.5,0,0,0,.708-.708Z\" style=\"fill:#009688\"/><path d=\"M23.146,30.146,20,33.293V28.5a.5.5,0,0,0-1,0v4.793l-3.146-3.147a.5.5,0,0,0-.708.708l4,4a.5.5,0,0,0,.708,0l4-4a.5.5,0,0,0-.708-.708Z\" style=\"fill:#009688\"/><path d=\"M10.5,19H5.707l3.147-3.146a.5.5,0,0,0-.708-.708l-4,4a.5.5,0,0,0,0,.708l4,4a.5.5,0,0,0,.708-.708L5.707,20H10.5a.5.5,0,0,0,0-1Z\" style=\"fill:#009688\"/><path d=\"M24.5,26h-10A1.5,1.5,0,0,1,13,24.5v-10A1.5,1.5,0,0,1,14.5,13h10A1.5,1.5,0,0,1,26,14.5v10A1.5,1.5,0,0,1,24.5,26Zm-10-12a.5.5,0,0,0-.5.5v10a.5.5,0,0,0,.5.5h10a.5.5,0,0,0,.5-.5v-10a.5.5,0,0,0-.5-.5Z\" style=\"fill:#b6b6b6\"/></svg>")
|
|
13
|
+
export const negativeIcon = 'data:image/svg+xml;utf8,' + encodeURIComponent("<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><path d=\"M.5,13.5V1.5a1,1,0,0,1,1-1h12a1,1,0,0,1,1,1v12a1,1,0,0,1-1,1H1.5A1,1,0,0,1,.5,13.5Z\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/><path d=\"M5,5h6v6H5z\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1;stroke-dasharray:2 1.5\"/></svg>")
|
|
14
|
+
export const onbedIcon = 'data:image/svg+xml;utf8,' + encodeURIComponent("<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><path d=\"M.5,13.5V1.5a1,1,0,0,1,1-1h12a1,1,0,0,1,1,1v12a1,1,0,0,1-1,1H1.5A1,1,0,0,1,.5,13.5Z\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/><path d=\"M8,3.5v5m-2-2 2,2 2-2\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/><path d=\"M4,11.5h8\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/></svg>")
|
|
15
|
+
export const openIcon = 'data:image/svg+xml;utf8,' + encodeURIComponent("<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"40\" height=\"40\" viewBox=\"0 0 40 40\"><path d=\"M34.923,10.25a.392.392,0,0,0-.033-.05.5.5,0,0,0-.2-.162l0,0-15-6a.5.5,0,0,0-.372,0l-15,6,0,0a.5.5,0,0,0-.2.162.392.392,0,0,0-.033.05A.478.478,0,0,0,4,10.5v18a.464.464,0,0,0,.028.138.429.429,0,0,0,.011.054l.01.015a.51.51,0,0,0,.1.144l.008,0a.5.5,0,0,0,.156.1l0,0,14.989,6,0,0,.006,0a.5.5,0,0,0,.372,0l.006,0,0,0,1.989-.8a.5.5,0,0,0-.372-.928L20,33.762V16.839l14-5.6V21.5a.5.5,0,0,0,1,0v-11A.481.481,0,0,0,34.923,10.25ZM19,33.762l-14-5.6V11.239l14,5.6Zm.5-17.8L5.846,10.5,19.5,5.039,33.153,10.5Z\" style=\"fill:#b6b6b6\"/><path d=\"M33.5,24h-8A1.5,1.5,0,0,0,24,25.5v8A1.5,1.5,0,0,0,25.5,35h8A1.5,1.5,0,0,0,35,33.5v-8A1.5,1.5,0,0,0,33.5,24Zm.5,9.5a.5.5,0,0,1-.5.5h-8a.5.5,0,0,1-.5-.5v-8a.5.5,0,0,1,.5-.5h8a.5.5,0,0,1,.5.5Z\" style=\"fill:#009688\"/><path d=\"M32.5,29H30V26.5a.5.5,0,0,0-1,0V29H26.5a.5.5,0,0,0,0,1H29v2.5a.5.5,0,0,0,1,0V30h2.5a.5.5,0,0,0,0-1Z\" style=\"fill:#009688\"/></svg>")
|
|
16
|
+
export const orientIcon = 'data:image/svg+xml;utf8,' + encodeURIComponent("<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"40\" height=\"40\" viewBox=\"0 0 40 40\"><path d=\"M25.5,22a.5.5,0,0,1-.5-.5V18H18v3.5a.5.5,0,0,1-1,0v-6a.5.5,0,0,1,.084-.277l2-3A.5.5,0,0,1,19.5,12h4a.5.5,0,0,1,.416.223l2,3A.5.5,0,0,1,26,15.5v6A.5.5,0,0,1,25.5,22ZM18,17h7V15.651L23.232,13H19.768L18,15.651Z\" style=\"fill:#009688\"/><path d=\"M11.964,29.314a.5.5,0,0,0-.65-.278L7.152,30.7a17.321,17.321,0,0,1,3.739-6.888.5.5,0,1,0-.782-.624A19.312,19.312,0,0,0,6.359,29.8L4.964,26.314a.5.5,0,1,0-.928.372l2,5c0,.01.016.015.021.025a.475.475,0,0,0,.15.185c.009.007.016.017.025.023a.5.5,0,0,0,.2.076A.367.367,0,0,0,6.5,32h0a.475.475,0,0,0,.181-.036h0l5-2A.5.5,0,0,0,11.964,29.314Z\" style=\"fill:#009688\"/><rect x=\"4\" y=\"34\" width=\"31\" height=\"1\" style=\"fill:#009688\"/><path d=\"M34.854,17.146l-13-13a.5.5,0,0,0-.708,0l-13,13a.5.5,0,0,0,.708.708L21.5,5.207,33.793,17.5,21.146,30.146a.5.5,0,0,0,.708.708l13-13A.5.5,0,0,0,34.854,17.146Z\" style=\"fill:#b6b6b6\"/><path d=\"M21.5,31a.5.5,0,0,1-.354-.146l-13-13a.5.5,0,0,1,.708-.708l13,13A.5.5,0,0,1,21.5,31Z\" style=\"fill:#009688\"/></svg>")
|
|
17
|
+
export const paintIcon = 'data:image/svg+xml;utf8,' + encodeURIComponent("<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"40\" height=\"40\" viewBox=\"0 0 40 40\"><path d=\"M27.878,34.926h-4.4c-.509,0-.845,0-.955-.394a.593.593,0,0,1,.36-.67,2.3,2.3,0,0,0,1.2-2.189,3.253,3.253,0,1,1,3.8,3.206Zm-3.538-1h2.988a2.253,2.253,0,1,0-2.253-2.253A3.445,3.445,0,0,1,24.34,33.926Z\" style=\"fill:#009688\"/><path d=\"M30.5,30.289l-.846-.535,4.364-6.9a.222.222,0,0,0-.36-.258l-5.4,6.644-.776-.631,5.4-6.644a1.222,1.222,0,0,1,1.982,1.423Z\" style=\"fill:#009688\"/><path d=\"M33.5,35h-1a.5.5,0,0,1,0-1h1a.5.5,0,0,0,.5-.5v-5a.5.5,0,0,1,1,0v5A1.5,1.5,0,0,1,33.5,35Z\" style=\"fill:#b6b6b6\"/><path d=\"M7.5,35a.5.5,0,0,1-.5-.5v-20a.5.5,0,0,1,1,0v20A.5.5,0,0,1,7.5,35Z\" style=\"fill:#009688\"/><path d=\"M10.5,35a.5.5,0,0,1-.5-.5v-20a.5.5,0,0,1,1,0v20A.5.5,0,0,1,10.5,35Z\" style=\"fill:#009688\"/><path d=\"M13.5,35h-9a.5.5,0,0,1-.5-.5v-20a.5.5,0,0,1,.5-.5h9a.5.5,0,0,1,.5.5v20A.5.5,0,0,1,13.5,35ZM5,34h8V15H5Z\" style=\"fill:#009688\"/><path d=\"M22.5,29a.5.5,0,0,1-.5-.5V15H4.5a.5.5,0,0,1-.5-.5v-9A1.5,1.5,0,0,1,5.5,4h28A1.5,1.5,0,0,1,35,5.5v13a.5.5,0,0,1-1,0V5.5a.5.5,0,0,0-.5-.5H5.5a.5.5,0,0,0-.5.5V14H22.5a.5.5,0,0,1,.5.5v14A.5.5,0,0,1,22.5,29Z\" style=\"fill:#b6b6b6\"/></svg>")
|
|
18
|
+
export const rotateIcon = 'data:image/svg+xml;utf8,' + encodeURIComponent("<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"40\" height=\"40\" viewBox=\"0 0 40 40\"><path d=\"M24.5,26h-10A1.5,1.5,0,0,1,13,24.5v-10A1.5,1.5,0,0,1,14.5,13h10A1.5,1.5,0,0,1,26,14.5v10A1.5,1.5,0,0,1,24.5,26Zm-10-12a.5.5,0,0,0-.5.5v10a.5.5,0,0,0,.5.5h10a.5.5,0,0,0,.5-.5v-10a.5.5,0,0,0-.5-.5Z\" style=\"fill:#b6b6b6\"/><path d=\"M35,19.5A15.517,15.517,0,0,1,19.5,35a15.767,15.767,0,0,1-2.063-.136.5.5,0,0,1-.43-.562.507.507,0,0,1,.562-.43A14.5,14.5,0,1,0,19.5,5,14.43,14.43,0,0,0,7.751,11H11.5a.5.5,0,0,1,0,1h-5a.5.5,0,0,1-.5-.5v-5a.5.5,0,0,1,1,0v3.836A15.5,15.5,0,0,1,35,19.5ZM5.943,24.66a.5.5,0,1,0-.933.356A15.426,15.426,0,0,0,7.354,29.13a.5.5,0,0,0,.783-.621A14.533,14.533,0,0,1,5.943,24.66Zm8.4,8.4a14.523,14.523,0,0,1-3.85-2.194.5.5,0,0,0-.621.784,15.455,15.455,0,0,0,4.115,2.343.487.487,0,0,0,.178.033.5.5,0,0,0,.178-.966ZM5.128,21.431A14.621,14.621,0,0,1,5,19.5a.5.5,0,0,0-1,0,15.729,15.729,0,0,0,.136,2.062.5.5,0,0,0,.992-.131Z\" style=\"fill:#009688\"/></svg>")
|
|
19
|
+
export const scaleIcon = 'data:image/svg+xml;utf8,' + encodeURIComponent("<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"40\" height=\"40\" viewBox=\"0 0 40 40\"><path d=\"M25.5,5h-2a.5.5,0,0,1,0-1h2a.5.5,0,0,1,0,1ZM21,4.5a.5.5,0,0,0-.5-.5h-2a.5.5,0,0,0,0,1h2A.5.5,0,0,0,21,4.5Zm-5,0a.5.5,0,0,0-.5-.5h-2a.5.5,0,0,0,0,1h2A.5.5,0,0,0,16,4.5Zm10,30a.5.5,0,0,0-.5-.5h-2a.5.5,0,0,0,0,1h2A.5.5,0,0,0,26,34.5Zm-5,0a.5.5,0,0,0-.5-.5h-2a.5.5,0,0,0,0,1h2A.5.5,0,0,0,21,34.5Zm-5,0a.5.5,0,0,0-.5-.5h-2a.5.5,0,0,0,0,1h2A.5.5,0,0,0,16,34.5ZM5,15.5v-2a.5.5,0,0,0-1,0v2a.5.5,0,0,0,1,0Zm0,5v-2a.5.5,0,0,0-1,0v2a.5.5,0,0,0,1,0Zm0,5v-2a.5.5,0,0,0-1,0v2a.5.5,0,0,0,1,0Zm30-10v-2a.5.5,0,0,0-1,0v2a.5.5,0,0,0,1,0Zm0,5v-2a.5.5,0,0,0-1,0v2a.5.5,0,0,0,1,0Zm0,5v-2a.5.5,0,0,0-1,0v2a.5.5,0,0,0,1,0Zm-9-1v-10A1.5,1.5,0,0,0,24.5,13h-10A1.5,1.5,0,0,0,13,14.5v10A1.5,1.5,0,0,0,14.5,26h10A1.5,1.5,0,0,0,26,24.5ZM24.5,14a.5.5,0,0,1,.5.5v10a.5.5,0,0,1-.5.5h-10a.5.5,0,0,1-.5-.5v-10a.5.5,0,0,1,.5-.5Z\" style=\"fill:#b6b6b6\"/><path d=\"M34.962,4.309A.5.5,0,0,0,34.5,4h-5a.5.5,0,0,0,0,1h3.793l-6.147,6.146a.5.5,0,0,0,.708.708L34,5.707V9.5a.5.5,0,0,0,1,0v-5A.5.5,0,0,0,34.962,4.309Z\" style=\"fill:#009688\"/><path d=\"M5.707,5H9.5a.5.5,0,0,0,0-1h-5a.5.5,0,0,0-.5.5v5a.5.5,0,0,0,1,0V5.707l6.146,6.147a.5.5,0,0,0,.708-.708Z\" style=\"fill:#009688\"/><path d=\"M34.5,29a.5.5,0,0,0-.5.5v3.793l-6.146-6.147a.5.5,0,0,0-.708.708L33.293,34H29.5a.5.5,0,0,0,0,1h5a.5.5,0,0,0,.5-.5v-5A.5.5,0,0,0,34.5,29Z\" style=\"fill:#009688\"/><path d=\"M11.146,27.146,5,33.293V29.5a.5.5,0,0,0-1,0v5a.5.5,0,0,0,.5.5h5a.5.5,0,0,0,0-1H5.707l6.147-6.146a.5.5,0,0,0-.708-.708Z\" style=\"fill:#009688\"/></svg>")
|
|
20
|
+
export const seamIcon = 'data:image/svg+xml;utf8,' + encodeURIComponent("<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><path d=\"M.5,13.5V1.5a1,1,0,0,1,1-1h12a1,1,0,0,1,1,1v12a1,1,0,0,1-1,1H1.5A1,1,0,0,1,.5,13.5Z\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/><path d=\"M8,3.5v2m0,2v2m0,2v2\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/></svg>")
|
|
21
|
+
export const splitIcon = 'data:image/svg+xml;utf8,' + encodeURIComponent("<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><path d=\"M.5,13.5V1.5a1,1,0,0,1,1-1h12a1,1,0,0,1,1,1v12a1,1,0,0,1-1,1H1.5A1,1,0,0,1,.5,13.5Z\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/><path d=\"M8,3.5v9\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/><path d=\"M6,6.5,4,8l2,1.5\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/><path d=\"M10,6.5,12,8l-2,1.5\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/></svg>")
|
|
22
|
+
export const textmarkIcon = 'data:image/svg+xml;utf8,' + encodeURIComponent("<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><path d=\"M.5,13.5V1.5a1,1,0,0,1,1-1h12a1,1,0,0,1,1,1v12a1,1,0,0,1-1,1H1.5A1,1,0,0,1,.5,13.5Z\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/><path d=\"M4.5,5h7\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/><path d=\"M8,5v6.5\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/></svg>")
|
|
23
|
+
export const varlayerIcon = 'data:image/svg+xml;utf8,' + encodeURIComponent("<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><path d=\"M3,4.5h10\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/><path d=\"M3,7h10\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/><path d=\"M3,9h10\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/><path d=\"M3,10.5h10\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/><path d=\"M3,11.6h10\" style=\"fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1\"/></svg>")
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// 슬라이서 워커 생성 — 이 파일은 번들되지 않고 dist/ 에 원형 복사된다 (build 스크립트).
|
|
2
|
+
// 이유: 소비자 번들러(Vite/webpack)가 워커를 청크로 인식하려면 `new Worker(new URL('리터럴', import.meta.url))`
|
|
3
|
+
// 정적 패턴이 소비자에게 보이는 파일에 그대로 남아 있어야 한다. viewer 자체 lib 빌드가 이걸 처리하면
|
|
4
|
+
// 사이트 루트 기준 절대경로 자산으로 굳어져 소비자 앱에서 404 가 난다.
|
|
5
|
+
// 경로 '../../engine/…' 은 dist/ 기준: 모노레포(packages/viewer/dist→packages/engine)와
|
|
6
|
+
// npm 설치(@three-slicer/ 스코프 형제 디렉토리) 양쪽에서 engine 패키지로 해석된다.
|
|
7
|
+
export function makeSlicerWorker() {
|
|
8
|
+
return new Worker(new URL('../../engine/src/slicer.worker.js', import.meta.url), { type: 'module' })
|
|
9
|
+
}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
// 26단계: 통일 모델 임포트 파이프라인 — STL/OBJ/3MF/AMF/PLY.
|
|
2
|
+
// three/examples/jsm 로더 재사용(신규 npm 의존성 없음). 각 로더 결과(BufferGeometry|Group) →
|
|
3
|
+
// 월드행렬 베이크 → 비인덱스 삼각형 → **model z-up** flat 배열(N*9). 슬라이스 경로(addObject→buildMergedSTL→커널) 재사용.
|
|
4
|
+
// 좌표계(실측): 3D 프린팅 포맷은 모두 z-up mm. three 로더는 축 변환을 하지 않고 파일 원좌표를 그대로 로드하므로,
|
|
5
|
+
// STL/3MF/AMF/PLY 는 z-up 그대로 model 좌표로 사용. OBJ 는 관례상 y-up(그래픽) 가능성이 있으나 프린팅 OBJ 는 z-up 이
|
|
6
|
+
// 일반적 → z-up 기본(부적절 시 기즈모 회전). 이 판단은 프린팅 워크플로 기준(근거 주석).
|
|
7
|
+
import * as THREE from 'three'
|
|
8
|
+
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js'
|
|
9
|
+
import { PLYLoader } from 'three/examples/jsm/loaders/PLYLoader.js'
|
|
10
|
+
import { ThreeMFLoader } from 'three/examples/jsm/loaders/3MFLoader.js'
|
|
11
|
+
import { AMFLoader } from 'three/examples/jsm/loaders/AMFLoader.js'
|
|
12
|
+
|
|
13
|
+
export const SUPPORTED_EXT = ['stl', 'obj', '3mf', 'amf', 'ply']
|
|
14
|
+
|
|
15
|
+
export function fileExt(name) { const i = name.lastIndexOf('.'); return i < 0 ? '' : name.slice(i + 1).toLowerCase() }
|
|
16
|
+
|
|
17
|
+
// --- STL 파서 (바이너리 + ASCII) → model 좌표 position (N*9) --- (기존 Viewport 로직 이관)
|
|
18
|
+
function parseSTL(buffer) {
|
|
19
|
+
const dv = new DataView(buffer)
|
|
20
|
+
if (buffer.byteLength >= 84) {
|
|
21
|
+
const n = dv.getUint32(80, true)
|
|
22
|
+
if (buffer.byteLength === 84 + n * 50) {
|
|
23
|
+
const pos = new Float32Array(n * 9)
|
|
24
|
+
let off = 84, p = 0
|
|
25
|
+
for (let i = 0; i < n; i++) {
|
|
26
|
+
off += 12
|
|
27
|
+
for (let v = 0; v < 3; v++) { pos[p++] = dv.getFloat32(off, true); pos[p++] = dv.getFloat32(off + 4, true); pos[p++] = dv.getFloat32(off + 8, true); off += 12 }
|
|
28
|
+
off += 2
|
|
29
|
+
}
|
|
30
|
+
return pos
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const text = new TextDecoder().decode(buffer)
|
|
34
|
+
const re = /vertex\s+([-\d.eE+]+)\s+([-\d.eE+]+)\s+([-\d.eE+]+)/g
|
|
35
|
+
const nums = []; let m
|
|
36
|
+
while ((m = re.exec(text))) nums.push(+m[1], +m[2], +m[3])
|
|
37
|
+
if (nums.length < 9) return null
|
|
38
|
+
return new Float32Array(nums)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// BufferGeometry(+월드행렬) → 비인덱스 삼각형 model z-up flat 배열(N*9). 로더 좌표=z-up 그대로 사용.
|
|
42
|
+
function geoToModelTris(geometry, matrix) {
|
|
43
|
+
const pos = geometry?.attributes?.position
|
|
44
|
+
if (!pos || pos.count < 3) return null
|
|
45
|
+
const idx = geometry.index
|
|
46
|
+
const v = new THREE.Vector3()
|
|
47
|
+
const nTri = Math.floor((idx ? idx.count : pos.count) / 3)
|
|
48
|
+
const out = new Float32Array(nTri * 9)
|
|
49
|
+
let o = 0
|
|
50
|
+
const emit = (i) => { v.fromBufferAttribute(pos, i); if (matrix) v.applyMatrix4(matrix); out[o++] = v.x; out[o++] = v.y; out[o++] = v.z }
|
|
51
|
+
if (idx) { for (let i = 0; i < nTri * 3; i++) emit(idx.getX(i)) }
|
|
52
|
+
else { for (let i = 0; i < nTri * 3; i++) emit(i) }
|
|
53
|
+
return out
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Group/Object3D 재귀 → [{geometry, matrixWorld}] (월드행렬 베이크용).
|
|
57
|
+
function collectMeshes(root) {
|
|
58
|
+
root.updateMatrixWorld(true)
|
|
59
|
+
const meshes = []
|
|
60
|
+
root.traverse(o => { if (o.isMesh && o.geometry) meshes.push({ geometry: o.geometry, matrix: o.matrixWorld }) })
|
|
61
|
+
return meshes
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// 로더 결과 → 오브젝트 목록. multi=true(3mf/amf) 면 메시별 개별 오브젝트, 아니면 하나로 병합.
|
|
65
|
+
function meshesToObjects(baseName, meshes, multi) {
|
|
66
|
+
const parts = meshes.map(m => geoToModelTris(m.geometry, m.matrix)).filter(Boolean)
|
|
67
|
+
if (!parts.length) return []
|
|
68
|
+
if (multi && parts.length > 1) {
|
|
69
|
+
return parts.map((p, i) => ({ name: `${baseName}#${i + 1}`, modelPos: p }))
|
|
70
|
+
}
|
|
71
|
+
if (parts.length === 1) return [{ name: baseName, modelPos: parts[0] }]
|
|
72
|
+
// 병합
|
|
73
|
+
let total = 0; for (const p of parts) total += p.length
|
|
74
|
+
const merged = new Float32Array(total); let o = 0
|
|
75
|
+
for (const p of parts) { merged.set(p, o); o += p.length }
|
|
76
|
+
return [{ name: baseName, modelPos: merged }]
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// 공개 API: (파일명, ArrayBuffer) → Promise<[{name, modelPos(N*9, model z-up)}]>. 커널 무관 순수.
|
|
80
|
+
export async function loadModel(name, buffer) {
|
|
81
|
+
const ext = fileExt(name)
|
|
82
|
+
switch (ext) {
|
|
83
|
+
case 'stl': {
|
|
84
|
+
const pos = parseSTL(buffer)
|
|
85
|
+
if (!pos) throw new Error('STL 파싱 실패')
|
|
86
|
+
return [{ name, modelPos: pos }]
|
|
87
|
+
}
|
|
88
|
+
case 'obj': {
|
|
89
|
+
const g = new OBJLoader().parse(new TextDecoder().decode(buffer)) // Group
|
|
90
|
+
return meshesToObjects(name, collectMeshes(g), false)
|
|
91
|
+
}
|
|
92
|
+
case 'ply': {
|
|
93
|
+
const geo = new PLYLoader().parse(buffer) // BufferGeometry
|
|
94
|
+
const tris = geoToModelTris(geo, null)
|
|
95
|
+
if (!tris) throw new Error('PLY 지오메트리 없음')
|
|
96
|
+
return [{ name, modelPos: tris }]
|
|
97
|
+
}
|
|
98
|
+
case '3mf': {
|
|
99
|
+
const g = new ThreeMFLoader().parse(buffer) // Group (fflate 로 unzip, three 내부)
|
|
100
|
+
const objs = meshesToObjects(name, collectMeshes(g), true) // 복수 오브젝트 개별 등록
|
|
101
|
+
if (!objs.length) throw new Error('3MF 메시 없음')
|
|
102
|
+
return objs
|
|
103
|
+
}
|
|
104
|
+
case 'amf': {
|
|
105
|
+
const g = new AMFLoader().parse(buffer) // Group (DOMParser 사용 — 브라우저)
|
|
106
|
+
const objs = meshesToObjects(name, collectMeshes(g), true)
|
|
107
|
+
if (!objs.length) throw new Error('AMF 메시 없음')
|
|
108
|
+
return objs
|
|
109
|
+
}
|
|
110
|
+
default:
|
|
111
|
+
throw new Error(`지원하지 않는 포맷: .${ext} (STEP 은 범위 외 — OCCT 필요)`)
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// ---- 33단계: 객체 분리 (원본 Split to objects / TriangleMesh::its_split) ----
|
|
116
|
+
// 원본 정의: "면은 **에지를 공유하면** 연결된 것으로 본다(공유 에지 = 정점 인덱스 2개 공유)"
|
|
117
|
+
// (TriangleMesh.cpp:1505). 그 연결 성분(patch)마다 독립 오브젝트가 된다.
|
|
118
|
+
// 우리 localPos 는 비인덱스 삼각형 스트림(정점 9개/삼각형)이라, 먼저 좌표를 양자화해 정점을 용접하고
|
|
119
|
+
// 에지를 만든 뒤 union-find 로 성분을 모은다. 인접 리스트를 만들지 않아 메모리/시간이 선형에 가깝다.
|
|
120
|
+
//
|
|
121
|
+
// 반환: 성분이 2개 이상이면 Float32Array[] (각 성분의 localPos, 좌표계는 입력 그대로),
|
|
122
|
+
// 1개면 null (분리 불가).
|
|
123
|
+
export function splitConnectedComponents(localPos) {
|
|
124
|
+
const nTri = Math.floor(localPos.length / 9)
|
|
125
|
+
if (nTri < 2) return null
|
|
126
|
+
|
|
127
|
+
// 정점 용접: 부동소수 오차로 같은 점이 갈라지지 않도록 1e-4mm 격자로 양자화
|
|
128
|
+
const Q = 1e4
|
|
129
|
+
const vmap = new Map()
|
|
130
|
+
const vidx = new Int32Array(nTri * 3)
|
|
131
|
+
for (let t = 0; t < nTri; t++) {
|
|
132
|
+
for (let k = 0; k < 3; k++) {
|
|
133
|
+
const o = t * 9 + k * 3
|
|
134
|
+
const key = `${Math.round(localPos[o] * Q)},${Math.round(localPos[o + 1] * Q)},${Math.round(localPos[o + 2] * Q)}`
|
|
135
|
+
let id = vmap.get(key)
|
|
136
|
+
if (id === undefined) { id = vmap.size; vmap.set(key, id) }
|
|
137
|
+
vidx[t * 3 + k] = id
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// union-find
|
|
142
|
+
const parent = new Int32Array(nTri)
|
|
143
|
+
for (let i = 0; i < nTri; i++) parent[i] = i
|
|
144
|
+
const find = (x) => { while (parent[x] !== x) { parent[x] = parent[parent[x]]; x = parent[x] } return x }
|
|
145
|
+
const union = (a, b) => { a = find(a); b = find(b); if (a !== b) parent[b] = a }
|
|
146
|
+
|
|
147
|
+
// 에지(정점쌍) → 처음 본 면. 같은 에지를 다시 만나면 두 면을 합친다.
|
|
148
|
+
// 에지당 면이 3개 이상인 비-매니폴드도 첫 면 기준으로 전부 이어져 문제없다.
|
|
149
|
+
const edge = new Map()
|
|
150
|
+
for (let t = 0; t < nTri; t++) {
|
|
151
|
+
for (let e = 0; e < 3; e++) {
|
|
152
|
+
const a = vidx[t * 3 + e], b = vidx[t * 3 + (e + 1) % 3]
|
|
153
|
+
const key = a < b ? a * 4294967296 + b : b * 4294967296 + a // 정점 인덱스 2개를 하나의 수로
|
|
154
|
+
const prev = edge.get(key)
|
|
155
|
+
if (prev === undefined) edge.set(key, t)
|
|
156
|
+
else union(t, prev)
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// 성분별 면 수집
|
|
161
|
+
const groups = new Map()
|
|
162
|
+
for (let t = 0; t < nTri; t++) {
|
|
163
|
+
const r = find(t)
|
|
164
|
+
let g = groups.get(r)
|
|
165
|
+
if (!g) { g = []; groups.set(r, g) }
|
|
166
|
+
g.push(t)
|
|
167
|
+
}
|
|
168
|
+
if (groups.size < 2) return null
|
|
169
|
+
|
|
170
|
+
// 큰 성분부터 (원본도 부피 순으로 정렬해 첫 오브젝트가 본체가 되게 한다)
|
|
171
|
+
const parts = [...groups.values()].sort((a, b) => b.length - a.length)
|
|
172
|
+
return parts.map(faces => {
|
|
173
|
+
const out = new Float32Array(faces.length * 9)
|
|
174
|
+
let w = 0
|
|
175
|
+
for (const t of faces) { const o = t * 9; for (let k = 0; k < 9; k++) out[w++] = localPos[o + k] }
|
|
176
|
+
return out
|
|
177
|
+
})
|
|
178
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React, { useLayoutEffect, useRef, useState } from 'react'
|
|
2
|
+
import { createPortal } from 'react-dom'
|
|
3
|
+
|
|
4
|
+
// Shadow DOM 격리 호스트 — 컴포넌트 스타일을 shadow root 에 주입해 호스트 앱 CSS 와
|
|
5
|
+
// 양방향 완전 차단한다 (클래스명 충돌 불가). React 17+ 는 포털 컨테이너에도 이벤트
|
|
6
|
+
// 리스너를 직접 붙이므로(preparePortalMount) shadow 안에서도 합성 이벤트가 정상 동작.
|
|
7
|
+
// 호스트 div/컨테이너는 display:contents 로 레이아웃 투명 — 자식이 종전처럼 배치된다.
|
|
8
|
+
//
|
|
9
|
+
// 포털 컨테이너는 렌더 전에 미리 만든다. shadow root 생성을 기다렸다 조건부로 포털을
|
|
10
|
+
// 열면 자식 ref 가 붙기 전에 자식의 mount useEffect 가 ref=null 로 소진된다
|
|
11
|
+
// (three.js 초기화 영구 불발). 첫 커밋부터 detached 컨테이너에 자식을 마운트하고,
|
|
12
|
+
// layout effect 에서 컨테이너를 shadow root 로 옮긴다 — paint 전이라 깜빡임 없음.
|
|
13
|
+
// (document 를 렌더 중 만지므로 SSR 불가 — Next 등에서는 ssr:false 로 로드할 것.)
|
|
14
|
+
export default function ShadowHost({ css, className, children }) {
|
|
15
|
+
const hostRef = useRef(null)
|
|
16
|
+
const [container] = useState(() => {
|
|
17
|
+
const el = document.createElement('div')
|
|
18
|
+
el.style.display = 'contents'
|
|
19
|
+
return el
|
|
20
|
+
})
|
|
21
|
+
useLayoutEffect(() => {
|
|
22
|
+
const host = hostRef.current
|
|
23
|
+
const shadow = host.shadowRoot || host.attachShadow({ mode: 'open' })
|
|
24
|
+
let style = shadow.querySelector('style[data-ts-css]')
|
|
25
|
+
if (!style) { style = document.createElement('style'); style.setAttribute('data-ts-css', ''); shadow.append(style) }
|
|
26
|
+
style.textContent = css
|
|
27
|
+
if (!shadow.contains(container)) shadow.append(container)
|
|
28
|
+
}, [css, container])
|
|
29
|
+
return <div ref={hostRef} className={className}>{createPortal(children, container)}</div>
|
|
30
|
+
}
|