bounding_boxes/
bounding_boxes.rs

1//! Bounding Box Example
2//!
3//! This example demonstrates how to use BoundingBox2D and BoundingBox3D types
4//! for spatial queries and region management.
5
6use spatio::{BoundingBox2D, BoundingBox3D, Point, Spatio, TemporalBoundingBox2D};
7use std::error::Error;
8use std::time::SystemTime;
9
10fn main() -> Result<(), Box<dyn Error>> {
11    println!("=== Spatio - Bounding Box Examples ===\n");
12
13    // Create an in-memory database
14    let mut db = Spatio::memory()?;
15    println!("✓ Created in-memory database\n");
16
17    // ========================================
18    // 1. Basic 2D Bounding Box Operations
19    // ========================================
20    println!("1. Basic 2D Bounding Box");
21    println!("-------------------------");
22
23    // Create a bounding box for Manhattan
24    let manhattan = BoundingBox2D::new(
25        -74.0479, 40.6829, // Southwest corner (Battery Park)
26        -73.9067, 40.8820, // Northeast corner (Inwood)
27    );
28
29    println!("   Manhattan bounding box:");
30    println!(
31        "     Min: ({:.4}, {:.4})",
32        manhattan.min_x(),
33        manhattan.min_y()
34    );
35    println!(
36        "     Max: ({:.4}, {:.4})",
37        manhattan.max_x(),
38        manhattan.max_y()
39    );
40    println!(
41        "     Center: ({:.4}, {:.4})",
42        manhattan.center().x(),
43        manhattan.center().y()
44    );
45    println!(
46        "     Width: {:.4}°, Height: {:.4}°",
47        manhattan.width(),
48        manhattan.height()
49    );
50
51    // Check if points are within Manhattan
52    let times_square = Point::new(-73.9855, 40.7580);
53    let brooklyn_bridge = Point::new(-73.9969, 40.7061);
54    let statue_of_liberty = Point::new(-74.0445, 40.6892);
55    let jfk_airport = Point::new(-73.7781, 40.6413);
56
57    println!("\n   Point containment checks:");
58    println!(
59        "     Times Square: {}",
60        manhattan.contains_point(&times_square)
61    );
62    println!(
63        "     Brooklyn Bridge: {}",
64        manhattan.contains_point(&brooklyn_bridge)
65    );
66    println!(
67        "     Statue of Liberty: {}",
68        manhattan.contains_point(&statue_of_liberty)
69    );
70    println!(
71        "     JFK Airport: {}",
72        manhattan.contains_point(&jfk_airport)
73    );
74
75    // ========================================
76    // 2. Bounding Box Intersection
77    // ========================================
78    println!("\n2. Bounding Box Intersection");
79    println!("-----------------------------");
80
81    // Create bounding boxes for different NYC boroughs
82    let manhattan_bbox = BoundingBox2D::new(-74.0479, 40.6829, -73.9067, 40.8820);
83    let brooklyn_bbox = BoundingBox2D::new(-74.0421, 40.5707, -73.8333, 40.7395);
84    let queens_bbox = BoundingBox2D::new(-73.9626, 40.5431, -73.7004, 40.8007);
85
86    println!(
87        "   Manhattan ∩ Brooklyn: {}",
88        manhattan_bbox.intersects(&brooklyn_bbox)
89    );
90    println!(
91        "   Manhattan ∩ Queens: {}",
92        manhattan_bbox.intersects(&queens_bbox)
93    );
94    println!(
95        "   Brooklyn ∩ Queens: {}",
96        brooklyn_bbox.intersects(&queens_bbox)
97    );
98
99    // ========================================
100    // 3. Expanding Bounding Boxes
101    // ========================================
102    println!("\n3. Expanding Bounding Boxes");
103    println!("----------------------------");
104
105    let central_park = BoundingBox2D::new(-73.9812, 40.7644, -73.9492, 40.8003);
106    println!("   Central Park original:");
107    println!(
108        "     Width: {:.4}°, Height: {:.4}°",
109        central_park.width(),
110        central_park.height()
111    );
112
113    // Expand by 0.01 degrees (~1 km)
114    let expanded = central_park.expand(0.01);
115    println!("\n   Expanded by 0.01°:");
116    println!(
117        "     Width: {:.4}°, Height: {:.4}°",
118        expanded.width(),
119        expanded.height()
120    );
121    println!(
122        "     Growth: {:.4}° in each direction",
123        (expanded.width() - central_park.width()) / 2.0
124    );
125
126    // ========================================
127    // 4. 3D Bounding Boxes
128    // ========================================
129    println!("\n4. 3D Bounding Boxes");
130    println!("--------------------");
131
132    // Create a 3D bounding box for a tall building's footprint with height
133    let one_world_trade = BoundingBox3D::new(
134        -74.0134, 40.7127, 0.0, // Ground level southwest
135        -74.0118, 40.7143, 541.0, // Top level northeast (541m height)
136    );
137
138    println!("   One World Trade Center:");
139    println!(
140        "     Footprint: {:.4}° × {:.4}°",
141        one_world_trade.width(),
142        one_world_trade.height()
143    );
144    println!("     Height: {:.1} meters", one_world_trade.depth());
145    println!(
146        "     Volume: {:.6} cubic degrees×meters",
147        one_world_trade.volume()
148    );
149
150    let (cx, cy, cz) = one_world_trade.center();
151    println!("     Center: ({:.4}, {:.4}, {:.1}m)", cx, cy, cz);
152
153    // Check if points at different altitudes are within the building
154    println!("\n   Altitude containment checks:");
155    println!(
156        "     Ground level (0m): {}",
157        one_world_trade.contains_point(-74.0126, 40.7135, 0.0)
158    );
159    println!(
160        "     Mid-level (270m): {}",
161        one_world_trade.contains_point(-74.0126, 40.7135, 270.0)
162    );
163    println!(
164        "     Top (540m): {}",
165        one_world_trade.contains_point(-74.0126, 40.7135, 540.0)
166    );
167    println!(
168        "     Above (600m): {}",
169        one_world_trade.contains_point(-74.0126, 40.7135, 600.0)
170    );
171
172    // ========================================
173    // 5. 3D to 2D Projection
174    // ========================================
175    println!("\n5. 3D to 2D Projection");
176    println!("----------------------");
177
178    let building_3d = BoundingBox3D::new(-74.0, 40.7, 0.0, -73.9, 40.8, 200.0);
179    let building_2d = building_3d.to_2d();
180
181    println!("   3D Bounding Box:");
182    println!(
183        "     Dimensions: {:.4}° × {:.4}° × {:.1}m",
184        building_3d.width(),
185        building_3d.height(),
186        building_3d.depth()
187    );
188
189    println!("\n   Projected to 2D:");
190    println!(
191        "     Dimensions: {:.4}° × {:.4}°",
192        building_2d.width(),
193        building_2d.height()
194    );
195
196    // ========================================
197    // 6. Temporal Bounding Boxes
198    // ========================================
199    println!("\n6. Temporal Bounding Boxes");
200    println!("--------------------------");
201
202    // Track how a delivery zone changes over time
203    let morning_zone = BoundingBox2D::new(-74.01, 40.71, -73.99, 40.73);
204    let afternoon_zone = BoundingBox2D::new(-74.02, 40.70, -73.98, 40.74);
205
206    let morning_time = SystemTime::now();
207    let afternoon_time = SystemTime::now();
208
209    let temporal_morning = TemporalBoundingBox2D::new(morning_zone.clone(), morning_time);
210    let temporal_afternoon = TemporalBoundingBox2D::new(afternoon_zone.clone(), afternoon_time);
211
212    println!("   Morning delivery zone:");
213    println!(
214        "     Area: {:.4}° × {:.4}°",
215        temporal_morning.bbox().width(),
216        temporal_morning.bbox().height()
217    );
218
219    println!("\n   Afternoon delivery zone:");
220    println!(
221        "     Area: {:.4}° × {:.4}°",
222        temporal_afternoon.bbox().width(),
223        temporal_afternoon.bbox().height()
224    );
225
226    println!(
227        "     Expansion: {:.4}° wider, {:.4}° taller",
228        afternoon_zone.width() - morning_zone.width(),
229        afternoon_zone.height() - morning_zone.height()
230    );
231
232    // ========================================
233    // 7. Storing Bounding Boxes in Database
234    // ========================================
235    println!("\n7. Storing Bounding Boxes");
236    println!("-------------------------");
237
238    // Serialize and store bounding boxes
239    let bbox_json = serde_json::to_vec(&manhattan)?;
240    db.insert("zones:manhattan", bbox_json, None)?;
241
242    let bbox3d_json = serde_json::to_vec(&one_world_trade)?;
243    db.insert("buildings:wtc", bbox3d_json, None)?;
244
245    println!("   ✓ Stored Manhattan bounding box");
246    println!("   ✓ Stored One World Trade Center 3D box");
247
248    // Retrieve and deserialize
249    if let Some(data) = db.get("zones:manhattan")? {
250        let retrieved: BoundingBox2D = serde_json::from_slice(&data)?;
251        println!("\n   Retrieved Manhattan box:");
252        println!(
253            "     Center: ({:.4}, {:.4})",
254            retrieved.center().x(),
255            retrieved.center().y()
256        );
257    }
258
259    // ========================================
260    // 8. Practical Use Cases
261    // ========================================
262    println!("\n8. Practical Use Cases");
263    println!("----------------------");
264
265    // Geofencing
266    let delivery_area = BoundingBox2D::new(-74.02, 40.70, -73.98, 40.75);
267    let current_location = Point::new(-74.00, 40.72);
268
269    if delivery_area.contains_point(&current_location) {
270        println!("   ✓ Delivery driver is within service area");
271    } else {
272        println!("   ✗ Delivery driver is outside service area");
273    }
274
275    // Airspace management
276    let airspace = BoundingBox3D::new(
277        -74.1, 40.6, 0.0, // Ground level
278        -73.8, 40.9, 3000.0, // 3000m ceiling
279    );
280    let drone_altitude = 150.0; // meters
281    let drone_location = (-74.0, 40.75, drone_altitude);
282
283    if airspace.contains_point(drone_location.0, drone_location.1, drone_location.2) {
284        println!("   ✓ Drone is within authorized airspace");
285    }
286
287    // Region overlap detection
288    let zone_a = BoundingBox2D::new(-74.05, 40.70, -74.00, 40.75);
289    let zone_b = BoundingBox2D::new(-74.02, 40.72, -73.97, 40.77);
290
291    if zone_a.intersects(&zone_b) {
292        println!("   ⚠ Service zones A and B overlap - coordination needed");
293    }
294
295    println!("\n=== Bounding Box Examples Complete! ===");
296    println!("\nKey Features Demonstrated:");
297    println!("  • Create and manipulate 2D/3D bounding boxes");
298    println!("  • Check point containment");
299    println!("  • Detect box intersections");
300    println!("  • Expand regions");
301    println!("  • Project 3D to 2D");
302    println!("  • Track temporal changes");
303    println!("  • Serialize and store in database");
304    println!("  • Geofencing and airspace management");
305
306    Ok(())
307}