Skip to content

Commit ba73829

Browse files
committed
Add Defn::geometry_field_index and Feature::geometry_field_index, drop Feature::geometry_by_name
1 parent a5aeb6c commit ba73829

File tree

5 files changed

+96
-21
lines changed

5 files changed

+96
-21
lines changed

CHANGES.md

+3
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,19 @@
1414
- Update `Feature::field_count` to return `usize` instead of `i32` ([#581](https://github.com/georust/gdal/pull/581))
1515
- Update `Feature::field_as_integer`, `Feature::field_as_integer64`, `Feature::field_as_double`, `Feature::field_as_string`, `Feature::field_as_datetime` to take the field index as `usize` instead of `i32` ([#581](https://github.com/georust/gdal/pull/581))
1616
- Drop `LayerAccess::create_feature_fields` ([#581](https://github.com/georust/gdal/pull/581))
17+
- Drop `Feature::geometry_by_name` ([#594](https://github.com/georust/gdal/pull/594))
1718
- Update `SpatialRef::auth_name`, `SpatialRef::name`, `SpatialRef::angular_units_name`, `SpatialRef::linear_units_name` to return `Option<String>` instead of `Result<String>` ([#589](https://github.com/georust/gdal/pull/589))
1819

1920
### Added
2021

2122
- Add `Dataset::delete_layer` ([#583](https://github.com/georust/gdal/pull/583))
23+
- Add `Dataset::has_capability` ([#585](https://github.com/georust/gdal/pull/585))
2224
- Add a `bundled` feature for `gdal-sys` for building and statically linking a minimal bundled version of GDAL ([#517](https://github.com/georust/gdal/pull/517))
2325
- Add pre-built bindings for GDAL 3.10 ([#573](https://github.com/georust/gdal/pull/573))
2426
- Add methods `alternative_name`, `is_nullable`, `is_unique`, `default_value` to `Field` ([#561](https://github.com/georust/gdal/pull/561))
2527
- Add `Defn::geometry_type` ([#562](https://github.com/georust/gdal/pull/562))
2628
- Add `Defn::field_index` and `Feature::field_index` ([#581](https://github.com/georust/gdal/pull/581))
29+
- Add `Defn::geometry_field_index` and `Feature::geometry_field_index` ([#594](https://github.com/georust/gdal/pull/594))
2730
- Add `Dataset::has_capability` for dataset capability check ([#581](https://github.com/georust/gdal/pull/585))
2831

2932
### Fixed

fixtures/two_geoms.csv

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
WKT,_WKTanother_geometry
2+
"POINT (1 2)","POINT (10 20)"

src/vector/defn.rs

+33-2
Original file line numberDiff line numberDiff line change
@@ -69,22 +69,53 @@ impl Defn {
6969

7070
/// Get the index of a field.
7171
///
72+
/// The comparison is done case-insensitively, and if multiple fields match the requested
73+
/// name, the first one is returned.
7274
/// If the field is missing, returns [`GdalError::InvalidFieldName`].
7375
///
7476
pub fn field_index<S: AsRef<str>>(&self, field_name: S) -> Result<usize> {
75-
let c_str_field_name = CString::new(field_name.as_ref())?;
77+
self._field_index(field_name.as_ref())
78+
}
79+
80+
fn _field_index(&self, field_name: &str) -> Result<usize> {
81+
let c_str_field_name = CString::new(field_name)?;
7682
let field_idx =
7783
unsafe { gdal_sys::OGR_FD_GetFieldIndex(self.c_defn(), c_str_field_name.as_ptr()) };
7884
if field_idx == -1 {
7985
return Err(GdalError::InvalidFieldName {
80-
field_name: field_name.as_ref().to_string(),
86+
field_name: field_name.to_string(),
8187
method_name: "OGR_FD_GetFieldIndex",
8288
});
8389
}
8490

8591
let idx = field_idx.try_into()?;
8692
Ok(idx)
8793
}
94+
95+
/// Get the index of a geometry field.
96+
///
97+
/// The comparison is done case-insensitively, and if multiple fields match the requested
98+
/// name, the first one is returned.
99+
/// If the field is missing, returns [`GdalError::InvalidFieldName`].
100+
///
101+
pub fn geometry_field_index<S: AsRef<str>>(&self, field_name: S) -> Result<usize> {
102+
self._geometry_field_index(field_name.as_ref())
103+
}
104+
105+
fn _geometry_field_index(&self, field_name: &str) -> Result<usize> {
106+
let c_str_field_name = CString::new(field_name)?;
107+
let field_idx =
108+
unsafe { gdal_sys::OGR_FD_GetGeomFieldIndex(self.c_defn(), c_str_field_name.as_ptr()) };
109+
if field_idx == -1 {
110+
return Err(GdalError::InvalidFieldName {
111+
field_name: field_name.to_string(),
112+
method_name: "OGR_FD_GetGeomFieldIndex",
113+
});
114+
}
115+
116+
let idx = field_idx.try_into()?;
117+
Ok(idx)
118+
}
88119
}
89120

90121
pub struct FieldIterator<'a> {

src/vector/feature.rs

+32-16
Original file line numberDiff line numberDiff line change
@@ -158,13 +158,18 @@ impl<'a> Feature<'a> {
158158
///
159159
/// If the field is missing, returns [`GdalError::InvalidFieldName`].
160160
///
161+
/// Calling [`Defn::field_index`] once and caching the index can be faster, and should be preferred.
161162
pub fn field_index<S: AsRef<str>>(&self, field_name: S) -> Result<usize> {
162-
let c_str_field_name = CString::new(field_name.as_ref())?;
163+
self._field_index(field_name.as_ref())
164+
}
165+
166+
fn _field_index(&self, field_name: &str) -> Result<usize> {
167+
let c_str_field_name = CString::new(field_name)?;
163168
let field_idx =
164169
unsafe { gdal_sys::OGR_F_GetFieldIndex(self.c_feature(), c_str_field_name.as_ptr()) };
165170
if field_idx == -1 {
166171
return Err(GdalError::InvalidFieldName {
167-
field_name: field_name.as_ref().to_string(),
172+
field_name: field_name.to_string(),
168173
method_name: "OGR_F_GetFieldIndex",
169174
});
170175
}
@@ -173,6 +178,31 @@ impl<'a> Feature<'a> {
173178
Ok(field_index)
174179
}
175180

181+
/// Get the index of a geometry field.
182+
///
183+
/// If the field is missing, returns [`GdalError::InvalidFieldName`].
184+
///
185+
/// Calling [`Defn::geometry_field_index`] once and caching the index can be faster, and should be preferred.
186+
pub fn geometry_field_index<S: AsRef<str>>(&self, field_name: S) -> Result<usize> {
187+
self._geometry_field_index(field_name.as_ref())
188+
}
189+
190+
fn _geometry_field_index(&self, field_name: &str) -> Result<usize> {
191+
let c_str_field_name = CString::new(field_name)?;
192+
let field_idx = unsafe {
193+
gdal_sys::OGR_F_GetGeomFieldIndex(self.c_feature(), c_str_field_name.as_ptr())
194+
};
195+
if field_idx == -1 {
196+
return Err(GdalError::InvalidFieldName {
197+
field_name: field_name.to_string(),
198+
method_name: "OGR_F_GetGeomFieldIndex",
199+
});
200+
}
201+
202+
let field_index = field_idx.try_into()?;
203+
Ok(field_index)
204+
}
205+
176206
/// Get the value of the specified field as a [`i32`].
177207
///
178208
/// If the field is missing, returns [`GdalError::InvalidFieldIndex`].
@@ -365,20 +395,6 @@ impl<'a> Feature<'a> {
365395
}
366396
}
367397

368-
pub fn geometry_by_name(&self, field_name: &str) -> Result<&Geometry> {
369-
let c_str_field_name = CString::new(field_name)?;
370-
let idx =
371-
unsafe { gdal_sys::OGR_F_GetGeomFieldIndex(self.c_feature, c_str_field_name.as_ptr()) };
372-
if idx == -1 {
373-
Err(GdalError::InvalidFieldName {
374-
field_name: field_name.to_string(),
375-
method_name: "geometry_by_name",
376-
})
377-
} else {
378-
self.geometry_by_index(idx as usize)
379-
}
380-
}
381-
382398
pub fn geometry_by_index(&self, idx: usize) -> Result<&Geometry> {
383399
if idx >= self.geometry.len() {
384400
return Err(GdalError::InvalidFieldIndex {

src/vector/layer.rs

+26-3
Original file line numberDiff line numberDiff line change
@@ -1284,11 +1284,14 @@ mod tests {
12841284
let geom = feature.geometry_by_index(0).unwrap();
12851285
assert_eq!(geom.geometry_type(), OGRwkbGeometryType::wkbLineString);
12861286
assert!(feature.geometry_by_index(1).is_err());
1287-
let geom = feature.geometry_by_name("");
1287+
let geom = feature.geometry_by_index(0);
12881288
assert!(geom.is_ok());
1289-
let geom = feature.geometry_by_name("").unwrap();
1289+
let geom = feature.geometry_by_index(0).unwrap();
12901290
assert_eq!(geom.geometry_type(), OGRwkbGeometryType::wkbLineString);
1291-
assert!(feature.geometry_by_name("FOO").is_err());
1291+
assert!(feature.geometry_by_index(1).is_err());
1292+
1293+
assert_eq!(feature.geometry_field_index("").unwrap(), 0);
1294+
assert!(feature.geometry_field_index("FOO").is_err());
12921295
});
12931296
}
12941297

@@ -1515,6 +1518,26 @@ mod tests {
15151518
assert_eq!(geom_field.spatial_ref().unwrap(), spatial_ref2);
15161519
}
15171520

1521+
#[test]
1522+
fn test_two_geom_fields() -> Result<()> {
1523+
let ds = Dataset::open(fixture("two_geoms.csv"))?;
1524+
let mut layer = ds.layer(0)?;
1525+
1526+
let geom_field_2_idx = layer
1527+
.defn()
1528+
.geometry_field_index("geom__WKTanother_geometry")
1529+
.unwrap();
1530+
assert_eq!(geom_field_2_idx, 1);
1531+
1532+
let feature = layer.features().next().unwrap();
1533+
let geom_1 = feature.geometry_by_index(0)?;
1534+
let geom_2 = feature.geometry_by_index(1)?;
1535+
assert_eq!(geom_1.get_point(0), (1.0, 2.0, 0.0));
1536+
assert_eq!(geom_2.get_point(0), (10.0, 20.0, 0.0));
1537+
1538+
Ok(())
1539+
}
1540+
15181541
#[test]
15191542
fn test_get_layer_by_name() {
15201543
let ds = Dataset::open(fixture("roads.geojson")).unwrap();

0 commit comments

Comments
 (0)