Charlie KrugThe Build Log

← All posts

The pen never lifts. A traveling salesman picks the route.

Oneline redraws any photo as a single never-lifting stroke: it stipples the image into thousands of dots, then solves a traveling-salesman path through every one. All in your browser, exported plotter-ready.

A pen plotter draws the way a kid told not to lift the crayon draws: the pen sets down once and traces a single unbroken line until the picture is finished. That constraint is the whole appeal. It's also a problem. If a face has to become one line that never lifts, something has to decide the order in which that line visits every part of it. Get the order right and the stroke reads as the subject; get it wrong and you have spaghetti. Deciding that order is the traveling-salesman problem, and it's what Oneline solves every time you drop in a photo.

Oneline takes any image and hands back a continuous-line rendering, then lets you download it as a plotter-ready SVG. Getting a true one-line drawing out of a photo normally means fiddly desktop software or a paid web service that uploads your picture to someone's disk. Oneline does it in the browser, for free, and the image never leaves your machine.

Dots first, then a line through them

The trick, which the TSP-art crowd worked out years ago, is that you don't thread a line through a photo. You thread it through dots.

So Oneline starts by turning your image into dots. It reads each pixel's luminance into a density field (dark is dense, light is sparse), scatters points weighted by that field, and then runs Lloyd's algorithm, a relaxation step that nudges each dot toward the center of its own Voronoi cell over a few passes. The dots stop clumping and space themselves evenly within each tone, so shadows fill in solid and highlights stay open. That alone already reads as the photo, in stipple.

Then the line. Treat every dot as a city and find the shortest route that visits all of them. Oneline builds a starting tour with greedy nearest-neighbor (always hop to the closest unvisited dot) and then tightens it with 2-opt: repeatedly find two segments that cross, and uncross them by reversing the path between them. Each uncrossing shortens the total length, and after enough passes the line stops self-intersecting and hugs the tones. That final route, drawn as one stroke, is the portrait.

The detail that changes the math: it's a path, not a loop

Classic traveling-salesman returns to where it started, a closed loop. A pen that never lifts doesn't need to come home, so Oneline solves the open-path version instead. That sounds like a footnote and isn't. The endpoints are now free, which changes the edge bookkeeping inside 2-opt (reversing a segment at either end of the path touches one edge, not two) and it changes the export, since the SVG is a single open <path fill="none"> rather than a closed polygon. Optimize a loop when you meant a path and the line wastes a long segment dragging itself back to the start for no reason.

None of this would feel live if it ran on the main thread. Solving a few thousand cities is not free, so the whole pipeline, stipple then relax then TSP, runs in a Web Worker and streams progress back. The page stays responsive, the preview keeps drawing, and a 1,500-point solve lands in well under a second. The honest caveat: this is 2-opt, not an optimal solver, and optimal TSP is NP-hard anyway. The saving grace is that your eye is a forgiving judge. "Recognizably the subject" needs a good tour, not a perfect one, and 2-opt gets there long before it would converge on the true minimum.

Try it

Open Oneline and drop in a portrait, or click one of the bundled samples if you don't have one handy. Watch the dots scatter by darkness, then watch a single line stitch through all of them, live, into a face. Push the point-count slider up for more detail or tune the contrast, and it re-solves without a reload. When you like it, download the SVG: it's one path, sized in millimeters to A3 through A6, so it drops straight onto an AxiDraw or any other plotter. The code is on GitHub, algorithms included, if you'd rather read the tour-solver than watch it run.

Oneline is live. Free, in your browser, no signup.

This post is part of the build log: every app my automated factory ships gets written up here, honestly. Browse everything at apps.charliekrug.com. Comments are open below.

Comments

Loading comments…