Engraive

Corner sharpening.

The third stage, and the one that puts points back. potrace decides corner-against-curve with a single threshold, and everything it calls a curve comes out as a chain of short Béziers — including the two or three it lays across what used to be a sharp point. A V-bit plunges to full depth where two edges meet, so that little fillet is the difference between a crisp corner and a rounded one, and no amount of tuning the tracer fixes it without faceting the genuinely curved parts of the same drawing. This pass puts the point back afterwards. It is off by default.
  1. Preprocess
  2. Trace
  3. Corners
  4. Vertices

It runs before vertex merging, and has to: merging collapses clusters of vertices, and the fillet this pass reads is exactly such a cluster. Thinned away first, there would be nothing left for it to recognise as a corner.

What it does

Three steps, in order. Every segment is classified straight or curved. Each run of straight segments is folded into as few lines as the tolerance allows. Then each short, high-turn run caught between two long straight edges is replaced by the single point where those two edges would have met, if they had been allowed to meet.

as traced — 209 vertices

sharpened5 vertices

209 vertices in, 5 out204 dropped, 98%

A five-cornered contour written the way a tracer writes one, at the stock settings — 25°, 10 px, 0.6 px. The rings mark the corners the shape was built around: dashed where the contour still rounds it, solid where the pass has put the point back. All five come back here, and the worst of them lands 0.06 px from where the two edges actually cross — the corner is reconstructed, not approximated.

The pass works on segment boundaries rather than on a flattened polyline, which is why the fold in step two never touches a curve: every endpoint of a curved segment is pinned before simplification starts, so a curve cannot be resampled and its ends cannot slide along it. What gets folded is the runs that are straight but written as dozens of segments.

Corner angle

The test for whether a rounded run is worth calling a corner at all. It is measured between the two straight edges either side of the run, once each has been fitted, and a turn shallower than this is left exactly as the tracer drew it.

The shape below has five corners of five different turns — 50°, 100°, 85°, 70°, 55° — and nothing else about them differs. Raise the threshold past one of those numbers and that corner drops out of the pass and stays round; every corner sharper than the threshold still comes back to a point.

as traced — 191 vertices

at 25°5 vertices

25 °

5 of 5 corners rebuiltthe ones turning more than 25°

191 vertices in, 5 out186 dropped, 97%

Max corner radius is held at 20 px here rather than at the stock 10, because this shape's fillets are 10 px across and the longest of them runs 17 px — past the stock radius, which would have refused every corner on length before the angle test ever ran. The two controls are not independent, and this is where you feel it.

Max corner radius

A length, not a curvature. It is the longest rounded run the pass will agree to collapse back to a point, measured along the run itself. That is what keeps step three from eating real curves: a fillet is shorter than this, and an actual curve is not.

The five corners below all turn the same 72°, so the angle test has nothing to separate them. What differs is the size of the fillet on each — 3 px, 6 px, 10 px, 15 px, 20 px. Raise the radius and they come back in order of size, smallest first.

as traced — 244 vertices

at 20 px6 vertices

20 px

4 of 5 corners rebuiltan edge must be 60 px long to be trusted

244 vertices in, 6 out238 dropped, 98%

Keep going and it turns over. This radius also sets the length an edge has to have before the pass will trust it as one of a corner's two sides — three times the radius — so once it passes a third of the shortest edge on the shape, there is nothing left it is willing to call a straight edge and the whole pass declines. On this contour that happens in the high thirties, and every corner goes back to round at once.

Line tolerance

How far a straightened run may stray from the outline the tracer drew. A traced edge does not arrive as one long line: it arrives as dozens of short ones, each end snapped to a fraction of a pixel, so a nominally straight edge is a staircase. This is the height of step the fold is allowed to ignore.

The shape below has one of each thing the tolerance has an opinion about: a long edge written as a quantized staircase, a deep curve that is unmistakably a curve, and a shallow bow that is a curve only just — it strays 3.5 px from its own chord. Raise the tolerance and the staircase folds away. Keep raising it and the bow stops counting as a curve at all and is folded flat with everything else, which is the cost of a tolerance set too high.

as traced — 90 vertices

at 0.60 px5 vertices

0.60 px

3 of 3 curves carried throughthe bow goes at 3.5 px

90 vertices in, 5 out85 dropped, 94%

A curve carried through is handed on as the cubic it arrived as, never resampled, so the deep curve here is bit-for-bit what the tracer drew at every setting that keeps it. The tolerance is in source-image pixels, like the corner radius and for the same reason: it has to mean one fixed distance whatever preprocess Scale is set to.

It also sets a floor under the other two. Corner reconstruction needs two long straight edges to extend, and the staircase only becomes a long straight edge once the fold has been allowed to flatten it. Set the tolerance below the quantization and no run folds, no edge is long enough to be trusted, and not one corner is rebuilt — whatever the other two controls say.

tolerance 0.10 px — 69 vertices

tolerance 0.30 px — 5 vertices

The same contour, the same 25° and 20 px, and the only difference is a fifth of a pixel of tolerance. On the left nothing has been folded, so nothing is a corner. This is what “I turned Corners on and nothing happened” looks like.

What it will not do

It will not resample a curve.

A curve that is really a curve is carried through as the cubic it arrived as. The pass works on segment boundaries rather than on a flattened polyline, and pins both ends of every curved segment before it folds anything, so simplification can neither redraw a curve nor slide its ends along it.

It will not rebuild a corner it has only one side of.

A corner is reconstructed from two straight edges extended until they cross, so both sides have to be long enough to trust — three times the max corner radius. A corner between two short edges, or between an edge and a curve, is left as it was.

It will not invent a corner out of a shallow bend.

Two nearly parallel edges meet a long way from the artwork. Where the crossing point lands further from the rounded run than twice the max corner radius, the pass takes that as evidence it has misread the shape and leaves the run alone.

It will not fire on an open path or a tiny one.

It works on closed contours of at least three segments, and if a step would leave fewer than three it hands back exactly what arrived rather than a shape with nothing left of it.

It will not change with preprocess Scale.

All three figures are in source-image pixels. Scale changes how finely the tracer samples, not what a pixel of the original means, so the same settings do the same thing to the same artwork at any Scale.

Reading it on the bench

Turn Corners on and watch two things. The node count in the header falls hard, because folding the straight runs is most of what the pass does by volume. Then switch to Overlay view and look at the corners themselves against the source: that is the only place where a corner reconstructed from the wrong two edges shows up, and it shows up as a point sitting off the artwork. If nothing at all changed, raise Line tolerance before touching anything else.

Open the trace workbench