@gridspace/raster-path 1.0.2

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 ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2014-Infinity Stewart Allen <sa@grid.space>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a
4
+ copy of this software and associated documentation files (the "Software"),
5
+ to deal in the Software without restriction, including without limitation
6
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
7
+ and/or sell copies of the Software, and to permit persons to whom the
8
+ Software is furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included
11
+ in all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
16
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
20
+
package/README.md ADDED
@@ -0,0 +1,292 @@
1
+ # Raster Path - WebGPU Toolpath Generator
2
+
3
+ Fast browser-based terrain + tool path generator using WebGPU compute shaders.
4
+
5
+ ## Features
6
+
7
+ - **Dual Mode Rasterization**: Planar (traditional XY grid) and Radial (cylindrical unwrap) modes
8
+ - **CNC Toolpath Generation**: Generate toolpaths by simulating tool movement over terrain
9
+ - **GPU Accelerated**: 20-100× faster than CPU-based solutions
10
+ - **Unified API**: Clean three-method interface that works uniformly across both modes
11
+ - **ESM Module**: Importable package for browser applications
12
+
13
+ ## Quick Start
14
+
15
+ ### As a Module
16
+
17
+ ```javascript
18
+ import { RasterPath } from '@gridspace/raster-path';
19
+
20
+ // Initialize for planar mode
21
+ const raster = new RasterPath({
22
+ mode: 'planar',
23
+ resolution: 0.1 // 0.1mm grid resolution
24
+ });
25
+ await raster.init();
26
+
27
+ // 1. Load tool (from STL triangles)
28
+ const toolTriangles = parseSTL(toolSTLBuffer);
29
+ const toolData = await raster.loadTool({
30
+ triangles: toolTriangles
31
+ });
32
+
33
+ // 2. Load terrain (rasterizes immediately in planar mode)
34
+ const terrainTriangles = parseSTL(terrainSTLBuffer);
35
+ const terrainData = await raster.loadTerrain({
36
+ triangles: terrainTriangles,
37
+ zFloor: -100
38
+ });
39
+
40
+ // 3. Generate toolpaths
41
+ const toolpathData = await raster.generateToolpaths({
42
+ xStep: 5, // Sample every 5th point in X
43
+ yStep: 5, // Sample every 5th point in Y
44
+ zFloor: -100
45
+ });
46
+
47
+ console.log(`Generated ${toolpathData.pathData.length} toolpath points`);
48
+
49
+ // Cleanup
50
+ raster.terminate();
51
+ ```
52
+
53
+ ### Radial Mode (for cylindrical parts)
54
+
55
+ ```javascript
56
+ // Initialize for radial mode
57
+ const raster = new RasterPath({
58
+ mode: 'radial',
59
+ resolution: 0.1, // Radial resolution (mm)
60
+ rotationStep: 1.0 // 1 degree between rays
61
+ });
62
+ await raster.init();
63
+
64
+ // Load tool and terrain (same API!)
65
+ await raster.loadTool({ triangles: toolTriangles });
66
+ await raster.loadTerrain({
67
+ triangles: terrainTriangles,
68
+ zFloor: 0
69
+ });
70
+
71
+ // Generate toolpaths with radius offset
72
+ const toolpathData = await raster.generateToolpaths({
73
+ xStep: 5,
74
+ yStep: 5,
75
+ zFloor: 0,
76
+ radiusOffset: 20 // Tool offset above surface (radial mode only)
77
+ });
78
+
79
+ // Output is array of strips (one per rotation angle)
80
+ console.log(`Generated ${toolpathData.numStrips} strips, ${toolpathData.totalPoints} points`);
81
+ ```
82
+
83
+ ### Demo UI
84
+
85
+ ```bash
86
+ npm install
87
+ npm run dev
88
+ ```
89
+
90
+ Open http://localhost:3000 and drag STL files onto the interface.
91
+
92
+ ## Algorithm
93
+
94
+ ### Planar Mode (XY Grid Rasterization)
95
+
96
+ 1. **Tool Rasterization**: Create XY grid at specified resolution and rasterize tool geometry (keeps min Z per grid cell)
97
+ 2. **Terrain Rasterization**: Rasterize terrain geometry on matching XY grid (keeps max Z per grid cell)
98
+ 3. **Toolpath Generation**:
99
+ - Scan tool over terrain in XY grid with configurable step sizes (xStep, yStep)
100
+ - At each position, calculate minimum Z-offset where tool doesn't collide with terrain
101
+ - Output scanline-based toolpath as array of Z-heights
102
+
103
+ ### Radial Mode (Cylindrical Rasterization)
104
+
105
+ 1. **Tool Rasterization**: Rasterize tool in planar mode (same as above)
106
+ 2. **Terrain Preparation**: Center terrain in YZ plane and store triangles
107
+ 3. **Toolpath Generation**:
108
+ - Cast rays from origin at specified rotation angles (e.g., every 1°)
109
+ - For each ray, rasterize terrain triangles along that angle
110
+ - Use X-bucketing optimization to partition triangles spatially
111
+ - Calculate tool-terrain collisions along each radial strip
112
+ - Output array of strips (one per angle), each containing Z-heights along X-axis
113
+
114
+ ## Performance
115
+
116
+ Example (84×84×28mm model, 6,120 triangles):
117
+
118
+ | Step Size | Points | WebGPU Time | CPU Time (WASM) |
119
+ |-----------|---------|-------------|-----------------|
120
+ | 0.5mm | 48K | 0.8s | 20-80s |
121
+ | 0.1mm | 1.2M | 2s | 280s |
122
+
123
+ **Speedup**: 20-100× faster with WebGPU
124
+
125
+ ## Project Structure
126
+
127
+ ```
128
+ src/
129
+ index.js # Main RasterPath API (ESM export)
130
+ web/
131
+ webgpu-worker.js # WebGPU worker (GPU compute shaders)
132
+ app.js # Demo web application
133
+ index.html # Demo UI entry point
134
+ style.css # Demo styles
135
+ parse-stl.js # STL file parser utility
136
+ test/
137
+ planar-test.cjs # Planar mode regression test
138
+ planar-tiling-test.cjs # Planar high-resolution test
139
+ radial-test.cjs # Radial mode regression test
140
+ benchmark/
141
+ fixtures/ # Test STL files (terrain.stl, tool.stl)
142
+ build/ # Built files (generated by npm run build)
143
+ ```
144
+
145
+ ## API Reference
146
+
147
+ ### `RasterPath`
148
+
149
+ Constructor: `new RasterPath(options)`
150
+
151
+ **Options**:
152
+ - `mode` (string): `'planar'` or `'radial'`
153
+ - `resolution` (number): Grid resolution in mm (e.g., 0.1)
154
+ - `rotationStep` (number, radial only): Degrees between rays (e.g., 1.0)
155
+
156
+ #### `async init()`
157
+ Initialize WebGPU worker. Must be called before other methods.
158
+
159
+ **Returns**: `Promise<void>`
160
+
161
+ **Example**:
162
+ ```javascript
163
+ const raster = new RasterPath({ mode: 'planar', resolution: 0.1 });
164
+ await raster.init();
165
+ ```
166
+
167
+ ---
168
+
169
+ #### `async loadTool({ triangles, sparseData })`
170
+ Load tool geometry for toolpath generation.
171
+
172
+ **Parameters** (one required):
173
+ - `triangles` (Float32Array, optional): STL triangle data (9 floats per triangle: v0.xyz, v1.xyz, v2.xyz)
174
+ - `sparseData` (object, optional): Pre-computed raster data with `{ bounds, positions, pointCount }`
175
+
176
+ **Returns**: `Promise<object>` - Tool raster data with `{ bounds, positions, pointCount }`
177
+
178
+ **Example**:
179
+ ```javascript
180
+ // From STL triangles
181
+ const toolData = await raster.loadTool({
182
+ triangles: toolTriangles
183
+ });
184
+
185
+ // From pre-computed sparse data (Kiri:Moto integration)
186
+ const toolData = await raster.loadTool({
187
+ sparseData: { bounds, positions, pointCount }
188
+ });
189
+ ```
190
+
191
+ ---
192
+
193
+ #### `async loadTerrain({ triangles, zFloor, boundsOverride, onProgress })`
194
+ Load terrain geometry. Behavior depends on mode:
195
+ - **Planar mode**: Rasterizes immediately and returns terrain data
196
+ - **Radial mode**: Stores triangles for later, returns `null`
197
+
198
+ **Parameters**:
199
+ - `triangles` (Float32Array): STL triangle data
200
+ - `zFloor` (number, optional): Z floor value for out-of-bounds areas
201
+ - `boundsOverride` (object, optional): Override bounding box `{min: {x, y, z}, max: {x, y, z}}`
202
+ - `onProgress` (function, optional): Progress callback `(progress: number) => void`
203
+
204
+ **Returns**:
205
+ - Planar mode: `Promise<object>` - Terrain raster data with `{ bounds, positions, pointCount }`
206
+ - Radial mode: `Promise<null>`
207
+
208
+ **Example**:
209
+ ```javascript
210
+ // Planar mode - returns terrain data immediately
211
+ const terrainData = await raster.loadTerrain({
212
+ triangles: terrainTriangles,
213
+ zFloor: -100
214
+ });
215
+
216
+ // Radial mode - stores for later
217
+ await raster.loadTerrain({
218
+ triangles: terrainTriangles,
219
+ zFloor: 0
220
+ });
221
+ ```
222
+
223
+ ---
224
+
225
+ #### `async generateToolpaths({ xStep, yStep, zFloor, radiusOffset, onProgress })`
226
+ Generate toolpaths from loaded tool and terrain. Must call `loadTool()` and `loadTerrain()` first.
227
+
228
+ **Parameters**:
229
+ - `xStep` (number): Sample every Nth point in X direction
230
+ - `yStep` (number): Sample every Nth point in Y direction
231
+ - `zFloor` (number): Z floor value for out-of-bounds areas
232
+ - `radiusOffset` (number, radial only): Tool offset above surface (mm)
233
+ - `onProgress` (function, optional): Progress callback `(progress: number) => void`
234
+
235
+ **Returns**:
236
+ - Planar mode: `Promise<object>` with:
237
+ - `pathData` (Float32Array): Z-heights in scanline order
238
+ - `width` (number): Points per scanline
239
+ - `height` (number): Number of scanlines
240
+
241
+ - Radial mode: `Promise<object>` with:
242
+ - `strips` (Array): Array of strip objects, each containing:
243
+ - `angle` (number): Rotation angle in degrees
244
+ - `pathData` (Float32Array): Z-heights along X-axis
245
+ - `numStrips` (number): Total number of strips
246
+ - `totalPoints` (number): Sum of all points across strips
247
+
248
+ **Example**:
249
+ ```javascript
250
+ // Works for both planar and radial modes!
251
+ const toolpathData = await raster.generateToolpaths({
252
+ xStep: 5,
253
+ yStep: 5,
254
+ zFloor: -100,
255
+ radiusOffset: 20 // radial mode only
256
+ });
257
+ ```
258
+
259
+ ---
260
+
261
+ #### `terminate()`
262
+ Terminate WebGPU worker and cleanup resources.
263
+
264
+ **Example**:
265
+ ```javascript
266
+ raster.terminate();
267
+ ```
268
+
269
+ ## Requirements
270
+
271
+ - Modern browser with WebGPU support (Chrome 113+, Edge 113+)
272
+ - For testing: Electron (provides headless WebGPU environment)
273
+
274
+ ## Development
275
+
276
+ ```bash
277
+ # Install dependencies
278
+ npm install
279
+
280
+ # Build (copies web files to build/)
281
+ npm run build
282
+
283
+ # Run demo
284
+ npm run serve
285
+
286
+ # Test
287
+ npm test
288
+ ```
289
+
290
+ ## License
291
+
292
+ MIT