#![allow(dead_code)]
use std::f32::consts::PI;
pub fn point_in_circle(px: f32, py: f32, cx: f32, cy: f32, r: f32) -> bool {
let dx = px - cx;
let dy = py - cy;
dx * dx + dy * dy <= r * r
}
pub fn point_in_rect(px: f32, py: f32, x: f32, y: f32, w: f32, h: f32) -> bool {
px >= x && px <= x + w && py >= y && py <= y + h
}
fn cross_2d(o: [f32; 2], a: [f32; 2], b: [f32; 2]) -> f32 {
(a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0])
}
pub fn segment_intersect(p1: [f32; 2], p2: [f32; 2], p3: [f32; 2], p4: [f32; 2]) -> bool {
let d1 = cross_2d(p3, p4, p1);
let d2 = cross_2d(p3, p4, p2);
let d3 = cross_2d(p1, p2, p3);
let d4 = cross_2d(p1, p2, p4);
if ((d1 > 0.0 && d2 < 0.0) || (d1 < 0.0 && d2 > 0.0))
&& ((d3 > 0.0 && d4 < 0.0) || (d3 < 0.0 && d4 > 0.0))
{
return true;
}
false
}
pub fn triangle_area_2d(a: [f32; 2], b: [f32; 2], c: [f32; 2]) -> f32 {
let s = (b[0] - a[0]) * (c[1] - a[1]) - (c[0] - a[0]) * (b[1] - a[1]);
s.abs() * 0.5
}
pub fn point_in_triangle_2d(p: [f32; 2], a: [f32; 2], b: [f32; 2], c: [f32; 2]) -> bool {
let d1 = cross_2d(p, a, b);
let d2 = cross_2d(p, b, c);
let d3 = cross_2d(p, c, a);
let has_neg = d1 < 0.0 || d2 < 0.0 || d3 < 0.0;
let has_pos = d1 > 0.0 || d2 > 0.0 || d3 > 0.0;
!(has_neg && has_pos)
}
pub fn polygon_perimeter_2d(pts: &[[f32; 2]]) -> f32 {
let n = pts.len();
if n < 2 {
return 0.0;
}
let mut total = 0.0f32;
for i in 0..n {
let a = pts[i];
let b = pts[(i + 1) % n];
let dx = b[0] - a[0];
let dy = b[1] - a[1];
total += (dx * dx + dy * dy).sqrt();
}
total
}
pub fn circle_area(r: f32) -> f32 {
PI * r * r
}
pub fn dist_2d(a: [f32; 2], b: [f32; 2]) -> f32 {
let dx = b[0] - a[0];
let dy = b[1] - a[1];
(dx * dx + dy * dy).sqrt()
}
pub fn polygon_centroid_2d(pts: &[[f32; 2]]) -> [f32; 2] {
let n = pts.len() as f32;
if n == 0.0 {
return [0.0, 0.0];
}
let sx: f32 = pts.iter().map(|p| p[0]).sum();
let sy: f32 = pts.iter().map(|p| p[1]).sum();
[sx / n, sy / n]
}
pub fn polygon_area_2d(pts: &[[f32; 2]]) -> f32 {
let n = pts.len();
if n < 3 {
return 0.0;
}
let mut area = 0.0f32;
for i in 0..n {
let a = pts[i];
let b = pts[(i + 1) % n];
area += a[0] * b[1] - b[0] * a[1];
}
area.abs() * 0.5
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_point_in_circle() {
assert!(point_in_circle(0.0, 0.0, 0.0, 0.0, 1.0));
assert!(!point_in_circle(2.0, 0.0, 0.0, 0.0, 1.0));
}
#[test]
fn test_point_in_rect() {
assert!(point_in_rect(0.5, 0.5, 0.0, 0.0, 1.0, 1.0));
assert!(!point_in_rect(2.0, 0.5, 0.0, 0.0, 1.0, 1.0));
}
#[test]
fn test_segment_intersect_crossing() {
let yes = segment_intersect([0.0, 0.0], [1.0, 1.0], [0.0, 1.0], [1.0, 0.0]);
assert!(yes);
}
#[test]
fn test_segment_no_intersect_parallel() {
let no = segment_intersect([0.0, 0.0], [1.0, 0.0], [0.0, 1.0], [1.0, 1.0]);
assert!(!no);
}
#[test]
fn test_triangle_area_2d() {
let area = triangle_area_2d([0.0, 0.0], [3.0, 0.0], [0.0, 4.0]);
assert!((area - 6.0).abs() < 1e-5);
}
#[test]
fn test_point_in_triangle_2d() {
let a = [0.0f32, 0.0];
let b = [1.0, 0.0];
let c = [0.0, 1.0];
assert!(point_in_triangle_2d([0.1, 0.1], a, b, c));
assert!(!point_in_triangle_2d([1.0, 1.0], a, b, c));
}
#[test]
fn test_polygon_perimeter_2d() {
let pts: Vec<[f32; 2]> = vec![[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 1.0]];
let p = polygon_perimeter_2d(&pts);
assert!((p - 4.0).abs() < 1e-5);
}
#[test]
fn test_circle_area() {
let a = circle_area(1.0);
assert!((a - std::f32::consts::PI).abs() < 1e-5);
}
#[test]
fn test_dist_2d() {
let d = dist_2d([0.0, 0.0], [3.0, 4.0]);
assert!((d - 5.0).abs() < 1e-5);
}
#[test]
fn test_polygon_area_2d_square() {
let pts: Vec<[f32; 2]> = vec![[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 1.0]];
let a = polygon_area_2d(&pts);
assert!((a - 1.0).abs() < 1e-5);
}
}