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 clipping;
93pub mod clustering;
94mod contains;
95pub mod de9im;
96pub mod delaunay;
97mod difference;
98mod distance;
99mod douglas_peucker;
100mod envelope;
101pub mod generalization;
102pub mod geodesic;
103pub(crate) mod intersection;
104mod length;
105pub mod min_bounds;
106pub mod network;
107pub mod offset;
108pub mod pool;
109pub mod ransac;
110mod repair;
111pub mod robust_location;
112mod simplify;
113pub mod snap_rounding;
114pub mod spatial_join;
115pub mod topology;
116mod topology_simplify;
117mod transform;
118mod union_ops;
119mod valid;
120pub mod voronoi;
121
122// Re-export from core
123pub use oxigdal_core::vector::{Coordinate, LineString, MultiPolygon, Point, Polygon};
124
125// Re-export area operations
126pub use area::{
127    AreaMethod, area, area_multipolygon, area_polygon, is_clockwise, is_counter_clockwise,
128};
129
130// Re-export buffer operations
131pub use buffer::{
132    BufferCapStyle, BufferJoinStyle, BufferOptions, buffer_linestring, buffer_linestring_pooled,
133    buffer_point, buffer_point_pooled, buffer_polygon, buffer_polygon_pooled,
134};
135
136// Re-export centroid operations
137pub use centroid::{
138    centroid, centroid_collection, centroid_linestring, centroid_multilinestring,
139    centroid_multipoint, centroid_multipolygon, centroid_point, centroid_polygon,
140};
141
142// Re-export spatial predicates
143pub use contains::{
144    ContainsPredicate, CrossesPredicate, IntersectsPredicate, OverlapsPredicate, TouchesPredicate,
145    contains, crosses, disjoint, intersects, overlaps, point_in_polygon_or_boundary,
146    point_on_polygon_boundary, point_strictly_inside_polygon, touches, within,
147};
148
149// Re-export DE-9IM types and predicates
150pub use de9im::{
151    CoveredByPredicate, CoversPredicate, De9im, Dimension, EqualsPredicate, relate,
152    relate_line_polygon, relate_point_polygon, relate_polygons,
153};
154
155// Re-export difference operations
156pub use difference::{
157    clip_to_box, difference_polygon, difference_polygon_pooled, difference_polygons,
158    difference_polygons_pooled, erase_small_holes, symmetric_difference,
159    symmetric_difference_pooled,
160};
161
162// Re-export distance operations
163pub use distance::{
164    DistanceMethod, directed_hausdorff, discrete_frechet_distance, distance_point_to_linestring,
165    distance_point_to_point, distance_point_to_polygon, hausdorff_distance,
166    hausdorff_distance_to_segments,
167};
168
169// Re-export Douglas-Peucker
170pub use douglas_peucker::simplify_linestring as simplify_linestring_dp;
171
172// Re-export envelope operations
173pub use envelope::{
174    envelope, envelope_collection, envelope_contains_point, envelope_intersection,
175    envelope_linestring, envelope_multilinestring, envelope_multipoint, envelope_multipolygon,
176    envelope_point, envelope_polygon, envelope_union, envelope_with_buffer, envelopes_intersect,
177};
178
179// Re-export intersection operations
180pub use intersection::{
181    SegmentIntersection, intersect_linestrings, intersect_linestrings_sweep, intersect_polygons,
182    intersect_polygons_pooled, intersect_segment_segment, point_in_polygon,
183};
184
185// Re-export length operations
186pub use length::{
187    LengthMethod, length, length_linestring, length_linestring_3d, length_multilinestring,
188};
189
190// Re-export simplification operations
191pub use simplify::{SimplifyMethod, simplify_linestring, simplify_polygon};
192
193// Re-export topology-preserving simplification
194pub use topology_simplify::{
195    TopologySimplifyOptions, simplify_topology, simplify_topology_with_options,
196};
197
198// Re-export minimum bounding geometry
199pub use min_bounds::{Circle, RotatedRect, aabb, min_area_rotated_rect, smallest_enclosing_circle};
200
201// Re-export line offset operations
202pub use offset::{JoinStyle, OffsetOptions, OffsetResult, offset_linestring, offset_polygon_rings};
203
204// Re-export snap rounding operations
205pub use snap_rounding::{
206    SnapRoundingOptions, SnapRoundingResult, SnappedSegment, snap_coordinate, snap_linestring,
207    snap_round,
208};
209
210// Re-export union operations
211pub use union_ops::{
212    cascaded_union, cascaded_union_pooled, convex_hull, convex_hull_pooled, merge_polygons,
213    union_polygon, union_polygon_pooled, union_polygons, union_polygons_pooled,
214};
215
216// Re-export pool types and utilities
217pub use pool::{
218    Pool, PoolGuard, PoolStats, clear_all_pools, get_pool_stats, get_pooled_coordinate_vec,
219    get_pooled_linestring, get_pooled_point, get_pooled_polygon,
220};
221
222// Re-export validation
223pub use valid::{
224    IssueType, Severity, ValidationIssue, validate_geometry, validate_linestring, validate_polygon,
225};
226
227// Re-export repair operations
228pub use repair::{
229    RepairOptions, close_ring, fix_self_intersection, remove_collinear_vertices,
230    remove_duplicate_vertices, remove_spikes, repair_linestring, repair_linestring_with_options,
231    repair_polygon, repair_polygon_with_options, reverse_ring,
232};
233
234// Re-export clipping operations
235pub use clipping::{ClipOperation, clip_multi, clip_polygons};
236
237// Re-export power diagram (weighted Voronoi) operations
238pub use voronoi::{
239    PowerCell, PowerDiagram, PowerDiagramOptions, WeightedPoint, power_diagram, weighted_bisector,
240};
241
242// Re-export generalization operators (ICA taxonomy: collapse, exaggerate, displace)
243pub use generalization::{
244    CollapseOptions, DisplaceOptions, DisplaceStats, ExaggerateAnchor, ExaggerateOptions,
245    collapse_linestring_to_point, collapse_polygon_to_point, displace_points,
246    displace_polygons_by_centroid, exaggerate_coord, exaggerate_linestring, exaggerate_polygon,
247    should_collapse_polygon,
248};
249
250// Re-export robust location estimators
251pub use robust_location::{
252    RobustLocationOptions, geometric_median, geometric_median_3d, geometric_median_with_options,
253    l1_median, spatial_mean, weighted_geometric_median,
254};
255
256// Re-export coordinate transformations
257pub use transform::{
258    CommonCrs, CrsTransformer, transform_geometry, transform_linestring, transform_point,
259    transform_polygon,
260};
261
262// Re-export RANSAC robust fitting
263pub use ransac::{
264    RansacLineModel, RansacOptions, RansacPlaneModel, RansacResult, ransac_fit_line,
265    ransac_fit_plane,
266};
267
268#[cfg(test)]
269mod tests {
270    use super::*;
271
272    #[test]
273    fn test_point_distance() {
274        let p1 = Coordinate::new_2d(0.0, 0.0);
275        let p2 = Coordinate::new_2d(3.0, 4.0);
276        let dx = p1.x - p2.x;
277        let dy = p1.y - p2.y;
278        let dist = (dx * dx + dy * dy).sqrt();
279        assert!((dist - 5.0).abs() < 1e-10);
280    }
281
282    #[test]
283    fn test_linestring_construction() {
284        let coords = vec![
285            Coordinate::new_2d(0.0, 0.0),
286            Coordinate::new_2d(3.0, 0.0),
287            Coordinate::new_2d(3.0, 4.0),
288        ];
289        let result = LineString::new(coords);
290        assert!(result.is_ok());
291        if let Ok(line) = result {
292            assert_eq!(line.len(), 3);
293        }
294    }
295
296    #[test]
297    fn test_polygon_construction() {
298        // Square with side length 10
299        let coords = vec![
300            Coordinate::new_2d(0.0, 0.0),
301            Coordinate::new_2d(10.0, 0.0),
302            Coordinate::new_2d(10.0, 10.0),
303            Coordinate::new_2d(0.0, 10.0),
304            Coordinate::new_2d(0.0, 0.0),
305        ];
306        let exterior = LineString::new(coords);
307        assert!(exterior.is_ok());
308        if let Ok(ext) = exterior {
309            let poly = Polygon::new(ext, vec![]);
310            assert!(poly.is_ok());
311        }
312    }
313}