Skip to content

Commit

Permalink
cp -r ../geo-validity-check/src/* geo/src/algorithm/validation/
Browse files Browse the repository at this point in the history
325ec00e5a1207308eecfb1d8fb5456cd5d5d121 from
https://github.com/michaelkirk/geo-validity-check
  • Loading branch information
michaelkirk committed Dec 10, 2024
1 parent 3da9289 commit 92d8bfc
Show file tree
Hide file tree
Showing 14 changed files with 1,824 additions and 0 deletions.
28 changes: 28 additions & 0 deletions geo/src/algorithm/validation/coord.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use crate::{utils, Problem, ProblemAtPosition, ProblemPosition, ProblemReport, Valid};
use geo::{Coord, GeoFloat};

impl<F: GeoFloat> Valid for Coord<F> {
fn is_valid(&self) -> bool {
if utils::check_coord_is_not_finite(self) {
return false;
}
true
}
fn explain_invalidity(&self) -> Option<ProblemReport> {
let mut reason = Vec::new();

if utils::check_coord_is_not_finite(self) {
reason.push(ProblemAtPosition(
Problem::NotFinite,
ProblemPosition::Point,
));
}

// Return the reason(s) of invalidity, or None if valid
if reason.is_empty() {
None
} else {
Some(ProblemReport(reason))
}
}
}
33 changes: 33 additions & 0 deletions geo/src/algorithm/validation/geometry.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use crate::{ProblemReport, Valid};
use geo::{GeoFloat, Geometry};

impl<F: GeoFloat> Valid for Geometry<F> {
fn is_valid(&self) -> bool {
match self {
Geometry::Point(e) => e.is_valid(),
Geometry::Line(e) => e.is_valid(),
Geometry::Rect(e) => e.is_valid(),
Geometry::Triangle(e) => e.is_valid(),
Geometry::LineString(e) => e.is_valid(),
Geometry::Polygon(e) => e.is_valid(),
Geometry::MultiPoint(e) => e.is_valid(),
Geometry::MultiLineString(e) => e.is_valid(),
Geometry::MultiPolygon(e) => e.is_valid(),
Geometry::GeometryCollection(e) => e.is_valid(),
}
}
fn explain_invalidity(&self) -> Option<ProblemReport> {
match self {
Geometry::Point(e) => e.explain_invalidity(),
Geometry::Line(e) => e.explain_invalidity(),
Geometry::Rect(e) => e.explain_invalidity(),
Geometry::Triangle(e) => e.explain_invalidity(),
Geometry::LineString(e) => e.explain_invalidity(),
Geometry::Polygon(e) => e.explain_invalidity(),
Geometry::MultiPoint(e) => e.explain_invalidity(),
Geometry::MultiLineString(e) => e.explain_invalidity(),
Geometry::MultiPolygon(e) => e.explain_invalidity(),
Geometry::GeometryCollection(e) => e.explain_invalidity(),
}
}
}
94 changes: 94 additions & 0 deletions geo/src/algorithm/validation/geometrycollection.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
use crate::{GeometryPosition, ProblemAtPosition, ProblemPosition, ProblemReport, Valid};
use geo::{GeoFloat, GeometryCollection};

/// GeometryCollection is valid if all its elements are valid
impl<F: GeoFloat> Valid for GeometryCollection<F> {
fn is_valid(&self) -> bool {
for geometry in self.0.iter() {
if !geometry.is_valid() {
return false;
}
}
true
}
fn explain_invalidity(&self) -> Option<ProblemReport> {
let mut reason = Vec::new();

// Loop over all the geometries, collect the reasons of invalidity
// and change the ProblemPosition to reflect the GeometryCollection
for (i, geometry) in self.0.iter().enumerate() {
let temp_reason = geometry.explain_invalidity();
if let Some(temp_reason) = temp_reason {
for ProblemAtPosition(problem, position) in temp_reason.0 {
reason.push(ProblemAtPosition(
problem,
ProblemPosition::GeometryCollection(
GeometryPosition(i),
Box::new(position),
),
));
}
}
}
// Return the reason(s) of invalidity, or None if valid
if reason.is_empty() {
None
} else {
Some(ProblemReport(reason))
}
}
}

#[cfg(test)]
mod tests {
use crate::{
CoordinatePosition, GeometryPosition, Problem, ProblemAtPosition, ProblemPosition,
ProblemReport, Valid,
};
use geo::{Coord, Geometry, GeometryCollection, LineString, Point};
use geos::Geom;

#[test]
fn test_geometrycollection_contain_invalid_element() {
let gc = GeometryCollection(vec![
Geometry::Point(Point::new(0., 0.)),
Geometry::LineString(LineString(vec![
Coord { x: 0., y: 0. },
Coord { x: 1., y: 1. },
])),
Geometry::LineString(LineString(vec![
Coord { x: 0., y: 0. },
Coord { x: 0., y: 0. },
])),
]);
assert!(!gc.is_valid());
assert_eq!(
gc.explain_invalidity(),
Some(ProblemReport(vec![ProblemAtPosition(
Problem::TooFewPoints,
ProblemPosition::GeometryCollection(
GeometryPosition(2),
Box::new(ProblemPosition::LineString(CoordinatePosition(0)))
)
)]))
);

let geoms =
gc.0.iter()
.map(|geometry| match geometry {
Geometry::Point(pt) => {
let geos_point: geos::Geometry = pt.try_into().unwrap();
geos_point
}
Geometry::LineString(ls) => {
let geos_linestring: geos::Geometry = ls.try_into().unwrap();
geos_linestring
}
_ => unreachable!(),
})
.collect::<Vec<_>>();
let geometrycollection_geos: geos::Geometry =
geos::Geometry::create_geometry_collection(geoms).unwrap();
assert_eq!(gc.is_valid(), geometrycollection_geos.is_valid());
}
}
Loading

0 comments on commit 92d8bfc

Please sign in to comment.