h3ron_graph/graph/
longedge.rs1use std::borrow::Borrow;
2
3use geo_types::LineString;
4use serde::{Deserialize, Serialize};
5
6use h3ron::collections::compressed::{IndexBlock, OwningDecompressedIter};
7use h3ron::collections::H3Treemap;
8use h3ron::to_geo::{ToLineString, ToMultiLineString};
9use h3ron::{H3Cell, H3DirectedEdge};
10
11use crate::error::Error;
12
13fn h3edge_path_to_h3cell_path<I>(h3edge_path: I) -> Result<Vec<H3Cell>, Error>
15where
16 I: IntoIterator,
17 I::Item: Borrow<H3DirectedEdge>,
18{
19 let mut iter = h3edge_path.into_iter();
20 let mut out_vec = Vec::with_capacity(iter.size_hint().0 + 1);
21 if let Some(h3edge) = iter.next() {
22 out_vec.push(h3edge.borrow().origin_cell()?);
23 out_vec.push(h3edge.borrow().destination_cell()?);
24 }
25 for h3edge in iter {
26 out_vec.push(h3edge.borrow().destination_cell()?);
27 }
28 Ok(out_vec)
29}
30
31#[derive(Serialize, Deserialize, Clone)]
37pub struct LongEdge {
38 pub in_edge: H3DirectedEdge,
39 pub out_edge: H3DirectedEdge,
40
41 pub(crate) edge_path: IndexBlock<H3DirectedEdge>,
44
45 cell_lookup: H3Treemap<H3Cell>,
48}
49
50impl LongEdge {
51 pub fn destination_cell(&self) -> Result<H3Cell, Error> {
52 Ok(self.out_edge.destination_cell()?)
53 }
54
55 pub fn origin_cell(&self) -> Result<H3Cell, Error> {
56 Ok(self.in_edge.origin_cell()?)
57 }
58
59 pub fn is_disjoint(&self, celltreemap: &H3Treemap<H3Cell>) -> bool {
60 self.cell_lookup.is_disjoint(celltreemap)
61 }
62
63 pub const fn h3edges_len(&self) -> usize {
65 self.edge_path.len().saturating_sub(1)
66 }
67
68 pub fn h3edge_path(&self) -> Result<OwningDecompressedIter<H3DirectedEdge>, Error> {
70 Ok(self.edge_path.iter_uncompressed()?)
71 }
72}
73
74impl TryFrom<Vec<H3DirectedEdge>> for LongEdge {
78 type Error = Error;
79
80 fn try_from(mut h3edges: Vec<H3DirectedEdge>) -> Result<Self, Self::Error> {
81 h3edges.dedup();
82 h3edges.shrink_to_fit();
83 if h3edges.len() >= 2 {
84 let cell_lookup: H3Treemap<_> = h3edge_path_to_h3cell_path(&h3edges)?.iter().collect();
85 Ok(Self {
86 in_edge: h3edges[0],
87 out_edge: *h3edges.last().unwrap(),
88 edge_path: h3edges.into(),
89 cell_lookup,
90 })
91 } else {
92 Err(Error::InsufficientNumberOfEdges)
93 }
94 }
95}
96
97impl ToLineString for LongEdge {
98 type Error = Error;
99
100 fn to_linestring(&self) -> Result<LineString<f64>, Self::Error> {
101 match self
102 .h3edge_path()?
103 .collect::<Vec<_>>()
104 .as_slice()
105 .to_multilinestring()
106 {
107 Ok(mut mls) => {
108 if mls.0.len() != 1 {
109 Err(Error::SegmentedPath)
110 } else {
111 Ok(mls.0.swap_remove(0))
112 }
113 }
114 Err(e) => Err(e.into()),
115 }
116 }
117}