1use spatio::{Point3d, Spatio};
2
3fn main() -> Result<(), Box<dyn std::error::Error>> {
4 println!("=== Spatio - Spatial Queries ===\n");
5
6 let db = Spatio::memory()?;
7 println!("✓ Created in-memory database\n");
8
9 println!("Setting up test data...");
11
12 let cities = vec![
13 ("New York", Point3d::new(-74.0060, 40.7128, 0.0)),
14 ("London", Point3d::new(-0.1278, 51.5074, 0.0)),
15 ("Paris", Point3d::new(2.3522, 48.8566, 0.0)),
16 ("Berlin", Point3d::new(13.4050, 52.5200, 0.0)),
17 ("Madrid", Point3d::new(-3.7038, 40.4168, 0.0)),
18 ("Rome", Point3d::new(12.4964, 41.9028, 0.0)),
19 ("Tokyo", Point3d::new(139.6503, 35.6762, 0.0)),
20 ("Sydney", Point3d::new(151.2093, -33.8688, 0.0)),
21 ("Mumbai", Point3d::new(72.8777, 19.0760, 0.0)),
22 ("Cairo", Point3d::new(31.2357, 30.0444, 0.0)),
23 ("São Paulo", Point3d::new(-46.6333, -23.5505, 0.0)),
24 ("Mexico City", Point3d::new(-99.1332, 19.4326, 0.0)),
25 ];
26
27 for (name, point) in &cities {
28 let object_id = name.to_lowercase().replace(" ", "_");
30 db.upsert(
31 "world_cities",
32 &object_id,
33 point.clone(),
34 serde_json::json!({"name": name}),
35 None,
36 )?;
37 }
38 println!(" Added {} cities to spatial index\n", cities.len());
39
40 for i in 0..10 {
43 for j in 0..10 {
44 let id = format!("point-{}-{}", i, j);
45 let lon = -74.0 + (i as f64) * 0.01;
46 let lat = 40.7 + (j as f64) * 0.01;
47 let pos = Point3d::new(lon, lat, 0.0);
48
49 db.upsert(
50 "nyc_grid",
51 &id,
52 pos,
53 serde_json::json!({"category": "grid_point"}),
54 None,
55 )?;
56 }
57 }
58 println!(" Populated database with 100 points in 'nyc_grid' namespace\n");
59
60 println!("1. Radius-Based Queries (query_radius)");
62 println!("-----------------------------------------------------");
63
64 let london = Point3d::new(-0.1278, 51.5074, 0.0);
65
66 let nearby_500km = db.query_radius("world_cities", &london, 500_000.0, 10)?;
68 println!(" Cities within 500km of London: {}", nearby_500km.len());
69 for (loc, dist) in &nearby_500km {
70 println!(" - {} ({:.1}m)", loc.metadata, dist);
71 }
72
73 let nearby_2000km = db.query_radius("world_cities", &london, 2_000_000.0, 10)?;
75 println!(
76 "\n Cities within 2000km of London: {}",
77 nearby_2000km.len()
78 );
79 for (loc, dist) in &nearby_2000km {
80 println!(" - {} ({:.1}m)", loc.metadata, dist);
81 }
82
83 let closest_3 = db.query_radius("world_cities", &london, f64::INFINITY, 3)?;
85 println!("\n Closest 3 cities to London:");
86 for (i, (loc, dist)) in closest_3.iter().enumerate() {
87 println!(" {}. {} ({:.1}m)", i + 1, loc.metadata, dist);
88 }
89 println!();
90
91 println!("2. Existence Checks (simulated via radius query)");
93 println!("------------------------------------------------");
94
95 let has_nearby_500km = !db
96 .query_radius("world_cities", &london, 500_000.0, 1)?
97 .is_empty();
98 let has_nearby_100km = !db
99 .query_radius("world_cities", &london, 100_000.0, 1)?
100 .is_empty();
101
102 println!(" Any cities within 500km of London? {}", has_nearby_500km);
103 println!(" Any cities within 100km of London? {}", has_nearby_100km);
104 println!();
105
106 println!("3. Bounding Box Queries (query_bbox)");
108 println!("---------------------------------------------------");
109
110 println!(" European region (lon: -10 to 20, lat: 40 to 60):");
112 let europe_cities = db.query_bbox("world_cities", -10.0, 40.0, 20.0, 60.0, 20)?;
113 println!(" Found {} cities:", europe_cities.len());
114 for loc in &europe_cities {
115 println!(
116 " - {} at ({:.2}°, {:.2}°)",
117 loc.metadata,
118 loc.position.x(),
119 loc.position.y()
120 );
121 }
122
123 let min_x = -74.06;
125 let min_y = 40.74;
126 let max_x = -74.04;
127 let max_y = 40.76;
128
129 println!("\n6. Bounding Box Query (query_bbox)");
130 println!(" BBox: [{}, {}] to [{}, {}]", min_x, min_y, max_x, max_y);
131
132 let bbox_results = db.query_bbox("nyc_grid", min_x, min_y, max_x, max_y, 100)?;
133 println!(" Found {} points in bounding box", bbox_results.len());
134 for loc in &bbox_results {
135 println!(
136 " - {} at ({:.4}, {:.4})",
137 loc.object_id,
138 loc.position.x(),
139 loc.position.y()
140 );
141 }
142
143 println!("\n Asia-Pacific region (lon: 70 to 180, lat: -40 to 40):");
145 let asia_cities = db.query_bbox("world_cities", 70.0, -40.0, 180.0, 40.0, 20)?;
146 println!(" Found {} cities:", asia_cities.len());
147 for loc in &asia_cities {
148 println!(" - {}", loc.metadata);
149 }
150
151 println!("\n Americas region (lon: -130 to -30, lat: -60 to 60):");
153 let americas_cities = db.query_bbox("world_cities", -130.0, -60.0, -30.0, 60.0, 20)?;
154 println!(" Found {} cities:", americas_cities.len());
155 for loc in &americas_cities {
156 println!(" - {}", loc.metadata);
157 }
158 println!();
159
160 println!("4. Bounding Box Intersection (simulated)");
162 println!("----------------------------------------");
163
164 let has_european = !db
165 .query_bbox("world_cities", -10.0, 40.0, 20.0, 60.0, 1)?
166 .is_empty();
167 let has_antarctica = !db
168 .query_bbox("world_cities", -180.0, -90.0, 180.0, -60.0, 1)?
169 .is_empty();
170
171 println!(" European region has cities? {}", has_european);
172 println!(" Antarctica region has cities? {}", has_antarctica);
173 println!();
174
175 println!("5. Multiple Namespaces");
177 println!("----------------------");
178
179 let london_landmarks = vec![
181 ("Big Ben", Point3d::new(-0.1245, 51.4994, 0.0)),
182 ("Tower Bridge", Point3d::new(-0.0754, 51.5055, 0.0)),
183 ("London Eye", Point3d::new(-0.1195, 51.5033, 0.0)),
184 ("Buckingham Palace", Point3d::new(-0.1419, 51.5014, 0.0)),
185 ];
186
187 for (name, point) in &london_landmarks {
188 let object_id = name.to_lowercase().replace(" ", "_");
189 db.upsert(
190 "landmarks",
191 &object_id,
192 point.clone(),
193 serde_json::json!({"name": name}),
194 None,
195 )?;
196 }
197
198 println!(" Added {} London landmarks", london_landmarks.len());
199
200 let center = Point3d::new(-74.05, 40.75, 0.0);
203 let radius = 3000.0; println!("\n5. Radius Query (query_radius)");
205 println!(" Center: ({:.4}, {:.4})", center.x(), center.y());
206 println!(" Radius: {:.0}m", radius);
207
208 let results = db.query_radius("nyc_grid", ¢er, radius, 100)?;
209 println!(" Found {} points within radius:", results.len());
210
211 if let Some((loc, dist)) = results.first() {
213 println!(" - Sample: {} at {:.1}m", loc.object_id, dist);
214 }
215
216 let start = std::time::Instant::now();
218 for _ in 0..1000 {
219 db.query_radius("nyc_grid", ¢er, radius, 100)?;
220 }
221 println!(" Perf: 1000 radius queries in {:?}", start.elapsed());
222
223 let center_london = Point3d::new(-0.1278, 51.5074, 0.0);
225
226 let nearby_cities = db.query_radius("world_cities", ¢er_london, 10_000.0, 10)?;
227 let nearby_landmarks = db.query_radius("landmarks", ¢er_london, 10_000.0, 10)?;
228
229 println!(" Within 10km of center London:");
230 println!(" Cities: {}", nearby_cities.len());
231 println!(" Landmarks: {}", nearby_landmarks.len());
232
233 println!("\n Landmarks within 2km:");
234 let close_landmarks = db.query_radius("landmarks", ¢er_london, 2_000.0, 10)?;
235 for (loc, dist) in &close_landmarks {
236 println!(" - {} ({:.1}m)", loc.metadata, dist);
237 }
238 println!();
239
240 println!("6. Query Result Limiting");
242 println!("------------------------");
243
244 let all_cities = db.query_radius("world_cities", &london, f64::INFINITY, 100)?;
245 let top_5 = db.query_radius("world_cities", &london, f64::INFINITY, 5)?;
246 let top_3 = db.query_radius("world_cities", &london, f64::INFINITY, 3)?;
247
248 println!(" Total cities in database: {}", all_cities.len());
249 println!(" With limit=5: {} cities", top_5.len());
250 println!(" With limit=3: {} cities", top_3.len());
251 println!();
252
253 let stats = db.stats();
255 println!("=== Query Summary ===");
256 println!("Database statistics:");
257 println!(" Operations: {}", stats.operations_count);
258
259 println!("\nSpatial query methods demonstrated:");
260 println!(" • query_radius - Find points within distance");
261 println!(" • query_bbox - Rectangular region queries");
262 println!(" • Multiple namespaces - Organize different point types");
263 println!(" • Result limiting - Control query result size");
264
265 Ok(())
266}