From e013d9916cd0b88966081d3fb6b879db2776cea8 Mon Sep 17 00:00:00 2001 From: Dustin Carlino Date: Tue, 31 Dec 2024 18:12:57 +0000 Subject: [PATCH] Speed up tests for finding roads inside a boundary polygon. #67 --- backend/src/neighbourhood.rs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/backend/src/neighbourhood.rs b/backend/src/neighbourhood.rs index 43e31c7..5c2c07b 100644 --- a/backend/src/neighbourhood.rs +++ b/backend/src/neighbourhood.rs @@ -2,8 +2,8 @@ use std::collections::{BTreeMap, BTreeSet}; use anyhow::Result; use geo::{ - Area, Contains, Distance, Euclidean, Intersects, Length, LineInterpolatePoint, LineLocatePoint, - LineString, Point, Polygon, + Area, Distance, Euclidean, Length, LineInterpolatePoint, LineLocatePoint, LineString, Point, + Polygon, PreparedGeometry, Relate, }; use geojson::FeatureCollection; use web_time::Instant; @@ -45,12 +45,14 @@ impl Neighbourhood { let t1 = Instant::now(); let bbox = buffer_aabb(aabb(&boundary_polygon), 50.0); + let prepared_boundary = PreparedGeometry::from(boundary_polygon.clone()); + let mut interior_roads = BTreeSet::new(); let mut crosses = BTreeMap::new(); for obj in map.closest_road.locate_in_envelope_intersecting(&bbox) { let r = &map.roads[obj.data.0]; - match line_in_polygon(&r.linestring, &boundary_polygon) { + match line_in_polygon(&r.linestring, &boundary_polygon, &prepared_boundary) { LineInPolygon::Inside => { interior_roads.insert(r.id); } @@ -217,13 +219,20 @@ enum LineInPolygon { Outside, } -fn line_in_polygon(linestring: &LineString, polygon: &Polygon) -> LineInPolygon { +fn line_in_polygon( + linestring: &LineString, + polygon: &Polygon, + prepared_polygon: &PreparedGeometry, +) -> LineInPolygon { // TODO Reconsider rewriting all of this logic based on clip_linestring_to_polygon - if polygon.contains(linestring) { + + let matrix = prepared_polygon.relate(linestring); + + if matrix.is_within() { return double_check_line_in_polygon(linestring, polygon); } - if !polygon.intersects(linestring) { + if !matrix.is_intersects() { return LineInPolygon::Outside; }