use togo::prelude::Point;
use std::f64::consts::PI;
const EPS: f64 = 1e-9;
pub fn distance(p1: Point, p2: Point) -> f64 {
let dx = p2.x - p1.x;
let dy = p2.y - p1.y;
(dx * dx + dy * dy).sqrt()
}
pub fn is_ccw(vertices: &[Point]) -> bool {
if vertices.len() < 3 {
return false;
}
let mut area = 0.0;
for i in 0..vertices.len() {
let j = (i + 1) % vertices.len();
area += (vertices[j].x - vertices[i].x) * (vertices[j].y + vertices[i].y);
}
area < 0.0
}
pub fn ensure_ccw(vertices: &mut Vec<Point>) {
if vertices.len() < 3 {
return;
}
let mut area = 0.0;
for i in 0..vertices.len() {
let j = (i + 1) % vertices.len();
area += (vertices[j].x - vertices[i].x) * (vertices[j].y + vertices[i].y);
}
if area > 0.0 {
vertices.reverse();
}
}
pub fn normalize_angle(angle: f64) -> f64 {
let mut a = angle % (2.0 * PI);
if a < 0.0 {
a += 2.0 * PI;
}
a
}
pub fn find_min_vertex(vertices: &[Point]) -> Option<Point> {
vertices.iter().min_by(|p1, p2| {
match p1.y.partial_cmp(&p2.y).unwrap_or(std::cmp::Ordering::Equal) {
std::cmp::Ordering::Equal => p1.x.partial_cmp(&p2.x).unwrap_or(std::cmp::Ordering::Equal),
other => other,
}
}).copied()
}
pub fn epsilon() -> f64 {
EPS
}
pub fn generate_ellipse_polygon(
steps: usize,
major_axis: f64,
minor_axis: f64,
perturbation_scale: f64,
seed: u64,
) -> Vec<Point> {
let mut points = Vec::new();
for i in 0..steps {
let t = 2.0 * PI * (i as f64) / (steps as f64);
let cos_t = t.cos();
let sin_t = t.sin();
let perturbation = ((seed.wrapping_mul(i as u64).wrapping_add(12345) % 1000) as f64 / 1000.0) * perturbation_scale;
let x = major_axis * cos_t + perturbation * cos_t;
let y = minor_axis * sin_t + perturbation * sin_t;
points.push(Point { x, y });
}
points
}