From d9528d4203e51a9c0a02842d717087edac81b673 Mon Sep 17 00:00:00 2001 From: Anton Bakker Date: Fri, 12 Feb 2021 16:17:21 +0100 Subject: [PATCH] added optional srid to extent parameter of generate command --- src/main.rs | 26 +++++++++++++++-- t-rex-core/src/datasource/datasource.rs | 14 ++++++++-- t-rex-core/src/datasource/postgis_ds.rs | 12 ++++++-- t-rex-gdal/src/gdal_ds.rs | 10 +++++-- t-rex-gdal/src/gdal_ds_test.rs | 4 +-- t-rex-service/src/datasources.rs | 11 ++++++-- t-rex-service/src/mvt_service.rs | 37 +++++++++++++++---------- t-rex-service/src/mvt_service_test.rs | 6 +++- tile-grid/src/grid.rs | 2 +- tile-grid/src/grid_test.rs | 4 +-- tile-grid/src/lib.rs | 2 +- 11 files changed, 95 insertions(+), 33 deletions(-) diff --git a/src/main.rs b/src/main.rs index 16bfcbb4..914987a9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -74,6 +74,20 @@ fn generate(args: &ArgMatches<'_>) { maxy: arr[3], }) }); + + let extent_srid = args.value_of("extent").and_then(|numlist| { + let arr: Vec<&str> = numlist.split(",").collect(); + match arr.len() { + 5 => { + let srid = arr[4]; + let srid_int: i32 = srid + .parse() + .expect("Error parsing 'srid' in 'extent' as integer"); + Some(srid_int) + } + _ => None, + } + }); let nodes = args.value_of("nodes").map(|s| { s.parse::() .expect("Error parsing 'nodes' as integer value") @@ -92,7 +106,15 @@ fn generate(args: &ArgMatches<'_>) { }); service.prepare_feature_queries(); service.generate( - tileset, minzoom, maxzoom, extent, nodes, nodeno, progress, overwrite, + tileset, + minzoom, + maxzoom, + extent, + nodes, + nodeno, + progress, + overwrite, + extent_srid, ); } @@ -184,7 +206,7 @@ fn main() { --tileset=[NAME] 'Tileset name' --minzoom=[LEVEL] 'Minimum zoom level' --maxzoom=[LEVEL] 'Maximum zoom level' - --extent=[minx,miny,maxx,maxy] 'Extent of tiles' + --extent=[minx,miny,maxx,maxy[,srid]] 'Extent of tiles' --nodes=[NUM] 'Number of generator nodes' --nodeno=[NUM] 'Number of this nodes (0 <= n < nodes)' --progress=[true|false] 'Show progress bar' diff --git a/t-rex-core/src/datasource/datasource.rs b/t-rex-core/src/datasource/datasource.rs index d18e91de..9b2c67c8 100644 --- a/t-rex-core/src/datasource/datasource.rs +++ b/t-rex-core/src/datasource/datasource.rs @@ -19,7 +19,12 @@ pub trait DatasourceType { fn layer_extent(&self, layer: &Layer, grid_srid: i32) -> Option; fn prepare_queries(&mut self, tileset: &str, layer: &Layer, grid_srid: i32); /// Projected extent - fn extent_from_wgs84(&self, extent: &Extent, dest_srid: i32) -> Option; + fn reproject_extent( + &self, + extent: &Extent, + dest_srid: i32, + src_srid: Option, + ) -> Option; /// Retrieve features of one layer. Return feature count. fn retrieve_features( &self, @@ -47,7 +52,12 @@ impl DatasourceType for DummyDatasource { fn detect_data_columns(&self, _layer: &Layer, _sql: Option<&String>) -> Vec<(String, String)> { unimplemented!(); } - fn extent_from_wgs84(&self, _extent: &Extent, _dest_srid: i32) -> Option { + fn reproject_extent( + &self, + _extent: &Extent, + _dest_srid: i32, + _src_srid: Option, + ) -> Option { unimplemented!(); } fn layer_extent(&self, _layer: &Layer, _grid_srid: i32) -> Option { diff --git a/t-rex-core/src/datasource/postgis_ds.rs b/t-rex-core/src/datasource/postgis_ds.rs index 2fdb9521..d21626c1 100644 --- a/t-rex-core/src/datasource/postgis_ds.rs +++ b/t-rex-core/src/datasource/postgis_ds.rs @@ -611,10 +611,16 @@ impl DatasourceType for PostgisDatasource { .collect() } /// Projected extent - fn extent_from_wgs84(&self, extent: &Extent, dest_srid: i32) -> Option { + fn reproject_extent( + &self, + extent: &Extent, + dest_srid: i32, + src_srid: Option, + ) -> Option { + let ext_srid = src_srid.unwrap_or(4326); let sql = format!( - "SELECT ST_Transform(ST_MakeEnvelope({}, {}, {}, {}, 4326), {}) AS extent", - extent.minx, extent.miny, extent.maxx, extent.maxy, dest_srid + "SELECT ST_Transform(ST_MakeEnvelope({}, {}, {}, {}, {}), {}) AS extent", + extent.minx, extent.miny, extent.maxx, extent.maxy, ext_srid, dest_srid ); self.extent_query(sql) } diff --git a/t-rex-gdal/src/gdal_ds.rs b/t-rex-gdal/src/gdal_ds.rs index e7f7e84a..83392703 100644 --- a/t-rex-gdal/src/gdal_ds.rs +++ b/t-rex-gdal/src/gdal_ds.rs @@ -72,8 +72,14 @@ impl DatasourceType for GdalDatasource { Vec::new() //TODO } /// Projected extent - fn extent_from_wgs84(&self, extent: &Extent, dest_srid: i32) -> Option { - transform_extent(extent, 4326, dest_srid).ok() + fn reproject_extent( + &self, + extent: &Extent, + dest_srid: i32, + src_srid: Option, + ) -> Option { + let ext_srid = src_srid.unwrap_or(4326); + transform_extent(extent, ext_srid, dest_srid).ok() } fn layer_extent(&self, layer: &Layer, grid_srid: i32) -> Option { let mut dataset = Dataset::open(Path::new(&self.path)).unwrap(); diff --git a/t-rex-gdal/src/gdal_ds_test.rs b/t-rex-gdal/src/gdal_ds_test.rs index f83bc917..ba82df26 100644 --- a/t-rex-gdal/src/gdal_ds_test.rs +++ b/t-rex-gdal/src/gdal_ds_test.rs @@ -140,12 +140,12 @@ fn test_coord_transformation() { } }; assert_eq!( - ds.extent_from_wgs84(&extent_wgs84, 3857), + ds.reproject_extent(&extent_wgs84, 3857, None), Some(extent_3857.clone()) ); // Invalid input extent doesn't panic - let result = ds.extent_from_wgs84(&extent_3857, 3857); + let result = ds.reproject_extent(&extent_3857, 3857, None); assert!(result.is_none()); let mut reccnt = 0; diff --git a/t-rex-service/src/datasources.rs b/t-rex-service/src/datasources.rs index d8f1e6df..5dbefbc8 100644 --- a/t-rex-service/src/datasources.rs +++ b/t-rex-service/src/datasources.rs @@ -41,10 +41,15 @@ impl DatasourceType for Datasource { &Datasource::Gdal(ref ds) => ds.detect_data_columns(layer, sql), } } - fn extent_from_wgs84(&self, extent: &Extent, dest_srid: i32) -> Option { + fn reproject_extent( + &self, + extent: &Extent, + dest_srid: i32, + src_srid: Option, + ) -> Option { match self { - &Datasource::Postgis(ref ds) => ds.extent_from_wgs84(extent, dest_srid), - &Datasource::Gdal(ref ds) => ds.extent_from_wgs84(extent, dest_srid), + &Datasource::Postgis(ref ds) => ds.reproject_extent(extent, dest_srid, src_srid), + &Datasource::Gdal(ref ds) => ds.reproject_extent(extent, dest_srid, src_srid), } } fn layer_extent(&self, layer: &Layer, grid_srid: i32) -> Option { diff --git a/t-rex-service/src/mvt_service.rs b/t-rex-service/src/mvt_service.rs index 2727ddb0..454a4d13 100644 --- a/t-rex-service/src/mvt_service.rs +++ b/t-rex-service/src/mvt_service.rs @@ -18,7 +18,7 @@ use t_rex_core::datasource::DatasourceType; use t_rex_core::mvt::tile::Tile; use t_rex_core::mvt::vector_tile; use t_rex_core::service::tileset::{Tileset, WORLD_EXTENT}; -use tile_grid::{extent_to_merc, Extent, ExtentInt, Grid, GridIterator}; +use tile_grid::{extent_wgs84_to_merc, Extent, ExtentInt, Grid, GridIterator}; use tokio::task; /// Mapbox Vector Tile Service @@ -202,18 +202,24 @@ impl MvtService { pb } /// Projected extent in grid SRS from WGS84 - pub fn extent_from_wgs84(&self, extent: &Extent) -> Extent { + pub fn extent_from_input_extent(&self, extent: &Extent, extent_srid: Option) -> Extent { // TODO: use proj4 (directly) - if self.grid.srid == 3857 { + let extent_srid_unwrapped = extent_srid.unwrap_or(4326); + + if self.grid.srid == 3857 && extent_srid_unwrapped == 4326 { // shortcut for Web Mercator - extent_to_merc(extent) + extent_wgs84_to_merc(extent) } else { let ds = self.datasources.default().unwrap(); - ds.extent_from_wgs84(extent, self.grid.srid) - .expect(&format!( - "Error transforming {:?} to SRID {}", - extent, self.grid.srid - )) + if self.grid.srid == extent_srid_unwrapped { + extent.clone() + } else { + ds.reproject_extent(extent, self.grid.srid, extent_srid) + .expect(&format!( + "Error transforming {:?} to SRID {}", + extent, self.grid.srid + )) + } } } /// Seed tile cache @@ -227,6 +233,7 @@ impl MvtService { nodeno: Option, progress: bool, overwrite: bool, + extent_srid: Option, ) { let rt = tokio::runtime::Runtime::new().expect("Couldn't initialize tokio runtime"); self.init_cache(); @@ -242,11 +249,13 @@ impl MvtService { } // Convert extent to grid SRS - let extent = extent.as_ref().or(tileset.extent.as_ref()); - debug!("wgs84 extent: {:?}", extent); - let ext_proj = match extent { + let input_extent = extent.as_ref().or(tileset.extent.as_ref()); + debug!("input extent: {:?}", input_extent); + let ext_proj = match input_extent { // (-180 -90) throws error when projecting - Some(ext_wgs84) if *ext_wgs84 != WORLD_EXTENT => self.extent_from_wgs84(ext_wgs84), + Some(ext_wgs84) if *ext_wgs84 != WORLD_EXTENT => { + self.extent_from_input_extent(ext_wgs84, extent_srid) + } _ => { warn!("Building cache for the full globe, please fill in the tileset extent"); self.grid.tile_extent(0, 0, 0) @@ -437,7 +446,7 @@ impl MvtService { maxx: point[0], maxy: point[1], }; - let ext_proj = self.extent_from_wgs84(&ext_wgs84); + let ext_proj = self.extent_from_input_extent(&ext_wgs84, None); debug!("point in grid SRS: {:?}", ext_proj); let tolerance = 0; diff --git a/t-rex-service/src/mvt_service_test.rs b/t-rex-service/src/mvt_service_test.rs index b6c08c08..39d4fad5 100644 --- a/t-rex-service/src/mvt_service_test.rs +++ b/t-rex-service/src/mvt_service_test.rs @@ -294,7 +294,10 @@ fn test_projected_extent() { maxy: 6982997.920389788, }; - assert_eq!(service.extent_from_wgs84(&extent_wgs84), extent_3857); + assert_eq!( + service.extent_from_input_extent(&extent_wgs84, None), + extent_3857 + ); } #[test] @@ -320,6 +323,7 @@ fn test_generate() { None, false, false, + None, ); } diff --git a/tile-grid/src/grid.rs b/tile-grid/src/grid.rs index 89cb66f0..0c418f69 100644 --- a/tile-grid/src/grid.rs +++ b/tile-grid/src/grid.rs @@ -317,7 +317,7 @@ pub fn lonlat_to_merc(lon: f64, lat: f64) -> (f64, f64) { } /// Projected extent -pub fn extent_to_merc(extent: &Extent) -> Extent { +pub fn extent_wgs84_to_merc(extent: &Extent) -> Extent { let (minx, miny) = lonlat_to_merc(extent.minx, extent.miny); let (maxx, maxy) = lonlat_to_merc(extent.maxx, extent.maxy); Extent { diff --git a/tile-grid/src/grid_test.rs b/tile-grid/src/grid_test.rs index 3fd10582..9f629a2a 100644 --- a/tile-grid/src/grid_test.rs +++ b/tile-grid/src/grid_test.rs @@ -3,7 +3,7 @@ // Licensed under the MIT License. See LICENSE file in the project root for full license information. // -use crate::grid::{extent_to_merc, lonlat_to_merc, Extent, ExtentInt, Grid}; +use crate::grid::{extent_wgs84_to_merc, lonlat_to_merc, Extent, ExtentInt, Grid}; #[test] fn test_bbox() { @@ -217,7 +217,7 @@ fn test_projected_extent() { maxx: 556597.4539663679, maxy: 6982997.920389788, }; - let projected = extent_to_merc(&extent_wgs84); + let projected = extent_wgs84_to_merc(&extent_wgs84); assert_eq!(projected, extent_3857); assert_eq!( lonlat_to_merc(extent_wgs84.minx, extent_wgs84.miny), diff --git a/tile-grid/src/lib.rs b/tile-grid/src/lib.rs index 6a6cced1..e76681de 100644 --- a/tile-grid/src/lib.rs +++ b/tile-grid/src/lib.rs @@ -70,5 +70,5 @@ mod grid_iterator; #[cfg(test)] mod grid_test; -pub use grid::{extent_to_merc, Extent, ExtentInt, Grid, Origin, Unit}; +pub use grid::{extent_wgs84_to_merc, Extent, ExtentInt, Grid, Origin, Unit}; pub use grid_iterator::GridIterator;