pub struct Point { /* private fields */ }Expand description
A geographic point with longitude/latitude coordinates.
This wraps geo::Point and provides additional functionality for
GeoJSON conversion, distance calculations, and other operations.
§Examples
use spatio_types::geo::Point;
let nyc = Point::new(-74.0060, 40.7128);
assert_eq!(nyc.x(), -74.0060);
assert_eq!(nyc.y(), 40.7128);Implementations§
Source§impl Point
impl Point
Sourcepub fn new(x: f64, y: f64) -> Point
pub fn new(x: f64, y: f64) -> Point
Create a new point from x (longitude) and y (latitude) coordinates.
§Arguments
x- Longitude in degrees (typically -180 to 180)y- Latitude in degrees (typically -90 to 90)
§Examples
use spatio_types::geo::Point;
let point = Point::new(-74.0060, 40.7128);Examples found in repository?
4fn main() -> Result<(), Box<dyn std::error::Error>> {
5 // Initialize logging (set RUST_LOG=debug to see detailed logs)
6 env_logger::init();
7
8 println!("=== Spatio - Getting Started ===\n");
9
10 // Create an in-memory database
11 let mut db = Spatio::memory()?;
12 println!("✓ Created in-memory database\n");
13
14 // === BASIC KEY-VALUE STORAGE ===
15 println!("1. Basic Key-Value Storage");
16 println!("---------------------------");
17
18 db.insert("user:123", b"John Doe", None)?;
19 let value = db.get("user:123")?.unwrap();
20 println!(" Stored: user:123 = {}", String::from_utf8_lossy(&value));
21
22 // Store data with TTL (time-to-live)
23 let ttl_options = SetOptions::with_ttl(Duration::from_secs(5));
24 db.insert("session:abc", b"expires_soon", Some(ttl_options))?;
25 println!(" Stored session data with 5-second TTL\n");
26
27 // === SPATIAL OPERATIONS ===
28 println!("2. Spatial Point Storage");
29 println!("------------------------");
30
31 // Store geographic points (lon, lat format)
32 let nyc = Point::new(-74.0060, 40.7128);
33 let london = Point::new(-0.1278, 51.5074);
34 let paris = Point::new(2.3522, 48.8566);
35
36 db.insert_point("cities", &nyc, b"New York", None)?;
37 db.insert_point("cities", &london, b"London", None)?;
38 db.insert_point("cities", &paris, b"Paris", None)?;
39 println!(" Stored 3 cities with automatic spatial indexing");
40
41 // Find nearby cities within radius (in meters)
42 let nearby = db.query_within_radius("cities", &london, 500_000.0, 10)?;
43 println!(" Found {} cities within 500km of London:", nearby.len());
44 for (_, data, _) in &nearby {
45 println!(" - {}", String::from_utf8_lossy(data));
46 }
47 println!();
48
49 // === SPATIAL QUERY METHODS ===
50 println!("3. Spatial Query Methods");
51 println!("------------------------");
52
53 // Check if any points exist within radius
54 let has_nearby = db.intersects_radius("cities", &paris, 1_000_000.0)?;
55 println!(" Cities within 1000km of Paris: {}", has_nearby);
56
57 // Count points within radius
58 let count = db.count_within_radius("cities", &nyc, 6_000_000.0)?;
59 println!(" Cities within 6000km of NYC: {}", count);
60
61 // Find points within bounding box (min_lon, min_lat, max_lon, max_lat)
62 let results = db.find_within_bounds("cities", -10.0, 40.0, 10.0, 55.0, 10)?;
63 println!(" Cities in European bounding box: {}", results.len());
64 for (_point, data) in results {
65 println!(" - {}", String::from_utf8_lossy(&data));
66 }
67 println!();
68
69 // === ATOMIC OPERATIONS ===
70 println!("4. Atomic Batch Operations");
71 println!("---------------------------");
72
73 db.atomic(|batch| {
74 batch.insert("sensor:temp", b"22.5C", None)?;
75 batch.insert("sensor:humidity", b"65%", None)?;
76 batch.insert("sensor:pressure", b"1013 hPa", None)?;
77 Ok(())
78 })?;
79 println!(" Atomically inserted 3 sensor readings\n");
80
81 // === TRAJECTORY TRACKING ===
82 println!("5. Trajectory Tracking");
83 println!("----------------------");
84
85 let vehicle_path = vec![
86 TemporalPoint {
87 point: Point::new(-74.0060, 40.7128),
88 timestamp: UNIX_EPOCH + Duration::from_secs(1640995200),
89 },
90 TemporalPoint {
91 point: Point::new(-74.0040, 40.7150),
92 timestamp: UNIX_EPOCH + Duration::from_secs(1640995260),
93 },
94 TemporalPoint {
95 point: Point::new(-74.0020, 40.7172),
96 timestamp: UNIX_EPOCH + Duration::from_secs(1640995320),
97 },
98 ];
99
100 db.insert_trajectory("vehicle:truck001", &vehicle_path, None)?;
101 println!(
102 " Stored vehicle trajectory with {} waypoints",
103 vehicle_path.len()
104 );
105
106 // Query trajectory for time range
107 let path_segment = db.query_trajectory("vehicle:truck001", 1640995200, 1640995320)?;
108 println!(
109 " Retrieved {} waypoints from trajectory\n",
110 path_segment.len()
111 );
112
113 // === DATABASE STATS ===
114 println!("6. Database Statistics");
115 println!("----------------------");
116
117 let stats = db.stats();
118 println!(" Total keys stored: {}", stats.key_count);
119 println!(" Total operations: {}\n", stats.operations_count);
120
121 // === TTL DEMONSTRATION (LAZY) ===
122 println!("7. TTL Expiration (Lazy Deletion)");
123 println!("----------------------------------");
124 println!(" Waiting 6 seconds for TTL expiration...");
125 std::thread::sleep(Duration::from_secs(6));
126
127 match db.get("session:abc")? {
128 Some(_) => println!(" Session still active (unexpected)"),
129 None => println!(" ✓ Session expired (lazy check on read)"),
130 }
131
132 // Manual cleanup
133 let removed = db.cleanup_expired()?;
134 println!(" Cleaned up {} expired keys from storage\n", removed);
135
136 println!("=== Getting Started Complete! ===");
137 println!("\nKey Features Demonstrated:");
138 println!(" • Simple key-value storage");
139 println!(" • Automatic spatial indexing");
140 println!(" • Radius-based queries");
141 println!(" • Bounding box queries");
142 println!(" • Trajectory tracking");
143 println!(" • TTL support (lazy expiration + manual cleanup)");
144 println!(" • Atomic operations");
145 println!("\nNext: Try 'spatial_queries' example for more advanced queries");
146
147 Ok(())
148}More examples
4fn main() -> Result<(), Box<dyn std::error::Error>> {
5 println!("=== Spatio - Comprehensive Demo ===\n");
6
7 let mut db = Spatio::memory()?;
8 println!("✓ Created in-memory database\n");
9
10 // === 1. BASIC KEY-VALUE OPERATIONS ===
11 println!("1. Basic Key-Value Operations");
12 println!("------------------------------");
13
14 db.insert("app:name", b"Spatio Demo", None)?;
15 db.insert("app:version", b"1.0.0", None)?;
16 db.insert("user:alice", b"Alice Johnson", None)?;
17
18 let app_name = db.get("app:name")?.unwrap();
19 println!(" Stored: {}", String::from_utf8_lossy(&app_name));
20
21 let count = db.stats().key_count;
22 println!(" Total keys: {}\n", count);
23
24 // === 2. TTL (TIME-TO-LIVE) ===
25 println!("2. TTL (Time-to-Live)");
26 println!("---------------------");
27
28 let session_opts = SetOptions::with_ttl(Duration::from_secs(10));
29 db.insert("session:temp", b"expires_soon", Some(session_opts))?;
30 println!(" Created session with 10-second TTL");
31
32 let cache_opts = SetOptions::with_ttl(Duration::from_secs(300));
33 db.insert("cache:weather", b"sunny, 22C", Some(cache_opts))?;
34 println!(" Cached data with 5-minute TTL\n");
35
36 // === 3. ATOMIC BATCH OPERATIONS ===
37 println!("3. Atomic Batch Operations");
38 println!("--------------------------");
39
40 db.atomic(|batch| {
41 batch.insert("sensor:temp", b"23.5", None)?;
42 batch.insert("sensor:humidity", b"68", None)?;
43 batch.insert("sensor:pressure", b"1013", None)?;
44 Ok(())
45 })?;
46 println!(" Atomically inserted 3 sensor readings\n");
47
48 // === 4. SPATIAL POINT STORAGE ===
49 println!("4. Spatial Point Storage");
50 println!("------------------------");
51
52 let cities = vec![
53 ("New York", Point::new(-74.0060, 40.7128)),
54 ("London", Point::new(-0.1278, 51.5074)),
55 ("Paris", Point::new(2.3522, 48.8566)),
56 ("Tokyo", Point::new(139.6503, 35.6762)),
57 ("Sydney", Point::new(151.2093, -33.8688)),
58 ];
59
60 for (name, point) in &cities {
61 db.insert_point("cities", point, name.as_bytes(), None)?;
62 }
63 println!(" Stored {} cities with spatial indexing", cities.len());
64
65 // Find nearby cities
66 let london = Point::new(-0.1278, 51.5074);
67 let nearby = db.query_within_radius("cities", &london, 1_000_000.0, 10)?;
68 println!(" Cities within 1000km of London: {}", nearby.len());
69 for (_, data, _) in &nearby {
70 println!(" - {}", String::from_utf8_lossy(data));
71 }
72 println!();
73
74 // === 5. SPATIAL QUERIES ===
75 println!("5. Spatial Query Methods");
76 println!("------------------------");
77
78 // Existence check
79 let has_nearby = db.intersects_radius("cities", &london, 500_000.0)?;
80 println!(" Cities within 500km of London exist: {}", has_nearby);
81
82 // Count points
83 let count = db.count_within_radius("cities", &london, 2_000_000.0)?;
84 println!(" Cities within 2000km of London: {}", count);
85
86 // Bounding box query (Europe)
87 let europe = db.find_within_bounds("cities", -10.0, 40.0, 20.0, 60.0, 10)?;
88 println!(" Cities in European bounding box: {}", europe.len());
89 for (_point, data) in europe {
90 println!(" - {}", String::from_utf8_lossy(&data));
91 }
92 println!();
93
94 // === 6. POINTS OF INTEREST ===
95 println!("6. Multiple Namespaces (POI)");
96 println!("----------------------------");
97
98 let landmarks = vec![
99 ("Big Ben", Point::new(-0.1245, 51.4994)),
100 ("Tower Bridge", Point::new(-0.0754, 51.5055)),
101 ("London Eye", Point::new(-0.1195, 51.5033)),
102 ];
103
104 for (name, point) in &landmarks {
105 db.insert_point("landmarks", point, name.as_bytes(), None)?;
106 }
107 println!(" Added {} London landmarks", landmarks.len());
108
109 // Query different namespaces
110 let nearby_landmarks = db.query_within_radius("landmarks", &london, 5_000.0, 10)?;
111 println!(
112 " Landmarks within 5km of London: {}",
113 nearby_landmarks.len()
114 );
115 for (_, data, _) in &nearby_landmarks {
116 println!(" - {}", String::from_utf8_lossy(data));
117 }
118 println!();
119
120 // === 7. TRAJECTORY TRACKING ===
121 println!("7. Trajectory Tracking");
122 println!("----------------------");
123
124 let delivery_route = vec![
125 TemporalPoint {
126 point: Point::new(-0.1278, 51.5074),
127 timestamp: UNIX_EPOCH + Duration::from_secs(1640995200),
128 },
129 TemporalPoint {
130 point: Point::new(-0.0931, 51.5055),
131 timestamp: UNIX_EPOCH + Duration::from_secs(1640995260),
132 },
133 TemporalPoint {
134 point: Point::new(-0.0865, 51.5045),
135 timestamp: UNIX_EPOCH + Duration::from_secs(1640995320),
136 },
137 TemporalPoint {
138 point: Point::new(-0.1245, 51.4994),
139 timestamp: UNIX_EPOCH + Duration::from_secs(1640995380),
140 },
141 ];
142
143 db.insert_trajectory("delivery:truck001", &delivery_route, None)?;
144 println!(
145 " Stored delivery trajectory ({} waypoints)",
146 delivery_route.len()
147 );
148
149 // Query trajectory for time range
150 let path = db.query_trajectory("delivery:truck001", 1640995200, 1640995320)?;
151 println!(
152 " Retrieved {} waypoints for first 2 minutes\n",
153 path.len()
154 );
155
156 // === 8. DATA UPDATES & DELETES ===
157 println!("8. Updates and Deletes");
158 println!("----------------------");
159
160 // Update existing key
161 db.insert("app:version", b"1.0.1", None)?;
162 let new_version = db.get("app:version")?.unwrap();
163 println!(
164 " Updated version to: {}",
165 String::from_utf8_lossy(&new_version)
166 );
167
168 // Delete key
169 let deleted = db.delete("user:alice")?;
170 println!(" Deleted key: {}", deleted.is_some());
171 println!();
172
173 // === 9. DATABASE STATISTICS ===
174 println!("9. Database Statistics");
175 println!("----------------------");
176
177 let stats = db.stats();
178 println!(" Total keys: {}", stats.key_count);
179 println!(" Total operations: {}\n", stats.operations_count);
180
181 // === 10. TTL EXPIRATION DEMO (LAZY) ===
182 println!("10. TTL Expiration (lazy deletion)");
183 println!("-----------------------------------");
184
185 std::thread::sleep(Duration::from_secs(11));
186
187 match db.get("session:temp")? {
188 Some(_) => println!(" Session still active (unexpected)"),
189 None => println!(" ✓ Session expired (lazy check on read)\n"),
190 }
191
192 // === 11. MANUAL CLEANUP ===
193 println!("11. Manual Cleanup");
194 println!("------------------");
195 let removed = db.cleanup_expired()?;
196 println!(" Removed {} expired keys from storage\n", removed);
197
198 println!("=== Comprehensive Demo Complete! ===");
199 println!("\nFeatures Demonstrated:");
200 println!(" • Key-value storage");
201 println!(" • TTL (lazy expiration + manual cleanup)");
202 println!(" • Atomic batch operations");
203 println!(" • Spatial point indexing");
204 println!(" • Radius queries");
205 println!(" • Bounding box queries");
206 println!(" • Multiple namespaces");
207 println!(" • Trajectory tracking");
208 println!(" • Updates and deletes");
209 println!(" • Manual expired key cleanup");
210
211 Ok(())
212}3fn main() -> Result<(), Box<dyn std::error::Error>> {
4 println!("=== Spatio - Spatial Queries ===\n");
5
6 let mut db = Spatio::memory()?;
7 println!("✓ Created in-memory database\n");
8
9 // === SETUP: Insert World Cities ===
10 println!("Setting up test data...");
11
12 let cities = vec![
13 ("New York", Point::new(-74.0060, 40.7128)),
14 ("London", Point::new(-0.1278, 51.5074)),
15 ("Paris", Point::new(2.3522, 48.8566)),
16 ("Berlin", Point::new(13.4050, 52.5200)),
17 ("Madrid", Point::new(-3.7038, 40.4168)),
18 ("Rome", Point::new(12.4964, 41.9028)),
19 ("Tokyo", Point::new(139.6503, 35.6762)),
20 ("Sydney", Point::new(151.2093, -33.8688)),
21 ("Mumbai", Point::new(72.8777, 19.0760)),
22 ("Cairo", Point::new(31.2357, 30.0444)),
23 ("São Paulo", Point::new(-46.6333, -23.5505)),
24 ("Mexico City", Point::new(-99.1332, 19.4326)),
25 ];
26
27 for (name, point) in &cities {
28 db.insert_point("world_cities", point, name.as_bytes(), None)?;
29 }
30 println!(" Added {} cities to spatial index\n", cities.len());
31
32 // === 1. RADIUS QUERIES ===
33 println!("1. Radius-Based Queries (query_within_radius)");
34 println!("----------------------------------------------");
35
36 let london = Point::new(-0.1278, 51.5074);
37
38 // Find cities within 500km of London
39 let nearby_500km = db.query_within_radius("world_cities", &london, 500_000.0, 10)?;
40 println!(" Cities within 500km of London: {}", nearby_500km.len());
41 for (_, data, _) in &nearby_500km {
42 println!(" - {}", String::from_utf8_lossy(data));
43 }
44
45 // Find cities within 2000km of London
46 let nearby_2000km = db.query_within_radius("world_cities", &london, 2_000_000.0, 10)?;
47 println!(
48 "\n Cities within 2000km of London: {}",
49 nearby_2000km.len()
50 );
51 for (_, data, _) in &nearby_2000km {
52 println!(" - {}", String::from_utf8_lossy(data));
53 }
54
55 // Use limit to get only closest N cities
56 let closest_3 = db.query_within_radius("world_cities", &london, f64::INFINITY, 3)?;
57 println!("\n Closest 3 cities to London:");
58 for (i, (_, data, _)) in closest_3.iter().enumerate() {
59 println!(" {}. {}", i + 1, String::from_utf8_lossy(data));
60 }
61 println!();
62
63 // === 2. EXISTENCE CHECKS ===
64 println!("2. Existence Checks (contains_point)");
65 println!("-------------------------------------");
66
67 let has_nearby_500km = db.intersects_radius("world_cities", &london, 500_000.0)?;
68 let has_nearby_100km = db.intersects_radius("world_cities", &london, 100_000.0)?;
69
70 println!(" Any cities within 500km of London? {}", has_nearby_500km);
71 println!(" Any cities within 100km of London? {}", has_nearby_100km);
72
73 // === 3. COUNTING POINTS ===
74 println!("3. Counting Points (count_within_radius)");
75 println!("----------------------------------------");
76
77 let count_500km = db.count_within_radius("world_cities", &london, 500_000.0)?;
78 let count_1000km = db.count_within_radius("world_cities", &london, 1_000_000.0)?;
79 let count_2000km = db.count_within_radius("world_cities", &london, 2_000_000.0)?;
80
81 println!(" Cities within 500km of London: {}", count_500km);
82 println!(" Cities within 1000km of London: {}", count_1000km);
83 println!(" Cities within 2000km of London: {}", count_2000km);
84 println!();
85
86 // === 4. BOUNDING BOX QUERIES ===
87 println!("4. Bounding Box Queries");
88 println!("-----------------------");
89
90 // European bounding box (min_lon, min_lat, max_lon, max_lat)
91 println!(" European region (lon: -10 to 20, lat: 40 to 60):");
92 let europe_cities = db.find_within_bounds("world_cities", -10.0, 40.0, 20.0, 60.0, 20)?;
93 println!(" Found {} cities:", europe_cities.len());
94 for (point, data) in &europe_cities {
95 println!(
96 " - {} at ({:.2}°, {:.2}°)",
97 String::from_utf8_lossy(data),
98 point.x(),
99 point.y()
100 );
101 }
102
103 // Asia-Pacific region
104 println!("\n Asia-Pacific region (lon: 70 to 180, lat: -40 to 40):");
105 let asia_cities = db.find_within_bounds("world_cities", 70.0, -40.0, 180.0, 40.0, 20)?;
106 println!(" Found {} cities:", asia_cities.len());
107 for (_, data) in &asia_cities {
108 println!(" - {}", String::from_utf8_lossy(data));
109 }
110
111 // Americas region
112 println!("\n Americas region (lon: -130 to -30, lat: -60 to 60):");
113 let americas_cities = db.find_within_bounds("world_cities", -130.0, -60.0, -30.0, 60.0, 20)?;
114 println!(" Found {} cities:", americas_cities.len());
115 for (_, data) in &americas_cities {
116 println!(" - {}", String::from_utf8_lossy(data));
117 }
118 println!();
119
120 // === 5. BOUNDING BOX INTERSECTION ===
121 println!("5. Bounding Box Intersection (intersects_bounds)");
122 println!("------------------------------------------------");
123
124 let has_european = db.intersects_bounds("world_cities", -10.0, 40.0, 20.0, 60.0)?;
125 let has_antarctica = db.intersects_bounds("world_cities", -180.0, -90.0, 180.0, -60.0)?;
126
127 println!(" European region has cities? {}", has_european);
128 println!(" Antarctica region has cities? {}", has_antarctica);
129 println!();
130
131 // === 6. MULTIPLE NAMESPACES ===
132 println!("6. Multiple Namespaces");
133 println!("----------------------");
134
135 // Add some landmarks in London
136 let london_landmarks = vec![
137 ("Big Ben", Point::new(-0.1245, 51.4994)),
138 ("Tower Bridge", Point::new(-0.0754, 51.5055)),
139 ("London Eye", Point::new(-0.1195, 51.5033)),
140 ("Buckingham Palace", Point::new(-0.1419, 51.5014)),
141 ];
142
143 for (name, point) in &london_landmarks {
144 db.insert_point("landmarks", point, name.as_bytes(), None)?;
145 }
146
147 println!(" Added {} London landmarks", london_landmarks.len());
148
149 // Query different namespaces from same location
150 let center_london = Point::new(-0.1278, 51.5074);
151
152 let nearby_cities = db.query_within_radius("world_cities", ¢er_london, 10_000.0, 10)?;
153 let nearby_landmarks = db.query_within_radius("landmarks", ¢er_london, 10_000.0, 10)?;
154
155 println!(" Within 10km of center London:");
156 println!(" Cities: {}", nearby_cities.len());
157 println!(" Landmarks: {}", nearby_landmarks.len());
158
159 println!("\n Landmarks within 2km:");
160 let close_landmarks = db.query_within_radius("landmarks", ¢er_london, 2_000.0, 10)?;
161 for (_, data, _) in &close_landmarks {
162 println!(" - {}", String::from_utf8_lossy(data));
163 }
164 println!();
165
166 // === 7. QUERY LIMITS ===
167 println!("7. Query Result Limiting");
168 println!("------------------------");
169
170 let all_cities = db.query_within_radius("world_cities", &london, f64::INFINITY, 100)?;
171 let top_5 = db.query_within_radius("world_cities", &london, f64::INFINITY, 5)?;
172 let top_3 = db.query_within_radius("world_cities", &london, f64::INFINITY, 3)?;
173
174 println!(" Total cities in database: {}", all_cities.len());
175 println!(" With limit=5: {} cities", top_5.len());
176 println!(" With limit=3: {} cities", top_3.len());
177 println!();
178
179 // === SUMMARY ===
180 let stats = db.stats();
181 println!("=== Query Summary ===");
182 println!("Database statistics:");
183 println!(" Total keys: {}", stats.key_count);
184 println!(" Operations: {}", stats.operations_count);
185
186 println!("\nSpatial query methods demonstrated:");
187 println!(" • query_within_radius - Find points within distance");
188 println!(" • contains_point - Check if points exist in radius");
189 println!(" • count_within_radius - Count points efficiently");
190 println!(" • find_within_bounds - Rectangular region queries");
191 println!(" • intersects_bounds - Check bounding box intersection");
192 println!(" • Multiple namespaces - Organize different point types");
193 println!(" • Result limiting - Control query result size");
194
195 Ok(())
196}4fn main() -> Result<(), Box<dyn std::error::Error>> {
5 println!("=== Spatio - Trajectory Tracking ===\n");
6
7 let mut db = Spatio::memory()?;
8 println!("✓ Created in-memory database\n");
9
10 // === 1. BASIC TRAJECTORY STORAGE ===
11 println!("1. Basic Trajectory Storage");
12 println!("---------------------------");
13
14 // Create a simple delivery route
15 let delivery_route = vec![
16 TemporalPoint {
17 point: Point::new(-74.0060, 40.7128), // NYC
18 timestamp: UNIX_EPOCH + Duration::from_secs(1640995200),
19 },
20 TemporalPoint {
21 point: Point::new(-74.0040, 40.7150),
22 timestamp: UNIX_EPOCH + Duration::from_secs(1640995260), // +1 min
23 },
24 TemporalPoint {
25 point: Point::new(-74.0020, 40.7172),
26 timestamp: UNIX_EPOCH + Duration::from_secs(1640995320), // +2 min
27 },
28 TemporalPoint {
29 point: Point::new(-74.0000, 40.7194),
30 timestamp: UNIX_EPOCH + Duration::from_secs(1640995380), // +3 min
31 },
32 ];
33
34 db.insert_trajectory("vehicle:truck001", &delivery_route, None)?;
35 println!(
36 " Stored delivery truck trajectory with {} waypoints\n",
37 delivery_route.len()
38 );
39
40 // === 2. QUERY FULL TRAJECTORY ===
41 println!("2. Query Full Trajectory");
42 println!("------------------------");
43
44 let full_path = db.query_trajectory("vehicle:truck001", 1640995200, 1640995400)?;
45 println!(" Retrieved {} waypoints:", full_path.len());
46 for (i, tp) in full_path.iter().enumerate() {
47 println!(
48 " {}. Point ({:.4}°, {:.4}°) at timestamp {}",
49 i + 1,
50 tp.point.x(),
51 tp.point.y(),
52 tp.timestamp.duration_since(UNIX_EPOCH).unwrap().as_secs()
53 );
54 }
55 println!();
56
57 // === 3. QUERY TIME RANGE ===
58 println!("3. Query Specific Time Range");
59 println!("----------------------------");
60
61 // Get only first 2 minutes of trajectory
62 let partial_path = db.query_trajectory("vehicle:truck001", 1640995200, 1640995320)?;
63 println!(" First 2 minutes: {} waypoints", partial_path.len());
64
65 // Get only middle segment
66 let middle_segment = db.query_trajectory("vehicle:truck001", 1640995260, 1640995320)?;
67 println!(" Middle segment: {} waypoints\n", middle_segment.len());
68
69 // === 4. MULTIPLE TRAJECTORIES ===
70 println!("4. Multiple Trajectories");
71 println!("------------------------");
72
73 // Add taxi route
74 let taxi_route = vec![
75 TemporalPoint {
76 point: Point::new(-0.1278, 51.5074), // London
77 timestamp: UNIX_EPOCH + Duration::from_secs(1640995200),
78 },
79 TemporalPoint {
80 point: Point::new(-0.1195, 51.5033),
81 timestamp: UNIX_EPOCH + Duration::from_secs(1640995260),
82 },
83 TemporalPoint {
84 point: Point::new(-0.1245, 51.4994),
85 timestamp: UNIX_EPOCH + Duration::from_secs(1640995320),
86 },
87 ];
88
89 db.insert_trajectory("vehicle:taxi042", &taxi_route, None)?;
90 println!(
91 " Stored taxi trajectory with {} waypoints",
92 taxi_route.len()
93 );
94
95 // Add bus route
96 let bus_route = vec![
97 TemporalPoint {
98 point: Point::new(2.3522, 48.8566), // Paris
99 timestamp: UNIX_EPOCH + Duration::from_secs(1640995200),
100 },
101 TemporalPoint {
102 point: Point::new(2.3550, 48.8580),
103 timestamp: UNIX_EPOCH + Duration::from_secs(1640995300),
104 },
105 TemporalPoint {
106 point: Point::new(2.3580, 48.8600),
107 timestamp: UNIX_EPOCH + Duration::from_secs(1640995400),
108 },
109 TemporalPoint {
110 point: Point::new(2.3610, 48.8620),
111 timestamp: UNIX_EPOCH + Duration::from_secs(1640995500),
112 },
113 TemporalPoint {
114 point: Point::new(2.3640, 48.8640),
115 timestamp: UNIX_EPOCH + Duration::from_secs(1640995600),
116 },
117 ];
118
119 db.insert_trajectory("vehicle:bus123", &bus_route, None)?;
120 println!(
121 " Stored bus trajectory with {} waypoints\n",
122 bus_route.len()
123 );
124
125 // === 5. QUERY DIFFERENT VEHICLES ===
126 println!("5. Query Different Vehicles");
127 println!("---------------------------");
128
129 let truck_path = db.query_trajectory("vehicle:truck001", 1640995200, 1640995400)?;
130 let taxi_path = db.query_trajectory("vehicle:taxi042", 1640995200, 1640995400)?;
131 let bus_path = db.query_trajectory("vehicle:bus123", 1640995200, 1640995700)?;
132
133 println!(" Truck waypoints: {}", truck_path.len());
134 println!(" Taxi waypoints: {}", taxi_path.len());
135 println!(" Bus waypoints: {}\n", bus_path.len());
136
137 // === 6. LONG-RUNNING TRAJECTORY ===
138 println!("6. Long-Running Trajectory (High Frequency)");
139 println!("-------------------------------------------");
140
141 // Simulate a drone with frequent position updates
142 let mut drone_path = Vec::new();
143 let start_time = 1641000000;
144
145 for i in 0..60 {
146 // 60 waypoints, 1 per second
147 drone_path.push(TemporalPoint {
148 point: Point::new(
149 -122.4194 + (i as f64 * 0.0001), // San Francisco area
150 37.7749 + (i as f64 * 0.0001),
151 ),
152 timestamp: UNIX_EPOCH + Duration::from_secs(start_time + i),
153 });
154 }
155
156 db.insert_trajectory("drone:delivery001", &drone_path, None)?;
157 println!(
158 " Stored drone trajectory with {} waypoints",
159 drone_path.len()
160 );
161
162 // Query specific time window (10 seconds)
163 let window = db.query_trajectory("drone:delivery001", start_time, start_time + 10)?;
164 println!(
165 " Retrieved 10-second window: {} waypoints\n",
166 window.len()
167 );
168
169 // === 7. TRAJECTORY UPDATES ===
170 println!("7. Trajectory Updates");
171 println!("---------------------");
172
173 // Add more waypoints to existing trajectory
174 let extended_route = vec![
175 TemporalPoint {
176 point: Point::new(-74.0060, 40.7128),
177 timestamp: UNIX_EPOCH + Duration::from_secs(1640995200),
178 },
179 TemporalPoint {
180 point: Point::new(-74.0040, 40.7150),
181 timestamp: UNIX_EPOCH + Duration::from_secs(1640995260),
182 },
183 TemporalPoint {
184 point: Point::new(-74.0020, 40.7172),
185 timestamp: UNIX_EPOCH + Duration::from_secs(1640995320),
186 },
187 TemporalPoint {
188 point: Point::new(-74.0000, 40.7194),
189 timestamp: UNIX_EPOCH + Duration::from_secs(1640995380),
190 },
191 // New waypoints
192 TemporalPoint {
193 point: Point::new(-73.9980, 40.7216),
194 timestamp: UNIX_EPOCH + Duration::from_secs(1640995440),
195 },
196 TemporalPoint {
197 point: Point::new(-73.9960, 40.7238),
198 timestamp: UNIX_EPOCH + Duration::from_secs(1640995500),
199 },
200 ];
201
202 db.insert_trajectory("vehicle:truck001", &extended_route, None)?;
203 let updated_path = db.query_trajectory("vehicle:truck001", 1640995200, 1640995600)?;
204 println!(
205 " Extended truck trajectory from 4 to {} waypoints\n",
206 updated_path.len()
207 );
208
209 // === 8. DATABASE STATISTICS ===
210 println!("8. Database Statistics");
211 println!("----------------------");
212
213 let stats = db.stats();
214 println!(" Total keys in database: {}", stats.key_count);
215 println!(" Total operations: {}\n", stats.operations_count);
216
217 // === 9. USE CASES ===
218 println!("=== Common Use Cases ===\n");
219
220 println!("Fleet Management:");
221 println!(" • Track multiple vehicles in real-time");
222 println!(" • Query historical routes for analysis");
223 println!(" • Retrieve specific time windows for incidents\n");
224
225 println!("Delivery Tracking:");
226 println!(" • Store complete delivery routes");
227 println!(" • Query progress during specific periods");
228 println!(" • Analyze route efficiency\n");
229
230 println!("Drone Operations:");
231 println!(" • High-frequency position updates");
232 println!(" • Flight path analysis");
233 println!(" • Time-based route queries\n");
234
235 println!("Asset Tracking:");
236 println!(" • Monitor movement of valuable items");
237 println!(" • Historical location queries");
238 println!(" • Route verification\n");
239
240 println!("=== Trajectory Tracking Complete! ===");
241 println!("\nKey Features Demonstrated:");
242 println!(" • Store trajectories with timestamps");
243 println!(" • Query full trajectories");
244 println!(" • Query specific time ranges");
245 println!(" • Track multiple vehicles/objects");
246 println!(" • High-frequency updates");
247 println!(" • Trajectory extensions/updates");
248
249 Ok(())
250}14fn main() -> Result<(), Box<dyn std::error::Error>> {
15 println!("=== Advanced Spatial Operations Demo ===\n");
16
17 // Create an in-memory database
18 let mut db = Spatio::memory()?;
19
20 // ========================================
21 // 1. Distance Calculations
22 // ========================================
23 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 // Calculate distances using different metrics
31 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 // Using the database method
41 let db_distance = db.distance_between(&new_york, &london, DistanceMetric::Haversine)?;
42 println!("\nNYC to London: {:.2} km", db_distance / 1000.0);
43
44 // ========================================
45 // 2. K-Nearest-Neighbors (KNN)
46 // ========================================
47 println!("\n2. K-Nearest-Neighbors Query");
48 println!("{}", "=".repeat(50));
49
50 // Insert major cities
51 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 // Find 3 nearest cities to a query point (somewhere in New Jersey)
69 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, // Search within 500km
75 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 // ========================================
90 // 3. Polygon Queries
91 // ========================================
92 println!("\n3. Polygon Queries");
93 println!("{}", "=".repeat(50));
94
95 // Define a polygon covering parts of the eastern US
96 use geo::polygon;
97 let east_coast_polygon = polygon![
98 (x: -80.0, y: 35.0), // South
99 (x: -70.0, y: 35.0), // Southeast
100 (x: -70.0, y: 45.0), // Northeast
101 (x: -80.0, y: 45.0), // Northwest
102 (x: -80.0, y: 35.0), // Close the polygon
103 ];
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 // ========================================
115 // 4. Bounding Box Operations
116 // ========================================
117 println!("\n4. Bounding Box Operations");
118 println!("{}", "=".repeat(50));
119
120 // Create a bounding box around the New York area
121 let ny_bbox = bounding_box(-74.5, 40.5, -73.5, 41.0)?;
122 println!("NY Area Bounding Box: {:?}", ny_bbox);
123
124 // Find cities in bounding box
125 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 // ========================================
133 // 5. Convex Hull
134 // ========================================
135 println!("\n5. Convex Hull Calculation");
136 println!("{}", "=".repeat(50));
137
138 // Get all city points
139 let city_points: Vec<Point> = cities.iter().map(|(p, _, _)| *p).collect();
140
141 // Calculate convex hull
142 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 // ========================================
151 // 6. Bounding Rectangle
152 // ========================================
153 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 // ========================================
165 // 7. Advanced Radius Queries
166 // ========================================
167 println!("\n7. Advanced Radius Queries");
168 println!("{}", "=".repeat(50));
169
170 // Count cities within 1000km of NYC
171 let count = db.count_within_radius("world_cities", &new_york, 1_000_000.0)?;
172 println!("Cities within 1000km of NYC: {}", count);
173
174 // Check if any cities exist within 100km
175 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 // Query with radius
179 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 // ========================================
188 // 8. Spatial Analytics
189 // ========================================
190 println!("\n8. Spatial Analytics");
191 println!("{}", "=".repeat(50));
192
193 // Find the two most distant cities (brute force)
194 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 // Calculate average distance between all US cities
214 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 // ========================================
238 // Summary
239 // ========================================
240 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}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}Sourcepub fn x(&self) -> f64
pub fn x(&self) -> f64
Get the x coordinate (longitude).
Examples found in repository?
3fn main() -> Result<(), Box<dyn std::error::Error>> {
4 println!("=== Spatio - Spatial Queries ===\n");
5
6 let mut db = Spatio::memory()?;
7 println!("✓ Created in-memory database\n");
8
9 // === SETUP: Insert World Cities ===
10 println!("Setting up test data...");
11
12 let cities = vec![
13 ("New York", Point::new(-74.0060, 40.7128)),
14 ("London", Point::new(-0.1278, 51.5074)),
15 ("Paris", Point::new(2.3522, 48.8566)),
16 ("Berlin", Point::new(13.4050, 52.5200)),
17 ("Madrid", Point::new(-3.7038, 40.4168)),
18 ("Rome", Point::new(12.4964, 41.9028)),
19 ("Tokyo", Point::new(139.6503, 35.6762)),
20 ("Sydney", Point::new(151.2093, -33.8688)),
21 ("Mumbai", Point::new(72.8777, 19.0760)),
22 ("Cairo", Point::new(31.2357, 30.0444)),
23 ("São Paulo", Point::new(-46.6333, -23.5505)),
24 ("Mexico City", Point::new(-99.1332, 19.4326)),
25 ];
26
27 for (name, point) in &cities {
28 db.insert_point("world_cities", point, name.as_bytes(), None)?;
29 }
30 println!(" Added {} cities to spatial index\n", cities.len());
31
32 // === 1. RADIUS QUERIES ===
33 println!("1. Radius-Based Queries (query_within_radius)");
34 println!("----------------------------------------------");
35
36 let london = Point::new(-0.1278, 51.5074);
37
38 // Find cities within 500km of London
39 let nearby_500km = db.query_within_radius("world_cities", &london, 500_000.0, 10)?;
40 println!(" Cities within 500km of London: {}", nearby_500km.len());
41 for (_, data, _) in &nearby_500km {
42 println!(" - {}", String::from_utf8_lossy(data));
43 }
44
45 // Find cities within 2000km of London
46 let nearby_2000km = db.query_within_radius("world_cities", &london, 2_000_000.0, 10)?;
47 println!(
48 "\n Cities within 2000km of London: {}",
49 nearby_2000km.len()
50 );
51 for (_, data, _) in &nearby_2000km {
52 println!(" - {}", String::from_utf8_lossy(data));
53 }
54
55 // Use limit to get only closest N cities
56 let closest_3 = db.query_within_radius("world_cities", &london, f64::INFINITY, 3)?;
57 println!("\n Closest 3 cities to London:");
58 for (i, (_, data, _)) in closest_3.iter().enumerate() {
59 println!(" {}. {}", i + 1, String::from_utf8_lossy(data));
60 }
61 println!();
62
63 // === 2. EXISTENCE CHECKS ===
64 println!("2. Existence Checks (contains_point)");
65 println!("-------------------------------------");
66
67 let has_nearby_500km = db.intersects_radius("world_cities", &london, 500_000.0)?;
68 let has_nearby_100km = db.intersects_radius("world_cities", &london, 100_000.0)?;
69
70 println!(" Any cities within 500km of London? {}", has_nearby_500km);
71 println!(" Any cities within 100km of London? {}", has_nearby_100km);
72
73 // === 3. COUNTING POINTS ===
74 println!("3. Counting Points (count_within_radius)");
75 println!("----------------------------------------");
76
77 let count_500km = db.count_within_radius("world_cities", &london, 500_000.0)?;
78 let count_1000km = db.count_within_radius("world_cities", &london, 1_000_000.0)?;
79 let count_2000km = db.count_within_radius("world_cities", &london, 2_000_000.0)?;
80
81 println!(" Cities within 500km of London: {}", count_500km);
82 println!(" Cities within 1000km of London: {}", count_1000km);
83 println!(" Cities within 2000km of London: {}", count_2000km);
84 println!();
85
86 // === 4. BOUNDING BOX QUERIES ===
87 println!("4. Bounding Box Queries");
88 println!("-----------------------");
89
90 // European bounding box (min_lon, min_lat, max_lon, max_lat)
91 println!(" European region (lon: -10 to 20, lat: 40 to 60):");
92 let europe_cities = db.find_within_bounds("world_cities", -10.0, 40.0, 20.0, 60.0, 20)?;
93 println!(" Found {} cities:", europe_cities.len());
94 for (point, data) in &europe_cities {
95 println!(
96 " - {} at ({:.2}°, {:.2}°)",
97 String::from_utf8_lossy(data),
98 point.x(),
99 point.y()
100 );
101 }
102
103 // Asia-Pacific region
104 println!("\n Asia-Pacific region (lon: 70 to 180, lat: -40 to 40):");
105 let asia_cities = db.find_within_bounds("world_cities", 70.0, -40.0, 180.0, 40.0, 20)?;
106 println!(" Found {} cities:", asia_cities.len());
107 for (_, data) in &asia_cities {
108 println!(" - {}", String::from_utf8_lossy(data));
109 }
110
111 // Americas region
112 println!("\n Americas region (lon: -130 to -30, lat: -60 to 60):");
113 let americas_cities = db.find_within_bounds("world_cities", -130.0, -60.0, -30.0, 60.0, 20)?;
114 println!(" Found {} cities:", americas_cities.len());
115 for (_, data) in &americas_cities {
116 println!(" - {}", String::from_utf8_lossy(data));
117 }
118 println!();
119
120 // === 5. BOUNDING BOX INTERSECTION ===
121 println!("5. Bounding Box Intersection (intersects_bounds)");
122 println!("------------------------------------------------");
123
124 let has_european = db.intersects_bounds("world_cities", -10.0, 40.0, 20.0, 60.0)?;
125 let has_antarctica = db.intersects_bounds("world_cities", -180.0, -90.0, 180.0, -60.0)?;
126
127 println!(" European region has cities? {}", has_european);
128 println!(" Antarctica region has cities? {}", has_antarctica);
129 println!();
130
131 // === 6. MULTIPLE NAMESPACES ===
132 println!("6. Multiple Namespaces");
133 println!("----------------------");
134
135 // Add some landmarks in London
136 let london_landmarks = vec![
137 ("Big Ben", Point::new(-0.1245, 51.4994)),
138 ("Tower Bridge", Point::new(-0.0754, 51.5055)),
139 ("London Eye", Point::new(-0.1195, 51.5033)),
140 ("Buckingham Palace", Point::new(-0.1419, 51.5014)),
141 ];
142
143 for (name, point) in &london_landmarks {
144 db.insert_point("landmarks", point, name.as_bytes(), None)?;
145 }
146
147 println!(" Added {} London landmarks", london_landmarks.len());
148
149 // Query different namespaces from same location
150 let center_london = Point::new(-0.1278, 51.5074);
151
152 let nearby_cities = db.query_within_radius("world_cities", ¢er_london, 10_000.0, 10)?;
153 let nearby_landmarks = db.query_within_radius("landmarks", ¢er_london, 10_000.0, 10)?;
154
155 println!(" Within 10km of center London:");
156 println!(" Cities: {}", nearby_cities.len());
157 println!(" Landmarks: {}", nearby_landmarks.len());
158
159 println!("\n Landmarks within 2km:");
160 let close_landmarks = db.query_within_radius("landmarks", ¢er_london, 2_000.0, 10)?;
161 for (_, data, _) in &close_landmarks {
162 println!(" - {}", String::from_utf8_lossy(data));
163 }
164 println!();
165
166 // === 7. QUERY LIMITS ===
167 println!("7. Query Result Limiting");
168 println!("------------------------");
169
170 let all_cities = db.query_within_radius("world_cities", &london, f64::INFINITY, 100)?;
171 let top_5 = db.query_within_radius("world_cities", &london, f64::INFINITY, 5)?;
172 let top_3 = db.query_within_radius("world_cities", &london, f64::INFINITY, 3)?;
173
174 println!(" Total cities in database: {}", all_cities.len());
175 println!(" With limit=5: {} cities", top_5.len());
176 println!(" With limit=3: {} cities", top_3.len());
177 println!();
178
179 // === SUMMARY ===
180 let stats = db.stats();
181 println!("=== Query Summary ===");
182 println!("Database statistics:");
183 println!(" Total keys: {}", stats.key_count);
184 println!(" Operations: {}", stats.operations_count);
185
186 println!("\nSpatial query methods demonstrated:");
187 println!(" • query_within_radius - Find points within distance");
188 println!(" • contains_point - Check if points exist in radius");
189 println!(" • count_within_radius - Count points efficiently");
190 println!(" • find_within_bounds - Rectangular region queries");
191 println!(" • intersects_bounds - Check bounding box intersection");
192 println!(" • Multiple namespaces - Organize different point types");
193 println!(" • Result limiting - Control query result size");
194
195 Ok(())
196}More examples
4fn main() -> Result<(), Box<dyn std::error::Error>> {
5 println!("=== Spatio - Trajectory Tracking ===\n");
6
7 let mut db = Spatio::memory()?;
8 println!("✓ Created in-memory database\n");
9
10 // === 1. BASIC TRAJECTORY STORAGE ===
11 println!("1. Basic Trajectory Storage");
12 println!("---------------------------");
13
14 // Create a simple delivery route
15 let delivery_route = vec![
16 TemporalPoint {
17 point: Point::new(-74.0060, 40.7128), // NYC
18 timestamp: UNIX_EPOCH + Duration::from_secs(1640995200),
19 },
20 TemporalPoint {
21 point: Point::new(-74.0040, 40.7150),
22 timestamp: UNIX_EPOCH + Duration::from_secs(1640995260), // +1 min
23 },
24 TemporalPoint {
25 point: Point::new(-74.0020, 40.7172),
26 timestamp: UNIX_EPOCH + Duration::from_secs(1640995320), // +2 min
27 },
28 TemporalPoint {
29 point: Point::new(-74.0000, 40.7194),
30 timestamp: UNIX_EPOCH + Duration::from_secs(1640995380), // +3 min
31 },
32 ];
33
34 db.insert_trajectory("vehicle:truck001", &delivery_route, None)?;
35 println!(
36 " Stored delivery truck trajectory with {} waypoints\n",
37 delivery_route.len()
38 );
39
40 // === 2. QUERY FULL TRAJECTORY ===
41 println!("2. Query Full Trajectory");
42 println!("------------------------");
43
44 let full_path = db.query_trajectory("vehicle:truck001", 1640995200, 1640995400)?;
45 println!(" Retrieved {} waypoints:", full_path.len());
46 for (i, tp) in full_path.iter().enumerate() {
47 println!(
48 " {}. Point ({:.4}°, {:.4}°) at timestamp {}",
49 i + 1,
50 tp.point.x(),
51 tp.point.y(),
52 tp.timestamp.duration_since(UNIX_EPOCH).unwrap().as_secs()
53 );
54 }
55 println!();
56
57 // === 3. QUERY TIME RANGE ===
58 println!("3. Query Specific Time Range");
59 println!("----------------------------");
60
61 // Get only first 2 minutes of trajectory
62 let partial_path = db.query_trajectory("vehicle:truck001", 1640995200, 1640995320)?;
63 println!(" First 2 minutes: {} waypoints", partial_path.len());
64
65 // Get only middle segment
66 let middle_segment = db.query_trajectory("vehicle:truck001", 1640995260, 1640995320)?;
67 println!(" Middle segment: {} waypoints\n", middle_segment.len());
68
69 // === 4. MULTIPLE TRAJECTORIES ===
70 println!("4. Multiple Trajectories");
71 println!("------------------------");
72
73 // Add taxi route
74 let taxi_route = vec![
75 TemporalPoint {
76 point: Point::new(-0.1278, 51.5074), // London
77 timestamp: UNIX_EPOCH + Duration::from_secs(1640995200),
78 },
79 TemporalPoint {
80 point: Point::new(-0.1195, 51.5033),
81 timestamp: UNIX_EPOCH + Duration::from_secs(1640995260),
82 },
83 TemporalPoint {
84 point: Point::new(-0.1245, 51.4994),
85 timestamp: UNIX_EPOCH + Duration::from_secs(1640995320),
86 },
87 ];
88
89 db.insert_trajectory("vehicle:taxi042", &taxi_route, None)?;
90 println!(
91 " Stored taxi trajectory with {} waypoints",
92 taxi_route.len()
93 );
94
95 // Add bus route
96 let bus_route = vec![
97 TemporalPoint {
98 point: Point::new(2.3522, 48.8566), // Paris
99 timestamp: UNIX_EPOCH + Duration::from_secs(1640995200),
100 },
101 TemporalPoint {
102 point: Point::new(2.3550, 48.8580),
103 timestamp: UNIX_EPOCH + Duration::from_secs(1640995300),
104 },
105 TemporalPoint {
106 point: Point::new(2.3580, 48.8600),
107 timestamp: UNIX_EPOCH + Duration::from_secs(1640995400),
108 },
109 TemporalPoint {
110 point: Point::new(2.3610, 48.8620),
111 timestamp: UNIX_EPOCH + Duration::from_secs(1640995500),
112 },
113 TemporalPoint {
114 point: Point::new(2.3640, 48.8640),
115 timestamp: UNIX_EPOCH + Duration::from_secs(1640995600),
116 },
117 ];
118
119 db.insert_trajectory("vehicle:bus123", &bus_route, None)?;
120 println!(
121 " Stored bus trajectory with {} waypoints\n",
122 bus_route.len()
123 );
124
125 // === 5. QUERY DIFFERENT VEHICLES ===
126 println!("5. Query Different Vehicles");
127 println!("---------------------------");
128
129 let truck_path = db.query_trajectory("vehicle:truck001", 1640995200, 1640995400)?;
130 let taxi_path = db.query_trajectory("vehicle:taxi042", 1640995200, 1640995400)?;
131 let bus_path = db.query_trajectory("vehicle:bus123", 1640995200, 1640995700)?;
132
133 println!(" Truck waypoints: {}", truck_path.len());
134 println!(" Taxi waypoints: {}", taxi_path.len());
135 println!(" Bus waypoints: {}\n", bus_path.len());
136
137 // === 6. LONG-RUNNING TRAJECTORY ===
138 println!("6. Long-Running Trajectory (High Frequency)");
139 println!("-------------------------------------------");
140
141 // Simulate a drone with frequent position updates
142 let mut drone_path = Vec::new();
143 let start_time = 1641000000;
144
145 for i in 0..60 {
146 // 60 waypoints, 1 per second
147 drone_path.push(TemporalPoint {
148 point: Point::new(
149 -122.4194 + (i as f64 * 0.0001), // San Francisco area
150 37.7749 + (i as f64 * 0.0001),
151 ),
152 timestamp: UNIX_EPOCH + Duration::from_secs(start_time + i),
153 });
154 }
155
156 db.insert_trajectory("drone:delivery001", &drone_path, None)?;
157 println!(
158 " Stored drone trajectory with {} waypoints",
159 drone_path.len()
160 );
161
162 // Query specific time window (10 seconds)
163 let window = db.query_trajectory("drone:delivery001", start_time, start_time + 10)?;
164 println!(
165 " Retrieved 10-second window: {} waypoints\n",
166 window.len()
167 );
168
169 // === 7. TRAJECTORY UPDATES ===
170 println!("7. Trajectory Updates");
171 println!("---------------------");
172
173 // Add more waypoints to existing trajectory
174 let extended_route = vec![
175 TemporalPoint {
176 point: Point::new(-74.0060, 40.7128),
177 timestamp: UNIX_EPOCH + Duration::from_secs(1640995200),
178 },
179 TemporalPoint {
180 point: Point::new(-74.0040, 40.7150),
181 timestamp: UNIX_EPOCH + Duration::from_secs(1640995260),
182 },
183 TemporalPoint {
184 point: Point::new(-74.0020, 40.7172),
185 timestamp: UNIX_EPOCH + Duration::from_secs(1640995320),
186 },
187 TemporalPoint {
188 point: Point::new(-74.0000, 40.7194),
189 timestamp: UNIX_EPOCH + Duration::from_secs(1640995380),
190 },
191 // New waypoints
192 TemporalPoint {
193 point: Point::new(-73.9980, 40.7216),
194 timestamp: UNIX_EPOCH + Duration::from_secs(1640995440),
195 },
196 TemporalPoint {
197 point: Point::new(-73.9960, 40.7238),
198 timestamp: UNIX_EPOCH + Duration::from_secs(1640995500),
199 },
200 ];
201
202 db.insert_trajectory("vehicle:truck001", &extended_route, None)?;
203 let updated_path = db.query_trajectory("vehicle:truck001", 1640995200, 1640995600)?;
204 println!(
205 " Extended truck trajectory from 4 to {} waypoints\n",
206 updated_path.len()
207 );
208
209 // === 8. DATABASE STATISTICS ===
210 println!("8. Database Statistics");
211 println!("----------------------");
212
213 let stats = db.stats();
214 println!(" Total keys in database: {}", stats.key_count);
215 println!(" Total operations: {}\n", stats.operations_count);
216
217 // === 9. USE CASES ===
218 println!("=== Common Use Cases ===\n");
219
220 println!("Fleet Management:");
221 println!(" • Track multiple vehicles in real-time");
222 println!(" • Query historical routes for analysis");
223 println!(" • Retrieve specific time windows for incidents\n");
224
225 println!("Delivery Tracking:");
226 println!(" • Store complete delivery routes");
227 println!(" • Query progress during specific periods");
228 println!(" • Analyze route efficiency\n");
229
230 println!("Drone Operations:");
231 println!(" • High-frequency position updates");
232 println!(" • Flight path analysis");
233 println!(" • Time-based route queries\n");
234
235 println!("Asset Tracking:");
236 println!(" • Monitor movement of valuable items");
237 println!(" • Historical location queries");
238 println!(" • Route verification\n");
239
240 println!("=== Trajectory Tracking Complete! ===");
241 println!("\nKey Features Demonstrated:");
242 println!(" • Store trajectories with timestamps");
243 println!(" • Query full trajectories");
244 println!(" • Query specific time ranges");
245 println!(" • Track multiple vehicles/objects");
246 println!(" • High-frequency updates");
247 println!(" • Trajectory extensions/updates");
248
249 Ok(())
250}14fn main() -> Result<(), Box<dyn std::error::Error>> {
15 println!("=== Advanced Spatial Operations Demo ===\n");
16
17 // Create an in-memory database
18 let mut db = Spatio::memory()?;
19
20 // ========================================
21 // 1. Distance Calculations
22 // ========================================
23 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 // Calculate distances using different metrics
31 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 // Using the database method
41 let db_distance = db.distance_between(&new_york, &london, DistanceMetric::Haversine)?;
42 println!("\nNYC to London: {:.2} km", db_distance / 1000.0);
43
44 // ========================================
45 // 2. K-Nearest-Neighbors (KNN)
46 // ========================================
47 println!("\n2. K-Nearest-Neighbors Query");
48 println!("{}", "=".repeat(50));
49
50 // Insert major cities
51 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 // Find 3 nearest cities to a query point (somewhere in New Jersey)
69 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, // Search within 500km
75 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 // ========================================
90 // 3. Polygon Queries
91 // ========================================
92 println!("\n3. Polygon Queries");
93 println!("{}", "=".repeat(50));
94
95 // Define a polygon covering parts of the eastern US
96 use geo::polygon;
97 let east_coast_polygon = polygon![
98 (x: -80.0, y: 35.0), // South
99 (x: -70.0, y: 35.0), // Southeast
100 (x: -70.0, y: 45.0), // Northeast
101 (x: -80.0, y: 45.0), // Northwest
102 (x: -80.0, y: 35.0), // Close the polygon
103 ];
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 // ========================================
115 // 4. Bounding Box Operations
116 // ========================================
117 println!("\n4. Bounding Box Operations");
118 println!("{}", "=".repeat(50));
119
120 // Create a bounding box around the New York area
121 let ny_bbox = bounding_box(-74.5, 40.5, -73.5, 41.0)?;
122 println!("NY Area Bounding Box: {:?}", ny_bbox);
123
124 // Find cities in bounding box
125 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 // ========================================
133 // 5. Convex Hull
134 // ========================================
135 println!("\n5. Convex Hull Calculation");
136 println!("{}", "=".repeat(50));
137
138 // Get all city points
139 let city_points: Vec<Point> = cities.iter().map(|(p, _, _)| *p).collect();
140
141 // Calculate convex hull
142 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 // ========================================
151 // 6. Bounding Rectangle
152 // ========================================
153 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 // ========================================
165 // 7. Advanced Radius Queries
166 // ========================================
167 println!("\n7. Advanced Radius Queries");
168 println!("{}", "=".repeat(50));
169
170 // Count cities within 1000km of NYC
171 let count = db.count_within_radius("world_cities", &new_york, 1_000_000.0)?;
172 println!("Cities within 1000km of NYC: {}", count);
173
174 // Check if any cities exist within 100km
175 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 // Query with radius
179 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 // ========================================
188 // 8. Spatial Analytics
189 // ========================================
190 println!("\n8. Spatial Analytics");
191 println!("{}", "=".repeat(50));
192
193 // Find the two most distant cities (brute force)
194 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 // Calculate average distance between all US cities
214 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 // ========================================
238 // Summary
239 // ========================================
240 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}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}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(×_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(¤t_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}Sourcepub fn y(&self) -> f64
pub fn y(&self) -> f64
Get the y coordinate (latitude).
Examples found in repository?
3fn main() -> Result<(), Box<dyn std::error::Error>> {
4 println!("=== Spatio - Spatial Queries ===\n");
5
6 let mut db = Spatio::memory()?;
7 println!("✓ Created in-memory database\n");
8
9 // === SETUP: Insert World Cities ===
10 println!("Setting up test data...");
11
12 let cities = vec![
13 ("New York", Point::new(-74.0060, 40.7128)),
14 ("London", Point::new(-0.1278, 51.5074)),
15 ("Paris", Point::new(2.3522, 48.8566)),
16 ("Berlin", Point::new(13.4050, 52.5200)),
17 ("Madrid", Point::new(-3.7038, 40.4168)),
18 ("Rome", Point::new(12.4964, 41.9028)),
19 ("Tokyo", Point::new(139.6503, 35.6762)),
20 ("Sydney", Point::new(151.2093, -33.8688)),
21 ("Mumbai", Point::new(72.8777, 19.0760)),
22 ("Cairo", Point::new(31.2357, 30.0444)),
23 ("São Paulo", Point::new(-46.6333, -23.5505)),
24 ("Mexico City", Point::new(-99.1332, 19.4326)),
25 ];
26
27 for (name, point) in &cities {
28 db.insert_point("world_cities", point, name.as_bytes(), None)?;
29 }
30 println!(" Added {} cities to spatial index\n", cities.len());
31
32 // === 1. RADIUS QUERIES ===
33 println!("1. Radius-Based Queries (query_within_radius)");
34 println!("----------------------------------------------");
35
36 let london = Point::new(-0.1278, 51.5074);
37
38 // Find cities within 500km of London
39 let nearby_500km = db.query_within_radius("world_cities", &london, 500_000.0, 10)?;
40 println!(" Cities within 500km of London: {}", nearby_500km.len());
41 for (_, data, _) in &nearby_500km {
42 println!(" - {}", String::from_utf8_lossy(data));
43 }
44
45 // Find cities within 2000km of London
46 let nearby_2000km = db.query_within_radius("world_cities", &london, 2_000_000.0, 10)?;
47 println!(
48 "\n Cities within 2000km of London: {}",
49 nearby_2000km.len()
50 );
51 for (_, data, _) in &nearby_2000km {
52 println!(" - {}", String::from_utf8_lossy(data));
53 }
54
55 // Use limit to get only closest N cities
56 let closest_3 = db.query_within_radius("world_cities", &london, f64::INFINITY, 3)?;
57 println!("\n Closest 3 cities to London:");
58 for (i, (_, data, _)) in closest_3.iter().enumerate() {
59 println!(" {}. {}", i + 1, String::from_utf8_lossy(data));
60 }
61 println!();
62
63 // === 2. EXISTENCE CHECKS ===
64 println!("2. Existence Checks (contains_point)");
65 println!("-------------------------------------");
66
67 let has_nearby_500km = db.intersects_radius("world_cities", &london, 500_000.0)?;
68 let has_nearby_100km = db.intersects_radius("world_cities", &london, 100_000.0)?;
69
70 println!(" Any cities within 500km of London? {}", has_nearby_500km);
71 println!(" Any cities within 100km of London? {}", has_nearby_100km);
72
73 // === 3. COUNTING POINTS ===
74 println!("3. Counting Points (count_within_radius)");
75 println!("----------------------------------------");
76
77 let count_500km = db.count_within_radius("world_cities", &london, 500_000.0)?;
78 let count_1000km = db.count_within_radius("world_cities", &london, 1_000_000.0)?;
79 let count_2000km = db.count_within_radius("world_cities", &london, 2_000_000.0)?;
80
81 println!(" Cities within 500km of London: {}", count_500km);
82 println!(" Cities within 1000km of London: {}", count_1000km);
83 println!(" Cities within 2000km of London: {}", count_2000km);
84 println!();
85
86 // === 4. BOUNDING BOX QUERIES ===
87 println!("4. Bounding Box Queries");
88 println!("-----------------------");
89
90 // European bounding box (min_lon, min_lat, max_lon, max_lat)
91 println!(" European region (lon: -10 to 20, lat: 40 to 60):");
92 let europe_cities = db.find_within_bounds("world_cities", -10.0, 40.0, 20.0, 60.0, 20)?;
93 println!(" Found {} cities:", europe_cities.len());
94 for (point, data) in &europe_cities {
95 println!(
96 " - {} at ({:.2}°, {:.2}°)",
97 String::from_utf8_lossy(data),
98 point.x(),
99 point.y()
100 );
101 }
102
103 // Asia-Pacific region
104 println!("\n Asia-Pacific region (lon: 70 to 180, lat: -40 to 40):");
105 let asia_cities = db.find_within_bounds("world_cities", 70.0, -40.0, 180.0, 40.0, 20)?;
106 println!(" Found {} cities:", asia_cities.len());
107 for (_, data) in &asia_cities {
108 println!(" - {}", String::from_utf8_lossy(data));
109 }
110
111 // Americas region
112 println!("\n Americas region (lon: -130 to -30, lat: -60 to 60):");
113 let americas_cities = db.find_within_bounds("world_cities", -130.0, -60.0, -30.0, 60.0, 20)?;
114 println!(" Found {} cities:", americas_cities.len());
115 for (_, data) in &americas_cities {
116 println!(" - {}", String::from_utf8_lossy(data));
117 }
118 println!();
119
120 // === 5. BOUNDING BOX INTERSECTION ===
121 println!("5. Bounding Box Intersection (intersects_bounds)");
122 println!("------------------------------------------------");
123
124 let has_european = db.intersects_bounds("world_cities", -10.0, 40.0, 20.0, 60.0)?;
125 let has_antarctica = db.intersects_bounds("world_cities", -180.0, -90.0, 180.0, -60.0)?;
126
127 println!(" European region has cities? {}", has_european);
128 println!(" Antarctica region has cities? {}", has_antarctica);
129 println!();
130
131 // === 6. MULTIPLE NAMESPACES ===
132 println!("6. Multiple Namespaces");
133 println!("----------------------");
134
135 // Add some landmarks in London
136 let london_landmarks = vec![
137 ("Big Ben", Point::new(-0.1245, 51.4994)),
138 ("Tower Bridge", Point::new(-0.0754, 51.5055)),
139 ("London Eye", Point::new(-0.1195, 51.5033)),
140 ("Buckingham Palace", Point::new(-0.1419, 51.5014)),
141 ];
142
143 for (name, point) in &london_landmarks {
144 db.insert_point("landmarks", point, name.as_bytes(), None)?;
145 }
146
147 println!(" Added {} London landmarks", london_landmarks.len());
148
149 // Query different namespaces from same location
150 let center_london = Point::new(-0.1278, 51.5074);
151
152 let nearby_cities = db.query_within_radius("world_cities", ¢er_london, 10_000.0, 10)?;
153 let nearby_landmarks = db.query_within_radius("landmarks", ¢er_london, 10_000.0, 10)?;
154
155 println!(" Within 10km of center London:");
156 println!(" Cities: {}", nearby_cities.len());
157 println!(" Landmarks: {}", nearby_landmarks.len());
158
159 println!("\n Landmarks within 2km:");
160 let close_landmarks = db.query_within_radius("landmarks", ¢er_london, 2_000.0, 10)?;
161 for (_, data, _) in &close_landmarks {
162 println!(" - {}", String::from_utf8_lossy(data));
163 }
164 println!();
165
166 // === 7. QUERY LIMITS ===
167 println!("7. Query Result Limiting");
168 println!("------------------------");
169
170 let all_cities = db.query_within_radius("world_cities", &london, f64::INFINITY, 100)?;
171 let top_5 = db.query_within_radius("world_cities", &london, f64::INFINITY, 5)?;
172 let top_3 = db.query_within_radius("world_cities", &london, f64::INFINITY, 3)?;
173
174 println!(" Total cities in database: {}", all_cities.len());
175 println!(" With limit=5: {} cities", top_5.len());
176 println!(" With limit=3: {} cities", top_3.len());
177 println!();
178
179 // === SUMMARY ===
180 let stats = db.stats();
181 println!("=== Query Summary ===");
182 println!("Database statistics:");
183 println!(" Total keys: {}", stats.key_count);
184 println!(" Operations: {}", stats.operations_count);
185
186 println!("\nSpatial query methods demonstrated:");
187 println!(" • query_within_radius - Find points within distance");
188 println!(" • contains_point - Check if points exist in radius");
189 println!(" • count_within_radius - Count points efficiently");
190 println!(" • find_within_bounds - Rectangular region queries");
191 println!(" • intersects_bounds - Check bounding box intersection");
192 println!(" • Multiple namespaces - Organize different point types");
193 println!(" • Result limiting - Control query result size");
194
195 Ok(())
196}More examples
4fn main() -> Result<(), Box<dyn std::error::Error>> {
5 println!("=== Spatio - Trajectory Tracking ===\n");
6
7 let mut db = Spatio::memory()?;
8 println!("✓ Created in-memory database\n");
9
10 // === 1. BASIC TRAJECTORY STORAGE ===
11 println!("1. Basic Trajectory Storage");
12 println!("---------------------------");
13
14 // Create a simple delivery route
15 let delivery_route = vec![
16 TemporalPoint {
17 point: Point::new(-74.0060, 40.7128), // NYC
18 timestamp: UNIX_EPOCH + Duration::from_secs(1640995200),
19 },
20 TemporalPoint {
21 point: Point::new(-74.0040, 40.7150),
22 timestamp: UNIX_EPOCH + Duration::from_secs(1640995260), // +1 min
23 },
24 TemporalPoint {
25 point: Point::new(-74.0020, 40.7172),
26 timestamp: UNIX_EPOCH + Duration::from_secs(1640995320), // +2 min
27 },
28 TemporalPoint {
29 point: Point::new(-74.0000, 40.7194),
30 timestamp: UNIX_EPOCH + Duration::from_secs(1640995380), // +3 min
31 },
32 ];
33
34 db.insert_trajectory("vehicle:truck001", &delivery_route, None)?;
35 println!(
36 " Stored delivery truck trajectory with {} waypoints\n",
37 delivery_route.len()
38 );
39
40 // === 2. QUERY FULL TRAJECTORY ===
41 println!("2. Query Full Trajectory");
42 println!("------------------------");
43
44 let full_path = db.query_trajectory("vehicle:truck001", 1640995200, 1640995400)?;
45 println!(" Retrieved {} waypoints:", full_path.len());
46 for (i, tp) in full_path.iter().enumerate() {
47 println!(
48 " {}. Point ({:.4}°, {:.4}°) at timestamp {}",
49 i + 1,
50 tp.point.x(),
51 tp.point.y(),
52 tp.timestamp.duration_since(UNIX_EPOCH).unwrap().as_secs()
53 );
54 }
55 println!();
56
57 // === 3. QUERY TIME RANGE ===
58 println!("3. Query Specific Time Range");
59 println!("----------------------------");
60
61 // Get only first 2 minutes of trajectory
62 let partial_path = db.query_trajectory("vehicle:truck001", 1640995200, 1640995320)?;
63 println!(" First 2 minutes: {} waypoints", partial_path.len());
64
65 // Get only middle segment
66 let middle_segment = db.query_trajectory("vehicle:truck001", 1640995260, 1640995320)?;
67 println!(" Middle segment: {} waypoints\n", middle_segment.len());
68
69 // === 4. MULTIPLE TRAJECTORIES ===
70 println!("4. Multiple Trajectories");
71 println!("------------------------");
72
73 // Add taxi route
74 let taxi_route = vec![
75 TemporalPoint {
76 point: Point::new(-0.1278, 51.5074), // London
77 timestamp: UNIX_EPOCH + Duration::from_secs(1640995200),
78 },
79 TemporalPoint {
80 point: Point::new(-0.1195, 51.5033),
81 timestamp: UNIX_EPOCH + Duration::from_secs(1640995260),
82 },
83 TemporalPoint {
84 point: Point::new(-0.1245, 51.4994),
85 timestamp: UNIX_EPOCH + Duration::from_secs(1640995320),
86 },
87 ];
88
89 db.insert_trajectory("vehicle:taxi042", &taxi_route, None)?;
90 println!(
91 " Stored taxi trajectory with {} waypoints",
92 taxi_route.len()
93 );
94
95 // Add bus route
96 let bus_route = vec![
97 TemporalPoint {
98 point: Point::new(2.3522, 48.8566), // Paris
99 timestamp: UNIX_EPOCH + Duration::from_secs(1640995200),
100 },
101 TemporalPoint {
102 point: Point::new(2.3550, 48.8580),
103 timestamp: UNIX_EPOCH + Duration::from_secs(1640995300),
104 },
105 TemporalPoint {
106 point: Point::new(2.3580, 48.8600),
107 timestamp: UNIX_EPOCH + Duration::from_secs(1640995400),
108 },
109 TemporalPoint {
110 point: Point::new(2.3610, 48.8620),
111 timestamp: UNIX_EPOCH + Duration::from_secs(1640995500),
112 },
113 TemporalPoint {
114 point: Point::new(2.3640, 48.8640),
115 timestamp: UNIX_EPOCH + Duration::from_secs(1640995600),
116 },
117 ];
118
119 db.insert_trajectory("vehicle:bus123", &bus_route, None)?;
120 println!(
121 " Stored bus trajectory with {} waypoints\n",
122 bus_route.len()
123 );
124
125 // === 5. QUERY DIFFERENT VEHICLES ===
126 println!("5. Query Different Vehicles");
127 println!("---------------------------");
128
129 let truck_path = db.query_trajectory("vehicle:truck001", 1640995200, 1640995400)?;
130 let taxi_path = db.query_trajectory("vehicle:taxi042", 1640995200, 1640995400)?;
131 let bus_path = db.query_trajectory("vehicle:bus123", 1640995200, 1640995700)?;
132
133 println!(" Truck waypoints: {}", truck_path.len());
134 println!(" Taxi waypoints: {}", taxi_path.len());
135 println!(" Bus waypoints: {}\n", bus_path.len());
136
137 // === 6. LONG-RUNNING TRAJECTORY ===
138 println!("6. Long-Running Trajectory (High Frequency)");
139 println!("-------------------------------------------");
140
141 // Simulate a drone with frequent position updates
142 let mut drone_path = Vec::new();
143 let start_time = 1641000000;
144
145 for i in 0..60 {
146 // 60 waypoints, 1 per second
147 drone_path.push(TemporalPoint {
148 point: Point::new(
149 -122.4194 + (i as f64 * 0.0001), // San Francisco area
150 37.7749 + (i as f64 * 0.0001),
151 ),
152 timestamp: UNIX_EPOCH + Duration::from_secs(start_time + i),
153 });
154 }
155
156 db.insert_trajectory("drone:delivery001", &drone_path, None)?;
157 println!(
158 " Stored drone trajectory with {} waypoints",
159 drone_path.len()
160 );
161
162 // Query specific time window (10 seconds)
163 let window = db.query_trajectory("drone:delivery001", start_time, start_time + 10)?;
164 println!(
165 " Retrieved 10-second window: {} waypoints\n",
166 window.len()
167 );
168
169 // === 7. TRAJECTORY UPDATES ===
170 println!("7. Trajectory Updates");
171 println!("---------------------");
172
173 // Add more waypoints to existing trajectory
174 let extended_route = vec![
175 TemporalPoint {
176 point: Point::new(-74.0060, 40.7128),
177 timestamp: UNIX_EPOCH + Duration::from_secs(1640995200),
178 },
179 TemporalPoint {
180 point: Point::new(-74.0040, 40.7150),
181 timestamp: UNIX_EPOCH + Duration::from_secs(1640995260),
182 },
183 TemporalPoint {
184 point: Point::new(-74.0020, 40.7172),
185 timestamp: UNIX_EPOCH + Duration::from_secs(1640995320),
186 },
187 TemporalPoint {
188 point: Point::new(-74.0000, 40.7194),
189 timestamp: UNIX_EPOCH + Duration::from_secs(1640995380),
190 },
191 // New waypoints
192 TemporalPoint {
193 point: Point::new(-73.9980, 40.7216),
194 timestamp: UNIX_EPOCH + Duration::from_secs(1640995440),
195 },
196 TemporalPoint {
197 point: Point::new(-73.9960, 40.7238),
198 timestamp: UNIX_EPOCH + Duration::from_secs(1640995500),
199 },
200 ];
201
202 db.insert_trajectory("vehicle:truck001", &extended_route, None)?;
203 let updated_path = db.query_trajectory("vehicle:truck001", 1640995200, 1640995600)?;
204 println!(
205 " Extended truck trajectory from 4 to {} waypoints\n",
206 updated_path.len()
207 );
208
209 // === 8. DATABASE STATISTICS ===
210 println!("8. Database Statistics");
211 println!("----------------------");
212
213 let stats = db.stats();
214 println!(" Total keys in database: {}", stats.key_count);
215 println!(" Total operations: {}\n", stats.operations_count);
216
217 // === 9. USE CASES ===
218 println!("=== Common Use Cases ===\n");
219
220 println!("Fleet Management:");
221 println!(" • Track multiple vehicles in real-time");
222 println!(" • Query historical routes for analysis");
223 println!(" • Retrieve specific time windows for incidents\n");
224
225 println!("Delivery Tracking:");
226 println!(" • Store complete delivery routes");
227 println!(" • Query progress during specific periods");
228 println!(" • Analyze route efficiency\n");
229
230 println!("Drone Operations:");
231 println!(" • High-frequency position updates");
232 println!(" • Flight path analysis");
233 println!(" • Time-based route queries\n");
234
235 println!("Asset Tracking:");
236 println!(" • Monitor movement of valuable items");
237 println!(" • Historical location queries");
238 println!(" • Route verification\n");
239
240 println!("=== Trajectory Tracking Complete! ===");
241 println!("\nKey Features Demonstrated:");
242 println!(" • Store trajectories with timestamps");
243 println!(" • Query full trajectories");
244 println!(" • Query specific time ranges");
245 println!(" • Track multiple vehicles/objects");
246 println!(" • High-frequency updates");
247 println!(" • Trajectory extensions/updates");
248
249 Ok(())
250}14fn main() -> Result<(), Box<dyn std::error::Error>> {
15 println!("=== Advanced Spatial Operations Demo ===\n");
16
17 // Create an in-memory database
18 let mut db = Spatio::memory()?;
19
20 // ========================================
21 // 1. Distance Calculations
22 // ========================================
23 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 // Calculate distances using different metrics
31 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 // Using the database method
41 let db_distance = db.distance_between(&new_york, &london, DistanceMetric::Haversine)?;
42 println!("\nNYC to London: {:.2} km", db_distance / 1000.0);
43
44 // ========================================
45 // 2. K-Nearest-Neighbors (KNN)
46 // ========================================
47 println!("\n2. K-Nearest-Neighbors Query");
48 println!("{}", "=".repeat(50));
49
50 // Insert major cities
51 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 // Find 3 nearest cities to a query point (somewhere in New Jersey)
69 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, // Search within 500km
75 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 // ========================================
90 // 3. Polygon Queries
91 // ========================================
92 println!("\n3. Polygon Queries");
93 println!("{}", "=".repeat(50));
94
95 // Define a polygon covering parts of the eastern US
96 use geo::polygon;
97 let east_coast_polygon = polygon![
98 (x: -80.0, y: 35.0), // South
99 (x: -70.0, y: 35.0), // Southeast
100 (x: -70.0, y: 45.0), // Northeast
101 (x: -80.0, y: 45.0), // Northwest
102 (x: -80.0, y: 35.0), // Close the polygon
103 ];
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 // ========================================
115 // 4. Bounding Box Operations
116 // ========================================
117 println!("\n4. Bounding Box Operations");
118 println!("{}", "=".repeat(50));
119
120 // Create a bounding box around the New York area
121 let ny_bbox = bounding_box(-74.5, 40.5, -73.5, 41.0)?;
122 println!("NY Area Bounding Box: {:?}", ny_bbox);
123
124 // Find cities in bounding box
125 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 // ========================================
133 // 5. Convex Hull
134 // ========================================
135 println!("\n5. Convex Hull Calculation");
136 println!("{}", "=".repeat(50));
137
138 // Get all city points
139 let city_points: Vec<Point> = cities.iter().map(|(p, _, _)| *p).collect();
140
141 // Calculate convex hull
142 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 // ========================================
151 // 6. Bounding Rectangle
152 // ========================================
153 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 // ========================================
165 // 7. Advanced Radius Queries
166 // ========================================
167 println!("\n7. Advanced Radius Queries");
168 println!("{}", "=".repeat(50));
169
170 // Count cities within 1000km of NYC
171 let count = db.count_within_radius("world_cities", &new_york, 1_000_000.0)?;
172 println!("Cities within 1000km of NYC: {}", count);
173
174 // Check if any cities exist within 100km
175 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 // Query with radius
179 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 // ========================================
188 // 8. Spatial Analytics
189 // ========================================
190 println!("\n8. Spatial Analytics");
191 println!("{}", "=".repeat(50));
192
193 // Find the two most distant cities (brute force)
194 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 // Calculate average distance between all US cities
214 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 // ========================================
238 // Summary
239 // ========================================
240 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}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}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(×_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(¤t_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}Sourcepub fn into_inner(self) -> Point
pub fn into_inner(self) -> Point
Convert into the inner geo::Point.
Sourcepub fn haversine_distance(&self, other: &Point) -> f64
pub fn haversine_distance(&self, other: &Point) -> f64
Calculate haversine distance to another point in meters.
Uses the haversine formula which accounts for Earth’s curvature.
§Examples
use spatio_types::geo::Point;
let nyc = Point::new(-74.0060, 40.7128);
let la = Point::new(-118.2437, 34.0522);
let distance = nyc.haversine_distance(&la);
assert!(distance > 3_900_000.0); // ~3,944 kmSourcepub fn geodesic_distance(&self, other: &Point) -> f64
pub fn geodesic_distance(&self, other: &Point) -> f64
Calculate geodesic distance to another point in meters.
Uses the Vincenty formula which is more accurate than haversine but slightly slower.
§Examples
use spatio_types::geo::Point;
let p1 = Point::new(-74.0060, 40.7128);
let p2 = Point::new(-74.0070, 40.7138);
let distance = p1.geodesic_distance(&p2);Sourcepub fn euclidean_distance(&self, other: &Point) -> f64
pub fn euclidean_distance(&self, other: &Point) -> f64
Calculate euclidean distance to another point.
This calculates straight-line distance in the coordinate space, which is only accurate for small distances.
§Examples
use spatio_types::geo::Point;
let p1 = Point::new(0.0, 0.0);
let p2 = Point::new(3.0, 4.0);
let distance = p1.euclidean_distance(&p2);
assert_eq!(distance, 5.0); // 3-4-5 triangleSourcepub fn to_geojson(&self) -> Result<String, GeoJsonError>
pub fn to_geojson(&self) -> Result<String, GeoJsonError>
Convert to GeoJSON string representation.
§Examples
use spatio_types::geo::Point;
let point = Point::new(-74.0060, 40.7128);
let json = point.to_geojson().unwrap();
assert!(json.contains("Point"));Sourcepub fn from_geojson(geojson: &str) -> Result<Point, GeoJsonError>
pub fn from_geojson(geojson: &str) -> Result<Point, GeoJsonError>
Parse from GeoJSON string.
§Examples
use spatio_types::geo::Point;
let json = r#"{"type":"Point","coordinates":[-74.006,40.7128]}"#;
let point = Point::from_geojson(json).unwrap();
assert_eq!(point.x(), -74.006);Trait Implementations§
Source§impl<'de> Deserialize<'de> for Point
impl<'de> Deserialize<'de> for Point
Source§fn deserialize<__D>(
__deserializer: __D,
) -> Result<Point, <__D as Deserializer<'de>>::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(
__deserializer: __D,
) -> Result<Point, <__D as Deserializer<'de>>::Error>where
__D: Deserializer<'de>,
Source§impl Serialize for Point
impl Serialize for Point
Source§fn serialize<__S>(
&self,
__serializer: __S,
) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>where
__S: Serializer,
fn serialize<__S>(
&self,
__serializer: __S,
) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>where
__S: Serializer,
impl Copy for Point
impl StructuralPartialEq for Point
Auto Trait Implementations§
impl Freeze for Point
impl RefUnwindSafe for Point
impl Send for Point
impl Sync for Point
impl Unpin for Point
impl UnwindSafe for Point
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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