axiolid-construct
Solid generation: profiles, lofts, sweeps, revolutions and half-space clipping.
| Latest release | 0.4.0 (2026-11-13) |
| crates.io | axiolid-construct |
| Facade | axiolid feature generate |
| Layer | algorithms (algorithm.construction) |
| API documentation | rustdoc · docs.rs |
| Source | crates/algorithms/construction/construct/ |
Overview
Solid generation from exact inputs: extrusion, revolution, sweeps, lofts, centre-line profiles, half-space clipping proxies, offsets, fillets and chamfers on supported families, and focused exact booleans (planar polyhedra, coaxial column solids). Every Profile variant extrudes to an exact B-rep, along or against its profile normal, and every one but the ellipse along a direction leaning off it (arcs sweeping oblique circular cylinders), and revolution -- a full turn, or a partial turn capped by the profile at both ends -- covers any profile that lowers to a contour; a disk swept along a segment or an arc is exact; other sweeps and lofts produce meshes by default, a disk swept along a chain of segments and arcs within a proven chord bound, as is a profile swept with a fixed reference along such a chain when it is tangent continuous and the reference is normal to or lies in every arc's plane (within a twist term the bound pays for). Geometry the kernel cannot represent exactly is refused, never tessellated in its place. The crate takes geometry and returns geometry: it owns no operation graph, cache, execution context or provider dispatch (ADR 0023); axiolid-mesh-compile does those and calls in here.
Design notes
A profile can be validated exactly on the contour the exact path lowers it to (profile_validate::ExactProfileValidator, ADR 0095): closure, self-contact and hole nesting, with findings that name segments. scripts/probe_profile_validate_mutants.py lists the faults its tests must catch.
Tests that check a generated mesh is accepted by a mesh Boolean provider live in crates/execution/compile/tests/, not here. A dev-dependency on a provider or execution crate would pull this algorithms crate's tests above its tier; the architecture check only enforces the tier edge for normal dependencies, so the allowlist in Cargo.toml is what keeps it out.
Depends on
axiolid-brepaxiolid-brep-auditaxiolid-contractsaxiolid-coreaxiolid-curveaxiolid-exactaxiolid-guaranteesaxiolid-meshaxiolid-mesh-boolean-contractaxiolid-mesh-contractsaxiolid-nurbsaxiolid-overlayaxiolid-predicatesaxiolid-primitiveaxiolid-profileaxiolid-referenceaxiolid-surfaceaxiolid-tessellation-contractaxiolid-topology
Changes
Latest release, 0.4.0 (2026-11-13):
Changed
- Breaking: requires
axiolid-overlay0.4, whoseOverlayErroris#[non_exhaustive]with the newHolesOverlapandPolygonsOverlap, and whoseRegion::newrefuses rings that cross into each other.ProfileFinding::DegenerateRingcarries thatOverlayError, so amatchon it needs a wildcard arm (#448, ADR 0104). revolve_arc_ringrefuses an axis origin withz != 0as "exact revolution about an axis out of the profile plane" (#450); it used to accept it unless the section touched the axis.- The exact revolution is built about the axis as given (#450). An axis exactly along y (either sense) builds in place with the same geometry as before (the pcurves of a wall's loop are added in another order); any other axis lying exactly in the profile plane (
zzero in its direction and origin) maps the section rigidly into the axis's own frame, revolves it about +y there and places the solid back withExactBRep::transformed, composites, holes and partial turns included. A tilt of a milliradian was silently snapped onto y within the tolerance, so a groove about an axis tilted 1e-3 rad at radius 2 sat 2 mm from where it was asked for (the mesh/exact comparison read a certified 4.5e-3 against a 1e-3 budget); it is now exact, and a section the tilted axis puts on both sides is refused as crossing it. An axis with a component out of the plane (a directionzor an originzother than exactly zero) isUnsupportedInput("exact revolution about an axis out of the profile plane"): its edges sweep hyperboloids, so there is no tolerance band to offer; a zero or non-finite axis is invalid input.revolve_arc_ringrefuses an origin off the plane the same way. In the axis's frame a vertex exactly on the axis is put on it and a disc edge exactly perpendicular to it keeps equal heights; a vertex the rotation's rounding cannot keep on its side, and an edge not exactly perpendicular whose heights round equal, are refused by name. - An arc of a lowered contour evaluates
sinandcosexactly at a quarter turn (#379): a parameter within2 * EPSILON * max(1, |t|)of one (every form a producer writes,FRAC_PI_2,-PI / 2,1.5 * PI,PI + FRAC_PI_2, ...) puts the end of the arc at exactly0and+-1in that coordinate, where it used to be up to0.55 * t * EPSILONoff (0.18at the quadrants of a turn or two). A ring that lowered before is unchanged except at the arc's ends and at split vertices that land on a quadrant, by less than the error of the point itself; a parameter 1e-12 from a quarter turn keeps its angle. The joint check reads the arc's radius timesmax(1, |t|)in its scale, so an arc of a large parameter closed by a line between its raw ends still lowers atTolerance::ZERO. This makes an arc end on a revolution axis through its centre exactly on it, which the exact revolution needs. A rounding gate like the joint rule (#250), not reported.
Added
revolve_profile_exactandrevolve_arc_ringrevolve a full turn of a profile that touches the axis (#379): along edges lying on it, at straight edges ending on it exactly perpendicularly (a disc cap: a solid cylinder, a stepped shaft), at any other straight edge ending on it (a cone up to its apex: a cone, a bolt, a spinning top, a top with a cavity) and at an arc ending on it with its circle centred on it (a sphere up to its pole: a ball, a domed column, a hemisphere cap). An axis edge sweeps no face. A vertex on the axis is admitted when one of its two edges lies on the axis; the contact is classified with the exactside_of_axissign, no tolerance. An apex or pole is a vertex of the B-rep, not a degenerate edge: the cone is framed at its apex with radius zero, the sphere on the axis at the height equidistant from both arc ends, and the wall's loop leaves a gap along the pole line in its parameters, which the boolean and the deviation oracle close. Whether an arc is a sphere's meridian is decided within64 * EPSILONof the largest magnitude it is computed from: its coordinates, the axis's and, about an axis in another direction, the given section's (a bulge cannot encode a quarter arc exactly, and a radius is a difference of numbers of the axis's size); the sphere is placed exactly on the axis, and the gate is not reported, as it only chooses between that sphere and a refusal. A section crossing the axis, touching it at a vertex with no edge along it (a pinch point), ending on it at an arc whose circle is not centred on it (a lemon, an apple, an ogive nose: a spindle or horn torus), at an arc with both ends on it or at an arc running across it staysUnsupportedInputby name, as does a vertex within the tolerance of the axis but not on it to the bit and an edge ending on the axis within the tolerance of perpendicular to it but not exactly, and a straight edge so near perpendicular that a cone's angle cannot carry its slope (below). A semicircle (a bulge of exactly one) between two vertices on the axis is split at its midpoint, as the lowering splits a half turn, and revolves to a ball; another bulge between them is a lemon and is refused. A section with several contacts (a cavity along the axis) gives one solid per outermost piece with the nested pieces as void shells, nested by the heights of every face's stations, poles included; a solid inside a cavity is refused.
Fixed
- A cone whose edge is nearly perpendicular to the axis was built with an angle that does not carry its slope when the tolerance did not cover it (#379): at
Tolerance::ZERO, a frustum[(1,0),(2,1e-12),(2,1),(1,1)]came backOkwith its pcurves 7e-5 off their curves, and the same for a cone's apex edge. The exact revolution now refuses an edge whoserise * tan(angle)differs from its radius change by more than the tolerance or eight machine epsilons of its largest coordinate, whichever is larger, as an edge so near perpendicular to the axis that a cone cannot carry its slope. revolve_arc_ringmirrored a section on the negative side of the axis without walking it backwards, so its walls faced inward and its signed volume was negative; the mirrored section is now walked the other way round (#379).
Full history: crates/algorithms/construction/construct/CHANGELOG.md