@gridspace/raster-path 1.0.2 → 1.0.4
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/README.md +3 -5
- package/build/app.js +363 -39
- package/build/index.html +39 -1
- package/build/raster-path.js +13 -13
- package/build/style.css +65 -0
- package/build/webgpu-worker.js +475 -686
- package/package.json +7 -4
- package/scripts/build-shaders.js +1 -1
- package/src/etc/serve.json +12 -0
- package/src/index.js +13 -13
- package/src/shaders/{radial-raster-v2.wgsl → radial-raster.wgsl} +8 -2
- package/src/test/batch-divisor-benchmark.cjs +286 -0
- package/src/test/lathe-cylinder-2-debug.cjs +334 -0
- package/src/test/lathe-cylinder-2-test.cjs +157 -0
- package/src/test/lathe-cylinder-test.cjs +198 -0
- package/src/test/planar-test.cjs +253 -0
- package/src/test/planar-tiling-test.cjs +230 -0
- package/src/test/radial-test.cjs +269 -0
- package/src/test/work-estimation-profile.cjs +406 -0
- package/src/test/workload-calculator-demo.cjs +113 -0
- package/src/test/workload-calibration.cjs +310 -0
- package/src/web/app.js +363 -39
- package/src/web/index.html +130 -0
- package/src/web/style.css +223 -0
- package/src/web/webgpu-worker.js +470 -687
- package/src/workload-calculator.js +318 -0
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
// planar-test.cjs
|
|
2
|
+
// Regression test for planar mode using new RasterPath API
|
|
3
|
+
// Tests: loadTool() + loadTerrain() + generateToolpaths()
|
|
4
|
+
|
|
5
|
+
const { app, BrowserWindow } = require('electron');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
|
|
9
|
+
const OUTPUT_DIR = path.join(__dirname, '../../test-output');
|
|
10
|
+
const BASELINE_FILE = path.join(OUTPUT_DIR, 'planar-baseline.json');
|
|
11
|
+
const CURRENT_FILE = path.join(OUTPUT_DIR, 'planar-current.json');
|
|
12
|
+
|
|
13
|
+
if (!fs.existsSync(OUTPUT_DIR)) {
|
|
14
|
+
fs.mkdirSync(OUTPUT_DIR, { recursive: true });
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let mainWindow;
|
|
18
|
+
|
|
19
|
+
function createWindow() {
|
|
20
|
+
mainWindow = new BrowserWindow({
|
|
21
|
+
width: 1200,
|
|
22
|
+
height: 800,
|
|
23
|
+
show: false,
|
|
24
|
+
webPreferences: {
|
|
25
|
+
nodeIntegration: false,
|
|
26
|
+
contextIsolation: true,
|
|
27
|
+
enableBlinkFeatures: 'WebGPU',
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const htmlPath = path.join(__dirname, '../../build/index.html');
|
|
32
|
+
mainWindow.loadFile(htmlPath);
|
|
33
|
+
|
|
34
|
+
mainWindow.webContents.on('did-finish-load', async () => {
|
|
35
|
+
console.log('✓ Page loaded');
|
|
36
|
+
|
|
37
|
+
const testScript = `
|
|
38
|
+
(async function() {
|
|
39
|
+
console.log('=== Planar Mode Regression Test ===');
|
|
40
|
+
|
|
41
|
+
if (!navigator.gpu) {
|
|
42
|
+
return { error: 'WebGPU not available' };
|
|
43
|
+
}
|
|
44
|
+
console.log('✓ WebGPU available');
|
|
45
|
+
|
|
46
|
+
// Import RasterPath
|
|
47
|
+
const { RasterPath } = await import('./raster-path.js');
|
|
48
|
+
|
|
49
|
+
// Load STL files
|
|
50
|
+
console.log('\\nLoading STL files...');
|
|
51
|
+
const terrainResponse = await fetch('../benchmark/fixtures/terrain.stl');
|
|
52
|
+
const terrainBuffer = await terrainResponse.arrayBuffer();
|
|
53
|
+
|
|
54
|
+
const toolResponse = await fetch('../benchmark/fixtures/tool.stl');
|
|
55
|
+
const toolBuffer = await toolResponse.arrayBuffer();
|
|
56
|
+
|
|
57
|
+
console.log('✓ Loaded terrain.stl:', terrainBuffer.byteLength, 'bytes');
|
|
58
|
+
console.log('✓ Loaded tool.stl:', toolBuffer.byteLength, 'bytes');
|
|
59
|
+
|
|
60
|
+
// Parse STL files
|
|
61
|
+
function parseBinarySTL(buffer) {
|
|
62
|
+
const dataView = new DataView(buffer);
|
|
63
|
+
const numTriangles = dataView.getUint32(80, true);
|
|
64
|
+
const positions = new Float32Array(numTriangles * 9);
|
|
65
|
+
let offset = 84;
|
|
66
|
+
|
|
67
|
+
for (let i = 0; i < numTriangles; i++) {
|
|
68
|
+
offset += 12; // Skip normal
|
|
69
|
+
for (let j = 0; j < 9; j++) {
|
|
70
|
+
positions[i * 9 + j] = dataView.getFloat32(offset, true);
|
|
71
|
+
offset += 4;
|
|
72
|
+
}
|
|
73
|
+
offset += 2; // Skip attribute byte count
|
|
74
|
+
}
|
|
75
|
+
return positions;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const terrainTriangles = parseBinarySTL(terrainBuffer);
|
|
79
|
+
const toolTriangles = parseBinarySTL(toolBuffer);
|
|
80
|
+
console.log('✓ Parsed terrain:', terrainTriangles.length / 9, 'triangles');
|
|
81
|
+
console.log('✓ Parsed tool:', toolTriangles.length / 9, 'triangles');
|
|
82
|
+
|
|
83
|
+
// Test parameters
|
|
84
|
+
const resolution = 0.05; // 0.05mm high resolution
|
|
85
|
+
const xStep = 1;
|
|
86
|
+
const yStep = 1;
|
|
87
|
+
const zFloor = -100;
|
|
88
|
+
|
|
89
|
+
console.log('\\nTest parameters:');
|
|
90
|
+
console.log(' Resolution:', resolution, 'mm');
|
|
91
|
+
console.log(' XY step:', xStep + 'x' + yStep, 'points');
|
|
92
|
+
console.log(' Z floor:', zFloor, 'mm');
|
|
93
|
+
|
|
94
|
+
// Create RasterPath instance for planar mode
|
|
95
|
+
console.log('\\nInitializing RasterPath (planar mode)...');
|
|
96
|
+
const raster = new RasterPath({
|
|
97
|
+
mode: 'planar',
|
|
98
|
+
resolution: resolution
|
|
99
|
+
});
|
|
100
|
+
await raster.init();
|
|
101
|
+
console.log('✓ RasterPath initialized');
|
|
102
|
+
|
|
103
|
+
// Load tool (NEW API)
|
|
104
|
+
console.log('\\n1. Loading tool...');
|
|
105
|
+
const t0 = performance.now();
|
|
106
|
+
const toolData = await raster.loadTool({
|
|
107
|
+
triangles: toolTriangles
|
|
108
|
+
});
|
|
109
|
+
const toolTime = performance.now() - t0;
|
|
110
|
+
console.log('✓ Tool:', toolData.pointCount, 'points in', toolTime.toFixed(1), 'ms');
|
|
111
|
+
|
|
112
|
+
// Load terrain (NEW API)
|
|
113
|
+
console.log('\\n2. Loading terrain...');
|
|
114
|
+
const t1 = performance.now();
|
|
115
|
+
const terrainData = await raster.loadTerrain({
|
|
116
|
+
triangles: terrainTriangles,
|
|
117
|
+
zFloor: zFloor
|
|
118
|
+
});
|
|
119
|
+
const terrainTime = performance.now() - t1;
|
|
120
|
+
console.log('✓ Terrain:', terrainData.pointCount, 'points in', terrainTime.toFixed(1), 'ms');
|
|
121
|
+
|
|
122
|
+
// Generate toolpaths (NEW API - no need to pass terrainData/toolData)
|
|
123
|
+
console.log('\\n3. Generating toolpaths...');
|
|
124
|
+
const t2 = performance.now();
|
|
125
|
+
const toolpathData = await raster.generateToolpaths({
|
|
126
|
+
xStep: xStep,
|
|
127
|
+
yStep: yStep,
|
|
128
|
+
zFloor: zFloor
|
|
129
|
+
});
|
|
130
|
+
const toolpathTime = performance.now() - t2;
|
|
131
|
+
console.log('✓ Toolpath:', toolpathData.numScanlines + 'x' + toolpathData.pointsPerLine, '=', toolpathData.pathData.length, 'Z-values');
|
|
132
|
+
console.log(' Generation time:', toolpathTime.toFixed(1), 'ms');
|
|
133
|
+
|
|
134
|
+
// Cleanup
|
|
135
|
+
raster.terminate();
|
|
136
|
+
|
|
137
|
+
// Calculate checksum for regression detection
|
|
138
|
+
let checksum = 0;
|
|
139
|
+
for (let i = 0; i < toolpathData.pathData.length; i++) {
|
|
140
|
+
checksum = (checksum + toolpathData.pathData[i] * (i + 1)) | 0;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Sample first 30 Z-values for debugging
|
|
144
|
+
const sampleSize = Math.min(30, toolpathData.pathData.length);
|
|
145
|
+
const sampleValues = [];
|
|
146
|
+
for (let i = 0; i < sampleSize; i++) {
|
|
147
|
+
sampleValues.push(toolpathData.pathData[i].toFixed(2));
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return {
|
|
151
|
+
success: true,
|
|
152
|
+
output: {
|
|
153
|
+
parameters: {
|
|
154
|
+
mode: 'planar',
|
|
155
|
+
resolution: resolution,
|
|
156
|
+
xStep,
|
|
157
|
+
yStep,
|
|
158
|
+
zFloor,
|
|
159
|
+
terrainTriangles: terrainTriangles.length / 9,
|
|
160
|
+
toolTriangles: toolTriangles.length / 9
|
|
161
|
+
},
|
|
162
|
+
result: {
|
|
163
|
+
terrainPoints: terrainData.pointCount,
|
|
164
|
+
toolPoints: toolData.pointCount,
|
|
165
|
+
toolpathSize: toolpathData.pathData.length,
|
|
166
|
+
numScanlines: toolpathData.numScanlines,
|
|
167
|
+
pointsPerLine: toolpathData.pointsPerLine,
|
|
168
|
+
checksum: checksum,
|
|
169
|
+
sampleValues: sampleValues
|
|
170
|
+
},
|
|
171
|
+
timing: {
|
|
172
|
+
terrain: terrainTime,
|
|
173
|
+
tool: toolTime,
|
|
174
|
+
toolpath: toolpathTime,
|
|
175
|
+
total: terrainTime + toolTime + toolpathTime
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
})();
|
|
180
|
+
`;
|
|
181
|
+
|
|
182
|
+
try {
|
|
183
|
+
const result = await mainWindow.webContents.executeJavaScript(testScript);
|
|
184
|
+
|
|
185
|
+
if (result.error) {
|
|
186
|
+
console.error('❌ Test failed:', result.error);
|
|
187
|
+
app.exit(1);
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Save current output
|
|
192
|
+
const currentData = {
|
|
193
|
+
parameters: result.output.parameters,
|
|
194
|
+
result: result.output.result,
|
|
195
|
+
timing: result.output.timing
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
fs.writeFileSync(CURRENT_FILE, JSON.stringify(currentData, null, 2));
|
|
199
|
+
console.log('\n✓ Saved current output to', CURRENT_FILE);
|
|
200
|
+
console.log(` Toolpath size: ${result.output.result.toolpathSize} Z-values`);
|
|
201
|
+
console.log(` Checksum: ${result.output.result.checksum}`);
|
|
202
|
+
console.log(` Total time: ${result.output.timing.total.toFixed(1)}ms`);
|
|
203
|
+
|
|
204
|
+
// Check if baseline exists
|
|
205
|
+
if (!fs.existsSync(BASELINE_FILE)) {
|
|
206
|
+
console.log('\n📝 No baseline found - saving current as baseline');
|
|
207
|
+
fs.writeFileSync(BASELINE_FILE, JSON.stringify(currentData, null, 2));
|
|
208
|
+
console.log('✅ Baseline created');
|
|
209
|
+
app.exit(0);
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Compare with baseline
|
|
214
|
+
const baseline = JSON.parse(fs.readFileSync(BASELINE_FILE, 'utf8'));
|
|
215
|
+
|
|
216
|
+
console.log('\n=== Comparison ===');
|
|
217
|
+
console.log('Baseline checksum:', baseline.result.checksum);
|
|
218
|
+
console.log('Current checksum:', result.output.result.checksum);
|
|
219
|
+
|
|
220
|
+
let passed = true;
|
|
221
|
+
|
|
222
|
+
if (baseline.result.toolpathSize !== result.output.result.toolpathSize) {
|
|
223
|
+
console.error('❌ Toolpath size mismatch!');
|
|
224
|
+
console.error(` Expected: ${baseline.result.toolpathSize}, Got: ${result.output.result.toolpathSize}`);
|
|
225
|
+
passed = false;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (baseline.result.checksum !== result.output.result.checksum) {
|
|
229
|
+
console.error('❌ Checksum mismatch!');
|
|
230
|
+
console.error(` Expected: ${baseline.result.checksum}, Got: ${result.output.result.checksum}`);
|
|
231
|
+
passed = false;
|
|
232
|
+
} else {
|
|
233
|
+
console.log('✓ Checksum matches');
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (passed) {
|
|
237
|
+
console.log('\n✅ All checks passed - output matches baseline');
|
|
238
|
+
app.exit(0);
|
|
239
|
+
} else {
|
|
240
|
+
console.log('\n❌ Regression detected - output differs from baseline');
|
|
241
|
+
console.log('To update baseline: cp', CURRENT_FILE, BASELINE_FILE);
|
|
242
|
+
app.exit(1);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
} catch (error) {
|
|
246
|
+
console.error('Error running test:', error);
|
|
247
|
+
app.exit(1);
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
app.whenReady().then(createWindow);
|
|
253
|
+
app.on('window-all-closed', () => app.quit());
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
// planar-tiling-test.cjs
|
|
2
|
+
// Test for planar tiling with very high resolution (0.01mm)
|
|
3
|
+
// This should trigger automatic tiling to avoid GPU memory allocation failures
|
|
4
|
+
|
|
5
|
+
const { app, BrowserWindow } = require('electron');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
|
|
9
|
+
const OUTPUT_DIR = path.join(__dirname, '../../test-output');
|
|
10
|
+
const OUTPUT_FILE = path.join(OUTPUT_DIR, 'planar-tiling-test.json');
|
|
11
|
+
|
|
12
|
+
if (!fs.existsSync(OUTPUT_DIR)) {
|
|
13
|
+
fs.mkdirSync(OUTPUT_DIR, { recursive: true });
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let mainWindow;
|
|
17
|
+
|
|
18
|
+
function createWindow() {
|
|
19
|
+
mainWindow = new BrowserWindow({
|
|
20
|
+
width: 1200,
|
|
21
|
+
height: 800,
|
|
22
|
+
show: false,
|
|
23
|
+
webPreferences: {
|
|
24
|
+
nodeIntegration: false,
|
|
25
|
+
contextIsolation: true,
|
|
26
|
+
enableBlinkFeatures: 'WebGPU',
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const htmlPath = path.join(__dirname, '../../build/index.html');
|
|
31
|
+
mainWindow.loadFile(htmlPath);
|
|
32
|
+
|
|
33
|
+
mainWindow.webContents.on('did-finish-load', async () => {
|
|
34
|
+
console.log('✓ Page loaded');
|
|
35
|
+
|
|
36
|
+
const testScript = `
|
|
37
|
+
(async function() {
|
|
38
|
+
console.log('=== Planar Tiling Test (0.01mm resolution) ===');
|
|
39
|
+
|
|
40
|
+
if (!navigator.gpu) {
|
|
41
|
+
return { error: 'WebGPU not available' };
|
|
42
|
+
}
|
|
43
|
+
console.log('✓ WebGPU available');
|
|
44
|
+
|
|
45
|
+
const { RasterPath } = await import('./raster-path.js');
|
|
46
|
+
|
|
47
|
+
console.log('\\nLoading STL files...');
|
|
48
|
+
const terrainResponse = await fetch('../benchmark/fixtures/terrain.stl');
|
|
49
|
+
const terrainBuffer = await terrainResponse.arrayBuffer();
|
|
50
|
+
|
|
51
|
+
const toolResponse = await fetch('../benchmark/fixtures/tool.stl');
|
|
52
|
+
const toolBuffer = await toolResponse.arrayBuffer();
|
|
53
|
+
|
|
54
|
+
console.log('✓ Loaded terrain.stl:', terrainBuffer.byteLength, 'bytes');
|
|
55
|
+
console.log('✓ Loaded tool.stl:', toolBuffer.byteLength, 'bytes');
|
|
56
|
+
|
|
57
|
+
function parseBinarySTL(buffer) {
|
|
58
|
+
const dataView = new DataView(buffer);
|
|
59
|
+
const numTriangles = dataView.getUint32(80, true);
|
|
60
|
+
const positions = new Float32Array(numTriangles * 9);
|
|
61
|
+
let offset = 84;
|
|
62
|
+
|
|
63
|
+
for (let i = 0; i < numTriangles; i++) {
|
|
64
|
+
offset += 12;
|
|
65
|
+
for (let j = 0; j < 9; j++) {
|
|
66
|
+
positions[i * 9 + j] = dataView.getFloat32(offset, true);
|
|
67
|
+
offset += 4;
|
|
68
|
+
}
|
|
69
|
+
offset += 2;
|
|
70
|
+
}
|
|
71
|
+
return positions;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const terrainTriangles = parseBinarySTL(terrainBuffer);
|
|
75
|
+
const toolTriangles = parseBinarySTL(toolBuffer);
|
|
76
|
+
console.log('✓ Parsed terrain:', terrainTriangles.length / 9, 'triangles');
|
|
77
|
+
console.log('✓ Parsed tool:', toolTriangles.length / 9, 'triangles');
|
|
78
|
+
|
|
79
|
+
// HIGH RESOLUTION - should trigger tiling
|
|
80
|
+
const resolution = 0.01;
|
|
81
|
+
const xStep = 1;
|
|
82
|
+
const yStep = 1;
|
|
83
|
+
const zFloor = -100;
|
|
84
|
+
|
|
85
|
+
console.log('\\nTest parameters:');
|
|
86
|
+
console.log(' Resolution:', resolution, 'mm (VERY HIGH - should trigger tiling)');
|
|
87
|
+
console.log(' XY step:', xStep + 'x' + yStep, 'points');
|
|
88
|
+
console.log(' Z floor:', zFloor, 'mm');
|
|
89
|
+
|
|
90
|
+
// Calculate expected grid size
|
|
91
|
+
// Terrain is roughly 1000x1000mm, so at 0.01mm = 100,000 x 100,000 grid
|
|
92
|
+
// = 10 billion points * 4 bytes = 40GB (way over GPU limit!)
|
|
93
|
+
const terrainSize = 1000; // approximate
|
|
94
|
+
const expectedGridSize = Math.ceil(terrainSize / resolution);
|
|
95
|
+
const expectedPoints = expectedGridSize * expectedGridSize;
|
|
96
|
+
const expectedMemoryMB = (expectedPoints * 4) / (1024 * 1024);
|
|
97
|
+
console.log('\\nExpected memory usage:');
|
|
98
|
+
console.log(' Grid size:', expectedGridSize + 'x' + expectedGridSize);
|
|
99
|
+
console.log(' Total points:', (expectedPoints / 1e6).toFixed(1) + 'M');
|
|
100
|
+
console.log(' Memory needed:', expectedMemoryMB.toFixed(0) + 'MB');
|
|
101
|
+
console.log(' GPU limit: ~512MB (should trigger tiling)');
|
|
102
|
+
|
|
103
|
+
console.log('\\nInitializing RasterPath (planar mode)...');
|
|
104
|
+
const raster = new RasterPath({
|
|
105
|
+
mode: 'planar',
|
|
106
|
+
resolution: resolution
|
|
107
|
+
});
|
|
108
|
+
await raster.init();
|
|
109
|
+
console.log('✓ RasterPath initialized');
|
|
110
|
+
|
|
111
|
+
console.log('\\n1. Loading tool (NEW API)...');
|
|
112
|
+
const t0 = performance.now();
|
|
113
|
+
const toolData = await raster.loadTool({
|
|
114
|
+
triangles: toolTriangles
|
|
115
|
+
});
|
|
116
|
+
const toolTime = performance.now() - t0;
|
|
117
|
+
console.log('✓ Tool:', toolData.pointCount, 'points in', toolTime.toFixed(1), 'ms');
|
|
118
|
+
|
|
119
|
+
console.log('\\n2. Loading terrain (NEW API - should use tiling)...');
|
|
120
|
+
const t1 = performance.now();
|
|
121
|
+
let terrainData;
|
|
122
|
+
let terrainTime;
|
|
123
|
+
try {
|
|
124
|
+
terrainData = await raster.loadTerrain({
|
|
125
|
+
triangles: terrainTriangles,
|
|
126
|
+
zFloor: zFloor
|
|
127
|
+
});
|
|
128
|
+
terrainTime = performance.now() - t1;
|
|
129
|
+
console.log('✓ Terrain:', terrainData.pointCount, 'points in', terrainTime.toFixed(1), 'ms');
|
|
130
|
+
} catch (error) {
|
|
131
|
+
console.error('❌ Terrain loading FAILED:', error.message);
|
|
132
|
+
return {
|
|
133
|
+
error: 'Terrain loading failed: ' + error.message,
|
|
134
|
+
expectedTiling: true,
|
|
135
|
+
resolution: resolution
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
console.log('\\n3. Generating toolpaths (NEW API)...');
|
|
140
|
+
const t2 = performance.now();
|
|
141
|
+
const toolpathData = await raster.generateToolpaths({
|
|
142
|
+
xStep: xStep,
|
|
143
|
+
yStep: yStep,
|
|
144
|
+
zFloor: zFloor
|
|
145
|
+
});
|
|
146
|
+
const toolpathTime = performance.now() - t2;
|
|
147
|
+
console.log('✓ Toolpath:', toolpathData.numScanlines + 'x' + toolpathData.pointsPerLine, '=', toolpathData.pathData.length, 'Z-values');
|
|
148
|
+
console.log(' Generation time:', toolpathTime.toFixed(1), 'ms');
|
|
149
|
+
|
|
150
|
+
raster.terminate();
|
|
151
|
+
|
|
152
|
+
// Calculate checksum
|
|
153
|
+
let checksum = 0;
|
|
154
|
+
for (let i = 0; i < Math.min(1000, toolpathData.pathData.length); i++) {
|
|
155
|
+
checksum = (checksum + toolpathData.pathData[i] * (i + 1)) | 0;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return {
|
|
159
|
+
success: true,
|
|
160
|
+
tilingWorked: true,
|
|
161
|
+
output: {
|
|
162
|
+
parameters: {
|
|
163
|
+
resolution: resolution,
|
|
164
|
+
expectedMemoryMB: Math.round(expectedMemoryMB)
|
|
165
|
+
},
|
|
166
|
+
result: {
|
|
167
|
+
terrainPoints: terrainData.pointCount,
|
|
168
|
+
toolPoints: toolData.pointCount,
|
|
169
|
+
toolpathSize: toolpathData.pathData.length,
|
|
170
|
+
checksum: checksum
|
|
171
|
+
},
|
|
172
|
+
timing: {
|
|
173
|
+
terrain: terrainTime,
|
|
174
|
+
tool: toolTime,
|
|
175
|
+
toolpath: toolpathTime,
|
|
176
|
+
total: terrainTime + toolTime + toolpathTime
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
})();
|
|
181
|
+
`;
|
|
182
|
+
|
|
183
|
+
try {
|
|
184
|
+
const result = await mainWindow.webContents.executeJavaScript(testScript);
|
|
185
|
+
|
|
186
|
+
if (result.error) {
|
|
187
|
+
console.error('\n❌ TEST FAILED - Tiling did not work!');
|
|
188
|
+
console.error('Error:', result.error);
|
|
189
|
+
console.error('Resolution:', result.resolution);
|
|
190
|
+
console.error('Expected tiling:', result.expectedTiling);
|
|
191
|
+
|
|
192
|
+
fs.writeFileSync(OUTPUT_FILE, JSON.stringify({
|
|
193
|
+
failed: true,
|
|
194
|
+
error: result.error,
|
|
195
|
+
resolution: result.resolution
|
|
196
|
+
}, null, 2));
|
|
197
|
+
|
|
198
|
+
app.exit(1);
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
console.log('\n=== Test Complete ===');
|
|
203
|
+
console.log('✅ Tiling worked correctly!');
|
|
204
|
+
console.log('Terrain points:', result.output.result.terrainPoints);
|
|
205
|
+
console.log('Tool points:', result.output.result.toolPoints);
|
|
206
|
+
console.log('Toolpath size:', result.output.result.toolpathSize);
|
|
207
|
+
console.log('Total time:', result.output.timing.total.toFixed(1), 'ms');
|
|
208
|
+
|
|
209
|
+
fs.writeFileSync(OUTPUT_FILE, JSON.stringify(result.output, null, 2));
|
|
210
|
+
console.log('\n✓ Results written to:', OUTPUT_FILE);
|
|
211
|
+
|
|
212
|
+
app.exit(0);
|
|
213
|
+
} catch (error) {
|
|
214
|
+
console.error('❌ Test execution error:', error);
|
|
215
|
+
app.exit(1);
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
mainWindow.webContents.on('console-message', (event, level, message) => {
|
|
220
|
+
if (message.includes('[Raster') || message.includes('[Worker') || message.includes('Tiling')) {
|
|
221
|
+
console.log('[Browser]', message);
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
app.whenReady().then(createWindow);
|
|
227
|
+
|
|
228
|
+
app.on('window-all-closed', () => {
|
|
229
|
+
app.quit();
|
|
230
|
+
});
|