@@ -73,9 +73,10 @@ mod vector_tile;
7373
7474use feature:: { Feature , Value } ;
7575use geo_types:: {
76- Coord , Geometry , LineString , MultiLineString , MultiPoint , MultiPolygon , Point , Polygon ,
76+ Coord , CoordNum , Geometry , LineString , MultiLineString , MultiPoint , MultiPolygon , Point , Polygon ,
7777} ;
7878use layer:: Layer ;
79+ use num_traits:: NumCast ;
7980use prost:: { Message , bytes:: Bytes } ;
8081use vector_tile:: { Tile , tile:: GeomType } ;
8182
@@ -210,6 +211,41 @@ impl Reader {
210211 /// }
211212 /// ```
212213 pub fn get_features ( & self , layer_index : usize ) -> Result < Vec < Feature > , error:: ParserError > {
214+ self . get_features_as :: < f32 > ( layer_index)
215+ }
216+
217+ /// Retrieves the features of a specific layer with geometry coordinates in the specified numeric type.
218+ ///
219+ /// This is a generic version of [`get_features`](Reader::get_features) that allows you to choose
220+ /// the coordinate type for the geometry. Supported types include `f32` (default), `i32`, and `i16`.
221+ ///
222+ /// # Arguments
223+ ///
224+ /// * `layer_index` - The index of the layer.
225+ ///
226+ /// # Type Parameters
227+ ///
228+ /// * `T` - The numeric type for geometry coordinates (e.g. `f32`, `i32`, `i16`).
229+ ///
230+ /// # Returns
231+ ///
232+ /// A result containing a vector of features if successful, or a `ParserError` if there is an error parsing the tile or accessing the layer.
233+ ///
234+ /// # Examples
235+ ///
236+ /// ```
237+ /// use mvt_reader::Reader;
238+ ///
239+ /// let data = vec![/* Vector tile data */];
240+ /// let reader = Reader::new(data).unwrap();
241+ ///
242+ /// // Get features with i32 coordinates
243+ /// let features = reader.get_features_as::<i32>(0);
244+ ///
245+ /// // Get features with i16 coordinates
246+ /// let features = reader.get_features_as::<i16>(0);
247+ /// ```
248+ pub fn get_features_as < T : CoordNum > ( & self , layer_index : usize ) -> Result < Vec < Feature < T > > , error:: ParserError > {
213249 let layer = self . tile . layers . get ( layer_index) ;
214250 match layer {
215251 Some ( layer) => {
@@ -218,7 +254,7 @@ impl Reader {
218254 if let Some ( geom_type) = feature. r#type {
219255 match GeomType :: try_from ( geom_type) {
220256 Ok ( geom_type) => {
221- let parsed_geometry = match parse_geometry ( & feature. geometry , geom_type) {
257+ let parsed_geometry = match parse_geometry :: < T > ( & feature. geometry , geom_type) {
222258 Ok ( parsed_geometry) => parsed_geometry,
223259 Err ( error) => {
224260 return Err ( error) ;
@@ -321,29 +357,33 @@ fn map_value(value: vector_tile::tile::Value) -> Value {
321357 Value :: Null
322358}
323359
324- fn shoelace_formula ( points : & [ Point < f32 > ] ) -> f32 {
360+ fn shoelace_formula < T : CoordNum > ( points : & [ Point < T > ] ) -> f32 {
325361 let mut area: f32 = 0.0 ;
326362 let n = points. len ( ) ;
327363 let mut v1 = points[ n - 1 ] ;
328364 for v2 in points. iter ( ) . take ( n) {
329- area += ( v2. y ( ) - v1. y ( ) ) * ( v2. x ( ) + v1. x ( ) ) ;
365+ let v2y: f32 = NumCast :: from ( v2. y ( ) ) . unwrap_or ( 0.0 ) ;
366+ let v1y: f32 = NumCast :: from ( v1. y ( ) ) . unwrap_or ( 0.0 ) ;
367+ let v2x: f32 = NumCast :: from ( v2. x ( ) ) . unwrap_or ( 0.0 ) ;
368+ let v1x: f32 = NumCast :: from ( v1. x ( ) ) . unwrap_or ( 0.0 ) ;
369+ area += ( v2y - v1y) * ( v2x + v1x) ;
330370 v1 = * v2;
331371 }
332372 area * 0.5
333373}
334374
335- fn parse_geometry (
375+ fn parse_geometry < T : CoordNum > (
336376 geometry_data : & [ u32 ] ,
337377 geom_type : GeomType ,
338- ) -> Result < Geometry < f32 > , error:: ParserError > {
378+ ) -> Result < Geometry < T > , error:: ParserError > {
339379 if geom_type == GeomType :: Unknown {
340380 return Err ( error:: ParserError :: new ( error:: GeometryError :: new ( ) ) ) ;
341381 }
342382
343383 // worst case capacity to prevent reallocation. not needed to be exact.
344- let mut coordinates: Vec < Coord < f32 > > = Vec :: with_capacity ( geometry_data. len ( ) ) ;
345- let mut polygons: Vec < Polygon < f32 > > = Vec :: new ( ) ;
346- let mut linestrings: Vec < LineString < f32 > > = Vec :: new ( ) ;
384+ let mut coordinates: Vec < Coord < T > > = Vec :: with_capacity ( geometry_data. len ( ) ) ;
385+ let mut polygons: Vec < Polygon < T > > = Vec :: new ( ) ;
386+ let mut linestrings: Vec < LineString < T > > = Vec :: new ( ) ;
347387
348388 let mut cursor: [ i32 ; 2 ] = [ 0 , 0 ] ;
349389 let mut parameter_count: u32 = 0 ;
@@ -412,8 +452,8 @@ fn parse_geometry(
412452 None => i32:: MAX , // clip value
413453 } ;
414454 coordinates. push ( Coord {
415- x : cursor[ 0 ] as f32 ,
416- y : cursor[ 1 ] as f32 ,
455+ x : NumCast :: from ( cursor[ 0 ] ) . unwrap_or_else ( T :: zero ) ,
456+ y : NumCast :: from ( cursor[ 1 ] ) . unwrap_or_else ( T :: zero ) ,
417457 } ) ;
418458 }
419459 parameter_count -= 1 ;
0 commit comments