1use spatio::{
8 Point, Polygon, Spatio,
9 compute::spatial::{
10 DistanceMetric, bounding_box, bounding_rect_for_points, convex_hull, distance_between,
11 },
12};
13
14fn main() -> Result<(), Box<dyn std::error::Error>> {
15 println!("=== Advanced Spatial Operations Demo ===\n");
16
17 let mut db = Spatio::memory()?;
19
20 println!("1. Distance Calculations");
24 println!("{}", "=".repeat(50));
25
26 let new_york = Point::new(-74.0060, 40.7128);
27 let los_angeles = Point::new(-118.2437, 34.0522);
28 let london = Point::new(-0.1278, 51.5074);
29
30 let dist_haversine = distance_between(&new_york, &los_angeles, DistanceMetric::Haversine);
32 let dist_geodesic = distance_between(&new_york, &los_angeles, DistanceMetric::Geodesic);
33 let dist_rhumb = distance_between(&new_york, &los_angeles, DistanceMetric::Rhumb);
34
35 println!("NYC to LA:");
36 println!(" Haversine: {:.2} km", dist_haversine / 1000.0);
37 println!(" Geodesic: {:.2} km", dist_geodesic / 1000.0);
38 println!(" Rhumb: {:.2} km", dist_rhumb / 1000.0);
39
40 let db_distance = db.distance_between(&new_york, &london, DistanceMetric::Haversine)?;
42 println!("\nNYC to London: {:.2} km", db_distance / 1000.0);
43
44 println!("\n2. K-Nearest-Neighbors Query");
48 println!("{}", "=".repeat(50));
49
50 let cities = vec![
52 (Point::new(-74.0060, 40.7128), "New York", "USA"),
53 (Point::new(-118.2437, 34.0522), "Los Angeles", "USA"),
54 (Point::new(-87.6298, 41.8781), "Chicago", "USA"),
55 (Point::new(-95.3698, 29.7604), "Houston", "USA"),
56 (Point::new(-75.1652, 39.9526), "Philadelphia", "USA"),
57 (Point::new(-122.4194, 37.7749), "San Francisco", "USA"),
58 (Point::new(-0.1278, 51.5074), "London", "UK"),
59 (Point::new(2.3522, 48.8566), "Paris", "France"),
60 (Point::new(139.6917, 35.6895), "Tokyo", "Japan"),
61 ];
62
63 for (point, name, country) in &cities {
64 let data = format!("{},{}", name, country);
65 db.insert_point("world_cities", point, data.as_bytes(), None)?;
66 }
67
68 let query_point = Point::new(-74.1719, 40.7357);
70 let nearest = db.knn(
71 "world_cities",
72 &query_point,
73 3,
74 500_000.0, DistanceMetric::Haversine,
76 )?;
77
78 println!("3 nearest cities to query point:");
79 for (i, (_point, data, distance)) in nearest.iter().enumerate() {
80 let city_info = String::from_utf8_lossy(data);
81 println!(
82 " {}. {} ({:.2} km away)",
83 i + 1,
84 city_info,
85 distance / 1000.0
86 );
87 }
88
89 println!("\n3. Polygon Queries");
93 println!("{}", "=".repeat(50));
94
95 use geo::polygon;
97 let east_coast_polygon = polygon![
98 (x: -80.0, y: 35.0), (x: -70.0, y: 35.0), (x: -70.0, y: 45.0), (x: -80.0, y: 45.0), (x: -80.0, y: 35.0), ];
104 let east_coast_polygon: Polygon = east_coast_polygon.into();
105
106 let cities_in_polygon = db.query_within_polygon("world_cities", &east_coast_polygon, 100)?;
107
108 println!("Cities within East Coast polygon:");
109 for (point, data) in &cities_in_polygon {
110 let city_info = String::from_utf8_lossy(data);
111 println!(" - {} at ({:.4}, {:.4})", city_info, point.x(), point.y());
112 }
113
114 println!("\n4. Bounding Box Operations");
118 println!("{}", "=".repeat(50));
119
120 let ny_bbox = bounding_box(-74.5, 40.5, -73.5, 41.0)?;
122 println!("NY Area Bounding Box: {:?}", ny_bbox);
123
124 let cities_in_bbox = db.find_within_bounds("world_cities", 40.5, -74.5, 41.0, -73.5, 100)?;
126 println!("\nCities in NY area bounding box:");
127 for (_point, data) in &cities_in_bbox {
128 let city_info = String::from_utf8_lossy(data);
129 println!(" - {}", city_info);
130 }
131
132 println!("\n5. Convex Hull Calculation");
136 println!("{}", "=".repeat(50));
137
138 let city_points: Vec<Point> = cities.iter().map(|(p, _, _)| *p).collect();
140
141 if let Some(hull) = convex_hull(&city_points) {
143 println!("Convex hull of all cities:");
144 println!(" Exterior points: {}", hull.exterior().0.len() - 1);
145 for coord in hull.exterior().0.iter().take(5) {
146 println!(" ({:.4}, {:.4})", coord.x, coord.y);
147 }
148 }
149
150 println!("\n6. Bounding Rectangle");
154 println!("{}", "=".repeat(50));
155
156 if let Some(bbox) = bounding_rect_for_points(&city_points) {
157 println!("Bounding rectangle of all cities:");
158 println!(" Min: ({:.4}, {:.4})", bbox.min().x, bbox.min().y);
159 println!(" Max: ({:.4}, {:.4})", bbox.max().x, bbox.max().y);
160 println!(" Width: {:.2}°", bbox.max().x - bbox.min().x);
161 println!(" Height: {:.2}°", bbox.max().y - bbox.min().y);
162 }
163
164 println!("\n7. Advanced Radius Queries");
168 println!("{}", "=".repeat(50));
169
170 let count = db.count_within_radius("world_cities", &new_york, 1_000_000.0)?;
172 println!("Cities within 1000km of NYC: {}", count);
173
174 let has_nearby = db.intersects_radius("world_cities", &new_york, 100_000.0)?;
176 println!("Has cities within 100km of NYC: {}", has_nearby);
177
178 let nearby = db.query_within_radius("world_cities", &new_york, 200_000.0, 10)?;
180 println!("\nCities within 200km of NYC:");
181 for (point, data, _distance) in &nearby {
182 let city_info = String::from_utf8_lossy(data);
183 let dist = distance_between(&new_york, point, DistanceMetric::Haversine);
184 println!(" - {} ({:.2} km)", city_info, dist / 1000.0);
185 }
186
187 println!("\n8. Spatial Analytics");
191 println!("{}", "=".repeat(50));
192
193 let mut max_distance = 0.0;
195 let mut furthest_pair = ("", "");
196
197 for (i, (p1, n1, _)) in cities.iter().enumerate() {
198 for (p2, n2, _) in cities.iter().skip(i + 1) {
199 let dist = distance_between(p1, p2, DistanceMetric::Geodesic);
200 if dist > max_distance {
201 max_distance = dist;
202 furthest_pair = (n1, n2);
203 }
204 }
205 }
206
207 println!(
208 "Most distant city pair: {} ↔ {}",
209 furthest_pair.0, furthest_pair.1
210 );
211 println!("Distance: {:.2} km", max_distance / 1000.0);
212
213 let us_cities: Vec<_> = cities
215 .iter()
216 .filter(|(_, _, country)| *country == "USA")
217 .collect();
218
219 if us_cities.len() > 1 {
220 let mut total_distance = 0.0;
221 let mut count = 0;
222
223 for (i, (p1, _, _)) in us_cities.iter().enumerate() {
224 for (p2, _, _) in us_cities.iter().skip(i + 1) {
225 total_distance += distance_between(p1, p2, DistanceMetric::Haversine);
226 count += 1;
227 }
228 }
229
230 let avg_distance = total_distance / count as f64;
231 println!(
232 "\nAverage distance between US cities: {:.2} km",
233 avg_distance / 1000.0
234 );
235 }
236
237 println!("\n{}", "=".repeat(50));
241 println!("Summary:");
242 println!(" - Demonstrated multiple distance metrics");
243 println!(" - Performed K-nearest-neighbor searches");
244 println!(" - Queried points within polygons");
245 println!(" - Used bounding box operations");
246 println!(" - Calculated convex hulls");
247 println!(" - Performed spatial analytics");
248 println!("\nAll spatial operations leverage the geo crate!");
249
250 Ok(())
251}