Skip to main content

Module within

Module within 

Source
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-CS within-strategy concept (apply/result two-phase),
  • boost/geometry/strategies/covered_by.hpp — same concept reused,
  • boost/geometry/strategies/cartesian/point_in_poly_winding.hppcartesian_winding, the default Cartesian PIP, implementing the classic winding-number algorithm with on-segment detection,
  • boost/geometry/strategies/cartesian/point_in_box.hppcartesian_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 codeMeaningwithincovered_by
-1outsidefalsefalse
0on the boundaryfalsetrue
+1strict interiortruetrue

§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§

WithinBox
Open point-in-box strategy. See the module docs.
WithinPoly
Open point-in-polygon (winding number, hole-aware) strategy. See the module docs.
WithinRing
Open point-in-ring (winding number) strategy. See the module docs.

Traits§

WithinStrategy
A strategy for point-in-geometry containment.