Package-level declarations
The query tier, split by answer kind: predicates carries the Boolean queries, rounded at the SCALE quantum; measures carries the scalar measurements — raw Euclidean distances and angles; the data queries at this level — penetration and gap — answer with geometry-flavored data — offending edge, depth, normal, the shortest segment — whose values stay raw behind rounded existence gates.
The penetration family
The dual collision queries: subject collide collider answers where the subject polygon reaches into the collider's solid region, subject escape boundary where it reaches out of the boundary's — the violated face, the penetration depth, and the way back. The queried polygon's orientation decides which side is solid, and with it the strategy:
| Pairing | Result |
|---|---|
Polygon collide Polygon (classic collider — an obstacle) | the subject's shallowest push-out past a single face, or null when they don't overlap or merely touch |
Polygon collide Polygon (inside-out collider — a wall) | the subject's deepest protrusion out of the allowed interior, or null when it lies inside |
Polygon escape Polygon (classic boundary — a container) | the subject's deepest protrusion out of the boundary's interior, or null when it lies inside |
Polygon escape Polygon (inside-out boundary — its loop forbidden) | the subject's shallowest push-out of the loop past a single face, or null when it lies clear of the loop or merely touches it |
Penetration? { onPenetration } | the handler spelling: runs the lambda on the penetration when there is one, and passes the answer through |
The two verbs are duals through negation — subject escape polygon agrees with subject collide -polygon, and subject collide polygon with subject escape -polygon, on depth and normal — each named in its own right rather than spelled through the other. The shared contract, inherited by constraints' coerce verbs:
Convex loop on the queried polygon. Candidate faces come from the collider or boundary — the subject contributes its vertices — and the pick is sound only when that loop is convex; a concave one yields an arbitrary pick, not an error. Where the subject is kept out of a bounded region (a classic collider, an inside-out boundary) the subject must be convex too — a concave one may be reported clear while it overlaps; where it is kept within one (an inside-out collider, a classic boundary) any polygon works.
One penetration per call. Situations violating several faces at once converge by resolving and querying again.
Touching is not penetration. Existence rounds at the
SCALEquantum: a subject exactly on the solid region's boundary needs no correction, so the query returnsnull— whichever side's vertex rests on the other's face. The returned depth itself stays raw.
Penetration.depth is a raw Euclidean distance and Penetration.normal a unit direction pointed out of the region the subject may not occupy — the correcting direction of the penetration.
The gap query
The closest pair of two polygons clear of each other: subject gap other answers the shortest segment from the subject's boundary to the other's, its length the shortest distance between them.
| Pairing | Result |
|---|---|
Polygon gap Polygon | the shortest Segment from this polygon to the other — start on this polygon, end on the other — or null when the solid regions share any point, touching included |
The contract:
Disjoint solid regions. Existence is the closed
intersectsgate of thepredicatespackage, rounded at theSCALEquantum: overlapping or touching regions have no gap.Oriented regions. Each operand is its oriented solid region — a polygon within an inside-out one pairs to the loop from inside, and two inside-out polygons never have a gap.
No convexity required of either operand.
Ties are arbitrary. Parallel faces share the shortest distance; one pair is picked, and the displacement from
starttoendis the same for all of them. The segment itself stays raw.
Types
Functions
Penetration? { onPenetration } => Penetration?
Runs onPenetration on the penetration when there is one, and returns the receiver unchanged either way.