|
33 | 33 | // derived from the real plot time (≈ x45–x60) |
34 | 34 | var INK = '#e8351f'; |
35 | 35 | var cur, len = 1, drawn = 0, painted = 0, playing = true, speed = 1, mmPerUnit = 1, totalMin = 1; |
36 | | - var termBody = $('pfTermBody'); // command journal (homepage only) |
37 | | - var polys = [], strokes = [], termIdx = -1; // parsed geometry + journal cursor |
| 36 | + var polys = []; // parsed polylines for the fast full-draw pass |
38 | 37 | var vb = { x: 0, y: 0, w: 1, h: 1 }; |
39 | 38 | var tf = { s: 1, ox: 0, oy: 0, dpr: 1, ready: false }; |
40 | 39 | var prevPt = null; |
|
141 | 140 | len = ppath.getTotalLength(); if (!len || !isFinite(len)) len = 1; |
142 | 141 | var md = Math.max(vb.w, vb.h); |
143 | 142 | mmPerUnit = 420 / md; // longest side ≈ 420mm |
144 | | - // parse the raw path once: polylines for fast full-draw, stroke table |
145 | | - // (start/end/len/cumulative draw length) for the command journal |
146 | | - polys = []; strokes = []; termIdx = -1; |
147 | | - if (termBody) termBody.textContent = ''; |
| 143 | + // parse the raw path once: polylines for the fast full-draw pass |
| 144 | + polys = []; |
148 | 145 | (function () { |
149 | 146 | var re = /([ML])\s*(-?\d+(?:\.\d+)?),(-?\d+(?:\.\d+)?)/g, m, curP = null; |
150 | 147 | while ((m = re.exec(cur.d)) !== null) { |
151 | 148 | var x = +m[2], y = +m[3]; |
152 | 149 | if (m[1] === 'M') { curP = [[x, y]]; polys.push(curP); } |
153 | 150 | else if (curP) curP.push([x, y]); |
154 | 151 | } |
155 | | - var cum = 0; |
156 | | - for (var i = 0; i < polys.length; i++) { |
157 | | - var pl = polys[i], L = 0; |
158 | | - for (var j = 0; j < pl.length - 1; j++) |
159 | | - L += Math.hypot(pl[j+1][0]-pl[j][0], pl[j+1][1]-pl[j][1]); |
160 | | - cum += L; |
161 | | - strokes.push({ sx: pl[0][0], sy: pl[0][1], len: L, cum: cum }); |
162 | | - } |
163 | 152 | })(); |
164 | 153 | var st = pathStats(cur.d); |
165 | 154 | totalMin = (st.draw * mmPerUnit) / FEED |
|
183 | 172 | if (!tf.ready) resetCanvas(); // self-heal if the bed wasn't laid out yet |
184 | 173 | var p = drawn / len; |
185 | 174 | paintTo(drawn); |
186 | | - updateJournal(); |
187 | 175 | if (pbar) pbar.style.width = (p * 100) + '%'; |
188 | 176 | if (pct) pct.textContent = Math.round(p * 100); |
189 | 177 | if (ink) ink.textContent = (drawn * mmPerUnit / 1000).toFixed(2); |
|
217 | 205 | prevPt = lastP ? { x: lastP[0], y: lastP[1] } : null; |
218 | 206 | } |
219 | 207 |
|
220 | | - // Command journal — emit pyaxidraw-style lines for the strokes just drawn. |
221 | | - function pad4(n) { return String(n).padStart(4, '0'); } |
222 | | - function updateJournal() { |
223 | | - if (!termBody || !strokes.length) return; |
224 | | - var lo = 0, hi = strokes.length - 1, idx = 0; // first stroke with cum >= drawn |
225 | | - while (lo <= hi) { var mid = (lo + hi) >> 1; |
226 | | - if (strokes[mid].cum < drawn) { lo = mid + 1; } else { idx = mid; hi = mid - 1; } } |
227 | | - if (drawn >= len) idx = strokes.length - 1; |
228 | | - if (idx === termIdx) return; |
229 | | - termIdx = idx; |
230 | | - var out = [], from = Math.max(0, idx - 2); |
231 | | - for (var k = from; k <= idx; k++) { |
232 | | - var st2 = strokes[k]; |
233 | | - out.push('ad.penup() z=+1'); |
234 | | - out.push('ad.moveto(' + (st2.sx * mmPerUnit).toFixed(2) + ', ' + (st2.sy * mmPerUnit).toFixed(2) + ') travel'); |
235 | | - out.push('ad.pendown() z=-1 · nib 0.30 mm'); |
236 | | - out.push('ad.lineto(…) stroke ' + pad4(k + 1) + '/' + strokes.length + ' · ' + (st2.len * mmPerUnit).toFixed(1) + ' mm'); |
237 | | - } |
238 | | - out.push(drawn >= len ? 'ad.penup() z=+1 · job complete' : '_'); |
239 | | - termBody.textContent = out.join('\n'); |
240 | | - } |
241 | | - |
242 | 208 | // Re-fit + repaint the current progress when the bed changes size. |
243 | 209 | function refit() { resetCanvas(); if (drawn >= len) fastPaintAll(); else paintTo(drawn); } |
244 | 210 | window.addEventListener('resize', refit); |
|
0 commit comments