Skip to main content

Crate max_inscribed_circle

Crate max_inscribed_circle 

Source
Expand description

Maximum inscribed circle (MIC) solvers for polygons.

The maximum inscribed circle is the largest circle that fits entirely inside a polygon. Holes are respected: the circle has to clear interior rings as well as the exterior, so the solve runs against every boundary segment.

§Quick start

use max_inscribed_circle::geo_types::{LineString, Polygon};
use max_inscribed_circle::{maximum_inscribed_circle, MicOptions};

let square = Polygon::new(
    LineString::from(vec![(0.0, 0.0), (4.0, 0.0), (4.0, 4.0), (0.0, 4.0), (0.0, 0.0)]),
    vec![],
);

let mic = maximum_inscribed_circle(&square, &MicOptions::default())?;
assert!((mic.center.x() - 2.0).abs() < 1e-9);
assert!((mic.radius - 2.0).abs() < 1e-9);

§Solve pipeline

Two stages, both native Rust. MicResult::used_engine and MicResult::approach report which one produced the answer:

  1. Closed-form fast paths for single-ring inputs of four or five vertices: triangle incenter, axis-aligned rectangle, then a convex-quad Chebyshev solve. Every result is re-measured against the segment table and falls through to the grid when the ring is not the class it claimed.
  2. Grid search over the bounding box, a branch and bound driven by the 1-Lipschitz property of boundary distance, refining to a tolerance of diag * 1e-7, then a compass hill climb on the clearance field.

The radius a result reports is always the measured distance from its centre to the nearest boundary segment, so a returned circle fits the polygon. A degenerate input, such as a zero-area ring or a non-finite coordinate, fails fast with MicError::InvalidInput instead of returning a meaningless circle.

§Entry points

FunctionUse
maximum_inscribed_circleone polygon
maximum_inscribed_circle_multipolygonbest circle across components
maximum_inscribed_circle_slicerayon-parallel batch, input order preserved
maximum_inscribed_circle_with_workspacereuse a MicWorkspace across calls

§GEOS comparison

The bench-geos feature compiles mic::solver::bench_geos, which calls the GEOS MaximumInscribedCircle construct so benchmarks can cross-check the native solver. It is not an engine: nothing in mic calls it, and the default feature set does not compile it. GEOS runs the same cell-refinement branch and bound as the grid stage, so agreement between them means two implementations of one algorithm match, not that an independent method confirms the radius.

§Features

FeatureEffect
bench-geoscomparison only: links the GEOS C library so benchmarks can compare solvers
geo-traitsgeneric solves over any geo_traits polygon, plus geo_types::Geometry dispatch
shewchukexact orient2d predicates from the robust crate in the containment and orientation tests
simd4-lane batched segment distance via the stable wide crate
hotpath#[hotpath::measure] instrumentation on the solver entry points
pythonPyO3 extension module named max_inscribed_circle
extension-modulebuild the Python module as an importable extension

Default features are empty. The bench-geos feature links against the GEOS C library, and its build script expects GEOS_LIB_DIR and GEOS_VERSION when GEOS cannot be found through pkg-config.

§C ABI

ffi exposes mic_solve, mic_solve_multipolygon and mic_options_default: flat coordinate arrays in, #[repr(C)] structs out, 0 on success and -1 on error, with panics caught at the boundary. The

Re-exports§

pub use mic::workspace::MicWorkspace;
pub use mic::maximum_inscribed_circle;
pub use mic::maximum_inscribed_circle_multipolygon;
pub use mic::maximum_inscribed_circle_slice;
pub use mic::maximum_inscribed_circle_with_workspace;
pub use mic::MicApproach;
pub use mic::MicError;
pub use mic::MicOptions;
pub use mic::MicResult;
pub use mic::MicUsedEngine;
pub use geo_types;

Modules§

ffi
C ABI for the MIC solvers (holes + multipolygon).
geo_interopgeo-traits
georust ecosystem interop (feature geo-traits).
mic
Maximum Inscribed Circle (MIC) solvers for polygonal inputs.
tuning
MIC tuning constants carried over from IGE ige-core::tuning.