Skip to content

Commit 595d601

Browse files
committed
Added THR file optimization script
1 parent b001808 commit 595d601

2 files changed

Lines changed: 114 additions & 0 deletions

File tree

readme.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,18 @@ Pattern classes are made up of at least 4 methods:
5454

5555
Once you've completed your design, submit a Pull Request and if it works, I'll merge it in. Thanks in advance!
5656

57+
## Optimize a THR track
58+
59+
When creating tracks, it may be that there are far too many points than necessary - the sand table
60+
may not be able to render the track with the precision specified. Since each instruction is processed
61+
this may lead to an unnecessarily slow drawing time. In order to prevent this I have created a THR
62+
optimization script that uses the drawing devices table and ball size to simplify the path to avoid
63+
unnecessary drawing steps.
64+
65+
```
66+
node ./scripts/optimize-thr.mjs {path_to_thr_file}
67+
```
68+
5769
## Patterns
5870

5971
- XY Coordinates

scripts/optimize-thr.mjs

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import fs from 'fs';
2+
import readline from 'readline';
3+
import path from 'path';
4+
5+
// Add definition for __dirname in ES modules
6+
// const __dirname = path.dirname(new URL(import.meta.url).pathname);
7+
8+
// Get file path from command line arguments
9+
const filePath = process.argv[2];
10+
11+
// Set the environment dimensions
12+
const ball_diameter_mm = 10;
13+
const table_diameter_mm = 406;
14+
15+
// Calculate the normalized resolution (where 1.0 is the full radius of the table)
16+
const norm_distance_threshold = ((0.5 * ball_diameter_mm) / (0.5 * table_diameter_mm)).toFixed(3);
17+
18+
if (!filePath) {
19+
console.error('Usage: node optimize-thr.js <path-to-file.thr>');
20+
process.exit(1);
21+
}
22+
23+
console.log(`Ball Diameter: ${ball_diameter_mm}mm`);
24+
console.log(`Table Diameter: ${table_diameter_mm}mm`);
25+
console.log(`Normalized Threshold: ${norm_distance_threshold}`);
26+
27+
// Create a readable stream and readline interface
28+
const rl = readline.createInterface({
29+
input: fs.createReadStream(filePath),
30+
crlfDelay: Infinity
31+
});
32+
33+
let prevTheta = null;
34+
let prevRho = null;
35+
let old_instruction_count = 0;
36+
let new_instruction_count = 0;
37+
38+
let new_path = [];
39+
40+
rl.on('line', (line) => {
41+
42+
// Preserve comment lines
43+
if (line.startsWith('#')) {
44+
new_path.push([line]);
45+
return;
46+
}
47+
48+
// Skip lines that aren't position data
49+
const match = line.match(/^([+-]?\d*\.?\d+)\s+([+-]?\d*\.?\d+)/);
50+
if (!match) {
51+
new_path.push([line]);
52+
return;
53+
}
54+
55+
// Count old lines
56+
old_instruction_count++;
57+
58+
// Parse data from line
59+
const [, num1Str, num2Str] = match;
60+
const theta = parseFloat(num1Str);
61+
const rho = parseFloat(num2Str);
62+
63+
// First data point
64+
if (prevTheta === null && prevRho === null) {
65+
new_path.push([theta, rho]);
66+
new_instruction_count++;
67+
prevTheta = theta;
68+
prevRho = rho;
69+
return;
70+
}
71+
72+
// Calculate distance between two polar points
73+
const distance = Math.sqrt(
74+
prevRho * prevRho + rho * rho - 2 * prevRho * rho * Math.cos(theta - prevTheta)
75+
);
76+
77+
if (distance > norm_distance_threshold) {
78+
new_path.push([theta, rho]);
79+
new_instruction_count++;
80+
prevTheta = theta;
81+
prevRho = rho;
82+
}
83+
});
84+
85+
rl.on('close', () => {
86+
87+
// Transform new_path: combine each coordinate pair into a string with a space separator.
88+
// Comments are already stored as single-element arrays, so they'll just be output as-is
89+
const combinedPath = new_path.map(pair => pair.length === 1 ? pair[0] : pair.join(' '));
90+
91+
// Determine output file path: same directory as input file but with a .opt.thr extension.
92+
const parsedPath = path.parse(filePath);
93+
const outputFilePath = path.join(parsedPath.dir, parsedPath.name + '.opt.thr');
94+
95+
// Write one line per coordinate pair with "number space number"
96+
fs.writeFileSync(outputFilePath, combinedPath.join('\n'), 'utf8');
97+
98+
// Print info
99+
console.log(`Original Point Count: ${old_instruction_count.toLocaleString()}`);
100+
console.log(`Optimized Point Count: ${new_instruction_count.toLocaleString()}`);
101+
console.log(`Saved to ${outputFilePath}`);
102+
});

0 commit comments

Comments
 (0)