use super::LineString;
use crate::{error::InvalidGeometry, geom::ToCells, CellIndex, Resolution};
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<'a>(Vec<LineString<'a>>);
impl<'a> MultiLineString<'a> {
/// 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: &'a geo::MultiLineString<f64>,
) -> Result<Self, InvalidGeometry> {
Ok(Self(
lines
.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, resolution: Resolution) -> usize {
self.0
.iter()
.map(|line| line.max_cells_count(resolution))
.sum()
}
fn to_cells(
&self,
resolution: Resolution,
) -> Box<dyn Iterator<Item = CellIndex> + '_> {
Box::new(
self.0
.iter()
.flat_map(move |line| line.to_cells(resolution)),
)
}
}