Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/404.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
name="description"
content="Turn a photo into single-thread string art — plotter/print-ready, made in your browser. No backend, nothing leaves your device."
/>
<script type="module" crossorigin src="./assets/index-DfywjaKV.js"></script>
<script type="module" crossorigin src="./assets/index-B21gUkMX.js"></script>
<link rel="stylesheet" crossorigin href="./assets/index-CYkW1RUW.css">
</head>
<body>
Expand Down
3 changes: 3 additions & 0 deletions docs/assets/index-B21gUkMX.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 0 additions & 3 deletions docs/assets/index-DfywjaKV.js

This file was deleted.

2 changes: 1 addition & 1 deletion docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
name="description"
content="Turn a photo into single-thread string art — plotter/print-ready, made in your browser. No backend, nothing leaves your device."
/>
<script type="module" crossorigin src="./assets/index-DfywjaKV.js"></script>
<script type="module" crossorigin src="./assets/index-B21gUkMX.js"></script>
<link rel="stylesheet" crossorigin href="./assets/index-CYkW1RUW.css">
</head>
<body>
Expand Down
14 changes: 11 additions & 3 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,15 @@ function startGeneration(): void {

residual = grayToResidual(sourceGray, RES, RES, settings.invert);
const radius = RES / 2 - 1;
nails = nailPositions(settings.nails, radius, RES / 2, RES / 2);
// Snapshot the nail count for the lifetime of this run. The "Nails" slider
// stays live (the user can drag it mid-run to preview a value for next
// time), but `nails`/`used`'s edge-key encoding must stay pinned to
// whatever count the nail positions were actually built with — reading
// `settings.nails` live here would silently corrupt `edgeKey` hashing
// partway through a run (bug: mid-run edge-key drift), letting the
// "never redraw the same chord" guarantee break.
const nailCount = settings.nails;
nails = nailPositions(nailCount, radius, RES / 2, RES / 2);
sequence = [0];
used = new Set<number>();
current = 0;
Expand All @@ -185,7 +193,7 @@ function startGeneration(): void {
width: RES,
height: RES,
used,
count: settings.nails,
count: nailCount,
});
if (next < 0) {
// Nothing worth drawing remains — finish early.
Expand All @@ -196,7 +204,7 @@ function startGeneration(): void {
const b = nails[next]!;
const px = linePixels(a.x, a.y, b.x, b.y);
subtractLine(residual, px, settings.strength, { width: RES, height: RES });
used.add(edgeKey(current, next, settings.nails));
used.add(edgeKey(current, next, nailCount));

ctx.beginPath();
ctx.moveTo(a.x, a.y);
Expand Down