flow_rs_core/spatial/
query.rs

1//! Query builder for spatial queries
2
3use crate::types::{NodeId, Position, Rect};
4
5use super::index::SpatialIndex;
6
7/// Query builder for spatial queries
8pub struct SpatialQuery<'a> {
9    index: &'a SpatialIndex,
10    bounds: Option<Rect>,
11    center: Option<Position>,
12    radius: Option<f64>,
13    max_results: Option<usize>,
14}
15
16impl<'a> SpatialQuery<'a> {
17    /// Create a new spatial query
18    pub fn new(index: &'a SpatialIndex) -> Self {
19        Self {
20            index,
21            bounds: None,
22            center: None,
23            radius: None,
24            max_results: None,
25        }
26    }
27
28    /// Filter by rectangular bounds
29    pub fn bounds(mut self, bounds: Rect) -> Self {
30        self.bounds = Some(bounds);
31        self
32    }
33
34    /// Filter by circular area
35    pub fn radius(mut self, center: Position, radius: f64) -> Self {
36        self.center = Some(center);
37        self.radius = Some(radius);
38        self
39    }
40
41    /// Limit the number of results
42    pub fn limit(mut self, max_results: usize) -> Self {
43        self.max_results = Some(max_results);
44        self
45    }
46
47    /// Execute the query and return node IDs
48    pub fn execute(self) -> Vec<NodeId> {
49        let mut results = if let Some(bounds) = self.bounds {
50            self.index.query_rect(&bounds)
51        } else if let (Some(center), Some(radius)) = (self.center, self.radius) {
52            self.index.query_radius(center, radius)
53        } else {
54            self.index.node_ids()
55        };
56
57        if let Some(max_results) = self.max_results {
58            results.truncate(max_results);
59        }
60
61        results
62    }
63}