Skip to main content

Crate geo_repair

Crate geo_repair 

Source
Expand description

Validate and repair invalid OGC GIS geometries in Rust.

Detects and fixes geometry defects — self-intersections, unclosed rings, degenerate shapes, NaN coordinates, and more — using algorithms selected by geometry type. The Structure strategy (default) mirrors GEOS’s ST_MakeValid algorithm; the Arrange strategy uses CDT-based repair as a robust fallback for complex topologies. Passes 2490/2490 GEOS XML validation tests, with parallel batch performance 0.30× GEOS (3.3× faster) on 1.58M data set polygons.

§Quick start

[dependencies]
geo-repair = "0.12"
use geo_repair::{is_valid, validate, MakeValid, ValidateAndFix};
use geo_repair::{read_wkb, write_wkb, read_wkt, write_wkt};

// Check validity
let result = validate(&geometry);
if !result.valid {
    for err in &result.errors {
        eprintln!("  {err}");
    }
}

// Fix invalid geometry
let fixed = geometry.make_valid();

// Combined validate-and-fix
let (result, fixed) = geometry.validate_and_fix();

// WKB roundtrip
let bytes: Vec<u8> = write_wkb(&geometry);
let geom = read_wkb(&bytes).unwrap();

// WKT roundtrip
let text: String = write_wkt(&geometry);
let geom = read_wkt(&text).unwrap();

§With method selection

use geo_repair::{MakeValid, MakeValidConfig, PolyMethod};

let config = MakeValidConfig {
    poly_method: PolyMethod::Arrange,
    keep_collapsed: false,
    ..Default::default()
};
let fixed = geometry.make_valid_with_config(&config);

§WKB I/O (built-in, no dependencies)

use geo_repair::{read_wkb, write_wkb, read_wkb_concat};

let wkb: Vec<u8> = write_wkb(&geom);
let geom = read_wkb(&wkb).unwrap();
let geoms: Vec<Geometry<f64>> = read_wkb_concat(&concat_buffer).unwrap();

§WKT I/O (built-in, no dependencies)

use geo_repair::{read_wkt, write_wkt};

let wkt: String = write_wkt(&geom);
let geom = read_wkt(&wkt).unwrap();

§Binary format loading (custom .bin format, fast bulk I/O)

use geo_repair::load_bin;

let polys: Vec<geo::Polygon<f64>> = load_bin("dataset.bin").unwrap();

§Feature flags

FeatureDescriptionDefault
stdStandard library + file I/O. Disable for no_std builds.yes
arrangeCDT-based polygon repair (requires spade)yes
structureStructure-based fast-path repairyes
parallelRayon parallel processing (non-WASM)yes
simdAVX2-accelerated orientation tests (x86_64)yes
simd-portablePortable SIMD via core::simd (nightly)no
validateOGC validation predicatesyes
memmapMemory-mapped binary file loadingno*
wasmWASM browser fetch (synchronous XHR)no
mimallocUse mimalloc global allocatoryes
io-shpShapefile format backendno
io-wkbNo-op (WKB is always compiled in)
io-wktNo-op (WKT is always compiled in)
io-csvCSV format backendno
io-gmlGML/XML format backendno
io-gpkgGeoPackage format backend (not WASM)no
io-allAll opt-in backends except gpkgno
io-all-nativeAll opt-in backends including gpkgno
ffiC-compatible FFI bindingsno
pythonPython bindings via PyO3no
projCRS transformation via PROJno
serdeGeometry serde supportno
bench-geosGEOS comparison benchmarks (static — MSVC, no LTO)no
bench-geos-systemGEOS comparison benchmarks (system — conda LLVM, full LTO)no

*memmap was default in 0.10 but moved to opt-in in 0.11.

§Platform support

PlatformCoreSIMDI/OParallelPython
x86_64 Windows/Linux/macOSYesYes (AVX2)YesYesYes
aarch64 macOS/LinuxYesScalarYesYesYes
WASM32YesScalarIn-memory onlyNoNo
no_std (embedded)YesScalarNoNoNo

AVX2 requires RUSTFLAGS="-C target-cpu=native" at build time. Falls back to scalar on CPUs without AVX2 or non-x86_64 targets.

§no_std

Disable the std feature for no_std builds. Core validation, repair, and WKB parsing work without std. File I/O, parallel processing, and Python/FFI bindings require std:

cargo check --no-default-features --features arrange,structure,simd

§Validation

The GeoValidation trait checks 18 OGC validity rules using Shewchuk adaptive-precision orientation tests (via the robust crate):

RuleApplies to
Coordinate finitenessAll geometries
Ring closurePolygon rings
Ring minimum vertices (≥4)Polygon rings
Ring self-intersectionPolygon rings
Pinch points (non-consecutive duplicates)Rings
Hole containment (inside shell)Polygon
No nested holesPolygon
Interior ring connectivityPolygon
Ring orientation (exterior CCW, interior CW)Polygon
Non-collinear ringsPolygon
Consecutive duplicatesLines/rings
Duplicate ringsPolygon
Duplicate pointsMultiPoint
Duplicate linesMultiLineString
Non-zero-length linesLine
Non-degenerate exteriorPolygon
Simplicity (no interior intersections)LineString, MultiLineString
Nesting depth limitGeometryCollection
use geo_repair::{is_valid, validate, validate_reason, GeoValidation, ValidationResult};

let ok: bool = geom.is_valid();
let ok2: bool = is_valid(&geom);

let result: ValidationResult = validate(&geom);
let reason: String = validate_reason(&geom);

§Polygon repair strategies

StrategyApproachStrengthsWeaknesses
Arrange (CDT)Constrained Delaunay triangulation → face labeling → ring extractionHandles any topology. No self-intersection limit.Slower, especially on large rings. Requires spade.
Structure (fast path)Planar graph extraction → face walking → winding-number assembly10-100× faster for valid/simple inputs. No external deps.Falls back on complex topologies (many holes, nested self-intersections).

Auto (default) tries Structure first and falls back to Arrange. The repair pipeline enforces OGC-correct winding order (CCW exterior, CW interior) on all output.

§CRS support

The Crs type stores EPSG codes and provides CRS-aware tolerance heuristics:

  • Geographic (lon/lat): 1e-10 degrees
  • Projected (metres): 1e-6 metres
  • Unknown: 1e-12

CRS is set directly on MakeValidConfig:

use geo_repair::{Crs, MakeValidConfig};

let config = MakeValidConfig {
    crs: Some(Crs::from_epsg(4326)),
    ..Default::default()
};

§I/O

GeoRepair provides format-agnostic dispatch and individual backends:

use geo_repair::{
    diagnose_file, load, load_bin, read_wkb, read_wkb_concat, read_wkb_from,
    read_ewkb, write_ewkb, EwkbGeometry, EwkbDims,
    read_wkt, read_wkt_from, write_wkt, write_wkt_to, infer_wkt_type,
    write_wkb, write_wkb_to, write_wkb_with_opts, Endianness, WriteOptions,
    repair_file, save, MakeValidConfig,
};

let geoms = load("input.wkb").unwrap();
let geoms = read_wkb_concat(&concat_buffer).unwrap();

for result in diagnose_file("input.bin").unwrap() {
    println!("{}", result.reason());
}

repair_file("invalid.wkb", "fixed.wkb", &MakeValidConfig::default()).unwrap();
save("output.wkt", &geoms[0]).unwrap();

// Standard LE WKB
let wkb: Vec<u8> = write_wkb(&geom);
// Big-endian WKB
let be_wkb: Vec<u8> = write_wkb_with_opts(&geom, &WriteOptions { endianness: Endianness::BigEndian });
// Write to any io::Write target
write_wkb_to(&geom, &mut std::io::stdout()).unwrap();
// Read from any io::Read source
let geom = read_wkb_from(&wkb[..]).unwrap();

// EWKB with SRID and Z/M preservation
let ewkb = EwkbGeometry {
    geometry: geom.clone(),
    srid: Some(4326),
    dims: EwkbDims::XYZ,
    extra_coords: vec![100.0],
};
let ewkb_bytes = write_ewkb(&ewkb);
let back = read_ewkb(&ewkb_bytes).unwrap();

// WKT with streaming I/O
let wkt: String = write_wkt(&geom);
let geom = read_wkt(&wkt).unwrap();
write_wkt_to(&geom, &mut std::io::stdout()).unwrap();
let geom = read_wkt_from(wkt.as_bytes()).unwrap();

// Peek at WKT type without parsing
let (type_name, _dims) = infer_wkt_type("POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))").unwrap();

let polys = load_bin("dataset.bin").unwrap();
ExtensionFormatBackend
.wkb / .wksWKB (LE/BE, EWKB SRID, Z/M variants, io::Read/Write)Zero-dep built-in
.binCustom binary bulk polygon formatZero-dep built-in
.shpShapefileio-shp feature
.wktWKT (io::Read/Write, type inference)Zero-dep built-in
.csvCSV with WKT geometryio-csv feature
.gmlGML/XMLio-gml feature
.gpkgGeoPackage (SQLite)io-gpkg feature

§Geometry type coverage

GeometryRepair approach
Polygon / MultiPolygonStructure fast path or Arrange CDT fallback
LineString / MultiLineStringNaN filtering, duplicate removal, self-intersection noding
LineZero-length and NaN detection
Point / MultiPointNaN/Inf filtering, deduplication
Rect / TriangleBasic degeneracy checks
GeometryCollectionRecursive repair of children

§Known limitations

  • CDT arranger may panic on certain degenerate inputs (all-collinear exterior rings, coordinates near f64::MAX). This is a known limitation of spade.
  • OGC compliance is a key goal but not yet formally certified. The validation module checks 18 OGC predicates and passes 2490/2490 GEOS XML tests.
  • GeometryCollection cross-component intersection is not validated.
  • Z/M coordinate consistency is not validated.

§License

Apache-2.0

Re-exports§

pub use core::MakeValidConfig;
pub use core::MakeValidError;
pub use core::PolyMethod;
pub use crs::Crs;
pub use feature::Feature;
pub use io::diagnose_file;
pub use io::infer_wkt_type;
pub use io::load;
pub use io::load_bin;
pub use io::load_bin_stream;
pub use io::read_ewkb;
pub use io::read_wkb;
pub use io::read_wkb_concat;
pub use io::read_wkb_from;
pub use io::read_wkt;
pub use io::read_wkt_from;
pub use io::repair_file;
pub use io::save;
pub use io::write_ewkb;
pub use io::write_wkb;
pub use io::write_wkb_to;
pub use io::write_wkb_with_opts;
pub use io::write_wkt;
pub use io::write_wkt_to;
pub use io::Endianness;
pub use io::EwkbDims;
pub use io::EwkbGeometry;
pub use io::WkbError;
pub use io::WktError;
pub use io::WriteOptions;
pub use make_valid::MakeValid;
pub use make_valid::ValidateAndFix;
pub use snap::snap_coord;
pub use snap::snap_coord_default;
pub use snap::snap_line;
pub use snap::snap_lines;
pub use snap::DEFAULT_GRID;
pub use validation::is_valid;
pub use validation::validate;
pub use validation::validate_reason;
pub use validation::GeoValidation;
pub use validation::GeometryValidationError;
pub use validation::ValidationResult;

Modules§

arrange
CDT-based polygon repair for complex topologies (Arrange strategy). CDT-based polygon repair for complex topologies (LEDOUX et al. 2014).
core
Core configuration types for geometry repair. Core configuration, error types, and numeric constants for geometry repair.
crs
Coordinate reference system (CRS) handling and transformation. Coordinate Reference System (CRS) metadata and transformation.
dd
Double-double arithmetic for robust geometric computations. Double-double arithmetic for robust geometric constructions.
feature
Feature metadata associated with geometries. GIS feature container with attribute, CRS, and Z/M preservation.
io
Geometry I/O: WKB, binary format, and format-dispatch helpers. Format-agnostic geometry I/O: WKB, WKT, and binary format backends.
make_valid
Geometry repair implementation via the MakeValid trait. Geometry repair implementations via the MakeValid and ValidateAndFix traits.
noding
Segment noding: intersection detection, snap-rounding, and validation. Noding utilities for linear geometry repair.
orient
Ring orientation utilities (CW/CCW winding). Adaptive-precision orientation predicates (Shewchuk’s algorithm).
parallel
Rayon-based parallel batch geometry repair. Rayon-based parallel batch geometry repair.
reduce
Geometry precision reduction with topology preservation. Geometry precision reduction with topology preservation.
simd
AVX2-accelerated geometric predicates (x86_64). SIMD-accelerated orientation predicates.
snap
Coordinate snapping to a precision grid. Coordinate snap-rounding utilities.
structure
GEOS-compatible fast-path polygon repair via planar graph extraction. GEOS-compatible fast-path polygon repair via planar graph extraction.
validation
OGC Simple Features geometry validation predicates. OGC Simple Features geometry validation predicates.
zm
Z/M coordinate value preservation through the repair pipeline. Z/M coordinate value preservation and querying.

Functions§

profile_structure_fastpath
Profile each step of the structure fast path on a sample of polygons. Prints timing breakdown and pass rates to stderr.