This is an automated email from the ASF dual-hosted git repository.

jiayu pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/sedona-spatialbench.git


The following commit(s) were added to refs/heads/main by this push:
     new efb3454  Ensure geometry validity,  CCW orientation and antimeridian 
handling (#60)
efb3454 is described below

commit efb345416f30197ac8405885ea65c666528da01e
Author: Pranav Toggi <[email protected]>
AuthorDate: Mon Nov 10 17:23:39 2025 -0800

    Ensure geometry validity,  CCW orientation and antimeridian handling (#60)
    
    * orient polygons to counter clockwise
    
    * fix zero area polygons
    
    * add wrap around logic to keep points within [-180, 180] degrees
    
    * add logic to handle antimeridian crossing geometries
    
    * add test suite for geometry validation
    
    * fix cli-integration tests
    
    * Update spatialbench/tests/geometry_tests.rs
    
    Co-authored-by: Copilot <[email protected]>
    
    * pin python version
    
    * update comments
    
    ---------
    
    Co-authored-by: Copilot <[email protected]>
---
 .github/workflows/packaging.yml                |   2 +-
 Cargo.toml                                     |   2 +-
 spatialbench-cli/tests/cli_integration.rs      |   2 +-
 spatialbench/data/sf-v1/building.tbl.gz        | Bin 38908 -> 39409 bytes
 spatialbench/data/sf-v1/trip.tbl.gz            | Bin 286086 -> 286085 bytes
 spatialbench/src/generators.rs                 |   6 +-
 spatialbench/src/spatial/geometry.rs           |  36 +++-
 spatialbench/src/spatial/utils/antimeridian.rs | 267 +++++++++++++++++++++++++
 spatialbench/src/spatial/utils/mod.rs          |   2 +
 spatialbench/tests/geometry_tests.rs           | 136 +++++++++++++
 10 files changed, 440 insertions(+), 13 deletions(-)

diff --git a/.github/workflows/packaging.yml b/.github/workflows/packaging.yml
index 507ba95..afce8ef 100644
--- a/.github/workflows/packaging.yml
+++ b/.github/workflows/packaging.yml
@@ -41,7 +41,7 @@ jobs:
 
       - uses: actions/setup-python@v5
         with:
-          python-version: "3.x"
+          python-version: "3.13"
 
       - name: Install docs requirements
         run: pip install -r docs/requirements.txt
diff --git a/Cargo.toml b/Cargo.toml
index 0d419ef..d95e73a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,7 +14,7 @@ repository = "https://github.com/apache/sedona-spatialbench/";
 version = "1.1.1"
 
 [workspace.dependencies]
-geo = "0.30.0"
+geo = "0.31.0"
 geozero = { version = "0.14.0", features = ["with-wkb", "with-geo"]}
 
 [profile.release]
diff --git a/spatialbench-cli/tests/cli_integration.rs 
b/spatialbench-cli/tests/cli_integration.rs
index 3a53f7e..d1f325c 100644
--- a/spatialbench-cli/tests/cli_integration.rs
+++ b/spatialbench-cli/tests/cli_integration.rs
@@ -108,7 +108,7 @@ fn test_spatialbench_cli_tbl_no_overwrite() {
     run_command();
     let original_metadata =
         fs::metadata(&expected_file).expect("Failed to get metadata of 
generated file");
-    assert_eq!(original_metadata.len(), 826311);
+    assert_eq!(original_metadata.len(), 826317);
 
     // Run the spatialbench-cli command again with the same parameters and 
expect the
     // file to not be overwritten
diff --git a/spatialbench/data/sf-v1/building.tbl.gz 
b/spatialbench/data/sf-v1/building.tbl.gz
index 297656c..9638c86 100644
Binary files a/spatialbench/data/sf-v1/building.tbl.gz and 
b/spatialbench/data/sf-v1/building.tbl.gz differ
diff --git a/spatialbench/data/sf-v1/trip.tbl.gz 
b/spatialbench/data/sf-v1/trip.tbl.gz
index 7114b91..8990906 100644
Binary files a/spatialbench/data/sf-v1/trip.tbl.gz and 
b/spatialbench/data/sf-v1/trip.tbl.gz differ
diff --git a/spatialbench/src/generators.rs b/spatialbench/src/generators.rs
index b7319e2..122718f 100644
--- a/spatialbench/src/generators.rs
+++ b/spatialbench/src/generators.rs
@@ -11,7 +11,7 @@ use crate::random::{RandomAlphaNumeric, 
RandomAlphaNumericInstance};
 use crate::random::{RandomBoundedInt, RandomString, RandomStringSequence, 
RandomText};
 use crate::spatial::overrides as spatial_overrides;
 use crate::spatial::utils::continent::{build_continent_cdf, WeightedTarget};
-use crate::spatial::utils::{hash_to_unit_u64, spider_seed_for_index};
+use crate::spatial::utils::{hash_to_unit_u64, spider_seed_for_index, 
wrap_around_longitude};
 use crate::spatial::{ContinentAffines, SpatialDefaults, SpatialGenerator};
 use crate::text::TextPool;
 use geo::Point;
@@ -1132,6 +1132,8 @@ impl TripGeneratorIterator {
         let angle: f64 = angle_rng.gen::<f64>() * std::f64::consts::TAU;
 
         let mut dropoff_x = pickuploc.x() + distance_value * angle.cos();
+        dropoff_x = wrap_around_longitude(dropoff_x);
+
         let mut dropoff_y = pickuploc.y() + distance_value * angle.sin();
 
         // Hard code coordinate precision to 8 decimal places - milimeter 
level precision for WGS 84
@@ -1570,6 +1572,6 @@ mod tests {
         // Check first Building
         let first = &buildings[1];
         assert_eq!(first.b_buildingkey, 2);
-        assert_eq!(first.to_string(), "2|blush|POLYGON((124.218033476 
10.538071565,124.215762091 10.536069114,124.214352934 
10.536014944,124.212486371 10.539913704,124.217919324 
10.539075339,124.218033476 10.538071565))|")
+        assert_eq!(first.to_string(), "2|blush|POLYGON((124.218033476 
10.538071565,124.217919324 10.539075339,124.212486371 
10.539913704,124.214352934 10.536014944,124.215762091 
10.536069114,124.218033476 10.538071565))|")
     }
 }
diff --git a/spatialbench/src/spatial/geometry.rs 
b/spatialbench/src/spatial/geometry.rs
index b856585..b753d57 100644
--- a/spatialbench/src/spatial/geometry.rs
+++ b/spatialbench/src/spatial/geometry.rs
@@ -1,11 +1,15 @@
-use crate::spatial::utils::{apply_affine, round_coordinates};
+use crate::spatial::utils::{
+    apply_affine, clamp_polygon_to_dateline, crosses_dateline, 
round_coordinates,
+    wrap_around_longitude,
+};
 use crate::spatial::{GeomType, SpatialConfig};
-use geo::{coord, Geometry, LineString, Point, Polygon};
+use geo::orient::Direction;
+use geo::{coord, Geometry, LineString, Orient, Point, Polygon};
 use rand::rngs::StdRng;
 use rand::Rng;
 use std::f64::consts::PI;
 
-const GEOMETRY_PRECISION: f64 = 1_000_000_000.0;
+pub const GEOMETRY_PRECISION: f64 = 1_000_000_000.0;
 
 pub fn emit_geom(
     center01: (f64, f64),
@@ -23,6 +27,7 @@ pub fn emit_geom(
 
 pub fn generate_point_geom(center: (f64, f64), m: &[f64; 6]) -> Geometry {
     let (x, y) = apply_affine(center.0, center.1, m);
+    let x = wrap_around_longitude(x);
     let (x, y) = round_coordinates(x, y, GEOMETRY_PRECISION);
     Geometry::Point(Point::new(x, y))
 }
@@ -51,7 +56,15 @@ pub fn generate_box_geom(
         .map(|(x, y)| coord! { x: x, y: y })
         .collect();
 
-    Geometry::Polygon(Polygon::new(LineString::from(coords), vec![]))
+    let mut polygon = Polygon::new(LineString::from(coords), vec![]);
+
+    // Handle polygons crossing the dateline
+    if crosses_dateline(&polygon) {
+        polygon = clamp_polygon_to_dateline(&polygon);
+    }
+
+    polygon = polygon.orient(Direction::Default);
+    Geometry::Polygon(polygon)
 }
 
 pub fn generate_polygon_geom(
@@ -79,9 +92,8 @@ pub fn generate_polygon_geom(
                 center.0 + config.polysize * ang.cos(),
                 center.1 + config.polysize * ang.sin(),
             );
-            let (x1, y1) = (x0.clamp(0.0, 1.0), y0.clamp(0.0, 1.0));
-            let (x2, y2) = apply_affine(x1, y1, m);
-            let (xr, yr) = round_coordinates(x2, y2, GEOMETRY_PRECISION);
+            let (x1, y1) = apply_affine(x0, y0, m);
+            let (xr, yr) = round_coordinates(x1, y1, GEOMETRY_PRECISION);
             coord! { x: xr, y: yr }
         })
         .collect::<Vec<_>>();
@@ -90,5 +102,13 @@ pub fn generate_polygon_geom(
         ring.push(first);
     }
 
-    Geometry::Polygon(Polygon::new(LineString::from(ring), vec![]))
+    let mut polygon = Polygon::new(LineString::from(ring), vec![]);
+
+    // Handle polygons crossing the dateline
+    if crosses_dateline(&polygon) {
+        polygon = clamp_polygon_to_dateline(&polygon);
+    }
+
+    polygon = polygon.orient(Direction::Default);
+    Geometry::Polygon(polygon)
 }
diff --git a/spatialbench/src/spatial/utils/antimeridian.rs 
b/spatialbench/src/spatial/utils/antimeridian.rs
new file mode 100644
index 0000000..22e9190
--- /dev/null
+++ b/spatialbench/src/spatial/utils/antimeridian.rs
@@ -0,0 +1,267 @@
+use geo::{Centroid, LineString, Polygon};
+
+/// Normalizes longitude values to the valid range [-180, 180] by wrapping 
around the antimeridian.
+///
+/// This function is specifically designed for point geometries (e.g., trip 
pickup/dropoff locations)
+/// that may have longitude values slightly outside the standard range. Unlike 
polygon clamping,
+/// which handles geometries crossing the dateline, this function simply 
normalizes point coordinates.
+///
+/// # Examples
+/// - POINT(181, 20) becomes POINT(-179, 20) after wraparound
+/// - POINT(-181, 20) becomes POINT(179, 20) after wraparound
+///
+/// # Note
+/// This is different from `clamp_polygon_to_dateline()`, which handles 
polygons that cross
+/// the dateline by splitting them. This function is used before CCW 
orientation enforcement.
+pub fn wrap_around_longitude(mut lon: f64) -> f64 {
+    while lon > 180.0 {
+        lon -= 360.0;
+    }
+    while lon < -180.0 {
+        lon += 360.0;
+    }
+    lon
+}
+
+/// Checks if a polygon crosses the dateline (antimeridian at ±180°)
+pub fn crosses_dateline(polygon: &Polygon) -> bool {
+    let coords = polygon.exterior().coords();
+    let mut has_east = false;
+    let mut has_west = false;
+
+    for coord in coords {
+        if (coord.x > 90.0 && coord.x <= 180.0) || coord.x < -180.0 {
+            has_east = true;
+        }
+        if coord.x > 180.0 || (coord.x >= -180.0 && coord.x < -90.0) {
+            has_west = true;
+        }
+        if has_east && has_west {
+            return true;
+        }
+    }
+    false
+}
+
+/// Clamps a polygon's longitude coordinates to prevent it from crossing the 
antimeridian (±180°).
+///
+/// This function is used to handle polygons that span across the dateline, 
which can cause
+/// rendering and spatial operation issues. It constrains the polygon to stay 
on one side of
+/// the dateline by clamping coordinates based on the polygon's centroid 
location.
+///
+/// # Behavior
+/// - If the centroid is in the eastern hemisphere (≥ 0°), coordinates are 
clamped to [0°, 180°]
+/// - If the centroid is in the western hemisphere (< 0°), coordinates are 
clamped to [-180°, 0°]
+/// - Latitude values (y-coordinates) remain unchanged
+///
+/// # Note
+/// This is different from `wrap_around_longitude()`, which normalizes 
individual point coordinates
+/// that fall slightly outside [-180, 180]. This function handles entire 
polygons that cross the dateline.
+pub fn clamp_polygon_to_dateline(polygon: &Polygon) -> Polygon {
+    let centroid = polygon.centroid().expect("Polygon should have centroid");
+    let east_bound = centroid.x() >= 0.0;
+    let keep_east = (centroid.x() >= 0.0 && centroid.x() <= 180.0) || 
(centroid.x() < -180.0);
+
+    let exterior_coords: Vec<_> = polygon
+        .exterior()
+        .coords()
+        .map(|coord| {
+            let clamped_x = if keep_east {
+                if east_bound {
+                    coord.x.clamp(0.0, 180.0)
+                } else {
+                    coord.x.max(-180.0)
+                }
+            } else if east_bound {
+                coord.x.min(180.0)
+            } else {
+                coord.x.clamp(-180.0, 0.0)
+            };
+            geo::Coord {
+                x: clamped_x,
+                y: coord.y,
+            }
+        })
+        .collect();
+
+    if exterior_coords.len() >= 4 {
+        Polygon::new(LineString::from(exterior_coords), vec![])
+    } else {
+        polygon.clone()
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use geo::polygon;
+
+    #[test]
+    fn test_wrap_around_longitude_positive_overflow() {
+        assert_eq!(wrap_around_longitude(190.0), -170.0);
+        assert_eq!(wrap_around_longitude(240.0), -120.0);
+    }
+
+    #[test]
+    fn test_wrap_around_longitude_negative_overflow() {
+        assert_eq!(wrap_around_longitude(-190.0), 170.0);
+        assert_eq!(wrap_around_longitude(-240.0), 120.0);
+    }
+
+    #[test]
+    fn test_wrap_around_longitude_within_range() {
+        assert_eq!(wrap_around_longitude(0.0), 0.0);
+        assert_eq!(wrap_around_longitude(90.0), 90.0);
+        assert_eq!(wrap_around_longitude(-90.0), -90.0);
+        assert_eq!(wrap_around_longitude(180.0), 180.0);
+        assert_eq!(wrap_around_longitude(-180.0), -180.0);
+    }
+
+    #[test]
+    fn test_crosses_dateline_no_crossing() {
+        let poly = polygon![
+            (x: 10.0, y: 10.0),
+            (x: 20.0, y: 10.0),
+            (x: 20.0, y: 20.0),
+            (x: 10.0, y: 20.0),
+            (x: 10.0, y: 10.0),
+        ];
+        assert!(!crosses_dateline(&poly));
+    }
+
+    #[test]
+    fn test_crosses_dateline_crossing() {
+        let mut poly = polygon![
+            (x: 170.0, y: 10.0),
+            (x: -170.0, y: 10.0),
+            (x: -170.0, y: 20.0),
+            (x: 170.0, y: 20.0),
+            (x: 170.0, y: 10.0),
+        ];
+        assert!(crosses_dateline(&poly));
+
+        poly = polygon![
+            (x: -160.0, y: 10.0),
+            (x: -170.0, y: 10.0),
+            (x: -170.0, y: 20.0),
+            (x: -160.0, y: 20.0),
+            (x: -160.0, y: 10.0),
+        ];
+        assert!(!crosses_dateline(&poly));
+    }
+
+    #[test]
+    fn test_clamp_polygon_to_dateline_positive_side() {
+        let mut poly = polygon![
+            (x: 170.0, y: 10.0),
+            (x: 180.0, y: 10.0),
+            (x: 180.0, y: 20.0),
+            (x: 170.0, y: 20.0),
+            (x: 170.0, y: 10.0),
+        ];
+        let mut clamped = clamp_polygon_to_dateline(&poly);
+
+        // Polygon should be preserved appropriately
+        assert_eq!(clamped, poly);
+
+        poly = polygon![
+            (x: 170.0, y: 10.0),
+            (x: 185.0, y: 10.0),
+            (x: 185.0, y: 20.0),
+            (x: 170.0, y: 20.0),
+            (x: 170.0, y: 10.0),
+        ];
+        clamped = clamp_polygon_to_dateline(&poly);
+
+        let expected = polygon![
+            (x: 170.0, y: 10.0),
+            (x: 180.0, y: 10.0),
+            (x: 180.0, y: 20.0),
+            (x: 170.0, y: 20.0),
+            (x: 170.0, y: 10.0),
+        ];
+
+        // Polygon should be clamped appropriately
+        assert_eq!(clamped, expected);
+    }
+
+    #[test]
+    fn test_clamp_polygon_to_dateline_with_centroid_on_dateline() {
+        // East bound polygon
+        let mut poly = polygon![
+            (x: 170.0, y: 10.0),
+            (x: 190.0, y: 10.0),
+            (x: 190.0, y: 20.0),
+            (x: 170.0, y: 20.0),
+            (x: 170.0, y: 10.0),
+        ];
+        let mut clamped = clamp_polygon_to_dateline(&poly);
+
+        let mut expected = polygon![
+            (x: 170.0, y: 10.0),
+            (x: 180.0, y: 10.0),
+            (x: 180.0, y: 20.0),
+            (x: 170.0, y: 20.0),
+            (x: 170.0, y: 10.0),
+        ];
+
+        // Polygon should be preserved appropriately
+        assert_eq!(clamped, expected);
+
+        // West bound polygon
+        poly = polygon![
+            (x: -170.0, y: 10.0),
+            (x: -190.0, y: 10.0),
+            (x: -190.0, y: 20.0),
+            (x: -170.0, y: 20.0),
+            (x: -170.0, y: 10.0),
+        ];
+        clamped = clamp_polygon_to_dateline(&poly);
+
+        expected = polygon![
+            (x: -170.0, y: 10.0),
+            (x: -180.0, y: 10.0),
+            (x: -180.0, y: 20.0),
+            (x: -170.0, y: 20.0),
+            (x: -170.0, y: 10.0),
+        ];
+
+        // Polygon should be clamped appropriately
+        assert_eq!(clamped, expected);
+    }
+
+    #[test]
+    fn test_clamp_polygon_to_dateline_negative_side() {
+        let mut poly = polygon![
+            (x: -170.0, y: 10.0),
+            (x: -180.0, y: 10.0),
+            (x: -180.0, y: 20.0),
+            (x: -170.0, y: 20.0),
+            (x: -170.0, y: 10.0),
+        ];
+        let mut clamped = clamp_polygon_to_dateline(&poly);
+
+        // Polygon should be preserved appropriately
+        assert_eq!(clamped, poly);
+
+        poly = polygon![
+            (x: -170.0, y: 10.0),
+            (x: -185.0, y: 10.0),
+            (x: -185.0, y: 20.0),
+            (x: -170.0, y: 20.0),
+            (x: -170.0, y: 10.0),
+        ];
+        clamped = clamp_polygon_to_dateline(&poly);
+
+        let expected = polygon![
+            (x: -170.0, y: 10.0),
+            (x: -180.0, y: 10.0),
+            (x: -180.0, y: 20.0),
+            (x: -170.0, y: 20.0),
+            (x: -170.0, y: 10.0),
+        ];
+
+        // Polygon should be clamped appropriately
+        assert_eq!(clamped, expected);
+    }
+}
diff --git a/spatialbench/src/spatial/utils/mod.rs 
b/spatialbench/src/spatial/utils/mod.rs
index 349537a..ab79032 100644
--- a/spatialbench/src/spatial/utils/mod.rs
+++ b/spatialbench/src/spatial/utils/mod.rs
@@ -1,7 +1,9 @@
 pub mod affine;
+mod antimeridian;
 pub mod continent;
 pub mod random;
 
 pub use affine::*;
+pub use antimeridian::*;
 pub use continent::*;
 pub use random::*;
diff --git a/spatialbench/tests/geometry_tests.rs 
b/spatialbench/tests/geometry_tests.rs
new file mode 100644
index 0000000..3c484e4
--- /dev/null
+++ b/spatialbench/tests/geometry_tests.rs
@@ -0,0 +1,136 @@
+//! Geometry validation tests for generated spatial data.
+//!
+//! This test suite validates that all generated geometries meet quality and 
correctness standards:
+//! - **Coordinate validity**: Longitude [-180°, 180°], latitude [-90°, 90°]
+//! - **OGC compliance**: Valid topology, counter-clockwise winding for 
exterior rings
+//! - **Precision constraints**: Coordinates limited to 9 decimal places
+//! - **Antimeridian handling**: No dateline crossings in generated polygons
+//!
+//! These tests ensure spatial data quality and compatibility with spatial 
databases and GIS tools.
+
+#[cfg(test)]
+mod geometry_tests {
+    use geo::{Validation, Winding};
+    use spatialbench::generators::{BuildingGenerator, TripGenerator};
+    use spatialbench::spatial::geometry::GEOMETRY_PRECISION;
+    use spatialbench::spatial::utils::crosses_dateline;
+
+    #[test]
+    fn test_trip_coordinates_are_valid() {
+        let generator = TripGenerator::new(0.1, 1, 1);
+        let trips: Vec<_> = generator.iter().collect();
+
+        for trip in trips {
+            // Check pickup coordinates are valid
+            assert!(
+                trip.t_pickuploc.x() >= -180.0 && trip.t_pickuploc.x() <= 
180.0,
+                "Pickup longitude out of range: {}",
+                trip.t_pickuploc.x()
+            );
+            assert!(
+                trip.t_pickuploc.y() >= -90.0 && trip.t_pickuploc.y() <= 90.0,
+                "Pickup latitude out of range: {}",
+                trip.t_pickuploc.y()
+            );
+
+            // Check dropoff coordinates are valid
+            assert!(
+                trip.t_dropoffloc.x() >= -180.0 && trip.t_dropoffloc.x() <= 
180.0,
+                "Dropoff longitude out of range: {}",
+                trip.t_dropoffloc.x()
+            );
+            assert!(
+                trip.t_dropoffloc.y() >= -90.0 && trip.t_dropoffloc.y() <= 
90.0,
+                "Dropoff latitude out of range: {}",
+                trip.t_dropoffloc.y()
+            );
+
+            // Check coordinates have proper precision (9 decimal places)
+            let pickup_x_precision =
+                (trip.t_pickuploc.x() * GEOMETRY_PRECISION).round() / 
GEOMETRY_PRECISION;
+            assert_eq!(trip.t_pickuploc.x(), pickup_x_precision);
+
+            let dropoff_x_precision =
+                (trip.t_dropoffloc.x() * GEOMETRY_PRECISION).round() / 
GEOMETRY_PRECISION;
+            assert_eq!(trip.t_dropoffloc.x(), dropoff_x_precision);
+        }
+    }
+
+    #[test]
+    fn test_building_polygons_are_valid() {
+        let generator = BuildingGenerator::new(10.0, 1, 1);
+        let buildings: Vec<_> = generator.iter().collect();
+
+        for building in buildings {
+            let polygon = &building.b_boundary;
+
+            assert!(
+                polygon.is_valid(),
+                "Building {} has invalid polygon",
+                building.b_buildingkey
+            );
+        }
+    }
+
+    #[test]
+    fn test_building_polygon_winding() {
+        // Create a generator with a small scale factor
+        let generator = BuildingGenerator::new(1.0, 1, 1);
+        let buildings: Vec<_> = generator.iter().collect();
+
+        // Check that all building polygons have counter-clockwise winding
+        for building in buildings.iter() {
+            let exterior = building.b_boundary.exterior();
+            assert!(
+                exterior.is_ccw(),
+                "Building {} polygon should have counter-clockwise winding",
+                building.b_buildingkey
+            );
+        }
+    }
+
+    #[test]
+    fn test_coordinate_precision() {
+        let generator = TripGenerator::new(0.01, 1, 1);
+        let trips: Vec<_> = generator.iter().collect();
+
+        for trip in trips {
+            // Check 9 decimal place precision
+            let pickup_x_str = format!("{:.9}", trip.t_pickuploc.x());
+            let pickup_y_str = format!("{:.9}", trip.t_pickuploc.y());
+            let dropoff_x_str = format!("{:.9}", trip.t_dropoffloc.x());
+            let dropoff_y_str = format!("{:.9}", trip.t_dropoffloc.y());
+
+            // Verify no extra precision beyond 9 decimals
+            let pickup_x_parsed: f64 = pickup_x_str.parse().unwrap();
+            let pickup_y_parsed: f64 = pickup_y_str.parse().unwrap();
+            let dropoff_x_parsed: f64 = dropoff_x_str.parse().unwrap();
+            let dropoff_y_parsed: f64 = dropoff_y_str.parse().unwrap();
+
+            assert_eq!(trip.t_pickuploc.x(), pickup_x_parsed);
+            assert_eq!(trip.t_pickuploc.y(), pickup_y_parsed);
+            assert_eq!(trip.t_dropoffloc.x(), dropoff_x_parsed);
+            assert_eq!(trip.t_dropoffloc.y(), dropoff_y_parsed);
+        }
+    }
+
+    #[test]
+    fn test_building_dateline_crossing() {
+        use spatialbench::generators::BuildingGenerator;
+
+        let generator = BuildingGenerator::new(1000.0, 1, 1);
+        let buildings: Vec<_> = generator.iter().collect();
+
+        for building in buildings {
+            let polygon = &building.b_boundary;
+
+            assert_eq!(
+                crosses_dateline(polygon),
+                false,
+                "Building {} polygon crosses dateline: {:?}",
+                building.b_buildingkey,
+                building.b_boundary
+            );
+        }
+    }
+}

Reply via email to