1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
use pyo3::prelude::*;
/// Computes the convex hull of a set of 2D points using Graham's scan algorithm.
///
/// # Arguments
///
/// * `points` - A mutable vector of tuples representing the points (x, y).
///
/// # Returns
///
/// A vector of tuples representing the points that form the convex hull in counter-clockwise order.
pub fn convex_hull(points: &mut Vec<(f64, f64)>) -> Vec<(f64, f64)> {
points.sort_by(|a, b| a.partial_cmp(b).unwrap());
let mut lower = Vec::new();
for &p in points.iter() {
while lower.len() >= 2 && cross(lower[lower.len()-2], lower[lower.len()-1], p) <= 0.0 {
lower.pop();
}
lower.push(p);
}
let mut upper = Vec::new();
for &p in points.iter().rev() {
while upper.len() >= 2 && cross(upper[upper.len()-2], upper[upper.len()-1], p) <= 0.0 {
upper.pop();
}
upper.push(p);
}
lower.pop();
upper.pop();
lower.append(&mut upper);
lower
}
/// Computes the cross product of vectors OA and OB. A positive cross product indicates a counter-clockwise turn,
/// a negative cross product indicates a clockwise turn, and zero indicates that the points are collinear.
///
/// # Arguments
///
/// * `o` - The origin point (x, y).
/// * `a` - The first point (x, y).
/// * `b` - The second point (x, y).
///
/// # Returns
///
/// The cross product of vectors OA and OB.
fn cross(o: (f64, f64), a: (f64, f64), b: (f64, f64)) -> f64 {
(a.0 - o.0) * (b.1 - o.1) - (a.1 - o.1) * (b.0 - o.0)
}
/// Computes the convex hull of a set of 2D points and returns it as a list of points.
///
/// This function serves as the Python interface for the convex hull computation,
/// accepting a list of tuples from Python and returning the result as a list of tuples.
///
/// # Arguments
///
/// * `points` - A list of tuples representing the points (x, y).
///
/// # Returns
///
/// A list of tuples representing the points that form the convex hull in counter-clockwise order.
#[pyfunction]
pub fn Convex_hull(py: Python, points: Vec<(f64, f64)>) -> PyResult<Vec<(f64, f64)>> {
let mut points = points;
let result = convex_hull(&mut points);
Ok(result)
}