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:

PairingResult
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 SCALE quantum: a subject exactly on the solid region's boundary needs no correction, so the query returns null — 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.

PairingResult
Polygon gap Polygonthe 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 intersects gate of the predicates package, rounded at the SCALE quantum: 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 start to end is the same for all of them. The segment itself stays raw.

Types

Link copied to clipboard
class Penetration(val edge: Segment, val depth: Double, val normal: Direction)

One polygon's resolved penetration into a region it may not occupy: the violated face, how deep, and the way out.

Functions

Link copied to clipboard
infix fun Polygon.collide(collider: Polygon): Penetration?

Polygon collide Polygon => Penetration?
Returns the penetration where this polygon reaches into collider's solid region, or null when the two are clear of each other, touching included.

Link copied to clipboard
infix fun Polygon.escape(boundary: Polygon): Penetration?

Polygon escape Polygon => Penetration?
Returns the penetration where this polygon reaches out of boundary's solid region, or null when it lies within, touching included.

Link copied to clipboard
infix fun Polygon.gap(other: Polygon): Segment?

Polygon gap Polygon => Segment?
Returns the shortest segment from this polygon to other — from a point of one boundary to the nearest point of the other's — or null when their solid regions share any point, touching included.

Link copied to clipboard
operator fun Penetration?.invoke(onPenetration: (Penetration) -> Unit): Penetration?

Penetration? { onPenetration } => Penetration?
Runs onPenetration on the penetration when there is one, and returns the receiver unchanged either way.