diff --git a/README.md b/README.md new file mode 100644 index 0000000..ab195ab --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +# Scrap Tracer + +Turn a phone photo of a laser-cut scrap piece into a 1:1 DXF/SVG outline, so you can check in +RDWorks (or LightBurn/Inkscape) whether your design fits on it. Built for Makerspace Delft. + +## Use + +1. Photograph the piece from straight above, on a contrasting surface, with something of known length visible. +2. Load the photo, click **Measure**, click both ends of the known length, and enter it in mm. +3. Check the green outline. If needed, adjust the threshold, tick "darker than background", + click the piece, or draw the outline by hand. +4. Set the safety margin (default −2 mm shrinks the usable area a little). +5. Download DXF and import it in your laser software at 1:1, in mm. + +## Develop + + npm install + npm run dev # local dev server + npm test # unit tests (Vitest, OpenCV runs headless in Node) + npm run check # type check + npm run build # static build in dist/ + +## Deploy (Cloudflare Pages) + +Build command `npm run build`, output directory `dist`. No server or environment variables needed. diff --git a/src/App.svelte b/src/App.svelte index da42345..18374ff 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -1,6 +1,7 @@ + +

Scrap Tracer

+ +{#if app.cvError} +

{app.cvError}

+{:else if !app.cv} +

Loading image processing…

+{/if} + +
+

1. Photo

+ + {#if app.loadError}

{app.loadError}

{/if} +
+ +
+

2. Scale

+

Click both ends of something whose length you know.

+ + + {#if app.scaleInvalid} +

Enter a length above 0 and pick two different points.

+ {:else if app.pxPerMm} +

{app.pxPerMm.toFixed(2)} px/mm

+ {/if} +
+ +
+

3. Outline

+ {#if app.mode === 'auto'} + + + + + {/if} + + {#if app.drawing.length > 0} + + {/if} + {#if app.mode === 'manual' || app.drawing.length > 0} + + {/if} + {#if nothingDetected} +

Nothing detected, try adjusting the threshold or invert, or draw manually.

+ {/if} +
+ +
+

4. Safety margin

+ + {#if !app.pxPerMm}

Set the scale first.

{/if} +
+ +
+

5. Export

+ {#if size}

Piece: {Math.round(size.width)} × {Math.round(size.height)} mm

{/if} + + + {#if !app.exportShape} +

{app.pxPerMm ? 'No outline to export yet.' : 'Set the scale first.'}

+ {/if} +
+ +