1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
use super::LineString;
use crate::{
error::InvalidGeometry,
geom::{PolyfillConfig, ToCells},
CellIndex,
};
use std::boxed::Box;
/// A collection of [`geo::LineString`].
///
/// Note that the `ToCells` implementation suffers from the same limitation
/// that [`grid_path_cells`](CellIndex::grid_path_cells), which means that on
/// error `max_cells_count` returns 0 and `to_cells` an empty iterator.
#[derive(Clone, Debug, PartialEq)]
pub struct MultiLineString(Vec<LineString>);
impl MultiLineString {
/// Initialize a collection of lines from lines whose coordinates are in
/// radians.
///
/// # Errors
///
/// [`InvalidGeometry`] if one of the line is invalid (e.g. contains
/// non-finite coordinates).
///
/// # Example
///
/// ```
/// use geo::line_string;
/// use h3o::geom::MultiLineString;
///
/// let line_string: geo::LineString<f64> = line_string![
/// (x: 1.996408325715777, y: 0.534292570530397),
/// (x: 2.208424012168513, y: 0.7995167582816788),
/// (x: 2.1213562369319434, y: 0.5449632604075227),
/// ];
/// let lines = geo::MultiLineString::new(vec![line_string]);
/// let lines = MultiLineString::from_radians(lines)?;
/// # Ok::<(), h3o::error::InvalidGeometry>(())
/// ```
pub fn from_radians(
lines: geo::MultiLineString<f64>,
) -> Result<Self, InvalidGeometry> {
Ok(Self(
lines
.into_iter()
.map(LineString::from_radians)
.collect::<Result<Vec<_>, _>>()?,
))
}
/// Initialize a collection of lines from lines whose coordinates are in
/// degrees.
///
/// # Errors
///
/// [`InvalidGeometry`] if one of the line is invalid (e.g. contains
/// non-finite coordinates).
///
/// # Example
///
/// ```
/// use geo::line_string;
/// use h3o::geom::MultiLineString;
///
/// let line_string: geo::LineString<f64> = line_string![
/// (x: 114.385771248293, y: 30.612709316587612),
/// (x: 126.53337527260373, y: 45.8089358995214),
/// (x: 121.54475921995464, y: 31.22409481103989),
/// ];
/// let lines = geo::MultiLineString::new(vec![line_string]);
/// let lines = MultiLineString::from_degrees(lines)?;
/// # Ok::<(), h3o::error::InvalidGeometry>(())
/// ```
pub fn from_degrees(
lines: geo::MultiLineString<f64>,
) -> Result<Self, InvalidGeometry> {
Ok(Self(
lines
.into_iter()
.map(LineString::from_degrees)
.collect::<Result<Vec<_>, _>>()?,
))
}
}
impl From<MultiLineString> for geo::MultiLineString<f64> {
fn from(value: MultiLineString) -> Self {
Self(value.0.into_iter().map(Into::into).collect())
}
}
impl ToCells for MultiLineString {
fn max_cells_count(&self, config: PolyfillConfig) -> usize {
self.0.iter().map(|line| line.max_cells_count(config)).sum()
}
fn to_cells(
&self,
config: PolyfillConfig,
) -> Box<dyn Iterator<Item = CellIndex> + '_> {
Box::new(self.0.iter().flat_map(move |line| line.to_cells(config)))
}
}