diff --git a/src/dataset.rs b/src/dataset.rs index 873fe85c..08afc3d6 100644 --- a/src/dataset.rs +++ b/src/dataset.rs @@ -16,9 +16,23 @@ use std::convert::TryInto; use bitflags::bitflags; +/// A 2-D affine transform mapping pixel coordiates to world +/// coordinates. See [GDALGetGeoTransform] for more details. +/// +/// [GDALGetGeoTransform]: https://gdal.org/api/gdaldataset_cpp.html#classGDALDataset_1a5101119705f5fa2bc1344ab26f66fd1d pub type GeoTransform = [c_double; 6]; static START: Once = Once::new(); +/// Wrapper around a [`GDALDataset`][GDALDataset] object. +/// +/// Represents both a [vector dataset][vector-data-model] +/// containing a collection of layers; and a [raster +/// dataset][raster-data-model] containing a collection of +/// rasterbands. +/// +/// [vector-data-model]: https://gdal.org/user/vector_data_model.html +/// [raster-data-model]: https://gdal.org/user/raster_data_model.html +/// [GDALDataset]: https://gdal.org/api/gdaldataset_cpp.html#_CPPv411GDALDataset #[derive(Debug)] pub struct Dataset { c_dataset: GDALDatasetH, @@ -32,44 +46,54 @@ pub fn _register_drivers() { } } -// GDal extended open flags, skipped by bindgen -// -// Note that the `GDAL_OF_SHARED` option is removed from the set -// of allowed option because it subverts the [`Send`] implementation -// that allow passing the dataset the another thread. -// See https://github.com/georust/gdal/issues/154. +// These are skipped by bindgen and manually updated. #[cfg(major_ge_2)] bitflags! { + /// GDal extended open flags used by [`Dataset::open_ex`]. + /// + /// Used in the `nOpenFlags` argument to [`GDALOpenEx`]. + /// + /// Note that the `GDAL_OF_SHARED` option is removed + /// from the set of allowed option because it subverts + /// the [`Send`] implementation that allow passing the + /// dataset the another thread. See + /// https://github.com/georust/gdal/issues/154. + /// + /// [`GDALOpenEx`]: https://gdal.org/doxygen/gdal_8h.html#a9cb8585d0b3c16726b08e25bcc94274a pub struct GdalOpenFlags: c_uint { + /// Open in read-only mode (default). const GDAL_OF_READONLY = 0x00; - // Open in update mode. + /// Open in update mode. const GDAL_OF_UPDATE = 0x01; - // Allow raster and vector drivers to be used. + /// Allow raster and vector drivers to be used. const GDAL_OF_ALL = 0x00; - // Allow raster drivers to be used. + /// Allow raster drivers to be used. const GDAL_OF_RASTER = 0x02; - // Allow vector drivers to be used. + /// Allow vector drivers to be used. const GDAL_OF_VECTOR = 0x04; - // Allow gnm drivers to be used. - #[cfg(all(major_ge_2,minor_ge_1))] + /// Allow gnm drivers to be used. + #[cfg(any( all(major_ge_2,minor_ge_1), major_ge_3 ))] const GDAL_OF_GNM = 0x08; - // Allow multidimensional raster drivers to be used. + /// Allow multidimensional raster drivers to be used. #[cfg(all(major_ge_3,minor_ge_1))] const GDAL_OF_MULTIDIM_RASTER = 0x10; - // Emit error message in case of failed open. + /// Emit error message in case of failed open. const GDAL_OF_VERBOSE_ERROR = 0x40; - // Open as internal dataset. Such dataset isn't registered in the global list - // of opened dataset. Cannot be used with GDAL_OF_SHARED. + /// Open as internal dataset. Such dataset isn't + /// registered in the global list of opened dataset. + /// Cannot be used with GDAL_OF_SHARED. const GDAL_OF_INTERNAL = 0x80; - // Let GDAL decide if a array-based or hashset-based storage strategy for - // cached blocks must be used. - // GDAL_OF_DEFAULT_BLOCK_ACCESS, GDAL_OF_ARRAY_BLOCK_ACCESS and - // GDAL_OF_HASHSET_BLOCK_ACCESS are mutually exclusive. - #[cfg(all(major_ge_2,minor_ge_1))] + + /// Default strategy for cached blocks. + #[cfg(any( all(major_ge_2,minor_ge_1), major_ge_3 ))] const GDAL_OF_DEFAULT_BLOCK_ACCESS = 0; - #[cfg(all(major_ge_2,minor_ge_1))] + + /// Array based strategy for cached blocks. + #[cfg(any( all(major_ge_2,minor_ge_1), major_ge_3 ))] const GDAL_OF_ARRAY_BLOCK_ACCESS = 0x100; - #[cfg(all(major_ge_2,minor_ge_1))] + + /// Hashset based strategy for cached blocks. + #[cfg(any( all(major_ge_2,minor_ge_1), major_ge_3 ))] const GDAL_OF_HASHSET_BLOCK_ACCESS = 0x200; } } @@ -115,10 +139,14 @@ impl Dataset { self.c_dataset } + /// Open a dataset at the given `path` with default + /// options. pub fn open(path: &Path) -> Result { Self::open_ex(path, DatasetOptions::default()) } + /// Open a dataset with extended options. See + /// [GDALOpenEx]. pub fn open_ex(path: &Path, options: DatasetOptions) -> Result { _register_drivers(); let filename = path.to_string_lossy(); @@ -217,11 +245,13 @@ impl Dataset { Dataset { c_dataset } } + /// Fetch the projection definition string for this dataset. pub fn projection(&self) -> String { let rv = unsafe { gdal_sys::GDALGetProjectionRef(self.c_dataset) }; _string(rv) } + /// Set the projection reference string for this dataset. pub fn set_projection(&self, projection: &str) -> Result<()> { let c_projection = CString::new(projection)?; unsafe { gdal_sys::GDALSetProjection(self.c_dataset, c_projection.as_ptr()) }; @@ -229,11 +259,13 @@ impl Dataset { } #[cfg(major_ge_3)] + /// Get the spatial reference system for this dataset. pub fn spatial_ref(&self) -> Result { unsafe { SpatialRef::from_c_obj(gdal_sys::GDALGetSpatialRef(self.c_dataset)) } } #[cfg(major_ge_3)] + /// Set the spatial reference system for this dataset. pub fn set_spatial_ref(&self, spatial_ref: &SpatialRef) -> Result<()> { let rv = unsafe { gdal_sys::GDALSetSpatialRef(self.c_dataset, spatial_ref.to_c_hsrs()) }; if rv != CPLErr::CE_None { @@ -261,6 +293,7 @@ impl Dataset { Ok(unsafe { Dataset::from_c_dataset(c_dataset) }) } + /// Fetch the driver to which this dataset relates. pub fn driver(&self) -> Driver { unsafe { let c_driver = gdal_sys::GDALGetDatasetDriver(self.c_dataset); @@ -268,6 +301,10 @@ impl Dataset { } } + /// Fetch a band object for a dataset. + /// + /// Applies to raster datasets, and fetches the + /// rasterband at the given _1-based_ index. pub fn rasterband(&self, band_index: isize) -> Result { unsafe { let c_band = gdal_sys::GDALGetRasterBand(self.c_dataset, band_index as c_int); @@ -282,10 +319,15 @@ impl Dataset { unsafe { Layer::from_c_layer(self, c_layer) } } + /// Get the number of layers in this dataset. pub fn layer_count(&self) -> isize { (unsafe { gdal_sys::OGR_DS_GetLayerCount(self.c_dataset) }) as isize } + /// Fetch a layer by index. + /// + /// Applies to vector datasets, and fetches by the given + /// _0-based_ index. pub fn layer(&mut self, idx: isize) -> Result { let c_layer = unsafe { gdal_sys::OGR_DS_GetLayer(self.c_dataset, idx as c_int) }; if c_layer.is_null() { @@ -294,6 +336,7 @@ impl Dataset { Ok(self.child_layer(c_layer)) } + /// Fetch a layer by name. pub fn layer_by_name(&mut self, name: &str) -> Result { let c_name = CString::new(name)?; let c_layer = unsafe { gdal_sys::OGR_DS_GetLayerByName(self.c_dataset(), c_name.as_ptr()) }; @@ -303,14 +346,17 @@ impl Dataset { Ok(self.child_layer(c_layer)) } + /// Returns an iterator over the layers of the dataset. pub fn layers(&self) -> LayerIterator { LayerIterator::with_dataset(self) } + /// Fetch the number of raster bands on this dataset. pub fn raster_count(&self) -> isize { (unsafe { gdal_sys::GDALGetRasterCount(self.c_dataset) }) as isize } + /// Returns the raster dimensions: (width, height). pub fn raster_size(&self) -> (usize, usize) { let size_x = unsafe { gdal_sys::GDALGetRasterXSize(self.c_dataset) } as usize; let size_y = unsafe { gdal_sys::GDALGetRasterYSize(self.c_dataset) } as usize; diff --git a/src/raster/rasterband.rs b/src/raster/rasterband.rs index 1f18d395..3f1a8435 100644 --- a/src/raster/rasterband.rs +++ b/src/raster/rasterband.rs @@ -202,7 +202,7 @@ impl<'a> RasterBand<'a> { Array2::from_shape_vec((size.1, size.0), data).map_err(Into::into) } - // Write a 'Buffer' into a 'Dataset'. + /// Write a 'Buffer' into a 'Dataset'. /// # Arguments /// * band_index - the band_index /// * window - the window position from top left @@ -236,10 +236,12 @@ impl<'a> RasterBand<'a> { Ok(()) } + /// Returns the pixel datatype of this band. pub fn band_type(&self) -> GDALDataType::Type { unsafe { gdal_sys::GDALGetRasterDataType(self.c_rasterband) } } + /// Returns the no data value of this band. pub fn no_data_value(&self) -> Option { let mut pb_success = 1; let no_data = @@ -250,6 +252,7 @@ impl<'a> RasterBand<'a> { None } + /// Set the no data value of this band. pub fn set_no_data_value(&self, no_data: f64) -> Result<()> { let rv = unsafe { gdal_sys::GDALSetRasterNoDataValue(self.c_rasterband, no_data) }; if rv != CPLErr::CE_None { @@ -258,6 +261,7 @@ impl<'a> RasterBand<'a> { Ok(()) } + /// Returns the scale of this band if set. pub fn scale(&self) -> Option { let mut pb_success = 1; let scale = unsafe { gdal_sys::GDALGetRasterScale(self.c_rasterband, &mut pb_success) }; @@ -267,6 +271,7 @@ impl<'a> RasterBand<'a> { None } + /// Returns the offset of this band if set. pub fn offset(&self) -> Option { let mut pb_success = 1; let offset = unsafe { gdal_sys::GDALGetRasterOffset(self.c_rasterband, &mut pb_success) };