Expand description
Lower an arbitrary contour profile onto the arc-ring extruder (ADR 0053).
§Why this is an adapter, not new geometry
ContourProfile carries segments of
any Curve2 kind. The arc-ring
extruder already builds exact walls for the two kinds that matter here –
Line2 becomes a planar wall, Circle2 becomes a cylindrical one – so
lowering a contour to an ArcRing is a translation, not a construction.
A Polyline2 segment is exact too: one straight vertex per polyline
vertex it passes (see lower_polyline).
Anything else is REFUSED rather than sampled. Tessellating an ellipse or a spline into short chords would produce a solid that looks right, passes every closure check, and silently is not the requested shape.
§Closure at Tolerance::ZERO (#250)
A ring is a cycle of vertices, each carrying the bulge of the edge that leaves it, so it is closed by construction: the vertex at a joint is ONE value, the end of the edge entering it and the start of the edge leaving it. It is the leaving segment’s start – a line’s stored origin bit for bit, an arc’s circle at its first parameter – and nothing is averaged or moved onto it.
The segments themselves cannot meet exactly in floating point, however
carefully the producer shares its points (the section router computes
every corner and tangent point once and hands that one value to both
segments). A line stored as origin + t direction ends at
origin + direction, which rounds, and its stored direction is already
the rounded difference of the two points; an arc ends at the cos and
sin of a transcendental sweep. No choice of Line2 or Circle2 makes
both ends of every segment bit-exact. So the joint check compares the
entering segment’s evaluated end with the leaving segment’s start
against the larger of the caller’s tolerance and the rounding of those
two evaluations: eight machine epsilons of the magnitudes they are
computed from, a few ulps of the coordinates. That is what lets a
section with non-dyadic sizes (IPE 300 left 2.6e-18 at the flange tip)
lower at Tolerance::ZERO, while a contour open by more than its own
rounding is still refused there. The check only decides WHETHER a ring
is built, never what it is: a ring that lowered before is bit-identical,
except at the vertices of an arc that land on a quarter turn (#379), below.
§Quarter turns evaluate exactly (#379)
At a quadrant parameter an arc’s cos or sin is the rounding of the
parameter, not zero: for every form a producer writes (FRAC_PI_2,
-PI / 2, 1.5 * PI, PI + FRAC_PI_2, TAU - FRAC_PI_2, …)
|cos t| is 0.18 * t * EPSILON at the quadrants of a turn or two and up
to 0.55 * t * EPSILON (at 20.5 * PI). That is the evaluation’s own
error, but it decides whether an arc’s end lies on a revolution axis
through its circle’s centre, which the exact revolution tests with an
exact sign. A parameter within QUADRANT_ROUNDING * max(1, |t|) of a
quarter turn therefore evaluates sin and cos as exactly 0 and +-1.
This moves a point by less than the error of the point itself, and
names no tolerance: a parameter further from the quadrant, by 1e-12
say, is its own angle. It is a rounding gate like the joint rule above,
never reported. The vertices it moves are the arc’s ends and any split
vertex (a sweep of a half turn or more is split) that lands on a quadrant;
the joint rule reads the arc’s radius times max(1, |t|) in its scale
(endpoint_scale), since the snap and an unsnapped sin_cos of a large
parameter differ by that much.
Functions§
- arc_
ring_ signed_ area - Signed area of a bulge-encoded ring; positive when counter-clockwise.
- contour_
to_ arc_ ring - Convert one closed contour into an arc ring.
- orient_
arc_ ring - Force a ring to the winding a boundary role requires.
- reverse_
arc_ ring - Reverse an arc ring in place, preserving its arcs.