#polygon #ogc #gis #multipolygon #graphics #floating-point

geo-validator

Functionality to validate geo-types MultiPolygon/Polgon according to the OGC rules

4 releases

0.1.3 Apr 21, 2020
0.1.2 Apr 17, 2020
0.1.1 Apr 16, 2020
0.1.0 Apr 15, 2020

#179 in Geospatial

24 downloads per month
Used in geo-repair-polygon

MIT license

29KB
464 lines

rust-geo-validator

A trait for MultiPolygon/Polygon geo-types to check for validity according to OGC standards. Validation currently conforms only partially to those rules.

Validation Traits

The current geo/geo-types packages contain no support for validation of Geometries other then succeeding/failing to create a Geometry. This package adds a trait to the MultiPolygon and Polygon type to check for validity according to the OGC specifications (currently a work in progress).

The validation function provided here look for violations of the following rules:

  • A polygon may not have less than three points
  • A polygon may not have any unclosed rings
  • A polygon may not be a multi-polygon (all inner rings must be contained by the outer ring)
  • No ring in the polygon may intersect another ring
  • No ring in the polygon may intersect itself
  • No point on a ring may be touching a line in it or any other ring
  • No points may be repeated in a ring
  • All points must have valid floating point values

validate()

The is_valid() trait will return false at the first error and provides no debugging information.

Examples

use geo_types::polygon;
use geo_validator::Validate;

// Polygon self intersects and has intersecting inner/outer rings
let poly = polygon!(
            exterior: [
                (x: 0., y: 0.),
                (x: 0., y: 200.),
                (x: 200., y: 0.),
                (x: 200., y: 200.),
            ],
            interiors: [
                [
                    (x: 10., y: 20.),
                    (x: 50., y: 20.),
                    (x: 20., y: 50.),
                    (x: 50., y: 50.),
                ],
            ],
        );

let valid = poly.validate();
assert_eq!(valid, false);

validate_detailed

The validate_detailed() function collects information about where the current MultiPolygon/Polygon is invalid, and returns that information to the caller.

Examples

use geo_types::polygon;
use geo_validator::Validate;

// Polygon self intersects and has intersecting inner/outer rings
let poly = polygon!(
            exterior: [
                (x: 0., y: 0.),
                (x: 0., y: 200.),
                (x: 200., y: 0.),
                (x: 200., y: 200.),
            ],
            interiors: [
                [
                    (x: 10., y: 20.),
                    (x: 50., y: 20.),
                    (x: 20., y: 50.),
                    (x: 50., y: 50.),
                ],
            ],
        );

let valid = poly.validate_detailed();
assert_eq!(valid.valid, false);
assert_eq!(valid.ring_intersects_other_ring.len(), 3);
assert_eq!(valid.self_intersections.len(), 2);
assert_eq!(valid.point_touching_line.len(), 1);

assert_eq!(valid.ring_intersects_other_ring[0].x, 20_f64);
assert_eq!(valid.ring_intersects_other_ring[0].y, 20_f64);
assert_eq!(valid.ring_intersects_other_ring[1].x, 35_f64);
assert_eq!(valid.ring_intersects_other_ring[1].y, 35_f64);
assert_eq!(valid.ring_intersects_other_ring[2].x, 50_f64);
assert_eq!(valid.ring_intersects_other_ring[2].y, 50_f64);

assert_eq!(valid.self_intersections[0].x, 100_f64);
assert_eq!(valid.self_intersections[0].y, 100_f64);
assert_eq!(valid.self_intersections[1].x, 32.857142857142854_f64);
assert_eq!(valid.self_intersections[1].y, 37.142857142857146_f64);

assert_eq!(valid.point_touching_line[0].x, 50_f64);
assert_eq!(valid.point_touching_line[0].y, 50_f64);

Dependencies

~2MB
~41K SLoC