Expand description
Per-CS strategy for point-in-polygon containment (within /
covered_by).
Mirrors the pieces of Boost.Geometry that collaborate to make
boost::geometry::within(p, g) / boost::geometry::covered_by(p, g)
work for any (point, polygonal | box) pair in any coordinate system:
boost/geometry/strategies/within.hpp— the per-CSwithin-strategy concept (apply/result two-phase),boost/geometry/strategies/covered_by.hpp— same concept reused,boost/geometry/strategies/cartesian/point_in_poly_winding.hpp—cartesian_winding, the default Cartesian PIP, implementing the classic winding-number algorithm with on-segment detection,boost/geometry/strategies/cartesian/point_in_box.hpp—cartesian_point_in_box, the per-corner strict / non-strict comparisons used to fold “is the point inside this axis-aligned box” into the dispatch.
The Boost concept exposes a stateful three-step API — construct a
state_type, call apply(point, s1, s2, state) for every segment,
then call result(state) to read off -1 / 0 / +1 (outside /
boundary / interior). The Rust analogue collapses that three-step
shape into a single within / covered_by pair on
WithinStrategy because the per-segment walk is identical for
every CS — only the per-segment kernel changes.
§Coherence note
Boost dispatches on the geometry’s tag via partial template
specialisation — dispatch::within<Point, Ring, _, ring_tag> and
dispatch::within<Point, Polygon, _, polygon_tag> are mutually
exclusive because the C++ side can prove tags distinct. Rust’s
trait system cannot prove a downstream type does not implement
several geometry traits at once, so two open blankets on one strategy
struct would collide (E0119). The port reproduces Boost’s tag
dispatch instead: one per-kind strategy struct (WithinBox,
WithinRing, WithinPoly) carries a single concept-bounded
WithinStrategy impl — distinct Self, so no overlap — and the
tag-keyed [WithinStrategyForKind] picker routes G::Kind to the
right struct. Because the picker keys on the tag, any concept-adapted
foreign type resolves through the same path as the equivalent
geometry-model value.
crate::intersects reaches point-in-polygon containment through
the open WithinPoly strategy directly (not the algorithm-layer
covered_by free fn — that would be an upward crate dependency /
cycle), so both crates share the one open kernel.
§Result-code convention
Mirrors Boost’s cartesian_winding::result at
strategy/cartesian/point_in_poly_winding.hpp:69-74:
| Boost code | Meaning | within | covered_by |
|---|---|---|---|
-1 | outside | false | false |
0 | on the boundary | false | true |
+1 | strict interior | true | true |
§Precision limit (Cartesian, f64)
The winding kernel decides each point’s side of a segment from the
sign of a cross product of coordinate differences. For f64 that
sign is exact only while the operands stay within the mantissa: past
roughly ±2^26 (67_108_864) the products no longer fit in 53 bits
and the sign can flip, so a strict-interior / boundary / exterior
classification may be wrong for coordinates beyond that magnitude.
This is the same limit the overlay engine gates on with its
SAFE_ABS_MAX range guard, and it matches Boost: the non-rescaled
cartesian_winding shares the bound (Boost’s rescaling only ever
applied at the overlay/turn layer, not here). within does not
reject out-of-range input — callers that work with coordinates beyond
±2^26 must scale down first.
Structs§
- Within
Box - Open point-in-box strategy. See the module docs.
- Within
Poly - Open point-in-polygon (winding number, hole-aware) strategy. See the module docs.
- Within
Ring - Open point-in-ring (winding number) strategy. See the module docs.
Traits§
- Within
Strategy - A strategy for point-in-geometry containment.