1 个不稳定版本
0.1.0 | 2023年4月11日 |
---|
#144 in 地理空间
73KB
1.5K SLoC
geo-validity-check
提供一个 Valid
trait 来检查 rust geo-types 几何形状是否有效。
Valid
trait 的签名如下
trait Valid {
fn is_valid(&self) -> bool;
fn explain_invalidity(&self) -> Option<ProblemReport>;
}
无效原因的结果以 ProblemReport
结构体(它包含一个 Vec
的 (Problem, ProblemPosition)
,两个枚举分别表示问题的类型和问题在测试几何形状中的位置 - 拥有这种机器可读信息可能有助于尝试修复几何形状)。此 ProblemReport
结果还可以格式化为字符串,因为它实现了 Display
trait。
实现检查
-
Coord
和Point
使用有限数字 -
MultiPoint
由有效点组成 -
Rect
、Line
和Triangle
由有效坐标组成 -
Triangle
不能为空或退化(即所有点都不同且不共线) -
Line
的长度不为0(即两个点不相同) -
LineString
由有效点组成 -
LineString
不能为空 -
LineString
至少有两个不同的点 -
MultiLineString
由有效线字符串组成 -
Polygon
环由有效点组成 -
Polygon
环至少有4个点(包括闭合点) -
Polygon
内部环包含在外部环中(但可以在一个点上接触它) -
Polygon
内部环互不交叉(但可以在一个点上接触) -
MultiPolygon
组件互不交叉(但可以在一个点上接触) -
MultiPolygon
由有效多边形组成 -
GeometryCollection
由有效几何形状组成
与 GEOS 进行验证(任何根据 GEOS 无效的几何形状都应在本 crate 中无效 - 反之不一定为真,因为我们进行了额外的检查)。
示例
use geo_validity_check::Valid;
use geo_types::{Point, LineString, Polygon, MultiPolygon};
let line1 = LineString::from(vec![(0., 0.), (1., 1.)]);
let line2 = LineString::from(vec![(0., 0.), (0., 0.)]);
let line3 = LineString::from(vec![(0., 0.), (f64::NAN, f64::NAN), (1., 1.)]);
assert!(line1.is_valid());
assert!(!line2.is_valid());
assert!(!line3.is_valid());
println!("{}", line2.invalidity_reason().unwrap()); // "LineString has too few points at coordinate 0 of the LineString"
println!("{}", line3.invalidity_reason().unwrap()); // "Coordinate is not finite (NaN or infinite) at coordinate 1 of the LineString"
let polygon = Polygon::new(
LineString::from(vec![(0.5, 0.5), (3., 0.5), (3., 2.5), (0.5, 2.5), (0.5, 0.5)]),
vec![LineString::from(vec![(1., 1.), (1., 2.), (2.5, 2.), (3.5, 1.), (1., 1.)])],
);
assert!(!polygon.is_valid());
println!("{}", polygon.invalidity_reason().unwrap()); // "The interior ring of a Polygon is not contained in the exterior ring on the interior ring n°0"
let multipolygon = MultiPolygon(vec![
Polygon::new(
LineString::from(vec![(0.5, 0.5), (3., 0.5), (3., 2.5), (0.5, 2.5), (0.5, 0.5)]),
vec![LineString::from(vec![(1., 1.), (1., 2.), (2.5, 2.), (3.5, 1.), (1., 1.)])],
),
Polygon::new(
LineString::from(vec![(0.5, 0.5), (3., 0.5), (3., 2.5), (0.5, 2.5), (0.5, 0.5)]),
vec![LineString::from(vec![(1., 1.), (1., 2.), (2.5, 2.), (3.5, 1.), (1., 1.)])],
),
]);
assert!(!multipolygon.is_valid());
println!("{}", multipolygon.invalidity_reason().unwrap());
// "The interior ring of a Polygon is not contained in the exterior ring on the interior ring n°0 of the Polygon n°0 of the MultiPolygon
// Two Polygons of MultiPolygons are identical on the exterior ring of the Polygon n°0 of the MultiPolygon
// The interior ring of a Polygon is not contained in the exterior ring on the interior ring n°0 of the Polygon n°1 of the MultiPolygon
// Two Polygons of MultiPolygons are identical on the exterior ring of the Polygon n°1 of the MultiPolygon"
待办事项 / 灵感
-
改进无效性原因的描述(例如,"内部环0与外部环相交"可以改为"内部环0在点(1.5, 1.5)与外部环相交")
-
添加一个
make_valid
或fix_invalidity
方法来尝试修复几何形状(例如,通过移除无效的点?) -
在
invalidity_reason
方法中返回找到的第一个无效性原因(而不是所有原因)?(因为其他检查可能因为第一个无效性原因而失败) -
实现一条规则,该规则规定如果多边形内部是单纯连通的(即,环必须不会以分割多边形成多个部分的方式接触),则
Polygon
是有效的?
许可证
以下任一许可证下许可:
- Apache License, Version 2.0, (LICENSE-APACHE 或 http://www.apache.org/licenses/LICENSE-2.0)
- MIT许可证 (LICENSE-MIT 或 http://opensource.org/licenses/MIT)
任选其一。
依赖关系
~3.5MB
~65K SLoC