pelorus 0.1.0

A high-performance GPS map-matching library for geospatial road network processing
Documentation
use geo::algorithm::euclidean_distance::EuclideanDistance;
use geo::Point;
use std::f64::consts::PI;

/// Calculates emission probability for a GPS measurement given a candidate point.
/// Uses Gaussian PDF to model GPS measurement noise.
///
/// # Arguments
/// * `gps` - GPS measurement point
/// * `candidate` - Candidate point on road network
/// * `sigma` - Standard deviation of GPS measurement noise in meters
///
/// # Returns
/// * Probability value between 0 and 1
pub fn emission_probability(
    gps: &Point<f64>,
    candidate: &Point<f64>,
    sigma: f64,
) -> f64 {
    let distance = gps.euclidean_distance(candidate);
    emission_probability_from_distance(distance, sigma)
}

/// Calculates emission probability from distance.
/// Uses a simplified Gaussian PDF: (1/√(2π)) * e^(-d²/(2σ²))
///
/// Note: The coefficient omits sigma, which differs from the standard Gaussian PDF
/// (1/√(2π*σ²)) * e^(-d²/(2σ²)), for map-matching applications.
///
/// # Arguments
/// * `distance` - Distance between GPS measurement and candidate point in meters
/// * `sigma` - Standard deviation of GPS measurement noise in meters
///
/// # Returns
/// * Probability value between 0 and 1
pub fn emission_probability_from_distance(distance: f64, sigma: f64) -> f64 {
    if distance > 200.0 {
        return 0.0;
    }

    // Handle edge case: sigma = 0
    if sigma == 0.0 {
        if distance == 0.0 {
            return 1.0 / (2.0 * PI).sqrt(); // Perfect match
        } else {
            return 0.0; // Any distance > 0 with zero tolerance
        }
    }

    // Simplified Gaussian: (1/√(2π)) * e^(-d²/(2σ²))
    // Note: This omits sigma from the coefficient
    let coefficient = 1.0 / (2.0 * PI).sqrt();
    let exponent = -(distance * distance) / (2.0 * sigma * sigma);
    coefficient * exponent.exp()
}