Skip to content

Commit 8155ca1

Browse files
committed
Tune tests and forward more functions for geo_types::Geometry
1 parent e5b3971 commit 8155ca1

File tree

4 files changed

+96
-122
lines changed

4 files changed

+96
-122
lines changed

rust/sedona-geo-traits-ext/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ byteorder = "1"
3636

3737
[dev-dependencies]
3838
wkt = "0.14.0"
39+
rstest = "0.24.0"
3940

4041
[patch.crates-io]
4142
wkb = { git = "https://github.com/georust/wkb.git", rev = "130eb0c2b343bc9299aeafba6d34c2a6e53f3b6a" }

rust/sedona-geo-traits-ext/src/line_string.rs

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,9 @@ where
6060
fn lines(&'_ self) -> impl ExactSizeIterator<Item = Line<<Self as GeometryTrait>::T>> + '_ {
6161
let num_coords = self.num_coords();
6262
(0..num_coords.saturating_sub(1)).map(|i| unsafe {
63-
let coord1 = self.coord_unchecked_ext(i);
64-
let coord2 = self.coord_unchecked_ext(i + 1);
65-
Line::new(coord1.geo_coord(), coord2.geo_coord())
63+
let coord1 = self.geo_coord_unchecked(i);
64+
let coord2 = self.geo_coord_unchecked(i + 1);
65+
Line::new(coord1, coord2)
6666
})
6767
}
6868

@@ -75,9 +75,9 @@ where
7575
fn rev_lines(&'_ self) -> impl ExactSizeIterator<Item = Line<<Self as GeometryTrait>::T>> + '_ {
7676
let num_coords = self.num_coords();
7777
(1..num_coords).rev().map(|i| unsafe {
78-
let coord1 = self.coord_unchecked_ext(i);
79-
let coord2 = self.coord_unchecked_ext(i - 1);
80-
Line::new(coord2.geo_coord(), coord1.geo_coord())
78+
let coord1 = self.geo_coord_unchecked(i);
79+
let coord2 = self.geo_coord_unchecked(i - 1);
80+
Line::new(coord2, coord1)
8181
})
8282
}
8383

@@ -89,10 +89,10 @@ where
8989
let num_coords = self.num_coords();
9090
let end = num_coords.saturating_sub(2);
9191
(0..end).map(|i| unsafe {
92-
let coord1 = self.coord_unchecked_ext(i);
93-
let coord2 = self.coord_unchecked_ext(i + 1);
94-
let coord3 = self.coord_unchecked_ext(i + 2);
95-
Triangle::new(coord1.geo_coord(), coord2.geo_coord(), coord3.geo_coord())
92+
let coord1 = self.geo_coord_unchecked(i);
93+
let coord2 = self.geo_coord_unchecked(i + 1);
94+
let coord3 = self.geo_coord_unchecked(i + 2);
95+
Triangle::new(coord1, coord2, coord3)
9696
})
9797
}
9898

@@ -161,6 +161,20 @@ where
161161
self.lines()
162162
}
163163

164+
fn rev_lines(&'_ self) -> impl ExactSizeIterator<Item = Line<<Self as GeometryTrait>::T>> + '_ {
165+
self.rev_lines()
166+
}
167+
168+
fn triangles(
169+
&'_ self,
170+
) -> impl ExactSizeIterator<Item = Triangle<<Self as GeometryTrait>::T>> + '_ {
171+
self.triangles()
172+
}
173+
174+
fn is_closed(&self) -> bool {
175+
self.is_closed()
176+
}
177+
164178
fn coord_iter(&self) -> impl Iterator<Item = Coord<<Self as GeometryTrait>::T>> {
165179
self.0.iter().copied()
166180
}
@@ -185,6 +199,20 @@ where
185199
(*self).lines()
186200
}
187201

202+
fn rev_lines(&'_ self) -> impl ExactSizeIterator<Item = Line<<Self as GeometryTrait>::T>> + '_ {
203+
(*self).rev_lines()
204+
}
205+
206+
fn triangles(
207+
&'_ self,
208+
) -> impl ExactSizeIterator<Item = Triangle<<Self as GeometryTrait>::T>> + '_ {
209+
(*self).triangles()
210+
}
211+
212+
fn is_closed(&self) -> bool {
213+
(*self).is_closed()
214+
}
215+
188216
fn coord_iter(&self) -> impl Iterator<Item = Coord<<Self as GeometryTrait>::T>> {
189217
self.0.iter().copied()
190218
}

rust/sedona-geo-traits-ext/src/triangle.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,14 @@ where
143143
fn third_coord(&self) -> Coord<<Self as GeometryTrait>::T> {
144144
self.2
145145
}
146+
147+
fn to_array(&self) -> [Coord<<Self as GeometryTrait>::T>; 3] {
148+
self.to_array()
149+
}
150+
151+
fn to_lines(&self) -> [Line<<Self as GeometryTrait>::T>; 3] {
152+
self.to_lines()
153+
}
146154
}
147155

148156
impl<T: CoordNum> GeoTraitExtWithTypeTag for Triangle<T> {
@@ -166,6 +174,14 @@ where
166174
fn third_coord(&self) -> Coord<<Self as GeometryTrait>::T> {
167175
self.2
168176
}
177+
178+
fn to_array(&self) -> [Coord<<Self as GeometryTrait>::T>; 3] {
179+
(*self).to_array()
180+
}
181+
182+
fn to_lines(&self) -> [Line<<Self as GeometryTrait>::T>; 3] {
183+
(*self).to_lines()
184+
}
169185
}
170186

171187
impl<T: CoordNum> GeoTraitExtWithTypeTag for &Triangle<T> {

rust/sedona-geo-traits-ext/tests/wkb_ext_tests.rs

Lines changed: 41 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -17,44 +17,56 @@
1717

1818
//! Tests for the WKB extension traits implemented in `wkb_ext`.
1919
20-
use geo_traits::{
21-
CoordTrait, GeometryTrait, LineStringTrait, MultiLineStringTrait, MultiPointTrait,
22-
MultiPolygonTrait, PointTrait, PolygonTrait,
23-
};
20+
use geo_traits::GeometryTrait;
21+
use rstest::rstest;
2422
use sedona_geo_traits_ext::*;
2523
use std::str::FromStr;
26-
use wkb::reader::Wkb;
24+
use wkb::{reader::Wkb, Endianness};
2725
use wkt::Wkt;
2826

2927
/// Helper to create WKB from WKT string using the wkb writer
3028
fn wkb_from_wkt(wkt_str: &str) -> Vec<u8> {
29+
wkb_from_wkt_with_endianness(wkt_str, wkb::Endianness::LittleEndian)
30+
}
31+
32+
/// Helper to create WKB from WKT string using the wkb writer
33+
fn wkb_from_wkt_with_endianness(wkt_str: &str, endianness: wkb::Endianness) -> Vec<u8> {
3134
let geometry = Wkt::<f64>::from_str(wkt_str).unwrap();
3235
let mut buf = Vec::new();
33-
let options = wkb::writer::WriteOptions {
34-
endianness: wkb::Endianness::LittleEndian,
35-
};
36+
let options = wkb::writer::WriteOptions { endianness };
3637
wkb::writer::write_geometry(&mut buf, &geometry, &options).unwrap();
3738
buf
3839
}
3940

40-
#[test]
41-
fn test_point_ext() {
42-
let buf = wkb_from_wkt("POINT(1.5 -2.0)");
41+
#[rstest]
42+
fn test_geo_coord(
43+
#[values(Endianness::LittleEndian, Endianness::BigEndian)] endianness: Endianness,
44+
) {
45+
let buf = wkb_from_wkt_with_endianness("POINT (1.0 2.0)", endianness);
46+
let wkb = Wkb::try_new(&buf).unwrap();
47+
let geo_traits::GeometryType::Point(pt) = wkb.as_type() else {
48+
panic!("expected point")
49+
};
50+
let coord = pt.geo_coord().unwrap();
51+
assert_eq!(coord.x, 1.0);
52+
assert_eq!(coord.y, 2.0);
53+
54+
let buf = wkb_from_wkt_with_endianness("POINT EMPTY", endianness);
4355
let wkb = Wkb::try_new(&buf).unwrap();
44-
let geo_traits::GeometryType::Point(p) = wkb.as_type() else {
56+
let geo_traits::GeometryType::Point(pt) = wkb.as_type() else {
4557
panic!("expected point")
4658
};
47-
let c = geo_traits::PointTrait::coord(&p).unwrap();
48-
assert_eq!(c.x(), 1.5);
49-
assert_eq!(c.y(), -2.0);
50-
assert_eq!(p.coord_ext().unwrap().geo_coord().x, 1.5);
59+
let coord = pt.geo_coord();
60+
assert!(coord.is_none());
5161
}
5262

53-
#[test]
54-
fn test_linestring_iterators() {
55-
let buf = wkb_from_wkt("LINESTRING(0 0, 1 1, 2 1.5)");
63+
#[rstest]
64+
fn test_linestring_iterators(
65+
#[values(Endianness::LittleEndian, Endianness::BigEndian)] endianness: Endianness,
66+
) {
67+
let buf = wkb_from_wkt_with_endianness("LINESTRING(0 0, 1 1, 2 1.5)", endianness);
5668
let wkb = Wkb::try_new(&buf).unwrap();
57-
let geo_traits::GeometryType::LineString(ls) = wkb.as_type() else {
69+
let GeometryTypeExt::LineString(ls) = wkb.as_type_ext() else {
5870
panic!("expected linestring")
5971
};
6072

@@ -69,51 +81,15 @@ fn test_linestring_iterators() {
6981
assert_eq!(segs.len(), coords.len() - 1);
7082
assert_eq!(segs[0].start.x, 0.0);
7183
assert_eq!(segs[0].end.x, 1.0);
72-
}
73-
74-
#[test]
75-
fn test_polygon_ext() {
76-
let buf = wkb_from_wkt("POLYGON((0 0, 2 0, 2 2, 0 2, 0 0))");
77-
let wkb = Wkb::try_new(&buf).unwrap();
78-
let geo_traits::GeometryType::Polygon(p) = wkb.as_type() else {
79-
panic!("expected polygon")
80-
};
81-
assert_eq!(PolygonTrait::num_interiors(&p), 0);
82-
let exterior = PolygonTrait::exterior(&p).unwrap();
83-
assert_eq!(exterior.num_coords(), 5);
84-
}
85-
86-
#[test]
87-
fn test_multi_geometries() {
88-
// MultiPoint
89-
let buf = wkb_from_wkt("MULTIPOINT(1 1, 2 2)");
90-
let wkb = Wkb::try_new(&buf).unwrap();
91-
let geo_traits::GeometryType::MultiPoint(mp) = wkb.as_type() else {
92-
panic!("expected multipoint")
93-
};
94-
assert_eq!(MultiPointTrait::num_points(&mp), 2);
95-
let p0 = geo_traits::MultiPointTrait::point(&mp, 0).unwrap();
96-
assert_eq!(p0.coord().unwrap().x(), 1.0);
97-
98-
// MultiLineString
99-
let buf = wkb_from_wkt("MULTILINESTRING((0 0, 1 0))");
100-
let wkb = Wkb::try_new(&buf).unwrap();
101-
let geo_traits::GeometryType::MultiLineString(mls) = wkb.as_type() else {
102-
panic!("expected multilinestring")
103-
};
104-
assert_eq!(MultiLineStringTrait::num_line_strings(&mls), 1);
105-
let ls0 = geo_traits::MultiLineStringTrait::line_string(&mls, 0).unwrap();
106-
assert_eq!(LineStringTrait::num_coords(&ls0), 2);
10784

108-
// MultiPolygon
109-
let buf = wkb_from_wkt("MULTIPOLYGON(((0 0, 1 0, 0 0)))");
85+
// Empty linestring
86+
let buf = wkb_from_wkt_with_endianness("LINESTRING EMPTY", endianness);
11087
let wkb = Wkb::try_new(&buf).unwrap();
111-
let geo_traits::GeometryType::MultiPolygon(mp) = wkb.as_type() else {
112-
panic!("expected multipolygon")
88+
let GeometryTypeExt::LineString(ls) = wkb.as_type_ext() else {
89+
panic!("expected linestring")
11390
};
114-
assert_eq!(MultiPolygonTrait::num_polygons(&mp), 1);
115-
let poly0 = geo_traits::MultiPolygonTrait::polygon(&mp, 0).unwrap();
116-
assert_eq!(PolygonTrait::exterior(&poly0).unwrap().num_coords(), 3);
91+
assert_eq!(ls.coord_iter().count(), 0);
92+
assert_eq!(ls.lines().count(), 0);
11793
}
11894

11995
#[test]
@@ -126,46 +102,21 @@ fn test_geometry_collection_ext() {
126102
assert_eq!(wkb.num_geometries_ext(), 2);
127103

128104
let child0 = wkb.geometry_ext(0).unwrap();
129-
let geo_traits::GeometryType::Point(_) = child0.as_type() else {
105+
let GeometryTypeExt::Point(_) = child0.as_type_ext() else {
130106
panic!("child0 expected point");
131107
};
132108

133109
// Iterate via geometries_ext
134110
let types: Vec<_> = wkb
135111
.geometries_ext()
136-
.map(|g| match g.as_type() {
137-
geo_traits::GeometryType::Point(_) => "P",
112+
.map(|g| match g.as_type_ext() {
113+
GeometryTypeExt::Point(_) => "P",
138114
_ => "?",
139115
})
140116
.collect();
141117
assert_eq!(types, vec!["P", "P"]);
142118
}
143119

144-
/// Helper to create big-endian WKB linestring (for testing endianness handling)
145-
fn wkb_linestring_be(coords: &[(f64, f64)]) -> Vec<u8> {
146-
let mut b = Vec::new();
147-
b.push(0u8); // Big endian
148-
b.extend_from_slice(&2u32.to_be_bytes());
149-
b.extend_from_slice(&(coords.len() as u32).to_be_bytes());
150-
for (x, y) in coords {
151-
b.extend_from_slice(&x.to_be_bytes());
152-
b.extend_from_slice(&y.to_be_bytes());
153-
}
154-
b
155-
}
156-
157-
#[test]
158-
fn test_linestring_iter_exact_size() {
159-
let buf = wkb_from_wkt("LINESTRING(0 0, 1 0, 2 1, 3 1)");
160-
let wkb = Wkb::try_new(&buf).unwrap();
161-
let geo_traits::GeometryType::LineString(ls) = wkb.as_type() else {
162-
panic!("expected linestring")
163-
};
164-
let mut iter = ls.lines();
165-
assert_eq!(iter.len(), 3); // ExactSizeIterator::len (4 coords - 1)
166-
assert!(iter.next().is_some());
167-
}
168-
169120
#[test]
170121
fn test_linestring_rev_lines() {
171122
// Empty linestring
@@ -277,25 +228,3 @@ fn test_linestring_triangles() {
277228
assert_eq!(ls.triangles().count(), 0);
278229
assert_eq!(ls.lines().len(), 0);
279230
}
280-
281-
#[test]
282-
fn test_linestring_big_endian_and_coord_iter() {
283-
// Big endian variant to exercise EndianCoordIter and EndianLineIter
284-
let coords = &[(1.0, 1.0), (2.0, 2.0), (3.0, 3.0)];
285-
let buf = wkb_linestring_be(coords);
286-
let wkb = Wkb::try_new(&buf).unwrap();
287-
let geo_traits::GeometryType::LineString(ls) = wkb.as_type() else {
288-
panic!("expected linestring")
289-
};
290-
291-
let collected: Vec<_> = ls.coord_iter().collect();
292-
assert_eq!(collected.len(), coords.len());
293-
for (c, (ex_x, ex_y)) in collected.iter().zip(coords.iter()) {
294-
assert_eq!((c.x, c.y), (*ex_x, *ex_y));
295-
}
296-
297-
let segs: Vec<_> = ls.lines().collect();
298-
assert_eq!(segs.len(), 2);
299-
assert_eq!(segs[0].start.x, 1.0);
300-
assert_eq!(segs[1].end.x, 3.0);
301-
}

0 commit comments

Comments
 (0)