Skip to main content

Module revolve

Module revolve 

Source
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.