bbox_database/
bbox_database.rs

1//! Bounding Box Database Integration Example
2//!
3//! This example demonstrates how to use bounding boxes with the Spatio database
4//! for storing and querying geographic regions and spatial data.
5
6use spatio::{BoundingBox2D, Point, Spatio};
7use std::error::Error;
8
9fn main() -> Result<(), Box<dyn Error>> {
10    println!("=== Spatio - Bounding Box Database ===\n");
11
12    let mut db = Spatio::memory()?;
13    println!("✓ Created in-memory database\n");
14
15    // ========================================
16    // 1. Store Geographic Regions
17    // ========================================
18    println!("1. Storing Geographic Regions");
19    println!("------------------------------");
20
21    // Define NYC boroughs as bounding boxes
22    let manhattan = BoundingBox2D::new(-74.0479, 40.6829, -73.9067, 40.8820);
23    let brooklyn = BoundingBox2D::new(-74.0421, 40.5707, -73.8333, 40.7395);
24    let queens = BoundingBox2D::new(-73.9626, 40.5431, -73.7004, 40.8007);
25    let bronx = BoundingBox2D::new(-73.9338, 40.7855, -73.7654, 40.9176);
26    let staten_island = BoundingBox2D::new(-74.2558, 40.4960, -74.0526, 40.6490);
27
28    // Store regions in database
29    db.insert_bbox("region:manhattan", &manhattan, None)?;
30    db.insert_bbox("region:brooklyn", &brooklyn, None)?;
31    db.insert_bbox("region:queens", &queens, None)?;
32    db.insert_bbox("region:bronx", &bronx, None)?;
33    db.insert_bbox("region:staten_island", &staten_island, None)?;
34
35    println!("   ✓ Stored 5 NYC borough boundaries");
36
37    // ========================================
38    // 2. Retrieve Stored Regions
39    // ========================================
40    println!("\n2. Retrieving Stored Regions");
41    println!("-----------------------------");
42
43    if let Some(retrieved_manhattan) = db.get_bbox("region:manhattan")? {
44        println!("   Manhattan:");
45        println!(
46            "     Area: {:.4}° × {:.4}°",
47            retrieved_manhattan.width(),
48            retrieved_manhattan.height()
49        );
50        println!(
51            "     Center: ({:.4}, {:.4})",
52            retrieved_manhattan.center().x(),
53            retrieved_manhattan.center().y()
54        );
55    }
56
57    // ========================================
58    // 3. Store POIs and Query by Region
59    // ========================================
60    println!("\n3. Store POIs and Query by Region");
61    println!("-----------------------------------");
62
63    // Store points of interest
64    db.insert_point("poi", &Point::new(-73.9855, 40.7580), b"times_square", None)?;
65    db.insert_point("poi", &Point::new(-73.9665, 40.7829), b"central_park", None)?;
66    db.insert_point("poi", &Point::new(-73.9857, 40.7484), b"empire_state", None)?;
67    db.insert_point(
68        "poi",
69        &Point::new(-73.9969, 40.7061),
70        b"brooklyn_bridge",
71        None,
72    )?;
73    db.insert_point(
74        "poi",
75        &Point::new(-73.9690, 40.6602),
76        b"prospect_park",
77        None,
78    )?;
79    db.insert_point("poi", &Point::new(-73.9799, 40.5755), b"coney_island", None)?;
80
81    println!("   ✓ Stored 6 points of interest");
82
83    // Query POIs in Manhattan
84    let manhattan_pois = db.query_within_bbox("poi", &manhattan, 100)?;
85    println!("\n   POIs in Manhattan: {}", manhattan_pois.len());
86    for (point, data) in &manhattan_pois {
87        let name = String::from_utf8_lossy(data);
88        println!("     - {} at ({:.4}, {:.4})", name, point.x(), point.y());
89    }
90
91    // Query POIs in Brooklyn
92    let brooklyn_pois = db.query_within_bbox("poi", &brooklyn, 100)?;
93    println!("\n   POIs in Brooklyn: {}", brooklyn_pois.len());
94
95    // ========================================
96    // 4. Find Intersecting Regions
97    // ========================================
98    println!("\n4. Finding Intersecting Regions");
99    println!("--------------------------------");
100
101    // Create a search area (covering parts of Manhattan and Queens)
102    let search_area = BoundingBox2D::new(-73.98, 40.72, -73.92, 40.78);
103
104    let intersecting = db.find_intersecting_bboxes("region:", &search_area)?;
105    println!(
106        "   Search area intersects with {} boroughs:",
107        intersecting.len()
108    );
109    for (key, _bbox) in &intersecting {
110        println!("     - {}", key.replace("region:", ""));
111    }
112
113    // ========================================
114    // 5. Delivery Zone Management
115    // ========================================
116    println!("\n5. Delivery Zone Management");
117    println!("----------------------------");
118
119    // Define delivery zones
120    let zone_a = BoundingBox2D::new(-74.02, 40.70, -73.98, 40.74);
121    let zone_b = BoundingBox2D::new(-74.00, 40.72, -73.96, 40.76);
122    let zone_c = BoundingBox2D::new(-73.98, 40.74, -73.94, 40.78);
123
124    db.insert_bbox("delivery:zone_a", &zone_a, None)?;
125    db.insert_bbox("delivery:zone_b", &zone_b, None)?;
126    db.insert_bbox("delivery:zone_c", &zone_c, None)?;
127
128    println!("   ✓ Created 3 delivery zones");
129
130    // Check which zones overlap
131    let overlapping_with_a = db.find_intersecting_bboxes("delivery:", &zone_a)?;
132    println!(
133        "\n   Zone A overlaps with {} zones (including itself)",
134        overlapping_with_a.len()
135    );
136
137    // ========================================
138    // 6. Service Area Lookup
139    // ========================================
140    println!("\n6. Service Area Lookup");
141    println!("-----------------------");
142
143    // Check if various locations are in service areas
144    let locations = vec![
145        ("Customer 1", Point::new(-74.00, 40.72)),
146        ("Customer 2", Point::new(-73.97, 40.75)),
147        ("Customer 3", Point::new(-74.05, 40.68)),
148    ];
149
150    for (name, location) in &locations {
151        let mut in_zone = false;
152        for (zone_key, zone_bbox) in &overlapping_with_a {
153            if zone_bbox.contains_point(location) {
154                println!(
155                    "   {} at ({:.4}, {:.4}) is in {}",
156                    name,
157                    location.x(),
158                    location.y(),
159                    zone_key.replace("delivery:", "")
160                );
161                in_zone = true;
162                break;
163            }
164        }
165        if !in_zone {
166            println!(
167                "   {} at ({:.4}, {:.4}) is outside all zones",
168                name,
169                location.x(),
170                location.y()
171            );
172        }
173    }
174
175    // ========================================
176    // 7. Geofencing Example
177    // ========================================
178    println!("\n7. Geofencing Example");
179    println!("----------------------");
180
181    // Define restricted areas
182    let airport_zone = BoundingBox2D::new(-73.82, 40.63, -73.76, 40.66);
183    db.insert_bbox("restricted:jfk_airport", &airport_zone, None)?;
184
185    let military_zone = BoundingBox2D::new(-74.08, 40.60, -74.03, 40.64);
186    db.insert_bbox("restricted:military", &military_zone, None)?;
187
188    println!("   ✓ Defined 2 restricted zones");
189
190    // Check if drone locations are in restricted areas
191    let drone_locations = vec![
192        ("Drone 1", Point::new(-73.79, 40.64)),
193        ("Drone 2", Point::new(-74.00, 40.70)),
194    ];
195
196    for (drone, location) in &drone_locations {
197        let restricted = db.find_intersecting_bboxes(
198            "restricted:",
199            &BoundingBox2D::new(
200                location.x() - 0.001,
201                location.y() - 0.001,
202                location.x() + 0.001,
203                location.y() + 0.001,
204            ),
205        )?;
206
207        if !restricted.is_empty() {
208            println!(
209                "   ⚠ {} at ({:.4}, {:.4}) is in restricted area: {}",
210                drone,
211                location.x(),
212                location.y(),
213                restricted[0].0.replace("restricted:", "")
214            );
215        } else {
216            println!(
217                "   ✓ {} at ({:.4}, {:.4}) is in safe area",
218                drone,
219                location.x(),
220                location.y()
221            );
222        }
223    }
224
225    // ========================================
226    // 8. Spatial Analytics
227    // ========================================
228    println!("\n8. Spatial Analytics");
229    println!("---------------------");
230
231    // Calculate coverage area
232    let mut total_width = 0.0;
233    let mut total_height = 0.0;
234    let mut count = 0;
235
236    let all_regions = vec![
237        ("Manhattan", &manhattan),
238        ("Brooklyn", &brooklyn),
239        ("Queens", &queens),
240        ("Bronx", &bronx),
241        ("Staten Island", &staten_island),
242    ];
243
244    for (name, bbox) in &all_regions {
245        total_width += bbox.width();
246        total_height += bbox.height();
247        count += 1;
248        println!(
249            "   {} coverage: {:.4}° × {:.4}°",
250            name,
251            bbox.width(),
252            bbox.height()
253        );
254    }
255
256    let avg_width = total_width / count as f64;
257    let avg_height = total_height / count as f64;
258
259    println!(
260        "\n   Average borough size: {:.4}° × {:.4}°",
261        avg_width, avg_height
262    );
263
264    // ========================================
265    // 9. Database Statistics
266    // ========================================
267    println!("\n9. Database Statistics");
268    println!("-----------------------");
269
270    let stats = db.stats();
271    println!("   Total keys: {}", stats.key_count);
272    println!("   Total operations: {}", stats.operations_count);
273
274    // Count different types of data
275    let poi_count = manhattan_pois.len() + brooklyn_pois.len();
276    println!("   Stored POIs: {}", poi_count);
277    println!("   Stored regions: 5");
278    println!("   Delivery zones: 3");
279    println!("   Restricted zones: 2");
280
281    println!("\n=== Bounding Box Database Integration Complete! ===");
282    println!("\nKey Features Demonstrated:");
283    println!("  • Store and retrieve bounding boxes");
284    println!("  • Query POIs within regions");
285    println!("  • Find intersecting regions");
286    println!("  • Delivery zone management");
287    println!("  • Service area lookups");
288    println!("  • Geofencing and restricted areas");
289    println!("  • Spatial analytics");
290
291    Ok(())
292}