gdal: `Geometry::get_point_vec()` returns empty `Vec`

I’m unable to access get the points of any GDAL Geometry instance I create. The following will fail at the last test:

#[test]
fn test_get_points() -> std::result::Result<(), GdalError> {
    let sample = "/vsicurl/https://gist.githubusercontent.com/metasim/15fb05bbe76c1d7e5583033f2b6757f7/raw/fac8b385b733f50f0b7a1466db03e7918084b4a1/test.geojson";
    let ds = Dataset::open(sample)?;
    let layer = ds.layer(0)?;
    let feature = layer.feature(0).unwrap();
    let geom = feature.geometry();

    assert_eq!(geom.geometry_count(), 1);
    assert!(geom.area() > 0.);
    assert_eq!(geom.geometry_type(), gdal_sys::OGRwkbGeometryType::wkbPolygon);
    assert!(geom.json()?.contains("Polygon"));
    let points = geom.get_point_vec();
    assert!(!points.is_empty());

    Ok(())
}

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 15 (15 by maintainers)

Commits related to this issue

Most upvoted comments

From my standpoint, modifying the Geometry::get_point_vec() method to got into the unowned geometries automatically seems like better ergonomics. Does that approach pass your sniff test, or should I take a different approach (like, have methods to expose rings)?

I don’t think it makes sense to return points from all the rings together. I think the first ring is the exterior of the polygon, while the others are “holes”.

We should try match the GDAL API:

>>> ring = ogr.Geometry(ogr.wkbLinearRing)
>>> ring.AddPoint(1179091.1646903288, 712782.8838459781)
>>> ring.AddPoint(1161053.0218226474, 667456.2684348812)
>>> ring.AddPoint(1214704.933941905, 641092.8288590391)
>>> ring.AddPoint(1228580.428455506, 682719.3123998424)
>>> ring.AddPoint(1218405.0658121984, 721108.1805541387)
>>> ring.AddPoint(1179091.1646903288, 712782.8838459781)
>>> poly = ogr.Geometry(ogr.wkbPolygon)
>>> poly.AddGeometry(ring)
0
>>> poly.GetPointCount()
0
>>> poly.GetPoints()
ERROR 6: Incompatible geometry for operation
>>> ring = poly.GetGeometryRef(0)
>>> ring.GetGeometryName()
'LINEARRING'
>>> ring.GetPoints()
[(1179091.1646903288, 712782.8838459781, 0.0), (1161053.0218226474, 667456.2684348812, 0.0), (1214704.933941905, 641092.8288590391, 0.0), (1228580.428455506, 682719.3123998424, 0.0), (1218405.0658121984, 721108.1805541387, 0.0), (1179091.1646903288, 712782.8838459781, 0.0)]

Notice how:

  • GetPoints is fallible
  • you can get a reference to an owned geometry using GetGeometryRef
  • our API isn’t really idiomatic, hence the unsafe get_unowned_geometry and the don't keep this object for long comment in its implementation; the return type is logically a &'self Geometry, since the ring is owned by the polygon.

@lnicola @rmanoka Wondering if either of you have advice to share on the appropriate route to take with the above. I think the GeometryRef approach is working.

Also, see geo_to_gdal.rs and gdal_to_geo.rs. Those two files were an awesome reference to accessing inner structures using our bindings.

We should try match the GDAL API:

Very helpful to know where to go for a “reference implementation”. Thanks! 😃