From c68ab7a40be010d0de0d2ad85a1f73da15cb2f85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Rocha?= Date: Thu, 14 Mar 2019 22:06:02 +0100 Subject: [PATCH] Ndarray placed inside a feature. --- Cargo.toml | 3 ++- src/errors.rs | 2 ++ src/lib.rs | 2 ++ src/raster/dataset.rs | 36 ++++++++++++++++++++++++++++++------ src/raster/rasterband.rs | 6 +++++- src/raster/tests.rs | 33 ++++++++++++++++++++++++++++++++- 6 files changed, 73 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 67d46d40..4761344c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ documentation = "https://georust.github.io/gdal/" [features] bindgen = ["gdal-sys/bindgen"] +array = ["ndarray"] [dependencies] failure = "0.1" @@ -21,7 +22,7 @@ geo-types = "0.3" # gdal-sys = { path = "gdal-sys", version = "0.2"} gdal-sys = "0.2" num-traits = "0.2" -ndarray = "0.12.1" +ndarray = {version = "0.12.1", optional = true } [workspace] members = ["gdal-sys"] diff --git a/src/errors.rs b/src/errors.rs index 3c0bc4a0..078bc7cf 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -18,6 +18,7 @@ pub enum ErrorKind { FfiNulError(#[cause] std::ffi::NulError), #[fail(display = "StrUtf8Error")] StrUtf8Error(#[cause] std::str::Utf8Error), + #[cfg(feature = "ndarray")] #[fail(display = "NdarrayShapeError")] NdarrayShapeError(#[cause] ndarray::ShapeError), #[fail(display = "CPL error class: '{:?}', error number: '{}', error msg: '{}'", class, number, msg)] @@ -112,6 +113,7 @@ impl From for Error { } } +#[cfg(feature = "ndarray")] impl From for Error { fn from(err: ndarray::ShapeError) -> Error { Error { inner: Context::new(ErrorKind::NdarrayShapeError(err)) } diff --git a/src/lib.rs b/src/lib.rs index c1b9cf6d..1a76c2c2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,6 +27,8 @@ extern crate gdal_sys; extern crate geo_types; extern crate libc; extern crate num_traits; + +#[cfg(feature = "ndarray")] extern crate ndarray; pub use version::version_info; diff --git a/src/raster/dataset.rs b/src/raster/dataset.rs index 68be1582..c67d3aa5 100644 --- a/src/raster/dataset.rs +++ b/src/raster/dataset.rs @@ -9,6 +9,8 @@ use raster::types::GdalType; use gdal_major_object::MajorObject; use metadata::Metadata; use gdal_sys::{self, CPLErr, GDALAccess, GDALDatasetH, GDALDataType, GDALMajorObjectH}; + +#[cfg(feature = "ndarray")] use ndarray::Array2; use errors::*; @@ -101,10 +103,23 @@ impl Dataset { Ok(()) } - pub fn set_geo_transform(&self, tr: &GeoTransform) -> Result<()> { - assert_eq!(tr.len(), 6); + /// Affine transformation called geotransformation. + /// + /// This is like a linear transformation preserves points, straight lines and planes. + /// Also, sets of parallel lines remain parallel after an affine transformation. + /// # Arguments + /// * transformation - coeficients of transformations + /// + /// x-coordinate of the top-left corner pixel (x-offset) + /// width of a pixel (x-resolution) + /// row rotation (typically zero) + /// y-coordinate of the top-left corner pixel + /// column rotation (typically zero) + /// height of a pixel (y-resolution, typically negative) + pub fn set_geo_transform(&self, transformation: &GeoTransform) -> Result<()> { + assert_eq!(transformation.len(), 6); let rv = unsafe { - gdal_sys::GDALSetGeoTransform(self.c_dataset, tr.as_ptr() as *mut f64) + gdal_sys::GDALSetGeoTransform(self.c_dataset, transformation.as_ptr() as *mut f64) }; if rv != CPLErr::CE_None { Err(_last_cpl_err(rv))?; @@ -112,12 +127,20 @@ impl Dataset { Ok(()) } + /// Get affine transformation coefficients. + /// + /// x-coordinate of the top-left corner pixel (x-offset) + /// width of a pixel (x-resolution) + /// row rotation (typically zero) + /// y-coordinate of the top-left corner pixel + /// column rotation (typically zero) + /// height of a pixel (y-resolution, typically negative) pub fn geo_transform(&self) -> Result { - let mut tr = GeoTransform::default(); + let mut transformation = GeoTransform::default(); let rv = unsafe { gdal_sys::GDALGetGeoTransform( self.c_dataset, - tr.as_mut_ptr() + transformation.as_mut_ptr() ) }; @@ -125,7 +148,7 @@ impl Dataset { if rv != CPLErr::CE_None { Err(_last_cpl_err(rv))?; } - Ok(tr) + Ok(transformation) } pub fn create_copy( @@ -202,6 +225,7 @@ impl Dataset { self.rasterband(band_index)?.read_as(window, window_size, size) } + #[cfg(feature = "ndarray")] /// Read a 'Array2' from a 'Dataset'. T implements 'GdalType'. /// # Arguments /// * band_index - the band_index diff --git a/src/raster/rasterband.rs b/src/raster/rasterband.rs index 0553d917..092bb4a6 100644 --- a/src/raster/rasterband.rs +++ b/src/raster/rasterband.rs @@ -4,9 +4,11 @@ use raster::types::GdalType; use gdal_major_object::MajorObject; use metadata::Metadata; use gdal_sys::{self, CPLErr, GDALDataType, GDALMajorObjectH, GDALRasterBandH, GDALRWFlag}; -use ndarray::{Array2}; use utils::_last_cpl_err; +#[cfg(feature = "ndarray")] +use ndarray::{Array2}; + use errors::*; pub struct RasterBand<'a> { @@ -83,6 +85,7 @@ impl <'a> RasterBand<'a> { Ok(Buffer{size, data}) } + #[cfg(feature = "ndarray")] /// Read a 'Array2' from a 'Dataset'. T implements 'GdalType'. /// # Arguments /// * window - the window position from top left @@ -143,6 +146,7 @@ impl <'a> RasterBand<'a> { ) } + #[cfg(feature = "ndarray")] /// Read a 'Array2' from a 'Dataset' block. T implements 'GdalType' /// # Arguments /// * block_index - the block index diff --git a/src/raster/tests.rs b/src/raster/tests.rs index d8bef946..576971d5 100644 --- a/src/raster/tests.rs +++ b/src/raster/tests.rs @@ -1,7 +1,9 @@ use std::path::Path; -use super::{ByteBuffer, Driver, Dataset}; +use super::{ByteBuffer, Driver, Dataset, warp}; use gdal_sys::GDALDataType; use metadata::Metadata; + +#[cfg(feature = "ndarray")] use ndarray::arr2; @@ -228,6 +230,7 @@ fn test_read_raster_as() { } #[test] +#[cfg(feature = "ndarray")] fn test_read_raster_as_array() { let band_index = 1; let (left, top) = (19, 5); @@ -259,6 +262,7 @@ fn test_read_full_raster_as() { } #[test] +#[cfg(feature = "ndarray")] fn test_read_block_as_array() { let band_index = 1; let block_index = (0, 0); @@ -269,6 +273,7 @@ fn test_read_block_as_array() { } #[test] +#[cfg(feature = "ndarray")] fn test_read_block_dimension() { let band_index = 1; let block = (0, 0); @@ -280,6 +285,7 @@ fn test_read_block_dimension() { } #[test] +#[cfg(feature = "ndarray")] fn test_read_block_last_dimension() { let band_index = 1; let block = (0, 49); @@ -291,6 +297,7 @@ fn test_read_block_last_dimension() { } #[test] +#[cfg(feature = "ndarray")] fn test_read_block_data() { let band_index = 1; let block = (0, 0); @@ -358,3 +365,27 @@ fn test_get_offset() { let offset = rasterband.offset(); assert_eq!(offset, Some(0.0)); } + +#[test] +fn test_reproject() { + let driver = Driver::get("MEM").unwrap(); + let size_x = 100; + let size_y = 50; + let bands = 3; + let filename = ""; // Don't need concrete filename because is a file in memory + let destiny = driver.create(filename, size_x, size_y, bands).unwrap(); + let source = Dataset::open(fixture!("tinybluemarble.tif")).unwrap(); + + println!("{:?}", source.geo_transform().expect("Geotransform vector.")); + + // c = x-coordinate of the upper-left corner of the upper-left pixel + // a = width of a pixel + // b = row rotation (typically zero) + // f = y-coordinate of the of the upper-left corner of the upper-left pixel + // d = column rotation (typically zero) + // e = height of a pixel (typically negative) + let transform = [0.0, 10.0, 0.0, 0.0, 0.0, -10.0]; + assert!(destiny.set_geo_transform(&transform).is_ok()); + assert!(warp::reproject(&source, &destiny).is_ok()); + println!("{:?}", destiny.geo_transform().expect("Geotransform vector.")); +}