use std::num::NonZeroUsize;
use std::ptr;
use std::ptr::NonNull;
use gdal_sys::{
GDALDEMProcessingOptions, GDALDEMProcessingOptionsFree, GDALDEMProcessingOptionsNew,
};
use crate::cpl::CslStringList;
use crate::errors;
use crate::utils::_last_null_pointer_err;
pub struct GdalDEMProcessingOptions(NonNull<GDALDEMProcessingOptions>);
impl GdalDEMProcessingOptions {
pub fn new(opts: &CslStringList) -> errors::Result<Self> {
let popts = unsafe { GDALDEMProcessingOptionsNew(opts.as_ptr(), ptr::null_mut()) };
match NonNull::new(popts) {
Some(popts) => Ok(Self(popts)),
None => Err(_last_null_pointer_err("GDALDEMProcessingOptionsNew")),
}
}
pub fn as_ptr(&self) -> *const GDALDEMProcessingOptions {
self.0.as_ptr()
}
}
impl Drop for GdalDEMProcessingOptions {
fn drop(&mut self) {
unsafe { GDALDEMProcessingOptionsFree(self.0.as_ptr()) };
}
}
#[derive(Debug, Clone, Copy)]
pub enum DemAlg {
Aspect,
ColorRelief,
Hillshade,
Roughness,
Slope,
Tpi,
Tri,
}
impl DemAlg {
pub(super) fn to_gdal_option(self) -> &'static str {
match self {
DemAlg::Aspect => "aspect",
DemAlg::ColorRelief => "color-relief",
DemAlg::Hillshade => "hillshade",
DemAlg::Roughness => "roughness",
DemAlg::Slope => "slope",
DemAlg::Tpi => "TPI",
DemAlg::Tri => "TRI",
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum DemSlopeAlg {
Horn,
ZevenbergenThorne,
}
impl DemSlopeAlg {
pub(super) fn to_gdal_option(self) -> &'static str {
match self {
DemSlopeAlg::Horn => "Horn",
DemSlopeAlg::ZevenbergenThorne => "ZevenbergenThorne",
}
}
}
#[derive(Debug, Clone, Default)]
pub(crate) struct CommonOptions {
pub(crate) input_band: Option<NonZeroUsize>,
pub(crate) compute_edges: Option<bool>,
pub(crate) output_format: Option<String>,
pub(crate) additional_options: CslStringList,
}
macro_rules! common_dem_options {
() => {
pub fn with_input_band(&mut self, band: NonZeroUsize) -> &mut Self {
self.common_options.input_band = Some(band);
self
}
pub fn with_output_format(&mut self, format: &str) -> &mut Self {
self.common_options.output_format = Some(format.to_owned());
self
}
pub fn with_compute_edges(&mut self, state: bool) -> &mut Self {
self.common_options.compute_edges = Some(state);
self
}
pub fn with_additional_options(&mut self, extra_options: CslStringList) -> &mut Self {
self.common_options
.additional_options
.extend(&extra_options);
self
}
fn store_common_options_to(&self, opts: &mut CslStringList) -> errors::Result<()> {
if matches!(self.common_options.compute_edges, Some(true)) {
opts.add_string("-compute_edges")?;
}
if let Some(band) = self.common_options.input_band {
opts.add_string("-b")?;
opts.add_string(&band.to_string())?;
}
if let Some(of) = &self.common_options.output_format {
opts.add_string("-of")?;
opts.add_string(of)?;
}
if !self.common_options.additional_options.is_empty() {
opts.extend(&self.common_options.additional_options);
}
Ok(())
}
};
}
pub(crate) use common_dem_options;