Skip to main content

oxigdal_algorithms/vector/
mod.rs

1//! Vector operations and geometric algorithms
2//!
3//! This module provides comprehensive geometric operations for vector data:
4//!
5//! ## Core Operations
6//! - Buffer generation (fixed and variable distance)
7//! - Intersection operations
8//! - Union operations
9//! - Difference operations
10//!
11//! ## Topology Operations
12//! - Overlay analysis (intersection, union, difference, symmetric difference)
13//! - Erase operations (cookie-cutter)
14//! - Split operations (geometry splitting)
15//!
16//! ## Network Analysis
17//! - Graph structures and building
18//! - Shortest path algorithms (Dijkstra, A*, bidirectional)
19//! - Service area calculation (isochrones)
20//! - Advanced routing with constraints
21//!
22//! ## Spatial Clustering
23//! - DBSCAN (density-based clustering)
24//! - K-means clustering
25//! - Hierarchical clustering
26//!
27//! ## Triangulation
28//! - Delaunay triangulation
29//! - Voronoi diagrams
30//! - Constrained Delaunay
31//!
32//! ## Spatial Joins
33//! - R-tree spatial index
34//! - Nearest neighbor search
35//! - K-nearest neighbors
36//! - Range queries
37//!
38//! ## Simplification
39//! - Douglas-Peucker algorithm
40//! - Visvalingam-Whyatt algorithm
41//! - Topology-preserving simplification
42//!
43//! ## Geometric Analysis
44//! - Centroid calculation (geometric and area-weighted)
45//! - Area calculation (planar and geodetic)
46//! - Length measurement (planar and geodetic)
47//! - Distance measurement (Euclidean, Haversine, Vincenty)
48//! - Convex hull computation
49//!
50//! ## Spatial Predicates
51//! - Contains, Within
52//! - Intersects, Disjoint
53//! - Touches, Overlaps, Crosses
54//!
55//! ## Validation & Repair
56//! - Geometry validation
57//! - Self-intersection detection
58//! - Duplicate vertex detection
59//! - Spike detection
60//! - Geometry repair (fix orientation, remove duplicates, close rings)
61//!
62//! ## Coordinate Transformation
63//! - CRS transformation (WGS84, Web Mercator, UTM, etc.)
64//! - Geometry reprojection
65//!
66//! ## Object Pooling
67//! - Thread-local object pools for Point, LineString, Polygon
68//! - Pooled versions of buffer, union, difference, intersection operations
69//! - Reduces allocations by 2-3x for batch operations
70//! - Automatic return to pool via RAII guards
71//!
72//! ### Using Object Pooling
73//!
74//! ```
75//! use oxigdal_algorithms::vector::{buffer_point_pooled, Point, BufferOptions};
76//!
77//! let point = Point::new(0.0, 0.0);
78//! let options = BufferOptions::default();
79//!
80//! // Get a pooled polygon - automatically returned to pool when dropped
81//! let buffered = buffer_point_pooled(&point, 10.0, &options)?;
82//! // Use buffered geometry...
83//! // Polygon returned to pool when `buffered` goes out of scope
84//! # Ok::<(), oxigdal_algorithms::error::AlgorithmError>(())
85//! ```
86//!
87//! All operations use geometry types from `oxigdal-core::vector`.
88
89mod area;
90mod buffer;
91mod centroid;
92pub mod clustering;
93mod contains;
94pub mod delaunay;
95mod difference;
96mod distance;
97mod douglas_peucker;
98mod envelope;
99mod intersection;
100mod length;
101pub mod network;
102pub mod pool;
103mod repair;
104mod simplify;
105pub mod spatial_join;
106pub mod topology;
107mod transform;
108mod union_ops;
109mod valid;
110pub mod voronoi;
111
112// Re-export from core
113pub use oxigdal_core::vector::{Coordinate, LineString, MultiPolygon, Point, Polygon};
114
115// Re-export area operations
116pub use area::{
117    AreaMethod, area, area_multipolygon, area_polygon, is_clockwise, is_counter_clockwise,
118};
119
120// Re-export buffer operations
121pub use buffer::{
122    BufferCapStyle, BufferJoinStyle, BufferOptions, buffer_linestring, buffer_linestring_pooled,
123    buffer_point, buffer_point_pooled, buffer_polygon, buffer_polygon_pooled,
124};
125
126// Re-export centroid operations
127pub use centroid::{
128    centroid, centroid_collection, centroid_linestring, centroid_multilinestring,
129    centroid_multipoint, centroid_multipolygon, centroid_point, centroid_polygon,
130};
131
132// Re-export spatial predicates
133pub use contains::{
134    ContainsPredicate, CrossesPredicate, IntersectsPredicate, OverlapsPredicate, TouchesPredicate,
135    contains, crosses, disjoint, intersects, overlaps, point_in_polygon_or_boundary,
136    point_on_polygon_boundary, point_strictly_inside_polygon, touches, within,
137};
138
139// Re-export difference operations
140pub use difference::{
141    clip_to_box, difference_polygon, difference_polygon_pooled, difference_polygons,
142    difference_polygons_pooled, erase_small_holes, symmetric_difference,
143    symmetric_difference_pooled,
144};
145
146// Re-export distance operations
147pub use distance::{
148    DistanceMethod, distance_point_to_linestring, distance_point_to_point,
149    distance_point_to_polygon,
150};
151
152// Re-export Douglas-Peucker
153pub use douglas_peucker::simplify_linestring as simplify_linestring_dp;
154
155// Re-export envelope operations
156pub use envelope::{
157    envelope, envelope_collection, envelope_contains_point, envelope_intersection,
158    envelope_linestring, envelope_multilinestring, envelope_multipoint, envelope_multipolygon,
159    envelope_point, envelope_polygon, envelope_union, envelope_with_buffer, envelopes_intersect,
160};
161
162// Re-export intersection operations
163pub use intersection::{
164    SegmentIntersection, intersect_linestrings, intersect_linestrings_sweep, intersect_polygons,
165    intersect_polygons_pooled, intersect_segment_segment, point_in_polygon,
166};
167
168// Re-export length operations
169pub use length::{
170    LengthMethod, length, length_linestring, length_linestring_3d, length_multilinestring,
171};
172
173// Re-export simplification operations
174pub use simplify::{SimplifyMethod, simplify_linestring, simplify_polygon};
175
176// Re-export union operations
177pub use union_ops::{
178    cascaded_union, cascaded_union_pooled, convex_hull, convex_hull_pooled, merge_polygons,
179    union_polygon, union_polygon_pooled, union_polygons, union_polygons_pooled,
180};
181
182// Re-export pool types and utilities
183pub use pool::{
184    Pool, PoolGuard, PoolStats, clear_all_pools, get_pool_stats, get_pooled_coordinate_vec,
185    get_pooled_linestring, get_pooled_point, get_pooled_polygon,
186};
187
188// Re-export validation
189pub use valid::{
190    IssueType, Severity, ValidationIssue, validate_geometry, validate_linestring, validate_polygon,
191};
192
193// Re-export repair operations
194pub use repair::{
195    RepairOptions, close_ring, fix_self_intersection, remove_collinear_vertices,
196    remove_duplicate_vertices, remove_spikes, repair_linestring, repair_linestring_with_options,
197    repair_polygon, repair_polygon_with_options, reverse_ring,
198};
199
200// Re-export coordinate transformations
201pub use transform::{
202    CommonCrs, CrsTransformer, transform_geometry, transform_linestring, transform_point,
203    transform_polygon,
204};
205
206#[cfg(test)]
207mod tests {
208    use super::*;
209
210    #[test]
211    fn test_point_distance() {
212        let p1 = Coordinate::new_2d(0.0, 0.0);
213        let p2 = Coordinate::new_2d(3.0, 4.0);
214        let dx = p1.x - p2.x;
215        let dy = p1.y - p2.y;
216        let dist = (dx * dx + dy * dy).sqrt();
217        assert!((dist - 5.0).abs() < 1e-10);
218    }
219
220    #[test]
221    fn test_linestring_construction() {
222        let coords = vec![
223            Coordinate::new_2d(0.0, 0.0),
224            Coordinate::new_2d(3.0, 0.0),
225            Coordinate::new_2d(3.0, 4.0),
226        ];
227        let result = LineString::new(coords);
228        assert!(result.is_ok());
229        if let Ok(line) = result {
230            assert_eq!(line.len(), 3);
231        }
232    }
233
234    #[test]
235    fn test_polygon_construction() {
236        // Square with side length 10
237        let coords = vec![
238            Coordinate::new_2d(0.0, 0.0),
239            Coordinate::new_2d(10.0, 0.0),
240            Coordinate::new_2d(10.0, 10.0),
241            Coordinate::new_2d(0.0, 10.0),
242            Coordinate::new_2d(0.0, 0.0),
243        ];
244        let exterior = LineString::new(coords);
245        assert!(exterior.is_ok());
246        if let Ok(ext) = exterior {
247            let poly = Polygon::new(ext, vec![]);
248            assert!(poly.is_ok());
249        }
250    }
251}