Expand description
Revolution of a profile about an axis.
The profile is flattened to rings in its own plane, then each ring point is rotated about the axis in steps chosen by the chord budget. A full turn closes on itself; a partial turn is capped by the profile at each end.
Pappus gives the oracle: a full revolution has volume 2*pi*R*A, where
R is the centroid’s distance from the axis and A the profile area.
§How far the walls sit from the surface (#231)
revolve bounds the distance from every point of the surface swept by
the GIVEN rings to its triangles by tolerance.linear(). Rings that
chord a curved profile add their own deviation on top: a caller that
wants the exact surface of revolution within a budget c flattens the
profile to c_p and revolves to c - c_p. The reference compiler takes
half each, which minimises the triangle count for a fixed sum: the steps
round the profile and round the axis each grow as the inverse square
root of their share, so their product is smallest at an even split. The
two shares add because a rotation is an isometry: a point of the exact
surface is the rotation of a profile point within c_p of the ring
polygon, so it is within c_p of the same rotation of the polygon.
Each ring segment q_a -> q_b sweeps, between the stations at angles
t and t + h, the surface R(s) q(x) with q(x) = (1-x) q_a + x q_b.
For fixed x the point R(s) q(x) runs along an arc of radius
rho(x), its distance from the axis, and the chord between the arc’s
ends is the row at x of the bilinear patch over the quad
R(t) q_a, R(t) q_b, R(t+h) q_a, R(t+h) q_b (a rotation is linear in
the point). An arc of angle h stays within its sagitta
rho (1 - cos(h/2)) of its chord, and rho(x) is the norm of an affine
function, so convex in x and largest at a ring vertex: every point of
the swept surface is within rho_max (1 - cos(h/2)) of the patch, with
rho_max the largest vertex distance from the axis over every ring –
the outer equator, for a torus, never the tube centre. The patch is in
turn within loft::quad_deviation of the two triangles the
loft cuts it into. When the axis lies in the profile’s plane every quad
is a planar trapezoid (its two chords are images of parallel radial
vectors under the same R(t+h) - R(t)), convex while the segment stays
on one side of the axis, and that term is zero: the bound is the sagitta
alone, whatever the sign of the Gaussian curvature (the inner side of a
torus is saddle-shaped, but its trapezoids are still flat). An axis off
the profile’s plane sweeps hyperboloidal quads; their measured twist is
added, and the step shrinks until the sum fits.
Every span of a revolution is the first span rotated, so the twist is measured once.
§Vertices on the axis (#363)
A ring vertex exactly on an in-plane axis (the exact side_of_axis sign
is zero) is fixed under the rotation, so all its stations coincide. It
gets one mesh vertex, shared by every station and by both caps of a
partial turn. Its quads collapse: the one with a single axis end keeps the
triangle that is not degenerate, and the one with both ends on the axis (a
profile edge lying along it) sweeps nothing and emits nothing; an axis
edge of a partial turn is then an edge between the two caps. The bound
above is untouched. A point at radius 0 traces no circle, so the step
count, which the largest radius governs, is unchanged. A collapsed quad is
the triangle (a, b, d) (for b = d) or (a, d, c) (for a = c), which
the patch bounds of loft::quad_deviation cover exactly: |c - a| is
zero for a = c, and 2|d - b| is zero for b = d, where the patch
degenerates into the triangle (a, d, c). The merge changes neither. Merging moves no
vertex: the shared one is the profile point itself, which every station’s
rotated copy equals up to rounding.
In a full turn only a vertex that ends a ring edge lying along the axis is
accepted (sphere, cylinder and cone profiles). One whose both ring
neighbours are off the axis is refused (UnsupportedInput): two nappes of
the surface meet at that point, the boundary is not a two-manifold there,
and its mesh would be non-manifold at the vertex whatever the edge audit
says, as for the horn torus of #248. In a partial turn the two caps close
the point into a sector point, as in the exact path, and it is meshed.
The weld is exact: it needs the axis origin and direction to have z
exactly zero. With z noise within the tolerance, which the in-plane check
forgives, a 2D-on-axis vertex is off the real axis and its orbit is a real
circle, so a touching profile is refused (UnsupportedInput) instead.
Functions§
- revolve
- Revolve a profile about an axis into a closed solid.