Skip to main content

Module pipe

Module pipe 

Source
Expand description

Swept disks along chains of straight segments and circular arcs (#232, #245, #248).

A pipe run, a rebar or a cable tray edge is a disk swept along legs joined by bends or corners: authoring formats write it as a disk swept along a composite of lines and arcs, or along a polyline whose corners are mitred or rounded to a fillet radius. swept_disk_along_pieces meshes all of them so that every point of the exact tube lies within the chord budget of the triangles.

§The bound

Each piece is bounded on its own, with the split crate::sweep uses for one arc (#231): half the budget c chords the disk, so a ring of n points inscribed in the circle of radius r lies within r (1 - cos(pi/n)) <= c/2 of it, and every point of the exact tube is within c/2 of the tube the ring polygon traces when it is carried rigidly along the exact centreline by the piece’s own frames (each exact section circle and its polygon lie in the same plane). The other half bounds that polygon tube against the triangles:

  • Along a segment the frames do not turn, so the polygon tube is a prism whose walls are the mesh’s own planar rectangles: zero.
  • Along an arc of radius R the frames are rotation-minimising, which along a circle means they turn with it: consecutive stations are rotations of one ring about the arc’s axis, and the ring’s plane contains that axis. The polygon tube between two stations is then the revolution crate::revolve bounds, and its triangles are within (R + r)(1 - cos(phi/2)) of it for a step phi: the sagitta of the outer side of the bend, not of the centreline. Its wall quads are planar trapezoids, so their twist adds nothing; the span bound crate::sweep computes, directrix sagitta plus the section’s reach plus crate::loft’s quad bound, is exactly that sum here. The step halves until every span fits c/2; more than 4096 steps on a bend is refused with BudgetExceeded.

§Joints

Consecutive pieces share one station, so the walls meet watertight and wound one way: the incoming piece’s end section. The outgoing piece’s own start frame is that frame turned by the least rotation that takes the incoming tangent to the outgoing one, moved to its start point, and its stations follow from it. Where the pieces are tangent continuous and meet, the two frames coincide. Where they turn by theta or leave a gap g, every vertex of the shared station lies at most delta <= g + 2 r sin(theta/2) from the station the outgoing piece’s bound was proved for; moving a triangle’s vertices by at most delta moves each of its points by at most delta (same barycentric weights), so the first span of the outgoing piece adds the measured delta to its bound and is refined until the sum fits.

A joint turning by at most

theta_max = 2 asin(c / (8 r)) (pi once c >= 8 r)

is tangent continuous at the requested accuracy: its shared section leans off the outgoing piece’s own by at most a quarter of the budget, which that piece’s first span pays as above. A gap above c/4 is refused.

§Mitres

A sharper joint between two straight segments is a corner, and a disk swept round a corner is mitred at half angle (#245): both tubes are cut by the plane through the corner whose normal n = (u + v) / |u + v| bisects the incoming and outgoing tangents u and v. Reflection in that plane maps u to -v, so it swaps the two axis lines and with them the two cylinders of radius r (and the two bores); it fixes the plane, so both cylinders cut it in the same ellipse. The outgoing frame is the incoming one turned by the least rotation about u x v, which agrees with that reflection on the plane square to u. So profile point k of the incoming end section and of the outgoing start section, each projected along its own axis onto the mitre plane, land on one point: the two pieces share that mitre ring, and every vertex of it lies on both exact cylinders. Each wall quad of a segment joins two generator lines of the prism over the ring polygon, so it is a planar trapezoid, exactly a face of that prism cut by the end planes: the walls add nothing, and the span bound measures them as zero.

The section pays instead. A point w + s u of the exact cylinder (w square to u, |w| = r; the mitre plane cuts its generator at s_cut(w) = -w.n / u.n, at most r tan(theta/2)) lies within (1 - l) r <= e = r (1 - cos(pi/m)) of the prism point w' + s u at its azimuth, w' = l w on the ring polygon of m points. When that point lies past the plane, the plane crosses the prism’s generator at l s_cut(w), which moves the point by at most (1 - l) s_cut(w) <= (1 - l) r tan(theta/2) along u, square to the first move: the distance is at most e / cos(theta/2), attained where the ellipse’s major axis ends. The rings are therefore chorded to (c/2) cos(theta_m/2) for the sharpest mitre theta_m (only finer elsewhere), and a mitred pipe keeps every point of the exact tube within c of its triangles, as a smooth one does. A hollow disk’s bore is mitred by the same plane and bounded the same way.

Along a segment of length L the tube runs, on the generator at w, from its start plane to its end plane; both cuts are linear in w, so the shortest generator is L - r |g_perp| with g = n1 / u.n1 - n0 / u.n0 (n0 = u at a square end), and it must be positive (one mitre: L > r tan(theta/2)). Refused by name: a segment whose mitres meet inside the tube, which would cut through itself, and a reversal (theta = pi, where the mitre plane holds both legs).

§Mitres beside an arc

A corner beside an arc is mitred at half angle too (#248), by the same bisector plane, but the plane cuts the bend’s torus in a different curve than the tube on its other side: no ring lies on both exact surfaces, and the exact solid (each tube continued to the plane and cut by it) has a planar face between the two section curves. The end of the bend is meshed as a MitreBand (see its module): from a square section back short of the corner, each profile vertex walks along its own circle of the torus to the plane, so the band’s vertices lie on the exact torus, and where the shared ring is not the band’s own cut, the band stops just short of the plane and a strip, nearly in the plane, joins it to that ring: the mesh of the planar face. The shared ring is the outgoing piece’s: a segment’s mitre ring as above (so a segment beside an arc keeps the proof of the previous section, its ring on its own cylinder), or, between two arcs, the outgoing band’s cut. Nothing proves the band and the strip within the budget by construction; the compiler certifies them against the mesh and reports that bound beside the proven one (pipe_plan gives it the bands). Refused by name: a corner whose plane does not clear the bend’s tube within a quarter turn of it, and bands that need more of an arc than it turns.

§Fillets

A fillet radius f rounds every corner between two straight segments (the swept disk’s fillet_radius): a corner turning by theta is replaced by the arc of radius f tangent to both segments, which cuts f tan(theta/2) off each. Segments shortened to nothing are dropped (two fillets then meet tangentially). Refused by name: a fillet that needs more of a segment than it has, a corner beside an arc (only corners between straight segments are rounded), a disk radius above the fillet radius, or any bend radius, whose tube folds through the bend’s axis on its inside, and a reversal.

A disk radius equal to the fillet (or bend) radius stays refused by name (#248), although the format rule permits it (fillet radius at least the disk radius): the bend is then a horn torus whose inner wall pinches to one point on the bend’s axis, where every section touches. That boundary is not a two-manifold; a closed mesh within the budget would have to either meet itself there (a non-manifold vertex, degenerate triangles along the pinch) or stand off the pinch and misstate it.

§Closed directrices

swept_disk_along_loop sweeps a loop: the last piece ends where the first starts, and that joint is mitred, filleted or tangent like any other (#248). The walls close on the first station, so there are no caps. A frame carried round a loop that leaves its plane does not come back to itself: least rotations at the joints and rotation-minimising frames along the bends return it turned about the first tangent by the loop’s holonomy tau, in (-pi, pi] (PipePlan::twist, the measure reported). The pipe turns its frames back by tau, distributed uniformly over the loop’s clear length: every segment’s length outside the mitre zones at its ends (r tan(theta/2) from each mitred corner, where the plane reaches along it), and every bend’s outside its mitre bands. In the zones and bands the frame is held, so a mitre still shares one ring on both cylinders and its walls stay planar. The twist is part of the proven bound: crate::sweep’s span bound measures the turn between two frames, twist included, and a twisted segment gets stations until each span’s twist fits (more than 4096 is refused with BudgetExceeded). The station closing the loop is the first one; the last span pays its measured distance from the station it was proved for. Refused by name: a loop whose frame comes back turned when no part of it is clear to take the twist.

§Profiles with a fixed reference

The same per-piece proof bounds an arbitrary profile swept with a fixed reference direction along a tangent-continuous chain (#122; see the fixed_reference module): where the reference is normal to the plane of every arc or lies in it, the fixed-reference frame is the rotation-minimising one, each arc is an exact revolution of the placed profile and each segment a prism, and the profile’s rings stand in for the disk’s. fixed_reference_plan refuses corners, a reference parallel to the tangent and a profile that folds through a bend’s axis by name, and reports an arc oblique to the reference as twisting, which nothing here bounds.

Structs§

ArcMitre
A corner mitred beside an arc (#248): the mitre plane and the tubes on its two sides.
FixedReferenceChain
A chain checked for a fixed-reference sweep; only fixed_reference_plan makes one, so a chain in hand has passed its checks.
MitreBand
The tube of a bend next to a corner mitred beside it (#248): the torus about the circle through corner round centre and axis, from the square section back short of the corner to the mitre plane.
PipePlan
How swept_disk_along_pieces and swept_disk_along_loop sweep a directrix (#248): what a caller needs to bound the parts of the mesh no construction proof covers.

Enums§

FixedReferencePlan
How fixed_reference_plan reads a chain.
MitreSide
One side of a corner mitred beside an arc (#248).
PathPiece
One smooth piece of a swept disk’s directrix.

Functions§

check_disk_along
Refuse a disk of radius swept along piece alone when it is malformed or the tube would fold through a bend’s axis: the checks swept_disk_along_pieces makes of each piece, for the one arc the conic sweep takes (#122).
fixed_reference_along_pieces
Sweep rings along a planned chain so that every point of the exact surface lies within chain.walls() of the mesh (see the module notes).
fixed_reference_plan
Check a chain of pieces for a fixed-reference sweep of a profile of reach at wall budget chord and decide whether the bound is proven.
joint_tolerance
The largest turn a joint may make and still be tangent continuous at chord budget chord for a disk of radius radius: 2 asin(c / (8 r)) (see the module notes).
pipe_plan
How swept_disk_along_pieces (closed false) or swept_disk_along_loop (closed true) sweeps these pieces at this budget, refused exactly as they refuse it.
reference_clearance
The smallest angle between reference and the line of the tangent over the piece, in [0, pi/2]. Zero where the frame degenerates.
ring_reach
The furthest ring vertex from the profile’s origin.
swept_disk_along_loop
swept_disk_along_pieces round a loop (#248): the last piece ends where the first starts, that joint is mitred, filleted or tangent like any other, and the walls close on the first station without caps. A frame that comes back turned is twisted back uniformly over the loop’s clear length (see the module notes and PipePlan::twist).
swept_disk_along_pieces
Sweep a disk, optionally hollow, along a chain of segments and arcs so that every point of the exact tube lies within chord of the mesh.