Skip to main content

routee_compass_core/model/map/
map_model.rs

1use super::map_error::MapError;
2use super::map_model_config::MapModelConfig;
3use super::matching_type::MatchingType;
4use super::spatial_index::SpatialIndex;
5use super::{geometry_model::GeometryModel, matching_type::MapInputResult};
6use crate::algorithm::search::SearchInstance;
7use crate::model::map::map_model_config::MapModelGeometryConfig;
8use crate::model::network::{EdgeId, EdgeListId, Graph};
9use geo::LineString;
10use std::sync::Arc;
11
12pub struct MapModel {
13    /// way in which map matching is attempted
14    pub matching_type: MatchingType,
15    /// index used during map matching
16    pub spatial_index: SpatialIndex,
17    /// collection of geometries associated with the graph edge lists
18    pub geometry: Vec<GeometryModel>,
19    /// allow for queries without a destination location, such as when generating
20    /// shortest path trees or isochrones.
21    pub queries_without_destinations: bool,
22    /// the configuration used to create this map model
23    pub config: MapModelConfig,
24}
25
26impl MapModel {
27    pub fn new(graph: Arc<Graph>, config: MapModelConfig) -> Result<MapModel, MapError> {
28        let geometry = config
29            .geometry
30            .iter()
31            .enumerate()
32            .map(|(edge_list, g)| {
33                let edge_list_id = EdgeListId(edge_list);
34                match g {
35                    MapModelGeometryConfig::FromVertices => {
36                        GeometryModel::new_from_vertices(graph.clone(), edge_list_id)
37                    }
38                    MapModelGeometryConfig::FromLinestrings {
39                        geometry_input_file,
40                    } => GeometryModel::new_from_edges(
41                        geometry_input_file,
42                        edge_list_id,
43                        graph.clone(),
44                    ),
45                }
46            })
47            .collect::<Result<Vec<_>, _>>()?;
48        let queries_without_destinations = config.queries_without_destinations;
49        let tolerance = config.tolerance.as_ref().map(|t| t.to_uom());
50        let matching_type =
51            MatchingType::deserialize_matching_types(config.matching_type.as_ref())?;
52        let spatial_index_type = config.spatial_index_type.clone().unwrap_or_default();
53        let spatial_index =
54            SpatialIndex::build(&spatial_index_type, graph.clone(), &geometry, tolerance);
55
56        Ok(MapModel {
57            matching_type,
58            spatial_index,
59            geometry,
60            queries_without_destinations,
61            config,
62        })
63    }
64
65    pub fn get_linestring<'a>(
66        &'a self,
67        edge_list_id: &EdgeListId,
68        edge_id: &EdgeId,
69    ) -> Result<&'a LineString<f32>, MapError> {
70        let linestrings = self
71            .geometry
72            .get(edge_list_id.0)
73            .ok_or(MapError::MissingEdgeListId(*edge_list_id))?;
74        linestrings
75            .get(edge_id)
76            .ok_or(MapError::MissingEdgeId(*edge_list_id, *edge_id))
77    }
78
79    pub fn map_match(
80        &self,
81        query: &mut serde_json::Value,
82        si: &SearchInstance,
83    ) -> Result<(), MapError> {
84        self.matching_type.process_origin(query, si)?;
85        let result = self.matching_type.process_destination(query, si)?;
86        match result {
87            MapInputResult::NotFound if !self.queries_without_destinations => {
88                Err(MapError::DestinationsRequired(self.matching_type.clone()))
89            }
90            _ => Ok(()),
91        }
92    }
93}