BoundingBox

Struct BoundingBox 

Source
pub struct BoundingBox {
    pub min_lat: f64,
    pub min_lon: f64,
    pub max_lat: f64,
    pub max_lon: f64,
}
Expand description

A bounding box defined by minimum and maximum latitude and longitude coordinates.

Fields§

§min_lat: f64§min_lon: f64§max_lat: f64§max_lon: f64

Implementations§

Source§

impl BoundingBox

Source

pub fn new(min_lat: f64, min_lon: f64, max_lat: f64, max_lon: f64) -> Self

Create a new bounding box

Examples found in repository?
examples/spatial_queries.rs (line 186)
3fn main() -> Result<(), Box<dyn std::error::Error>> {
4    println!("Spatio - Spatio-Temporal Queries Example");
5    println!("=================================");
6
7    // Create an in-memory database
8    let db = Spatio::memory()?;
9    println!("Created spatio-temporal database");
10
11    // Add world cities with their coordinates
12    let cities = vec![
13        ("New York", Point::new(40.7128, -74.0060)),
14        ("London", Point::new(51.5074, -0.1278)),
15        ("Tokyo", Point::new(35.6762, 139.6503)),
16        ("Sydney", Point::new(-33.8688, 151.2093)),
17        ("Paris", Point::new(48.8566, 2.3522)),
18        ("Berlin", Point::new(52.5200, 13.4050)),
19        ("Mumbai", Point::new(19.0760, 72.8777)),
20        ("Cairo", Point::new(30.0444, 31.2357)),
21        ("São Paulo", Point::new(-23.5505, -46.6333)),
22        ("Mexico City", Point::new(19.4326, -99.1332)),
23    ];
24
25    // Insert cities into the database (automatically indexed)
26    for (name, point) in &cities {
27        db.insert_point("world_cities", point, name.as_bytes(), None)?;
28    }
29    println!("Added {} cities to spatial index", cities.len());
30
31    // Define a reference point (London)
32    let reference_point = Point::new(51.5074, -0.1278);
33    println!("Using London as reference point: {}", reference_point);
34
35    // Find cities within 1000km of London
36    println!("\nCities within 1000km of London:");
37    let nearby_cities =
38        db.query_within_radius("world_cities", &reference_point, 1_000_000.0, 10)?;
39
40    for (point, data) in &nearby_cities {
41        let city_name = String::from_utf8_lossy(data);
42        let distance_km = reference_point.distance_to(point) / 1000.0;
43        println!("  - {} ({:.0} km away)", city_name, distance_km);
44    }
45
46    // Find cities within 2000km of London
47    println!("\nCities within 2000km of London:");
48    let medium_range_cities =
49        db.query_within_radius("world_cities", &reference_point, 2_000_000.0, 10)?;
50
51    for (point, data) in &medium_range_cities {
52        let city_name = String::from_utf8_lossy(data);
53        let distance_km = reference_point.distance_to(point) / 1000.0;
54        println!("  - {} ({:.0} km away)", city_name, distance_km);
55    }
56
57    // Find the 3 closest cities to London (regardless of distance)
58    println!("\n3 closest cities to London:");
59    let closest_cities =
60        db.query_within_radius("world_cities", &reference_point, f64::INFINITY, 3)?;
61
62    for (i, (point, data)) in closest_cities.iter().enumerate() {
63        let city_name = String::from_utf8_lossy(data);
64        let distance_km = reference_point.distance_to(point) / 1000.0;
65        println!("  {}. {} ({:.0} km away)", i + 1, city_name, distance_km);
66    }
67
68    // Demonstrate distance calculations between specific cities
69    println!("\nDistance calculations:");
70    let nyc = Point::new(40.7128, -74.0060);
71    let tokyo = Point::new(35.6762, 139.6503);
72    let sydney = Point::new(-33.8688, 151.2093);
73
74    println!(
75        "  - New York ↔ London: {:.0} km",
76        nyc.distance_to(&reference_point) / 1000.0
77    );
78    println!(
79        "  - London ↔ Tokyo: {:.0} km",
80        reference_point.distance_to(&tokyo) / 1000.0
81    );
82    println!(
83        "  - Tokyo ↔ Sydney: {:.0} km",
84        tokyo.distance_to(&sydney) / 1000.0
85    );
86
87    // Add some points of interest in London
88    let london_poi = vec![
89        ("Tower Bridge", Point::new(51.5055, -0.0754)),
90        ("Big Ben", Point::new(51.4994, -0.1245)),
91        ("London Eye", Point::new(51.5033, -0.1195)),
92        ("Buckingham Palace", Point::new(51.5014, -0.1419)),
93        ("Hyde Park", Point::new(51.5074, -0.1657)),
94    ];
95
96    for (name, point) in &london_poi {
97        db.insert_point("london_poi", point, name.as_bytes(), None)?;
98    }
99    println!("\nAdded {} London points of interest", london_poi.len());
100
101    // Find POI within 2km of Big Ben
102    let big_ben = Point::new(51.4994, -0.1245);
103    println!("\nPoints of interest within 2km of Big Ben:");
104    let nearby_poi = db.query_within_radius("london_poi", &big_ben, 2000.0, 10)?;
105
106    for (point, data) in &nearby_poi {
107        let poi_name = String::from_utf8_lossy(data);
108        let distance_m = big_ben.distance_to(point);
109        if distance_m < 10.0 {
110            println!("  - {} (same location)", poi_name);
111        } else {
112            println!("  - {} ({:.0}m away)", poi_name, distance_m);
113        }
114    }
115
116    // Database statistics
117    let stats = db.stats()?;
118    println!("\nDatabase statistics:");
119    println!("  - Total keys: {}", stats.key_count);
120    println!("  - Operations performed: {}", stats.operations_count);
121
122    // Demonstrate new spatial query methods
123    println!("\nAdvanced Spatial Query Methods:");
124
125    // Test contains_point - check if there are any cities within 1000km of London
126    let has_nearby_cities = db.contains_point("world_cities", &reference_point, 1_000_000.0)?;
127    println!(
128        "  Cities within 1000km of London exist: {}",
129        has_nearby_cities
130    );
131
132    // Count cities within different distances from London
133    let count_500km = db.count_within_radius("world_cities", &reference_point, 500_000.0)?;
134    let count_1000km = db.count_within_radius("world_cities", &reference_point, 1_000_000.0)?;
135    let count_2000km = db.count_within_radius("world_cities", &reference_point, 2_000_000.0)?;
136
137    println!("  Cities within 500km: {}", count_500km);
138    println!("  Cities within 1000km: {}", count_1000km);
139    println!("  Cities within 2000km: {}", count_2000km);
140
141    // Test bounding box queries - European region
142    let europe_bounds = (45.0, -10.0, 60.0, 30.0); // min_lat, min_lon, max_lat, max_lon
143    let has_european_cities = db.intersects_bounds(
144        "world_cities",
145        europe_bounds.0,
146        europe_bounds.1,
147        europe_bounds.2,
148        europe_bounds.3,
149    )?;
150    println!("  European cities exist: {}", has_european_cities);
151
152    // Find all cities in European region
153    let european_cities = db.find_within_bounds(
154        "world_cities",
155        europe_bounds.0,
156        europe_bounds.1,
157        europe_bounds.2,
158        europe_bounds.3,
159        10,
160    )?;
161
162    println!("  Cities in European region:");
163    for (point, data) in &european_cities {
164        let city_name = String::from_utf8_lossy(data);
165        println!("    - {} at {}", city_name, point);
166    }
167
168    // Test bounding box around London area
169    let london_area = (51.0, -1.0, 52.0, 1.0);
170    let london_area_cities = db.find_within_bounds(
171        "world_cities",
172        london_area.0,
173        london_area.1,
174        london_area.2,
175        london_area.3,
176        5,
177    )?;
178
179    println!("  Cities in London area:");
180    for (point, data) in &london_area_cities {
181        let city_name = String::from_utf8_lossy(data);
182        println!("    - {} at {}", city_name, point);
183    }
184
185    // Demonstrate BoundingBox struct usage
186    let asia_pacific = BoundingBox::new(-50.0, 100.0, 50.0, 180.0);
187    let europe_box = BoundingBox::new(35.0, -10.0, 70.0, 40.0);
188
189    println!("  BoundingBox intersection test:");
190    println!(
191        "    - Asia-Pacific and Europe intersect: {}",
192        asia_pacific.intersects(&europe_box)
193    );
194
195    // Test point containment methods
196    println!("  Point containment tests:");
197    let central_london = Point::new(51.5074, -0.1278);
198    let tower_bridge = Point::new(51.5055, -0.0754);
199
200    println!(
201        "    - Tower Bridge within 5km of Central London: {}",
202        central_london.contains_point(&tower_bridge, 5000.0)
203    );
204    println!(
205        "    - Central London within 2km of Tower Bridge: {}",
206        tower_bridge.contains_point(&central_london, 2000.0)
207    );
208
209    println!("\nEnhanced spatial queries example completed successfully!");
210    println!("\nNew spatial query features demonstrated:");
211    println!("- contains_point: Check if points exist within a circular region");
212    println!("- count_within_radius: Count points within a radius (efficient)");
213    println!("- intersects_bounds: Check if points exist within a bounding box");
214    println!("- find_within_bounds: Find all points within a rectangular region");
215    println!("- BoundingBox: Dedicated struct for bounding box operations");
216    println!("- Point containment methods for distance-based checks");
217    println!("\nPrevious features:");
218    println!("- Automatic spatial indexing of geographic points");
219    println!("- Efficient nearby point searches with distance filtering");
220    println!("- Distance calculations between any two points");
221    println!("- Multiple namespaces (world_cities, london_poi)");
222    println!("- Flexible radius-based and count-based queries");
223
224    Ok(())
225}
Source

pub fn intersects(&self, other: &BoundingBox) -> bool

Check if this bounding box intersects with another bounding box.

§Examples
use spatio::BoundingBox;

let nyc_area = BoundingBox::new(40.5, -74.5, 41.0, -73.5);
let ny_state = BoundingBox::new(40.0, -80.0, 45.0, -71.0);

assert!(nyc_area.intersects(&ny_state));
Examples found in repository?
examples/spatial_queries.rs (line 192)
3fn main() -> Result<(), Box<dyn std::error::Error>> {
4    println!("Spatio - Spatio-Temporal Queries Example");
5    println!("=================================");
6
7    // Create an in-memory database
8    let db = Spatio::memory()?;
9    println!("Created spatio-temporal database");
10
11    // Add world cities with their coordinates
12    let cities = vec![
13        ("New York", Point::new(40.7128, -74.0060)),
14        ("London", Point::new(51.5074, -0.1278)),
15        ("Tokyo", Point::new(35.6762, 139.6503)),
16        ("Sydney", Point::new(-33.8688, 151.2093)),
17        ("Paris", Point::new(48.8566, 2.3522)),
18        ("Berlin", Point::new(52.5200, 13.4050)),
19        ("Mumbai", Point::new(19.0760, 72.8777)),
20        ("Cairo", Point::new(30.0444, 31.2357)),
21        ("São Paulo", Point::new(-23.5505, -46.6333)),
22        ("Mexico City", Point::new(19.4326, -99.1332)),
23    ];
24
25    // Insert cities into the database (automatically indexed)
26    for (name, point) in &cities {
27        db.insert_point("world_cities", point, name.as_bytes(), None)?;
28    }
29    println!("Added {} cities to spatial index", cities.len());
30
31    // Define a reference point (London)
32    let reference_point = Point::new(51.5074, -0.1278);
33    println!("Using London as reference point: {}", reference_point);
34
35    // Find cities within 1000km of London
36    println!("\nCities within 1000km of London:");
37    let nearby_cities =
38        db.query_within_radius("world_cities", &reference_point, 1_000_000.0, 10)?;
39
40    for (point, data) in &nearby_cities {
41        let city_name = String::from_utf8_lossy(data);
42        let distance_km = reference_point.distance_to(point) / 1000.0;
43        println!("  - {} ({:.0} km away)", city_name, distance_km);
44    }
45
46    // Find cities within 2000km of London
47    println!("\nCities within 2000km of London:");
48    let medium_range_cities =
49        db.query_within_radius("world_cities", &reference_point, 2_000_000.0, 10)?;
50
51    for (point, data) in &medium_range_cities {
52        let city_name = String::from_utf8_lossy(data);
53        let distance_km = reference_point.distance_to(point) / 1000.0;
54        println!("  - {} ({:.0} km away)", city_name, distance_km);
55    }
56
57    // Find the 3 closest cities to London (regardless of distance)
58    println!("\n3 closest cities to London:");
59    let closest_cities =
60        db.query_within_radius("world_cities", &reference_point, f64::INFINITY, 3)?;
61
62    for (i, (point, data)) in closest_cities.iter().enumerate() {
63        let city_name = String::from_utf8_lossy(data);
64        let distance_km = reference_point.distance_to(point) / 1000.0;
65        println!("  {}. {} ({:.0} km away)", i + 1, city_name, distance_km);
66    }
67
68    // Demonstrate distance calculations between specific cities
69    println!("\nDistance calculations:");
70    let nyc = Point::new(40.7128, -74.0060);
71    let tokyo = Point::new(35.6762, 139.6503);
72    let sydney = Point::new(-33.8688, 151.2093);
73
74    println!(
75        "  - New York ↔ London: {:.0} km",
76        nyc.distance_to(&reference_point) / 1000.0
77    );
78    println!(
79        "  - London ↔ Tokyo: {:.0} km",
80        reference_point.distance_to(&tokyo) / 1000.0
81    );
82    println!(
83        "  - Tokyo ↔ Sydney: {:.0} km",
84        tokyo.distance_to(&sydney) / 1000.0
85    );
86
87    // Add some points of interest in London
88    let london_poi = vec![
89        ("Tower Bridge", Point::new(51.5055, -0.0754)),
90        ("Big Ben", Point::new(51.4994, -0.1245)),
91        ("London Eye", Point::new(51.5033, -0.1195)),
92        ("Buckingham Palace", Point::new(51.5014, -0.1419)),
93        ("Hyde Park", Point::new(51.5074, -0.1657)),
94    ];
95
96    for (name, point) in &london_poi {
97        db.insert_point("london_poi", point, name.as_bytes(), None)?;
98    }
99    println!("\nAdded {} London points of interest", london_poi.len());
100
101    // Find POI within 2km of Big Ben
102    let big_ben = Point::new(51.4994, -0.1245);
103    println!("\nPoints of interest within 2km of Big Ben:");
104    let nearby_poi = db.query_within_radius("london_poi", &big_ben, 2000.0, 10)?;
105
106    for (point, data) in &nearby_poi {
107        let poi_name = String::from_utf8_lossy(data);
108        let distance_m = big_ben.distance_to(point);
109        if distance_m < 10.0 {
110            println!("  - {} (same location)", poi_name);
111        } else {
112            println!("  - {} ({:.0}m away)", poi_name, distance_m);
113        }
114    }
115
116    // Database statistics
117    let stats = db.stats()?;
118    println!("\nDatabase statistics:");
119    println!("  - Total keys: {}", stats.key_count);
120    println!("  - Operations performed: {}", stats.operations_count);
121
122    // Demonstrate new spatial query methods
123    println!("\nAdvanced Spatial Query Methods:");
124
125    // Test contains_point - check if there are any cities within 1000km of London
126    let has_nearby_cities = db.contains_point("world_cities", &reference_point, 1_000_000.0)?;
127    println!(
128        "  Cities within 1000km of London exist: {}",
129        has_nearby_cities
130    );
131
132    // Count cities within different distances from London
133    let count_500km = db.count_within_radius("world_cities", &reference_point, 500_000.0)?;
134    let count_1000km = db.count_within_radius("world_cities", &reference_point, 1_000_000.0)?;
135    let count_2000km = db.count_within_radius("world_cities", &reference_point, 2_000_000.0)?;
136
137    println!("  Cities within 500km: {}", count_500km);
138    println!("  Cities within 1000km: {}", count_1000km);
139    println!("  Cities within 2000km: {}", count_2000km);
140
141    // Test bounding box queries - European region
142    let europe_bounds = (45.0, -10.0, 60.0, 30.0); // min_lat, min_lon, max_lat, max_lon
143    let has_european_cities = db.intersects_bounds(
144        "world_cities",
145        europe_bounds.0,
146        europe_bounds.1,
147        europe_bounds.2,
148        europe_bounds.3,
149    )?;
150    println!("  European cities exist: {}", has_european_cities);
151
152    // Find all cities in European region
153    let european_cities = db.find_within_bounds(
154        "world_cities",
155        europe_bounds.0,
156        europe_bounds.1,
157        europe_bounds.2,
158        europe_bounds.3,
159        10,
160    )?;
161
162    println!("  Cities in European region:");
163    for (point, data) in &european_cities {
164        let city_name = String::from_utf8_lossy(data);
165        println!("    - {} at {}", city_name, point);
166    }
167
168    // Test bounding box around London area
169    let london_area = (51.0, -1.0, 52.0, 1.0);
170    let london_area_cities = db.find_within_bounds(
171        "world_cities",
172        london_area.0,
173        london_area.1,
174        london_area.2,
175        london_area.3,
176        5,
177    )?;
178
179    println!("  Cities in London area:");
180    for (point, data) in &london_area_cities {
181        let city_name = String::from_utf8_lossy(data);
182        println!("    - {} at {}", city_name, point);
183    }
184
185    // Demonstrate BoundingBox struct usage
186    let asia_pacific = BoundingBox::new(-50.0, 100.0, 50.0, 180.0);
187    let europe_box = BoundingBox::new(35.0, -10.0, 70.0, 40.0);
188
189    println!("  BoundingBox intersection test:");
190    println!(
191        "    - Asia-Pacific and Europe intersect: {}",
192        asia_pacific.intersects(&europe_box)
193    );
194
195    // Test point containment methods
196    println!("  Point containment tests:");
197    let central_london = Point::new(51.5074, -0.1278);
198    let tower_bridge = Point::new(51.5055, -0.0754);
199
200    println!(
201        "    - Tower Bridge within 5km of Central London: {}",
202        central_london.contains_point(&tower_bridge, 5000.0)
203    );
204    println!(
205        "    - Central London within 2km of Tower Bridge: {}",
206        tower_bridge.contains_point(&central_london, 2000.0)
207    );
208
209    println!("\nEnhanced spatial queries example completed successfully!");
210    println!("\nNew spatial query features demonstrated:");
211    println!("- contains_point: Check if points exist within a circular region");
212    println!("- count_within_radius: Count points within a radius (efficient)");
213    println!("- intersects_bounds: Check if points exist within a bounding box");
214    println!("- find_within_bounds: Find all points within a rectangular region");
215    println!("- BoundingBox: Dedicated struct for bounding box operations");
216    println!("- Point containment methods for distance-based checks");
217    println!("\nPrevious features:");
218    println!("- Automatic spatial indexing of geographic points");
219    println!("- Efficient nearby point searches with distance filtering");
220    println!("- Distance calculations between any two points");
221    println!("- Multiple namespaces (world_cities, london_poi)");
222    println!("- Flexible radius-based and count-based queries");
223
224    Ok(())
225}

Trait Implementations§

Source§

impl Clone for BoundingBox

Source§

fn clone(&self) -> BoundingBox

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for BoundingBox

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl PartialEq for BoundingBox

Source§

fn eq(&self, other: &BoundingBox) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Copy for BoundingBox

Source§

impl StructuralPartialEq for BoundingBox

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<G1, G2> Within<G2> for G1
where G2: Contains<G1>,

Source§

fn is_within(&self, b: &G2) -> bool