Skip to content

Commit

Permalink
Merge pull request #1 from Pandicon/main
Browse files Browse the repository at this point in the history
Add a function to get the angular distance between two points
  • Loading branch information
Pandicon authored Oct 2, 2024
2 parents c2c235c + 15c0d86 commit 3082400
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 2 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@ State key:

| Feature | State |
|----------------------------------------------------------------------------------------------------------|:-----:|
| **Points** | 🟡 |
| **Points** | 🟢 |
| Spherical ↔ Cartesian conversion | 🟢 |
| (Approximate) equality check | 🟢 |
| Distance between points (metric) | 🟢 |
| Distance between points (angular value) | 🔴 |
| Distance between points (angular value) | 🟢 |
| **Great circles** | 🟡 |
| Construction from two points | 🟢 |
| Construction from an arc | 🟢 |
Expand Down
40 changes: 40 additions & 0 deletions src/point.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,15 @@ impl SphericalPoint {
(1.0 - cos_angle) < tolerance.powi(2)
}

/// Calculates the angular distance between the points
///
/// If you need to sort points by distance, but do not need the actual angular values for each of them, consider using `SphericalPoint::minus_cotan_distance`
pub fn distance(&self, other: &Self) -> f32 {
let angle_sin = self.cartesian().cross(&other.cartesian()).magnitude();
let angle_cos = self.cartesian().dot(&other.cartesian());
angle_sin.atan2(angle_cos)
}

/// Calculates `-1/tan(distance between points)`
///
/// Useful when sorting points based on distance without needing to know the actual distance as it avoid inverse trigonometric functions. `-1/tan(x)` is increasing for `0 < x < pi`, which is (more than) the needed range
Expand Down Expand Up @@ -207,4 +216,35 @@ mod tests {
}
}
}

#[test]
fn distance() {
let tolerance = 10e-6;

let point_1_1 = SphericalPoint::new(0.0, 0.0);
let point_1_2 = SphericalPoint::new(0.0, PI / 2.0);
let distance_1 = PI / 2.0;
assert!((point_1_1.distance(&point_1_2) - distance_1).abs() < tolerance);

let point_2_1 = SphericalPoint::new(0.0, 0.0);
let point_2_2 = SphericalPoint::new(PI / 2.0, 0.0);
let distance_2 = PI / 2.0;
assert!((point_2_1.distance(&point_2_2) - distance_2).abs() < tolerance);

let point_3_1 = SphericalPoint::new(PI / 3.0, PI / 6.0);
let point_3_2 = SphericalPoint::new(PI / 3.0 + PI, -PI / 6.0);
let distance_3 = PI;
assert!((point_3_1.distance(&point_3_2) - distance_3).abs() < tolerance);

let point_4_1 = SphericalPoint::new(PI / 3.0, PI / 6.0);
let point_4_2 = SphericalPoint::new(250.0 * PI / 180.0, -25.0 * PI / 180.0);
let distance_4 = 169.82426 * PI / 180.0;
assert!((point_4_1.distance(&point_4_2) - distance_4).abs() < tolerance);

let point_5_1 = SphericalPoint::new(PI / 12.0, PI / 9.0);
let point_5_2 = SphericalPoint::new(PI / 4.0, -PI / 15.0);
println!("{}", point_5_1.distance(&point_5_2));
let distance_5 = 43.53911 * PI / 180.0;
assert!((point_5_1.distance(&point_5_2) - distance_5).abs() < tolerance);
}
}

0 comments on commit 3082400

Please sign in to comment.