Generic 2-D polygon area — no topology or rendering dependency, so it
lives here rather than in geop-ops-rasterize: geop-core-topology’s
own edit code (splice_edge_into_face’s loop-orientation check) needs
it too, and topology sits below rasterize in the dependency order.
Like format!, but for WithContext::with_context: builds a
ContextSource that formats its message lazily, only if the result is
actually an Err — .with_context(with_context!("failed at i={i}"))
costs nothing on the success path, unlike .with_context(&format!(...))
(eagerly formats every time, even when nothing is wrong).