use crate::Rect;
#[derive(Debug, Clone, Copy, PartialEq)]
#[repr(C)]
pub struct Point {
pub x: f64,
pub y: f64,
}
impl Point {
#[inline]
pub const fn new(x: f64, y: f64) -> Self {
Self { x, y }
}
#[inline]
pub fn rect(self) -> Rect {
let r = unsafe { tg_geom_sys::tg_point_rect(self.into()) };
r.into()
}
#[inline]
pub fn intersects_rect(self, rect: Rect) -> bool {
unsafe { tg_geom_sys::tg_point_intersects_rect(self.into(), rect.into()) }
}
}
impl From<tg_geom_sys::tg_point> for Point {
#[inline]
fn from(p: tg_geom_sys::tg_point) -> Self {
Self { x: p.x, y: p.y }
}
}
impl From<Point> for tg_geom_sys::tg_point {
#[inline]
fn from(p: Point) -> Self {
Self { x: p.x, y: p.y }
}
}
impl From<(f64, f64)> for Point {
#[inline]
fn from((x, y): (f64, f64)) -> Self {
Self { x, y }
}
}
#[cfg(test)]
mod tests {
use super::*;
fn p(x: f64, y: f64) -> Point {
Point::new(x, y)
}
fn r(min_x: f64, min_y: f64, max_x: f64, max_y: f64) -> Rect {
Rect::from_coords(min_x, min_y, max_x, max_y)
}
#[test]
fn test_point_rect() {
let pt = p(5.0, 5.0);
let rect = pt.rect();
assert_eq!(rect, r(5.0, 5.0, 5.0, 5.0));
}
#[test]
fn test_point_intersects_rect() {
assert!(p(5.0, 5.0).intersects_rect(r(5.0, 5.0, 5.0, 5.0)));
assert!(p(5.0, 5.0).intersects_rect(r(0.0, 0.0, 10.0, 10.0)));
assert!(p(0.0, 0.0).intersects_rect(r(0.0, 0.0, 10.0, 10.0)));
assert!(!p(-1.0, 0.0).intersects_rect(r(0.0, 0.0, 10.0, 10.0)));
assert!(!p(11.0, 5.0).intersects_rect(r(0.0, 0.0, 10.0, 10.0)));
assert!(!p(5.0, 11.0).intersects_rect(r(0.0, 0.0, 10.0, 10.0)));
assert!(!p(5.0, -1.0).intersects_rect(r(0.0, 0.0, 10.0, 10.0)));
}
#[test]
fn test_point_new() {
let pt = Point::new(1.5, 2.5);
assert_eq!(pt.x, 1.5);
assert_eq!(pt.y, 2.5);
}
#[test]
fn test_point_from_tuple() {
let pt: Point = (3.0, 4.0).into();
assert_eq!(pt.x, 3.0);
assert_eq!(pt.y, 4.0);
}
#[test]
fn test_point_eq() {
assert_eq!(p(1.0, 2.0), p(1.0, 2.0));
assert_ne!(p(1.0, 2.0), p(1.0, 3.0));
assert_ne!(p(1.0, 2.0), p(2.0, 2.0));
}
#[test]
fn test_point_copy() {
let pt1 = p(1.0, 2.0);
let pt2 = pt1;
assert_eq!(pt1, pt2);
}
#[test]
fn test_point_negative_coords() {
let pt = p(-5.0, -10.0);
assert_eq!(pt.x, -5.0);
assert_eq!(pt.y, -10.0);
let rect = pt.rect();
assert_eq!(rect.min.x, -5.0);
assert_eq!(rect.min.y, -10.0);
}
#[test]
fn test_point_zero() {
let pt = p(0.0, 0.0);
assert_eq!(pt.rect(), r(0.0, 0.0, 0.0, 0.0));
assert!(pt.intersects_rect(r(-1.0, -1.0, 1.0, 1.0)));
}
#[test]
fn test_point_sys_roundtrip() {
let pt = p(1.5, 2.5);
let sys_pt: tg_geom_sys::tg_point = pt.into();
let back: Point = sys_pt.into();
assert_eq!(pt, back);
}
#[test]
fn test_point_debug() {
let pt = p(1.0, 2.0);
let debug_str = format!("{pt:?}");
assert!(debug_str.contains("Point"));
assert!(debug_str.contains("1"));
assert!(debug_str.contains("2"));
}
}