Skip to content

Commit 026ecbd

Browse files
fix: changes requested, remove internal clone
1 parent 01c408f commit 026ecbd

2 files changed

Lines changed: 53 additions & 44 deletions

File tree

vortex-geo/src/extension/coordinate.rs

Lines changed: 45 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use vortex_array::dtype::PType;
2626
use vortex_array::scalar::Scalar;
2727
use vortex_error::VortexResult;
2828
use vortex_error::vortex_bail;
29+
use vortex_error::vortex_ensure;
2930
use vortex_error::vortex_err;
3031

3132
/// Coordinate dimensions, matching GeoArrow. Field order is fixed: `x`, `y`, then `z` before `m`.
@@ -61,13 +62,13 @@ impl Dimension {
6162
#[derive(Debug, Clone, Copy, PartialEq)]
6263
pub struct Coordinate {
6364
/// The x (longitude/easting) ordinate.
64-
x: f64,
65+
pub x: f64,
6566
/// The y (latitude/northing) ordinate.
66-
y: f64,
67+
pub y: f64,
6768
/// The optional `z?` (elevation) ordinate.
68-
z: Option<f64>,
69+
pub z: Option<f64>,
6970
/// The optional `m?` (measure) ordinate.
70-
m: Option<f64>,
71+
pub m: Option<f64>,
7172
}
7273

7374
impl Coordinate {
@@ -80,31 +81,16 @@ impl Coordinate {
8081
m: None,
8182
}
8283
}
83-
84-
/// The x (longitude/easting) ordinate.
85-
pub fn x(&self) -> f64 {
86-
self.x
87-
}
88-
89-
/// The y (latitude/northing) ordinate.
90-
pub fn y(&self) -> f64 {
91-
self.y
92-
}
93-
94-
/// The `z?` (elevation) ordinate, if the dimension includes one.
95-
pub fn z(&self) -> Option<f64> {
96-
self.z
97-
}
98-
99-
/// The `m?` (measure) ordinate, if the dimension includes one.
100-
pub fn m(&self) -> Option<f64> {
101-
self.m
102-
}
10384
}
10485

10586
impl Display for Coordinate {
106-
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
107-
write!(f, "POINT({} {})", self.x, self.y)
87+
fn fmt(&self, fmt: &mut Formatter<'_>) -> std::fmt::Result {
88+
match (self.z, self.m) {
89+
(None, None) => write!(fmt, "POINT({} {})", self.x, self.y),
90+
(Some(z), None) => write!(fmt, "POINT Z ({} {} {})", self.x, self.y, z),
91+
(None, Some(m)) => write!(fmt, "POINT M ({} {} {})", self.x, self.y, m),
92+
(Some(z), Some(m)) => write!(fmt, "POINT ZM ({} {} {} {})", self.x, self.y, z, m),
93+
}
10894
}
10995
}
11096

@@ -116,15 +102,14 @@ pub(crate) fn coordinate_dimension(dtype: &DType) -> VortexResult<Dimension> {
116102
};
117103
let names: Vec<&str> = fields.names().iter().map(|n| n.as_ref()).collect();
118104
for (i, field) in fields.fields().enumerate() {
119-
if !matches!(
120-
field,
121-
DType::Primitive(PType::F64, Nullability::NonNullable)
122-
) {
123-
vortex_bail!(
124-
"coordinate field {} must be non-nullable f64, was {field}",
125-
names[i]
126-
);
127-
}
105+
vortex_ensure!(
106+
matches!(
107+
field,
108+
DType::Primitive(PType::F64, Nullability::NonNullable)
109+
),
110+
"coordinate field {} must be non-nullable f64, was {field}",
111+
names[i]
112+
);
128113
}
129114
Dimension::from_field_names(&names)
130115
}
@@ -157,8 +142,8 @@ pub(crate) fn coordinate_from_struct(scalar: &Scalar) -> VortexResult<Coordinate
157142
/// Decode a [`Coordinate`] from an extension-typed point scalar (unwrapped to its coordinate
158143
/// storage) or a bare coordinate `Struct` scalar. The per-row decode used by the distance fns.
159144
pub(crate) fn coordinate_from_scalar(scalar: &Scalar) -> VortexResult<Coordinate> {
160-
match scalar.dtype().as_extension_opt() {
161-
Some(_) => coordinate_from_struct(&scalar.as_extension().to_storage_scalar()),
145+
match scalar.as_extension_opt() {
146+
Some(ext_scalar) => coordinate_from_struct(&ext_scalar.to_storage_scalar()),
162147
None => coordinate_from_struct(scalar),
163148
}
164149
}
@@ -185,3 +170,26 @@ pub(crate) fn xy_columns(
185170
.execute::<PrimitiveArray>(ctx)?;
186171
Ok((xs, ys))
187172
}
173+
174+
#[cfg(test)]
175+
mod tests {
176+
use super::Coordinate;
177+
178+
/// Display emits WKT, including `z?`/`m?` when present.
179+
#[test]
180+
fn display_is_wkt() {
181+
let coordinate = |z, m| Coordinate {
182+
x: 1.0,
183+
y: 2.0,
184+
z,
185+
m,
186+
};
187+
assert_eq!(coordinate(None, None).to_string(), "POINT(1 2)");
188+
assert_eq!(coordinate(Some(3.0), None).to_string(), "POINT Z (1 2 3)");
189+
assert_eq!(coordinate(None, Some(4.0)).to_string(), "POINT M (1 2 4)");
190+
assert_eq!(
191+
coordinate(Some(3.0), Some(4.0)).to_string(),
192+
"POINT ZM (1 2 3 4)"
193+
);
194+
}
195+
}

vortex-geo/src/scalar_fn/distance.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use vortex_array::ArrayRef;
77
use vortex_array::ExecutionCtx;
88
use vortex_array::IntoArray;
9+
use vortex_array::arrays::Constant;
910
use vortex_array::arrays::ConstantArray;
1011
use vortex_array::arrays::PrimitiveArray;
1112
use vortex_array::arrays::ScalarFnArray;
@@ -93,19 +94,19 @@ impl ScalarFnVTable for GeoDistance {
9394
) -> VortexResult<ArrayRef> {
9495
let a = args.get(0)?;
9596
let b = args.get(1)?;
96-
match (a.as_constant(), b.as_constant()) {
97+
match (a.as_opt::<Constant>(), b.as_opt::<Constant>()) {
9798
(Some(qa), Some(qb)) => {
98-
let qa = coordinate_from_scalar(&qa)?;
99-
let qb = coordinate_from_scalar(&qb)?;
100-
let distance = euclidean_distance(qa.x(), qa.y(), qb.x(), qb.y());
99+
let qa = coordinate_from_scalar(qa.scalar())?;
100+
let qb = coordinate_from_scalar(qb.scalar())?;
101+
let distance = euclidean_distance(qa.x, qa.y, qb.x, qb.y);
101102
Ok(ConstantArray::new(
102103
Scalar::primitive(distance, Nullability::NonNullable),
103104
a.len(),
104105
)
105106
.into_array())
106107
}
107-
(Some(query), None) => distances_to_constant(&b, &query, ctx),
108-
(None, Some(query)) => distances_to_constant(&a, &query, ctx),
108+
(Some(query), None) => distances_to_constant(&b, query.scalar(), ctx),
109+
(None, Some(query)) => distances_to_constant(&a, query.scalar(), ctx),
109110
(None, None) => {
110111
let (axs, ays) = xy_columns(&a, ctx)?;
111112
let (bxs, bys) = xy_columns(&b, ctx)?;
@@ -134,7 +135,7 @@ fn distances_to_constant(
134135
.as_slice::<f64>()
135136
.iter()
136137
.zip(ys.as_slice::<f64>())
137-
.map(|(&x, &y)| euclidean_distance(x, y, query.x(), query.y()));
138+
.map(|(&x, &y)| euclidean_distance(x, y, query.x, query.y));
138139
Ok(PrimitiveArray::from_iter(distances).into_array())
139140
}
140141

0 commit comments

Comments
 (0)