Polygon

Struct Polygon 

Source
pub struct Polygon { /* private fields */ }
Expand description

A polygon with exterior and optional interior rings.

This wraps geo::Polygon and provides additional functionality for GeoJSON conversion and spatial operations.

§Examples

use spatio_types::geo::Polygon;
use geo::polygon;

let poly = polygon![
    (x: -80.0, y: 35.0),
    (x: -70.0, y: 35.0),
    (x: -70.0, y: 45.0),
    (x: -80.0, y: 45.0),
    (x: -80.0, y: 35.0),
];
let wrapped = Polygon::from(poly);

Implementations§

Source§

impl Polygon

Source

pub fn new(exterior: LineString, interiors: Vec<LineString>) -> Polygon

Create a new polygon from an exterior ring and optional interior rings (holes).

§Arguments
  • exterior - The outer boundary of the polygon
  • interiors - Optional holes within the polygon
Source

pub fn from_coords( exterior: &[(f64, f64)], interiors: Vec<Vec<(f64, f64)>>, ) -> Polygon

Create a new polygon from coordinate arrays without requiring geo::LineString.

This is a convenience method that allows creating polygons from raw coordinates without needing to import types from the geo crate.

§Arguments
  • exterior - Coordinates for the outer boundary [(lon, lat), …]
  • interiors - Optional holes within the polygon, each as [(lon, lat), …]
§Examples
use spatio_types::geo::Polygon;

// Create a simple rectangle
let polygon = Polygon::from_coords(
    &[
        (-80.0, 35.0),
        (-70.0, 35.0),
        (-70.0, 45.0),
        (-80.0, 45.0),
        (-80.0, 35.0),  // Close the ring
    ],
    vec![],
);

// Create a polygon with a hole
let polygon_with_hole = Polygon::from_coords(
    &[
        (-80.0, 35.0),
        (-70.0, 35.0),
        (-70.0, 45.0),
        (-80.0, 45.0),
        (-80.0, 35.0),
    ],
    vec![
        vec![
            (-75.0, 38.0),
            (-74.0, 38.0),
            (-74.0, 40.0),
            (-75.0, 40.0),
            (-75.0, 38.0),
        ]
    ],
);
Source

pub fn exterior(&self) -> &LineString

Get a reference to the exterior ring.

Examples found in repository?
examples/advanced_spatial.rs (line 144)
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}
Source

pub fn interiors(&self) -> &[LineString]

Get references to the interior rings (holes).

Source

pub fn inner(&self) -> &Polygon

Access the inner geo::Polygon.

Source

pub fn into_inner(self) -> Polygon

Convert into the inner geo::Polygon.

Source

pub fn contains(&self, point: &Point) -> bool

Check if a point is contained within this polygon.

§Examples
use spatio_types::geo::{Point, Polygon};
use geo::polygon;

let poly = polygon![
    (x: -80.0, y: 35.0),
    (x: -70.0, y: 35.0),
    (x: -70.0, y: 45.0),
    (x: -80.0, y: 45.0),
    (x: -80.0, y: 35.0),
];
let polygon = Polygon::from(poly);
let point = Point::new(-75.0, 40.0);
assert!(polygon.contains(&point));
Source

pub fn to_geojson(&self) -> Result<String, GeoJsonError>

Convert to GeoJSON string representation.

§Examples
use spatio_types::geo::Polygon;
use geo::polygon;

let poly = polygon![
    (x: -80.0, y: 35.0),
    (x: -70.0, y: 35.0),
    (x: -70.0, y: 45.0),
    (x: -80.0, y: 45.0),
    (x: -80.0, y: 35.0),
];
let polygon = Polygon::from(poly);
let json = polygon.to_geojson().unwrap();
assert!(json.contains("Polygon"));
Source

pub fn from_geojson(geojson: &str) -> Result<Polygon, GeoJsonError>

Parse from GeoJSON string.

§Examples
use spatio_types::geo::Polygon;

let json = r#"{"type":"Polygon","coordinates":[[[-80.0,35.0],[-70.0,35.0],[-70.0,45.0],[-80.0,45.0],[-80.0,35.0]]]}"#;
let polygon = Polygon::from_geojson(json).unwrap();
assert_eq!(polygon.exterior().coords().count(), 5);

Trait Implementations§

Source§

impl Clone for Polygon

Source§

fn clone(&self) -> Polygon

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Polygon

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for Polygon

Source§

fn deserialize<__D>( __deserializer: __D, ) -> Result<Polygon, <__D as Deserializer<'de>>::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl From<Polygon> for Polygon

Source§

fn from(polygon: Polygon) -> Polygon

Converts to this type from the input type.
Source§

impl PartialEq for Polygon

Source§

fn eq(&self, other: &Polygon) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Serialize for Polygon

Source§

fn serialize<__S>( &self, __serializer: __S, ) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for Polygon

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<G1, G2> Within<G2> for G1
where G2: Contains<G1>,

Source§

fn is_within(&self, b: &G2) -> bool

Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,