33pub mod json;
44
55use crate :: { Error , ItemCollection , Result } ;
6- use arrow_array:: { RecordBatch , RecordBatchIterator , RecordBatchReader , cast:: AsArray } ;
6+ use arrow_array:: {
7+ Array , RecordBatch , RecordBatchIterator , RecordBatchReader , builder:: BinaryBuilder ,
8+ cast:: AsArray ,
9+ } ;
710use arrow_json:: ReaderBuilder ;
811use arrow_schema:: { DataType , Field , SchemaBuilder , SchemaRef , TimeUnit } ;
912use geo_types:: Geometry ;
@@ -14,17 +17,14 @@ use geoarrow_array::{
1417} ;
1518use geoarrow_schema:: { GeoArrowType , GeometryType , Metadata } ;
1619use serde_json:: { Value , json} ;
17- use std:: { collections :: HashMap , sync:: Arc } ;
20+ use std:: { io :: Cursor , sync:: Arc } ;
1821
1922/// The stac-geoparquet version metadata key.
2023pub const VERSION_KEY : & str = "stac:geoparquet_version" ;
2124
2225/// The stac-geoparquet version.
2326pub const VERSION : & str = "1.0.0" ;
2427
25- /// Geometry columns.
26- pub const GEOMETRY_COLUMNS : [ & str ; 2 ] = [ "geometry" , "proj:geometry" ] ;
27-
2828/// Datetime columns.
2929pub const DATETIME_COLUMNS : [ & str ; 8 ] = [
3030 "datetime" ,
@@ -79,7 +79,8 @@ impl TableBuilder {
7979 /// ```
8080 pub fn build ( self ) -> Result < Table > {
8181 let mut values = Vec :: with_capacity ( self . item_collection . items . len ( ) ) ;
82- let mut geometry_builders = HashMap :: new ( ) ;
82+ let mut geometry_builder = GeometryBuilder :: new ( GeometryType :: new ( Default :: default ( ) ) ) ;
83+ let mut proj_geometry_builder = BinaryBuilder :: new ( ) ;
8384
8485 for item in self . item_collection . items {
8586 let mut value =
@@ -88,18 +89,20 @@ impl TableBuilder {
8889 let value = value
8990 . as_object_mut ( )
9091 . expect ( "a flat item should serialize to an object" ) ;
91- for key in GEOMETRY_COLUMNS {
92- if let Some ( value) = value. remove ( key) {
93- let entry = geometry_builders. entry ( key) . or_insert_with ( || {
94- let geometry_type = GeometryType :: new ( Default :: default ( ) ) ;
95- GeometryBuilder :: new ( geometry_type)
96- } ) ;
97- let geometry =
98- geojson:: Geometry :: from_json_value ( value) . map_err ( Box :: new) ?;
99- entry. push_geometry ( Some (
100- & ( Geometry :: try_from ( geometry) . map_err ( Box :: new) ?) ,
101- ) ) ?;
102- }
92+ if let Some ( value) = value. remove ( "geometry" ) {
93+ let geometry = geojson:: Geometry :: from_json_value ( value) . map_err ( Box :: new) ?;
94+ geometry_builder
95+ . push_geometry ( Some ( & ( Geometry :: try_from ( geometry) . map_err ( Box :: new) ?) ) ) ?;
96+ }
97+ if let Some ( value) = value. remove ( "proj:geometry" ) {
98+ let geometry = geojson:: Geometry :: from_json_value ( value) . map_err ( Box :: new) ?;
99+ let mut cursor = Cursor :: new ( Vec :: new ( ) ) ;
100+ wkb:: writer:: write_geometry (
101+ & mut cursor,
102+ & Geometry :: try_from ( geometry) . map_err ( Box :: new) ?,
103+ & Default :: default ( ) ,
104+ ) ?;
105+ proj_geometry_builder. append_value ( cursor. into_inner ( ) ) ;
103106 }
104107 if let Some ( bbox) = value. remove ( "bbox" ) {
105108 let bbox = convert_bbox ( bbox) ?;
@@ -132,10 +135,14 @@ impl TableBuilder {
132135 // Add the geometries back in.
133136 let mut schema_builder = SchemaBuilder :: from ( schema. fields ( ) ) ;
134137 let mut columns = record_batch. columns ( ) . to_vec ( ) ;
135- for ( key, geometry_builder) in geometry_builders {
136- let geometry_array = geometry_builder. finish ( ) ;
137- columns. push ( geometry_array. to_array_ref ( ) ) ;
138- schema_builder. push ( geometry_array. data_type ( ) . to_field ( key, true ) ) ;
138+ let geometry_array = geometry_builder. finish ( ) ;
139+ columns. push ( geometry_array. to_array_ref ( ) ) ;
140+ schema_builder. push ( geometry_array. data_type ( ) . to_field ( "geometry" , true ) ) ;
141+ let proj_geometry_array = proj_geometry_builder. finish ( ) ;
142+ if !proj_geometry_array. is_empty ( ) {
143+ let data_type = proj_geometry_array. data_type ( ) . clone ( ) ;
144+ columns. push ( Arc :: new ( proj_geometry_array) ) ;
145+ schema_builder. push ( Field :: new ( "proj:geometry" , data_type, true ) ) ;
139146 }
140147 let _ = schema_builder
141148 . metadata_mut ( )
@@ -350,4 +357,20 @@ mod tests {
350357 let record_batch = record_batches. pop ( ) . unwrap ( ) ;
351358 let _ = super :: with_wkb_geometry ( record_batch, "geometry" ) . unwrap ( ) ;
352359 }
360+
361+ #[ test]
362+ fn has_proj_geometry ( ) {
363+ let item: Item =
364+ crate :: read ( "examples/extensions-collection/proj-example/proj-example.json" ) . unwrap ( ) ;
365+ let table = Table :: from_item_collection ( vec ! [ item] ) . unwrap ( ) ;
366+ let ( mut record_batches, _) = table. into_inner ( ) ;
367+ assert_eq ! ( record_batches. len( ) , 1 ) ;
368+ let record_batch = record_batches. pop ( ) . unwrap ( ) ;
369+ assert ! (
370+ record_batch
371+ . schema( )
372+ . column_with_name( "proj:geometry" )
373+ . is_some( )
374+ ) ;
375+ }
353376}
0 commit comments