use std::ops::{Add, AddAssign, Div, Mul, Sub, SubAssign};
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Point {
pub x: f64,
pub y: f64,
}
impl Point {
pub fn new(x: f64, y: f64) -> Self {
Self { x, y }
}
pub fn is_inside_polygon(&self, vertices: &[Point]) -> bool {
if vertices.len() < 3 {
return false;
}
let signs = vertices
.iter()
.zip(vertices.iter().cycle().skip(1))
.map(|(&a, &b)| {
let edge_vector = b - a;
let point_vector = *self - a;
edge_vector.cross(point_vector).signum()
})
.collect::<Vec<_>>();
let first_sign = signs[0];
if first_sign == 0.0 {
return true;
}
signs.iter().all(|&s| s == 0.0 || s == first_sign)
}
}
impl Add<Vector> for Point {
type Output = Point;
fn add(self, rhs: Vector) -> Self::Output {
Point {
x: self.x + rhs.x,
y: self.y + rhs.y,
}
}
}
impl Sub for Point {
type Output = Vector;
fn sub(self, rhs: Point) -> Self::Output {
Vector {
x: self.x - rhs.x,
y: self.y - rhs.y,
}
}
}
impl Sub<Vector> for Point {
type Output = Point;
fn sub(self, rhs: Vector) -> Self::Output {
Point {
x: self.x - rhs.x,
y: self.y - rhs.y,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Vector {
pub x: f64,
pub y: f64,
}
impl Vector {
pub fn new(x: f64, y: f64) -> Self {
Self { x, y }
}
pub fn length(&self) -> f64 {
(self.x.powi(2) + self.y.powi(2)).sqrt()
}
pub fn zero() -> Self {
Self { x: 0.0, y: 0.0 }
}
pub fn normalize(&self) -> Vector {
let len = self.length();
if len == 0.0 {
Vector::zero()
} else {
*self / len
}
}
pub fn perpendicular(&self) -> Vector {
Vector::new(-self.y, self.x)
}
pub fn dot(&self, other: Vector) -> f64 {
self.x * other.x + self.y * other.y
}
pub fn cross(&self, other: Vector) -> f64 {
self.x * other.y - self.y * other.x
}
}
impl Add for Vector {
type Output = Vector;
fn add(self, rhs: Vector) -> Self::Output {
Vector {
x: self.x + rhs.x,
y: self.y + rhs.y,
}
}
}
impl AddAssign for Vector {
fn add_assign(&mut self, rhs: Self) {
self.x += rhs.x;
self.y += rhs.y;
}
}
impl Sub for Vector {
type Output = Vector;
fn sub(self, rhs: Vector) -> Self::Output {
Vector {
x: self.x - rhs.x,
y: self.y - rhs.y,
}
}
}
impl SubAssign for Vector {
fn sub_assign(&mut self, rhs: Self) {
self.x -= rhs.x;
self.y -= rhs.y;
}
}
impl Mul<f64> for Vector {
type Output = Vector;
fn mul(self, rhs: f64) -> Self::Output {
Vector {
x: self.x * rhs,
y: self.y * rhs,
}
}
}
impl Mul<Vector> for f64 {
type Output = Vector;
fn mul(self, rhs: Vector) -> Self::Output {
rhs * self
}
}
impl Div<f64> for Vector {
type Output = Vector;
fn div(self, rhs: f64) -> Self::Output {
Vector {
x: self.x / rhs,
y: self.y / rhs,
}
}
}
pub fn bounding_box_u32(points: &[Point]) -> (u32, u32, u32, u32) {
let (mut min_x, mut min_y) = (f64::INFINITY, f64::INFINITY);
let (mut max_x, mut max_y) = (f64::NEG_INFINITY, f64::NEG_INFINITY);
for point in points {
if point.x < min_x {
min_x = point.x;
}
if point.y < min_y {
min_y = point.y;
}
if point.x > max_x {
max_x = point.x;
}
if point.y > max_y {
max_y = point.y;
}
}
(min_x as u32, min_y as u32, max_x as u32, max_y as u32)
}