h3ron_graph/algorithm/
covered_area.rs

1use std::borrow::Borrow;
2
3use geo::algorithm::simplify::Simplify;
4use geo_types::{MultiPolygon, Polygon};
5
6use h3ron::collections::H3CellSet;
7use h3ron::iter::change_resolution;
8use h3ron::{H3Cell, ToLinkedPolygons};
9
10use crate::error::Error;
11
12/// calculates a [`MultiPolygon`] of the area covered by a graph
13pub trait CoveredArea {
14    type Error;
15
16    /// calculates a [`MultiPolygon`] of the area covered by a graph
17    ///
18    /// As the resulting geometry will be quite complex, it is recommended
19    /// to reduce the h3 resolution using `reduce_resolution_by`. A value of 3
20    /// will make the calculation based on resolution 7 for a graph of resolution 10.
21    /// Reducing the resolution leads to a overestimation of the area.
22    ///
23    /// A slight simplification will be applied to the output geometry and
24    /// eventual holes will be removed.
25    fn covered_area(&self, reduce_resolution_by: u8) -> Result<MultiPolygon<f64>, Self::Error>;
26}
27
28/// calculates a [`MultiPolygon`] of the area covered by a [`H3Cell`] iterator.
29pub fn cells_covered_area<I>(
30    cell_iter: I,
31    cell_iter_resolution: u8,
32    reduce_resolution_by: u8,
33) -> Result<MultiPolygon<f64>, Error>
34where
35    I: IntoIterator,
36    I::Item: Borrow<H3Cell>,
37{
38    let t_res = cell_iter_resolution.saturating_sub(reduce_resolution_by);
39    let mut cells =
40        change_resolution(cell_iter.into_iter(), t_res).collect::<Result<H3CellSet, _>>()?;
41    let cell_vec: Vec<_> = cells.drain().collect();
42    let mp = MultiPolygon::from(
43        cell_vec
44            // remove the number of vertices by smoothing
45            .to_linked_polygons(true)?
46            .drain(..)
47            // reduce the number of vertices again and discard all holes
48            .map(|p| Polygon::new(p.exterior().simplify(&0.000001), vec![]))
49            .collect::<Vec<_>>(),
50    );
51    Ok(mp)
52}