h3o 0.3.0

A Rust implementation of the H3 geospatial indexing system.
Documentation
use super::Point;
use crate::{error::InvalidGeometry, geom::ToCells, CellIndex, Resolution};
use std::boxed::Box;

/// A collection of [`geo::Point`]s.
#[derive(Clone, Debug, PartialEq)]
pub struct MultiPoint(Vec<Point>);

impl MultiPoint {
    /// Initialize a collection of points from points whose coordinates are in
    /// radians.
    ///
    /// # Errors
    ///
    /// [`InvalidGeometry`] if one of the point is invalid (e.g. contains
    /// non-finite coordinates).
    ///
    /// # Example
    ///
    /// ```
    /// use h3o::geom::MultiPoint;
    ///
    /// let points: geo::MultiPoint<f64> = vec![
    ///     (-2.1489548115593986, 0.8584581881195188),
    ///     (-1.382430711985295,  0.7628836324009612),
    /// ].into();
    /// let points = MultiPoint::from_radians(&points)?;
    /// # Ok::<(), h3o::error::InvalidGeometry>(())
    /// ```
    pub fn from_radians(
        points: &geo::MultiPoint<f64>,
    ) -> Result<Self, InvalidGeometry> {
        Ok(Self(
            points
                .iter()
                .copied()
                .map(Point::from_radians)
                .collect::<Result<Vec<_>, _>>()?,
        ))
    }

    /// Initialize a collection of points from points whose coordinates are in
    /// degrees.
    ///
    /// # Errors
    ///
    /// [`InvalidGeometry`] if one of the point is invalid (e.g. contains
    /// non-finite coordinates).
    ///
    /// # Example
    ///
    /// ```
    /// use h3o::geom::MultiPoint;
    ///
    /// let points: geo::MultiPoint<f64> = vec![
    ///     (-123.12604106668468, 49.18603106769609),
    ///     (-79.20744526602287,  43.71001239618482),
    /// ].into();
    /// let points = MultiPoint::from_degrees(&points)?;
    /// # Ok::<(), h3o::error::InvalidGeometry>(())
    /// ```
    pub fn from_degrees(
        points: &geo::MultiPoint<f64>,
    ) -> Result<Self, InvalidGeometry> {
        Ok(Self(
            points
                .iter()
                .copied()
                .map(Point::from_degrees)
                .collect::<Result<Vec<_>, _>>()?,
        ))
    }
}

impl From<MultiPoint> for geo::MultiPoint<f64> {
    fn from(value: MultiPoint) -> Self {
        Self(value.0.into_iter().map(Into::into).collect())
    }
}

impl ToCells for MultiPoint {
    fn max_cells_count(&self, _resolution: Resolution) -> usize {
        self.0.len()
    }

    fn to_cells(
        &self,
        resolution: Resolution,
    ) -> Box<dyn Iterator<Item = CellIndex> + '_> {
        Box::new(
            self.0
                .iter()
                .flat_map(move |point| point.to_cells(resolution)),
        )
    }
}