@@ -26,6 +26,7 @@ use vortex_array::dtype::PType;
2626use vortex_array:: scalar:: Scalar ;
2727use vortex_error:: VortexResult ;
2828use vortex_error:: vortex_bail;
29+ use vortex_error:: vortex_ensure;
2930use 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 ) ]
6263pub 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
7374impl 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
10586impl 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.
159144pub ( 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+ }
0 commit comments