Skip to content

Commit 7b0b306

Browse files
committed
Make ContourBuilder generic over the raster data type
Signed-off-by: netthier <[email protected]>
1 parent f8d08df commit 7b0b306

File tree

10 files changed

+164
-124
lines changed

10 files changed

+164
-124
lines changed

Cargo.toml

+4-2
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,19 @@ license = "MIT OR Apache-2.0"
1414

1515
[dependencies]
1616
geojson = { version = ">=0.16, <=0.24", optional = true }
17-
geo-types= { version = "0.7" }
17+
geo-types = { version = "0.7" }
1818
lazy_static = "1.0"
1919
serde_json = { version = "^1.0", optional = true }
20+
serde = { version = "1.0", optional = true }
2021
rustc-hash = "1.0"
2122
slab = "0.4"
23+
num-traits = "0.2"
2224

2325
[dev-dependencies]
2426
serde_json = "^1.0"
2527

2628
[features]
27-
geojson = ["dep:geojson", "dep:serde_json"]
29+
geojson = ["dep:geojson", "dep:serde_json", "dep:serde"]
2830
f32 = []
2931

3032
[package.metadata.docs.rs]

benches/bench.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
extern crate contour;
33
extern crate test;
44

5-
use contour::contour_rings;
6-
use contour::ContourBuilder;
5+
use contour::{contour_rings, ContourBuilder};
76
use test::{black_box, Bencher};
87

98
#[rustfmt::skip]

examples/ex.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
use contour::{ContourBuilder, Float};
22
use geojson::{FeatureCollection, GeoJson};
3-
use std::fs::File;
4-
use std::io::{BufWriter, Write};
3+
use std::{
4+
fs::File,
5+
io::{BufWriter, Write},
6+
};
57

68
fn main() {
79
let pot_pop_fr = include_str!("../tests/fixtures/pot_pop_fr.json");
@@ -46,7 +48,8 @@ fn main() {
4648
let features = contours
4749
.iter()
4850
.map(|contour| contour.to_geojson())
49-
.collect::<Vec<geojson::Feature>>();
51+
.collect::<Result<Vec<geojson::Feature>, _>>()
52+
.unwrap();
5053

5154
let geojson_str = GeoJson::from(FeatureCollection {
5255
bbox: None,
@@ -91,7 +94,8 @@ fn main() {
9194
let features = contours
9295
.iter()
9396
.map(|contour| contour.to_geojson())
94-
.collect::<Vec<geojson::Feature>>();
97+
.collect::<Result<Vec<geojson::Feature>, _>>()
98+
.unwrap();
9599

96100
let geojson_str = GeoJson::from(FeatureCollection {
97101
bbox: None,

src/band.rs

+17-15
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,38 @@
1-
use crate::Float;
1+
use crate::{Float, GridValue};
22
use geo_types::MultiPolygon;
33

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

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

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

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

2828
/// Get the maximum value used to construct this band.
29-
pub fn max_v(&self) -> Float {
29+
pub fn max_v(&self) -> V {
3030
self.max_v
3131
}
32+
}
3233

33-
#[cfg(feature = "geojson")]
34+
#[cfg(feature = "geojson")]
35+
impl<V: GridValue + serde::Serialize> Band<V> {
3436
/// Convert the band to a struct from the `geojson` crate.
3537
///
3638
/// To get a string representation, call to_geojson().to_string().
@@ -53,21 +55,21 @@ impl Band {
5355
/// # 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.
5456
/// ], &[0.5, 1.5, 2.5]).unwrap();
5557
///
56-
/// let geojson_string = contours[0].to_geojson().to_string();
58+
/// let geojson_string = contours[0].to_geojson().unwrap().to_string();
5759
///
5860
/// assert_eq!(&geojson_string[0..27], r#"{"geometry":{"coordinates":"#);
5961
/// ```
60-
pub fn to_geojson(&self) -> geojson::Feature {
62+
pub fn to_geojson(&self) -> serde_json::Result<geojson::Feature> {
6163
let mut properties = geojson::JsonObject::with_capacity(2);
62-
properties.insert("min_v".to_string(), self.min_v.into());
63-
properties.insert("max_v".to_string(), self.max_v.into());
64+
properties.insert("min_v".to_string(), serde_json::to_value(self.min_v)?);
65+
properties.insert("max_v".to_string(), serde_json::to_value(self.max_v)?);
6466

65-
geojson::Feature {
67+
Ok(geojson::Feature {
6668
bbox: None,
6769
geometry: Some(geojson::Geometry::from(self.geometry())),
6870
id: None,
6971
properties: Some(properties),
7072
foreign_members: None,
71-
}
73+
})
7274
}
7375
}

src/contour.rs

+17-12
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,32 @@
1-
use crate::Float;
1+
use crate::{Float, GridValue};
22
use geo_types::MultiPolygon;
33

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

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

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

2222
/// Get the threshold used to construct this contour.
23-
pub fn threshold(&self) -> Float {
23+
pub fn threshold(&self) -> V {
2424
self.threshold
2525
}
26+
}
2627

27-
#[cfg(feature = "geojson")]
28+
#[cfg(feature = "geojson")]
29+
impl<V: GridValue + serde::Serialize> Contour<V> {
2830
/// Convert the contour to a struct from the `geojson` crate.
2931
///
3032
/// To get a string representation, call to_geojson().to_string().
@@ -47,20 +49,23 @@ impl Contour {
4749
/// # 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.
4850
/// ], &[0.5]).unwrap();
4951
///
50-
/// let geojson_string = contours[0].to_geojson().to_string();
52+
/// let geojson_string = contours[0].to_geojson().unwrap().to_string();
5153
///
5254
/// assert_eq!(&geojson_string[0..27], r#"{"geometry":{"coordinates":"#);
5355
/// ```
54-
pub fn to_geojson(&self) -> geojson::Feature {
56+
pub fn to_geojson(&self) -> serde_json::Result<geojson::Feature> {
5557
let mut properties = geojson::JsonObject::with_capacity(1);
56-
properties.insert("threshold".to_string(), self.threshold.into());
58+
properties.insert(
59+
"threshold".to_string(),
60+
serde_json::to_value(self.threshold)?,
61+
);
5762

58-
geojson::Feature {
63+
Ok(geojson::Feature {
5964
bbox: None,
6065
geometry: Some(geojson::Geometry::from(self.geometry())),
6166
id: None,
6267
properties: Some(properties),
6368
foreign_members: None,
64-
}
69+
})
6570
}
6671
}

0 commit comments

Comments
 (0)