traj_dist_rs/lib.rs
1//! # traj-dist-rs
2//!
3//! `traj-dist-rs` is a high-performance trajectory distance and similarity measurement library implemented in Rust.
4//! It provides efficient implementations of various trajectory distance algorithms with both
5//! Rust native APIs and Python bindings.
6//!
7//! ## Overview
8//!
9//! This crate implements multiple trajectory distance algorithms including:
10//!
11//! - SSPD (Symmetric Segment-Path Distance)
12//! - DTW (Dynamic Time Warping)
13//! - Hausdorff Distance
14//! - LCSS (Longest Common Subsequence)
15//! - EDR (Edit Distance on Real sequence)
16//! - ERP (Edit distance with Real Penalty)
17//! - Frechet Distance (Continuous) - Euclidean only
18//! - Discrete Frechet Distance
19//! - EDwP (Edit Distance with Projections) - Euclidean only
20//! - SOWD (One-Way Distance) (planned)
21//!
22//! Trajectory similarity is often measured via trajectory distances such as DTW, LCSS, EDR, ERP, EDwP, Hausdorff, (Discrete) Fréchet, and SSPD.
23//!
24//! ## Features
25//!
26//! - High-performance Rust implementations
27//! - Support for both Euclidean and Spherical(Haversine / great-circle) distance calculations
28//! - Python bindings via PyO3
29//! - Compatible with the original `traj-dist` library
30//! - Support for various trajectory distance algorithms
31//! - Batch computation functions (pdist, cdist) with parallel processing
32//! - Zero-copy NumPy array support for Python bindings
33//!
34//! ## Similarity vs Distance
35//!
36//! This library computes trajectory **distances**, which can be easily converted to **similarity scores**:
37//!
38//! - **Similarity = 1 / (1 + distance)**: Commonly used for similarity scoring
39//! - **Similarity = exp(-distance / σ)**: Gaussian kernel similarity, where σ controls the sensitivity
40//! - **Normalized LCSS/EDR**: These algorithms can return normalized scores in [0, 1] range
41//!
42//! For example, if DTW distance is 2.0:
43//! ```rust
44//! let distance = 2.0;
45//! let similarity = 1.0 / (1.0 + distance); // similarity = 0.333
46//! ```
47//!
48//! ## Use Cases and Applications
49//!
50//! This library is useful for various trajectory analysis tasks:
51//!
52//! - **Trajectory similarity search**: Find similar trajectories from a database via kNN and pdist/cdist
53//! - **Nearest neighbor retrieval**: Query by example trajectory
54//! - **Trajectory clustering**: Group similar trajectories together
55//! - **Map-matching preprocessing**: Match GPS traces to road networks
56//! - **Anomaly detection**: Identify unusual trajectory patterns
57//! - **Route pattern mining**: Discover common movement patterns
58//! - **Mobility data analysis**: Analyze GPS traces and movement data
59//! - **Time series similarity**: Treat trajectories as 2D time series
60//!
61//! ## Glossary and Terminology
62//!
63//! - **Trajectory similarity / distance / dissimilarity**: Related concepts for measuring how alike two trajectories are
64//! - **Sequence alignment**: Matching elements between two sequences (e.g., DTW, LCSS)
65//! - **Warping / matching**: Non-linear alignment between sequences (DTW concept)
66//! - **Spatiotemporal trajectories / GPS traces**: Trajectories with both spatial (location) and temporal (time) information
67//!
68//! ## Usage
69//!
70//! ```rust
71//! use traj_dist_rs::distance::sspd::sspd;
72//! use traj_dist_rs::distance::distance_type::DistanceType;
73//!
74//! let traj1 = vec![[0.0, 0.0], [1.0, 1.0]];
75//! let traj2 = vec![[0.0, 1.0], [1.0, 0.0]];
76//!
77//! let distance = sspd(&traj1, &traj2, DistanceType::Euclidean);
78//! println!("SSPD distance: {}", distance);
79//!
80//! // Convert to similarity score
81//! let similarity = 1.0 / (1.0 + distance);
82//! println!("SSPD similarity: {}", similarity);
83//! ```
84
85pub mod distance;
86pub mod err;
87pub mod traits;
88
89#[cfg(feature = "python-binding")]
90pub mod binding;
91
92#[cfg(feature = "python-binding")]
93use pyo3::prelude::*;
94
95/// Trajectory distance calculation library
96#[cfg(feature = "python-binding")]
97#[pymodule]
98fn _lib(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> {
99 // Register the DpResult class
100 m.add_class::<crate::binding::PyDpResult>()?;
101
102 // Register the Metric class for batch computation
103 m.add_class::<crate::binding::batch::PyMetric>()?;
104
105 // Register batch computation functions
106 m.add_function(wrap_pyfunction!(crate::binding::batch::pdist, m)?)?;
107 m.add_function(wrap_pyfunction!(crate::binding::batch::cdist, m)?)?;
108
109 // Register distance functions
110 m.add_function(wrap_pyfunction!(crate::binding::distance::sspd::sspd, m)?)?;
111 m.add_function(wrap_pyfunction!(crate::binding::distance::dtw::dtw, m)?)?;
112 m.add_function(wrap_pyfunction!(
113 crate::binding::distance::dtw::dtw_with_matrix,
114 m
115 )?)?;
116 m.add_function(wrap_pyfunction!(
117 crate::binding::distance::hausdorff::hausdorff,
118 m
119 )?)?;
120 m.add_function(wrap_pyfunction!(crate::binding::distance::lcss::lcss, m)?)?;
121 m.add_function(wrap_pyfunction!(
122 crate::binding::distance::lcss::lcss_with_matrix,
123 m
124 )?)?;
125 m.add_function(wrap_pyfunction!(crate::binding::distance::edr::edr, m)?)?;
126 m.add_function(wrap_pyfunction!(
127 crate::binding::distance::edr::edr_with_matrix,
128 m
129 )?)?;
130 m.add_function(wrap_pyfunction!(
131 crate::binding::distance::discret_frechet::discret_frechet,
132 m
133 )?)?;
134 m.add_function(wrap_pyfunction!(
135 crate::binding::distance::discret_frechet::discret_frechet_with_matrix,
136 m
137 )?)?;
138 m.add_function(wrap_pyfunction!(
139 crate::binding::distance::erp::erp_compat_traj_dist,
140 m
141 )?)?;
142 m.add_function(wrap_pyfunction!(
143 crate::binding::distance::erp::erp_compat_traj_dist_with_matrix,
144 m
145 )?)?;
146 m.add_function(wrap_pyfunction!(
147 crate::binding::distance::erp::erp_standard,
148 m
149 )?)?;
150 m.add_function(wrap_pyfunction!(
151 crate::binding::distance::erp::erp_standard_with_matrix,
152 m
153 )?)?;
154 m.add_function(wrap_pyfunction!(crate::binding::distance::edwp::edwp, m)?)?;
155 m.add_function(wrap_pyfunction!(
156 crate::binding::distance::frechet::frechet,
157 m
158 )?)?;
159
160 // Register helper function for pickle deserialization
161 m.add_function(wrap_pyfunction!(
162 crate::binding::__dp_result_from_pickle,
163 m
164 )?)?;
165
166 Ok(())
167}