Created
October 27, 2019 13:57
-
-
Save stuartlynn/e4b856d7e771c5c420dfd764c4bdbd8c to your computer and use it in GitHub Desktop.
Fast Agg point in polygon search
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pub fn agg_in(&self, poly: &Geometry<f32>) -> HashMap<String, f32> { | |
// Find the bounds of the target polygon | |
let bounds = match poly { | |
Geometry::Polygon(p) => Ok(p.bounding_rect().unwrap()), | |
Geometry::MultiPolygon(p) => Ok(p.bounding_rect().unwrap()), | |
_ => Err("Wrong poly type"), | |
} | |
.unwrap(); | |
// Use the bounds to create an r-tree query | |
let target_bounds = | |
AABB::from_corners([bounds.min.x, bounds.min.y], [bounds.max.x, bounds.max.y]); | |
let mut results: HashMap<String, f32> = HashMap::new(); | |
// Do the r-tree search to get back the candidates points | |
let candidates = self.rtree.locate_in_envelope(&target_bounds); | |
// Filter the candidates to make sure we only have points explicitly within | |
// the polygon | |
let hits = candidates.filter(|p| match poly { | |
Geometry::MultiPolygon(target) => target.contains(&p.coords), | |
_ => false, | |
}); | |
let mut count = 0; | |
// Calculate the aggregates | |
for hit in hits { | |
count = count + 1; | |
for key in hit.data.keys() { | |
let val = hit.data.get(key).unwrap(); | |
*results.entry(key.to_string()).or_insert(0.0) += val; | |
} | |
} | |
results.insert("count".to_string(), count as f32); | |
// Return! | |
results | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment