11// SPDX-License-Identifier: Apache-2.0
22// SPDX-FileCopyrightText: Copyright the Vortex contributors
33
4- //! The coordinate building block shared by geometry extension types: the `Struct<x, y, [z], [m]>`
5- //! storage, its [`Dimension`], the decoded [`Coordinate`] value, and the readers that decode it.
6- //! `z`/`m` are optional, so all four GeoArrow dimensions share one value type — no third-party deps.
4+ //! Coordinate building blocks for geometry extension types: the `Struct<x, y, [z], [m]>` storage,
5+ //! its [`Dimension`], and the decoded [`Coordinate`] value.
76
87use std:: fmt:: Display ;
98use std:: fmt:: Formatter ;
109
1110use vortex_array:: ArrayRef ;
12- use vortex_array:: Canonical ;
1311use vortex_array:: ExecutionCtx ;
12+ use vortex_array:: arrays:: ExtensionArray ;
1413use vortex_array:: arrays:: PrimitiveArray ;
14+ use vortex_array:: arrays:: StructArray ;
1515use vortex_array:: arrays:: extension:: ExtensionArrayExt ;
1616use vortex_array:: arrays:: struct_:: StructArrayExt ;
1717use vortex_array:: dtype:: DType ;
18- use vortex_array:: dtype:: FieldNames ;
1918use vortex_array:: dtype:: Nullability ;
2019use vortex_array:: dtype:: PType ;
21- use vortex_array:: dtype:: StructFields ;
2220use vortex_array:: scalar:: Scalar ;
2321use vortex_error:: VortexResult ;
2422use vortex_error:: vortex_bail;
2523use vortex_error:: vortex_err;
2624
2725/// Coordinate dimensions, matching GeoArrow. Field order is fixed: x, y, then z before m.
2826#[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
29- pub enum Dimension {
27+ pub ( crate ) enum Dimension {
3028 /// 2D: `x`, `y`.
3129 Xy ,
3230 /// 3D with elevation: `x`, `y`, `z`.
@@ -38,18 +36,8 @@ pub enum Dimension {
3836}
3937
4038impl Dimension {
41- /// The coordinate struct field names for this dimension, in GeoArrow order.
42- pub fn field_names ( self ) -> & ' static [ & ' static str ] {
43- match self {
44- Dimension :: Xy => & [ "x" , "y" ] ,
45- Dimension :: Xyz => & [ "x" , "y" , "z" ] ,
46- Dimension :: Xym => & [ "x" , "y" , "m" ] ,
47- Dimension :: Xyzm => & [ "x" , "y" , "z" , "m" ] ,
48- }
49- }
50-
5139 /// Recover the dimension from a coordinate's field names, in GeoArrow order.
52- pub fn from_field_names ( names : & [ & str ] ) -> VortexResult < Dimension > {
40+ pub ( crate ) fn from_field_names ( names : & [ & str ] ) -> VortexResult < Dimension > {
5341 Ok ( match names {
5442 [ "x" , "y" ] => Dimension :: Xy ,
5543 [ "x" , "y" , "z" ] => Dimension :: Xyz ,
@@ -61,16 +49,19 @@ impl Dimension {
6149}
6250
6351/// A decoded coordinate. `z`/`m` are `Some` iff the storage dimension includes them.
52+ ///
53+ /// This is the native value produced when unpacking a [`Point`](crate::extension::Point) scalar;
54+ /// the rest of the coordinate machinery is crate-internal.
6455#[ derive( Debug , Clone , Copy , PartialEq ) ]
6556pub struct Coordinate {
6657 /// The x (longitude/easting) ordinate.
67- pub x : f64 ,
58+ x : f64 ,
6859 /// The y (latitude/northing) ordinate.
69- pub y : f64 ,
60+ y : f64 ,
7061 /// The optional z (elevation) ordinate.
71- pub z : Option < f64 > ,
62+ z : Option < f64 > ,
7263 /// The optional m (measure) ordinate.
73- pub m : Option < f64 > ,
64+ m : Option < f64 > ,
7465}
7566
7667impl Coordinate {
@@ -83,6 +74,26 @@ impl Coordinate {
8374 m : None ,
8475 }
8576 }
77+
78+ /// The x (longitude/easting) ordinate.
79+ pub fn x ( & self ) -> f64 {
80+ self . x
81+ }
82+
83+ /// The y (latitude/northing) ordinate.
84+ pub fn y ( & self ) -> f64 {
85+ self . y
86+ }
87+
88+ /// The z (elevation) ordinate, if the dimension includes one.
89+ pub fn z ( & self ) -> Option < f64 > {
90+ self . z
91+ }
92+
93+ /// The m (measure) ordinate, if the dimension includes one.
94+ pub fn m ( & self ) -> Option < f64 > {
95+ self . m
96+ }
8697}
8798
8899impl Display for Coordinate {
@@ -91,23 +102,9 @@ impl Display for Coordinate {
91102 }
92103}
93104
94- /// The coordinate storage dtype for a dimension: `Struct<x, y, [z], [m]>` of non-nullable f64.
95- pub fn coordinate_dtype ( dim : Dimension , nullability : Nullability ) -> DType {
96- let names = dim. field_names ( ) ;
97- let fields = std:: iter:: repeat_n (
98- DType :: Primitive ( PType :: F64 , Nullability :: NonNullable ) ,
99- names. len ( ) ,
100- )
101- . collect :: < Vec < _ > > ( ) ;
102- DType :: Struct (
103- StructFields :: new ( FieldNames :: from ( names) , fields) ,
104- nullability,
105- )
106- }
107-
108105/// Validate that `dtype` is a coordinate struct of non-nullable `f64` fields, returning its
109106/// [`Dimension`]. Any of the four GeoArrow dimensions validates.
110- pub fn coordinate_dimension ( dtype : & DType ) -> VortexResult < Dimension > {
107+ pub ( crate ) fn coordinate_dimension ( dtype : & DType ) -> VortexResult < Dimension > {
111108 let DType :: Struct ( fields, _) = dtype else {
112109 vortex_bail ! ( "coordinate storage must be a Struct, was {dtype}" ) ;
113110 } ;
@@ -153,36 +150,32 @@ pub(crate) fn coordinate_from_struct(scalar: &Scalar) -> VortexResult<Coordinate
153150
154151/// Decode a [`Coordinate`] from an extension-typed point scalar (unwrapped to its coordinate
155152/// storage) or a bare coordinate `Struct` scalar. The per-row decode used by the distance fns.
156- pub fn coordinate_from_scalar ( scalar : & Scalar ) -> VortexResult < Coordinate > {
153+ pub ( crate ) fn coordinate_from_scalar ( scalar : & Scalar ) -> VortexResult < Coordinate > {
157154 match scalar. dtype ( ) . as_extension_opt ( ) {
158155 Some ( _) => coordinate_from_struct ( & scalar. as_extension ( ) . to_storage_scalar ( ) ) ,
159156 None => coordinate_from_struct ( scalar) ,
160157 }
161158}
162159
163160/// Canonicalize a point column once and return its flat `x`/`y` `f64` columns. The bulk counterpart
164- /// to [`coordinate_from_scalar`]; distance is planar , so `z`/`m` are ignored.
161+ /// to [`coordinate_from_scalar`]; distances use only `x`/`y` , so `z`/`m` are ignored.
165162pub ( crate ) fn xy_columns (
166163 points : & ArrayRef ,
167164 ctx : & mut ExecutionCtx ,
168165) -> VortexResult < ( PrimitiveArray , PrimitiveArray ) > {
169166 let storage = points
170167 . clone ( )
171- . execute :: < Canonical > ( ctx) ?
172- . into_extension ( )
168+ . execute :: < ExtensionArray > ( ctx) ?
173169 . storage_array ( )
174170 . clone ( )
175- . execute :: < Canonical > ( ctx) ?
176- . into_struct ( ) ;
171+ . execute :: < StructArray > ( ctx) ?;
177172 let xs = storage
178173 . unmasked_field_by_name ( "x" ) ?
179174 . clone ( )
180- . execute :: < Canonical > ( ctx) ?
181- . into_primitive ( ) ;
175+ . execute :: < PrimitiveArray > ( ctx) ?;
182176 let ys = storage
183177 . unmasked_field_by_name ( "y" ) ?
184178 . clone ( )
185- . execute :: < Canonical > ( ctx) ?
186- . into_primitive ( ) ;
179+ . execute :: < PrimitiveArray > ( ctx) ?;
187180 Ok ( ( xs, ys) )
188181}
0 commit comments