-
Notifications
You must be signed in to change notification settings - Fork 96
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Geometry::get_point_vec()
returns empty Vec
#269
Comments
An even simpler test case: #[test]
fn test_get_points() -> std::result::Result<(), GdalError> {
let geom = Geometry::bbox(0., 0., 1., 1.)?;
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(())
} |
Interestingly, running gdal/src/vector/vector_tests/mod.rs Lines 485 to 509 in 492e0c8
|
Would love to know if I'm doing something wrong, or if there's a workaround (e.g. call methods in certain order). |
The unit test uses a line string. Polygons don't contain points, but rings, so you need to go through those. I can't give an example right now. |
I don't see any methods to get rings. Only points. I took a look at the implementation of unsafe { geom.get_unowned_geometry(0) }.get_point_vec() However, this doesn't really seem like the best user-facing method. I'd like to submit a PR for something more friendlly, but don't want to waste time on something that isn't inline with the maintainers' thinking. From my standpoint, modifying the |
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:
|
Very helpful to know where to go for a "reference implementation". Thanks! :-) |
Also, see |
What is the definition of "(un)owned" in a. The lifecycle is managed by Rust; if the binding leaves scope, then My real question is how to think about returning a reference to something that is logically bound to /// Get a reference to the contained geometry at `index`.
pub fn get_geometry<'a>(&'a self, index: usize) -> Result<&'a Geometry> {
let ring = unsafe { self.get_unowned_geometry(index) };
let ring_ref: &'a Geometry = unsafe { &*(&ring as * const Geometry) };
Ok(ring_ref)
} (I also tried using I'm also wondering if I should be considering a |
To further refine my questions, I'm interpreting this: Lines 306 to 308 in 8cb6e92
and this:
To mean the naïve implementation such as this will eventually break: pub fn get_geometry(&self, index: usize) -> Result<Geometry> {
let ring = unsafe { self.get_unowned_geometry(index) };
Ok(ring)
} With that assumption, I've given up on figuring out how to return The implementation below works. However, I'm not confident enough in my pub struct GeometryRef<'a> {
geom: Geometry,
_lifetime: PhantomData<&'a ()>
}
impl <'a> Deref for GeometryRef<'a> {
type Target = Geometry;
fn deref(&self) -> &Self::Target {
&self.geom
}
}
...
pub fn get_geometry(&self, index: usize) -> Result<GeometryRef> {
let ring = unsafe { self.get_unowned_geometry(index) };
let gref = GeometryRef { geom: ring, _lifetime: PhantomData::default() };
Ok(gref)
}
...
// This (mostly) works using the `GeometryRef` approach.
#[test]
fn test_ring_points() {
let mut ring = Geometry::empty(wkbLinearRing).unwrap();
ring.add_point_2d((1179091.1646903288, 712782.8838459781));
ring.add_point_2d((1161053.0218226474, 667456.2684348812));
ring.add_point_2d((1214704.933941905, 641092.8288590391));
ring.add_point_2d((1228580.428455506, 682719.3123998424));
ring.add_point_2d((1218405.0658121984, 721108.1805541387));
ring.add_point_2d((1179091.1646903288, 712782.8838459781));
assert!(!ring.is_empty());
assert_eq!(ring.get_point_vec().len(), 6);
let mut poly = Geometry::empty(wkbPolygon).unwrap();
poly.add_geometry(ring.to_owned()).unwrap();
// Points are in ring, not containing geometry.
// TODO: In Python SWIG bindings, `GetPoints` is fallible.
assert!(poly.get_point_vec().is_empty());
assert_eq!(poly.geometry_count(), 1);
let ring_out = poly.get_geometry(0).unwrap();
println!("{}", ring_out.wkt().unwrap());
// TODO: This fails. Returns `wkbLineString`, but `wkb()` shows it to be a `LINEARRING`
//assert_eq!(ring_out.geometry_type(), wkbLinearRing);
assert!(!&ring_out.is_empty());
assert_eq!(ring.get_point_vec(), ring_out.get_point_vec());
} |
Sorry, I've been less around lately. It's not really clear to me why the original approach didn't work. |
Well, sorry to bother you!. I'm excited this project exists at all, and want to help out when I run into friction. That said, I'm still struggling to understand lifetimes when FFI is concerned, and may require more hand-holding than you're able to provide. IOW, helping out may be above my current Rust skillset.
Yes. |
Reading Polygon points like this should work: let ring_count = geom.geometry_count();
for i in 0..ring_count {
let ring = unsafe { geom.get_unowned_geometry(i) };
let length = unsafe { gdal_sys::OGR_G_GetPointCount(ring.c_geometry()) } as usize;
for i in 0..length {
let (x, y, z) = ring.get_point(i as i32);
}
} |
@pka Thanks, I've seen that code. I'm actually want the whole |
I'm unable to access get the points of any GDAL
Geometry
instance I create. The following will fail at the last test:The text was updated successfully, but these errors were encountered: