Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make value type generic and independent from coordinate type #14

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,19 @@ license = "MIT OR Apache-2.0"

[dependencies]
geojson = { version = ">=0.16, <=0.24", optional = true }
geo-types= { version = "0.7" }
geo-types = { version = "0.7" }
lazy_static = "1.0"
serde_json = { version = "^1.0", optional = true }
serde = { version = "1.0", optional = true }
rustc-hash = "1.0"
slab = "0.4"
num-traits = "0.2"

[dev-dependencies]
serde_json = "^1.0"

[features]
geojson = ["dep:geojson", "dep:serde_json"]
geojson = ["dep:geojson", "dep:serde_json", "dep:serde"]
f32 = []

[package.metadata.docs.rs]
Expand Down
3 changes: 1 addition & 2 deletions benches/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
extern crate contour;
extern crate test;

use contour::contour_rings;
use contour::ContourBuilder;
use contour::{contour_rings, ContourBuilder};
use test::{black_box, Bencher};

#[rustfmt::skip]
Expand Down
12 changes: 8 additions & 4 deletions examples/ex.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use contour::{ContourBuilder, Float};
use geojson::{FeatureCollection, GeoJson};
use std::fs::File;
use std::io::{BufWriter, Write};
use std::{
fs::File,
io::{BufWriter, Write},
};

fn main() {
let pot_pop_fr = include_str!("../tests/fixtures/pot_pop_fr.json");
Expand Down Expand Up @@ -46,7 +48,8 @@ fn main() {
let features = contours
.iter()
.map(|contour| contour.to_geojson())
.collect::<Vec<geojson::Feature>>();
.collect::<Result<Vec<geojson::Feature>, _>>()
.unwrap();

let geojson_str = GeoJson::from(FeatureCollection {
bbox: None,
Expand Down Expand Up @@ -91,7 +94,8 @@ fn main() {
let features = contours
.iter()
.map(|contour| contour.to_geojson())
.collect::<Vec<geojson::Feature>>();
.collect::<Result<Vec<geojson::Feature>, _>>()
.unwrap();

let geojson_str = GeoJson::from(FeatureCollection {
bbox: None,
Expand Down
32 changes: 17 additions & 15 deletions src/band.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,38 @@
use crate::Float;
use crate::{Float, GridValue};
use geo_types::MultiPolygon;

/// An isoband has the geometry and min / max values of a contour ring, built by [`ContourBuilder`].
#[derive(Debug, Clone)]
pub struct Band {
pub struct Band<V: GridValue> {
pub(crate) geometry: MultiPolygon<Float>,
pub(crate) min_v: Float,
pub(crate) max_v: Float,
pub(crate) min_v: V,
pub(crate) max_v: V,
}

impl Band {
impl<V: GridValue> Band<V> {
/// Borrow the [`MultiPolygon`](geo_types::MultiPolygon) geometry of this contour.
pub fn geometry(&self) -> &MultiPolygon<Float> {
&self.geometry
}

/// Get the owned polygons and thresholds (min and max) of this band.
pub fn into_inner(self) -> (MultiPolygon<Float>, Float, Float) {
pub fn into_inner(self) -> (MultiPolygon<Float>, V, V) {
(self.geometry, self.min_v, self.max_v)
}

/// Get the minimum value used to construct this band.
pub fn min_v(&self) -> Float {
pub fn min_v(&self) -> V {
self.min_v
}

/// Get the maximum value used to construct this band.
pub fn max_v(&self) -> Float {
pub fn max_v(&self) -> V {
self.max_v
}
}

#[cfg(feature = "geojson")]
#[cfg(feature = "geojson")]
impl<V: GridValue + serde::Serialize> Band<V> {
/// Convert the band to a struct from the `geojson` crate.
///
/// To get a string representation, call to_geojson().to_string().
Expand All @@ -53,21 +55,21 @@ impl Band {
/// # 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.
/// ], &[0.5, 1.5, 2.5]).unwrap();
///
/// let geojson_string = contours[0].to_geojson().to_string();
/// let geojson_string = contours[0].to_geojson().unwrap().to_string();
///
/// assert_eq!(&geojson_string[0..27], r#"{"geometry":{"coordinates":"#);
/// ```
pub fn to_geojson(&self) -> geojson::Feature {
pub fn to_geojson(&self) -> crate::Result<geojson::Feature> {
let mut properties = geojson::JsonObject::with_capacity(2);
properties.insert("min_v".to_string(), self.min_v.into());
properties.insert("max_v".to_string(), self.max_v.into());
properties.insert("min_v".to_string(), serde_json::to_value(self.min_v)?);
properties.insert("max_v".to_string(), serde_json::to_value(self.max_v)?);

geojson::Feature {
Ok(geojson::Feature {
bbox: None,
geometry: Some(geojson::Geometry::from(self.geometry())),
id: None,
properties: Some(properties),
foreign_members: None,
}
})
}
}
29 changes: 17 additions & 12 deletions src/contour.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
use crate::Float;
use crate::{Float, GridValue};
use geo_types::MultiPolygon;

/// A contour has the geometry and threshold of a contour ring, built by [`ContourBuilder`].
#[derive(Debug, Clone)]
pub struct Contour {
pub struct Contour<V: GridValue> {
pub(crate) geometry: MultiPolygon<Float>,
pub(crate) threshold: Float,
pub(crate) threshold: V,
}

impl Contour {
impl<V: GridValue> Contour<V> {
/// Borrow the [`MultiPolygon`](geo_types::MultiPolygon) geometry of this contour.
pub fn geometry(&self) -> &MultiPolygon<Float> {
&self.geometry
}

/// Get the owned polygons and threshold of this contour.
pub fn into_inner(self) -> (MultiPolygon<Float>, Float) {
pub fn into_inner(self) -> (MultiPolygon<Float>, V) {
(self.geometry, self.threshold)
}

/// Get the threshold used to construct this contour.
pub fn threshold(&self) -> Float {
pub fn threshold(&self) -> V {
self.threshold
}
}

#[cfg(feature = "geojson")]
#[cfg(feature = "geojson")]
impl<V: GridValue + serde::Serialize> Contour<V> {
/// Convert the contour to a struct from the `geojson` crate.
///
/// To get a string representation, call to_geojson().to_string().
Expand All @@ -47,20 +49,23 @@ impl Contour {
/// # 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.
/// ], &[0.5]).unwrap();
///
/// let geojson_string = contours[0].to_geojson().to_string();
/// let geojson_string = contours[0].to_geojson().unwrap().to_string();
///
/// assert_eq!(&geojson_string[0..27], r#"{"geometry":{"coordinates":"#);
/// ```
pub fn to_geojson(&self) -> geojson::Feature {
pub fn to_geojson(&self) -> crate::Result<geojson::Feature> {
let mut properties = geojson::JsonObject::with_capacity(1);
properties.insert("threshold".to_string(), self.threshold.into());
properties.insert(
"threshold".to_string(),
serde_json::to_value(self.threshold)?,
);

geojson::Feature {
Ok(geojson::Feature {
bbox: None,
geometry: Some(geojson::Geometry::from(self.geometry())),
id: None,
properties: Some(properties),
foreign_members: None,
}
})
}
}
Loading
Loading