A circle against a polygon is SAT with one extra axis - the direction from the nearest corner - so corners are handled as well as faces. Today you build the last shape pair.
Detect a circle overlapping a convex polygon using the polygon's normals plus the nearest-vertex axis.
A circle has no edges, so it contributes no face normals to SAT - but there is still a direction that can separate a circle from a polygon that none of the polygon’s own normals cover: the line from the circle’s center to the nearest vertex. Add that one axis to the polygon’s edge normals, project the circle (its shadow on any axis is just its center’s dot product plus and minus the radius), and run the same overlap test as before.
That extra axis is what makes a circle rolling off a corner of a polygon behave
correctly instead of snapping to a face. For a circle pressing flat against a side, the
face normal still wins as the shallowest overlap, giving normal {1, 0} and penetration
0.5 here. With this pair done, the engine can now detect a contact between any two of
its shapes - circles, boxes, and polygons in every combination. The next lesson wires
them together behind one dispatcher.
func projectCircle(center Vec2, r float64, axis Vec2) Interval {d := Dot(center, axis)return Interval{d - r, d + r}}// axes = polygon Normals, plus Normalize(center - nearestVertex).// Overlap circle-vs-polygon on each; any gap -> no collision;// smallest overlap -> normal (flipped toward the circle) + penetration.