Skip to content

Commit

Permalink
Merge pull request #158 from rmanoka/fix/docs-and-open-flags-cfg
Browse files Browse the repository at this point in the history
Add documentation
  • Loading branch information
jdroenner authored Feb 4, 2021
2 parents 7e4fd8a + 9f07fcc commit 29a9585
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 24 deletions.
92 changes: 69 additions & 23 deletions src/dataset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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;
}
}
Expand Down Expand Up @@ -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<Dataset> {
Self::open_ex(path, DatasetOptions::default())
}

/// Open a dataset with extended options. See
/// [GDALOpenEx].
pub fn open_ex(path: &Path, options: DatasetOptions) -> Result<Dataset> {
_register_drivers();
let filename = path.to_string_lossy();
Expand Down Expand Up @@ -217,23 +245,27 @@ 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()) };
Ok(())
}

#[cfg(major_ge_3)]
/// Get the spatial reference system for this dataset.
pub fn spatial_ref(&self) -> Result<SpatialRef> {
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 {
Expand Down Expand Up @@ -261,13 +293,18 @@ 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);
Driver::from_c_driver(c_driver)
}
}

/// 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<RasterBand> {
unsafe {
let c_band = gdal_sys::GDALGetRasterBand(self.c_dataset, band_index as c_int);
Expand All @@ -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<Layer> {
let c_layer = unsafe { gdal_sys::OGR_DS_GetLayer(self.c_dataset, idx as c_int) };
if c_layer.is_null() {
Expand All @@ -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<Layer> {
let c_name = CString::new(name)?;
let c_layer = unsafe { gdal_sys::OGR_DS_GetLayerByName(self.c_dataset(), c_name.as_ptr()) };
Expand All @@ -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;
Expand Down
7 changes: 6 additions & 1 deletion src/raster/rasterband.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ impl<'a> RasterBand<'a> {
Array2::from_shape_vec((size.1, size.0), data).map_err(Into::into)
}

// Write a 'Buffer<T>' into a 'Dataset'.
/// Write a 'Buffer<T>' into a 'Dataset'.
/// # Arguments
/// * band_index - the band_index
/// * window - the window position from top left
Expand Down Expand Up @@ -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<f64> {
let mut pb_success = 1;
let no_data =
Expand All @@ -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 {
Expand All @@ -258,6 +261,7 @@ impl<'a> RasterBand<'a> {
Ok(())
}

/// Returns the scale of this band if set.
pub fn scale(&self) -> Option<f64> {
let mut pb_success = 1;
let scale = unsafe { gdal_sys::GDALGetRasterScale(self.c_rasterband, &mut pb_success) };
Expand All @@ -267,6 +271,7 @@ impl<'a> RasterBand<'a> {
None
}

/// Returns the offset of this band if set.
pub fn offset(&self) -> Option<f64> {
let mut pb_success = 1;
let offset = unsafe { gdal_sys::GDALGetRasterOffset(self.c_rasterband, &mut pb_success) };
Expand Down

0 comments on commit 29a9585

Please sign in to comment.