use std::ops::{Add, AddAssign, Neg, Sub, SubAssign};
use num::Num;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq)]
pub struct Vector<T> {
pub x: T,
pub y: T,
}
impl<T> Vector<T>
where
T: Num + Copy,
{
pub fn new(x: T, y: T) -> Self {
Self { x, y }
}
pub fn scale(&mut self, scale: T) {
self.x = self.x * scale;
self.y = self.y * scale;
}
pub fn scaled(self, scale: T) -> Vector<T> {
let mut out = self;
out.scale(scale);
out
}
pub fn zero() -> Vector<T> {
Self {
x: T::zero(),
y: T::zero(),
}
}
}
impl<T> Add for Vector<T>
where
T: Num + Copy,
{
type Output = Vector<T>;
fn add(self, rhs: Self) -> Self::Output {
let mut out = self;
out.add_assign(rhs);
out
}
}
impl<T> AddAssign for Vector<T>
where
T: Num + Copy,
{
fn add_assign(&mut self, rhs: Self) {
self.x = self.x + rhs.x;
self.y = self.y + rhs.y;
}
}
impl<T> Sub for Vector<T>
where
T: Num + Copy,
{
type Output = Vector<T>;
fn sub(self, rhs: Self) -> Self::Output {
let mut out = self;
out.sub_assign(rhs);
out
}
}
impl<T> SubAssign for Vector<T>
where
T: Num + Copy,
{
fn sub_assign(&mut self, rhs: Self) {
self.x = self.x - rhs.x;
self.y = self.y - rhs.y;
}
}
impl<T> Neg for Vector<T>
where
T: Num + Copy + Neg<Output = T>,
{
type Output = Self;
fn neg(self) -> Self::Output {
Self {
x: -self.x,
y: -self.y,
}
}
}
impl From<Vector<f32>> for Vector<i32> {
fn from(value: Vector<f32>) -> Self {
Vector {
x: value.x as i32,
y: value.y as i32,
}
}
}
impl From<Vector<f32>> for iced::Point {
fn from(val: Vector<f32>) -> Self {
iced::Point::new(val.x, val.y)
}
}
impl From<Vector<f32>> for iced::Vector {
fn from(val: Vector<f32>) -> Self {
iced::Vector::new(val.x, val.y)
}
}
impl From<Vector<f32>> for iced::Size {
fn from(val: Vector<f32>) -> Self {
iced::Size::new(val.x, val.y)
}
}
impl From<iced::Point> for Vector<f32> {
fn from(value: iced::Point) -> Self {
Self {
x: value.x,
y: value.y,
}
}
}
impl From<iced::Vector> for Vector<f32> {
fn from(value: iced::Vector) -> Self {
Self {
x: value.x,
y: value.y,
}
}
}
impl From<iced::Size> for Vector<f32> {
fn from(value: iced::Size) -> Self {
Self {
x: value.width,
y: value.height,
}
}
}
#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq)]
pub struct Rect<T> {
pub x0: Vector<T>,
pub x1: Vector<T>,
}
impl<T> Rect<T>
where
T: Num + Copy + std::fmt::Debug + PartialOrd,
{
pub fn from_points(top_left: Vector<T>, bottom_right: Vector<T>) -> Self {
Self {
x0: top_left,
x1: bottom_right,
}
}
pub fn from_pos_size(pos: Vector<T>, size: Vector<T>) -> Self {
Self {
x0: pos,
x1: pos + size,
}
}
pub fn center(&self) -> Vector<T> {
(self.x0 + self.x1).scaled(T::one() + T::one())
}
pub fn width(&self) -> T {
self.x1.x - self.x0.x
}
pub fn height(&self) -> T {
self.x1.y - self.x0.y
}
pub fn size(&self) -> Vector<T> {
Vector::new(self.width(), self.height())
}
pub fn translate(&mut self, offset: Vector<T>) {
self.x0 += offset;
self.x1 += offset;
}
pub fn scale(&mut self, s: T) {
let x0 = self.x0;
let x1 = self.x1;
self.x0 = (x0.scaled(T::one() + s) + x1.scaled(T::one() - s))
.scaled(T::one() / (T::one() + T::one()));
self.x1 = (x0.scaled(T::one() - s) + x1.scaled(T::one() + s))
.scaled(T::one() / (T::one() + T::one()));
}
pub fn scaled(&self, s: T) -> Self {
let mut out = *self;
out.scale(s);
out
}
pub fn contains(&self, v: Vector<T>) -> bool {
self.x0.x < v.x && self.x1.x > v.x && self.x0.y < v.y && self.x1.y > v.y
}
}
impl From<Rect<f32>> for mupdf::Rect {
fn from(val: Rect<f32>) -> Self {
mupdf::Rect::new(val.x0.x, val.x0.y, val.x1.x, val.x1.y)
}
}
impl From<Rect<i32>> for mupdf::IRect {
fn from(val: Rect<i32>) -> Self {
mupdf::IRect::new(val.x0.x, val.x0.y, val.x1.x, val.x1.y)
}
}
impl From<Rect<f32>> for mupdf::IRect {
fn from(val: Rect<f32>) -> Self {
let irect: Rect<i32> = val.into();
irect.into()
}
}
impl From<Rect<f32>> for Rect<i32> {
fn from(val: Rect<f32>) -> Self {
Rect {
x0: val.x0.into(),
x1: val.x1.into(),
}
}
}
impl From<iced::Rectangle> for Rect<f32> {
fn from(value: iced::Rectangle) -> Self {
let top_left: Vector<f32> = value.position().into();
let size: Vector<f32> = value.size().into();
Self {
x0: top_left,
x1: top_left + size,
}
}
}
impl From<mupdf::Rect> for Rect<f32> {
fn from(value: mupdf::Rect) -> Self {
Self {
x0: Vector {
x: value.x0,
y: value.y0,
},
x1: Vector {
x: value.x1,
y: value.y1,
},
}
}
}
impl From<mupdf::IRect> for Rect<i32> {
fn from(value: mupdf::IRect) -> Self {
Self {
x0: Vector {
x: value.x0,
y: value.y0,
},
x1: Vector {
x: value.x1,
y: value.y1,
},
}
}
}
impl From<mupdf::Rect> for Rect<i32> {
fn from(value: mupdf::Rect) -> Self {
Self {
x0: Vector {
x: value.x0 as i32,
y: value.y0 as i32,
},
x1: Vector {
x: value.x1 as i32,
y: value.y1 as i32,
},
}
}
}
impl From<mupdf::IRect> for Rect<f32> {
fn from(value: mupdf::IRect) -> Self {
Self {
x0: Vector {
x: value.x0 as f32,
y: value.y0 as f32,
},
x1: Vector {
x: value.x1 as f32,
y: value.y1 as f32,
},
}
}
}
impl<T> From<Rect<T>> for iced::Rectangle<T>
where
T: Num + Copy,
{
fn from(val: Rect<T>) -> Self {
iced::Rectangle {
x: val.x0.x,
y: val.x0.y,
width: val.x1.x - val.x0.x,
height: val.x1.y - val.x0.y,
}
}
}