Expand description
An outline of lines, arcs and circles fitted around a silhouette, clear of it by a play and within a tolerance band.
The band is every point whose signed distance from the silhouette,
positive outside it and negative inside, lies between play and
play + 2 tolerance. The fit has three stages, and only the last one
decides what is returned.
- The middle of the band. The silhouette is first traced afresh as
a region, so its loops bound it exactly, and with
fill_belowset it is closed (see Filling) and stands for the silhouette from then on. Its offset byplay + toleranceis then the union of the silhouette with a rectangle along each edge, on the outside, and a sector at each convex corner, or for a negative offset the silhouette less such rectangles inside and sectors at the reflex corners. The sectors’ arcs are chords sagging a quarter of the tolerance, the offset is taken an eighth further out to centre the sag, and the region engine ofogeom_mesh::planartraces the result: loops whose every point is within an eighth of the tolerance, and the engine’s snapping, of the middle of the band. Holes the band closes over and parts it pinches off are gone from them, and as the boundary of a region they never run out and back. - The fit. Each loop is split into runs a line or a circle follows
within three quarters of the tolerance, less the snapping: the whole
loop as one circle where that holds. A line or an arc spanning a run
lies that close to the loop, so within the band. Consecutive pieces
are joined where their curves meet: a corner turning less than
round_belowtakes the largest tangent arc found to fit the band, a sharper one stays a corner where that fits and takes an arc where it does not, and a joint where neither fits is bridged by the short line between the pieces’ ends, which lies near the loop too. No piece is moved past its middle by a joint, so the joints at its two ends never meet. - The check. Every piece is sampled at a quarter of the tolerance and every sample’s signed distance from the silhouette must lie an eighth of the tolerance inside the band. Distance is 1-Lipschitz, so the whole piece then lies in the band. A loop with any piece failing is returned as the polygon of its middle-of-the-band loop, which is checked the same way.
§Filling
With fill_below = w > 0 the silhouette S is replaced by its
morphological closing by a disc of radius r = w / 2: dilated by r,
then eroded by r. A point outside S stays out of the exact closing
C exactly when some closed disc of radius r holds it and misses S.
So a hole, or a notch, whose largest inscribed circle is no wider than
w across is filled, and one wider keeps the points such discs reach:
a round hole wider than w stays whole, a slot of width s < w closes
but for a dent where the disc dips into its mouth, r - sqrt(r^2 - s^2/4) deep. A convex corner with nothing else of S within w of
it is kept sharp, every point outside it near it lying in such a disc,
while a reflex corner takes a fillet of radius r, the disc’s own.
Both steps are offsets as in stage 1, their arcs chords sagging sigma = min(tolerance, r) / 32: the dilation by r + sigma, its chords
covering the disc of radius r, and the erosion by r, its chords
removing at least the disc of radius r - sigma. The result F
therefore holds C, and lies within the closing by r - sigma of S
dilated by 2 sigma: everything C fills is filled, a hole or notch
more than w + 2 sigma across is kept, and a straight side moves out
by sigma at most; all to within the engine’s snapping. F holds
S, so the outline clears S by the play wherever it clears F, and
the band holds about F.
Structs§
- Outline
- How an outline is fitted around a silhouette.
- Wire2d
- A closed outline: pieces end to end, each starting where the one before ends and the last ending where the first starts. An outer boundary runs counter-clockwise and a hole clockwise.
Enums§
- Piece2
- One piece of a fitted outline.
Functions§
- fit_
outline - Fit an outline of lines, tangent arcs and circles around a silhouette,
every point of it between
playandplay + 2 toleranceoutside the region the loops bound. See the module documentation.