wedge function
Wedge w, anticlockwise from end w to end w + 1: its points on the
central polygon, in anticlockwise order (spec 07 D5.2, D6).
One corner, end w's outgoing-left face ∩ end w + 1's outgoing-right
face, computed once in that argument order so both walls hold the same
bits. Both faces are taken through hub, not through each end's own
point: the members' points differ by up to wallJoin.linear, and a face
at offset 0 must pass exactly through the node, so that a corner and a
foot on it coincide bitwise and the lobes split there (D5.5). Measured on
spike Q5b's generator with every wall in its own rotated group: through
each end's own point, 1.19% of nodes leave a hole and 0.17% of walls fall
back; through hub, 0.76% and 0.11%, as with bitwise joints.
A wedge narrower than 90° is never clamped: its long inner mitre is real
geometry. A wider wedge whose faces are parallel, or whose corner lies
farther than mitreLimit / 2 × the thicker wall from hub, is clamped to
two feet: end w's left face point at hub, then end w + 1's right
face point at hub.
Implementation
List<Vector2> wedge(List<End> ends, int w, Vector2 hub) {
final x = ends[w], y = ends[(w + 1) % ends.length];
final s = sweep(x, y);
final c = intersect(x.leftPoint(hub), x.a, y.rightPoint(hub), y.a);
final limit = mitreLimit / 2 * math.max(x.wall.t, y.wall.t);
if (c != null && (s < math.pi / 2 || (c - hub).length <= limit)) return [c];
return [x.leftPoint(hub), y.rightPoint(hub)];
}