use super::{PointF, RectF};
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Circle {
pub center: PointF,
pub radius: f32,
}
impl Circle {
#[inline]
pub const fn new(center: PointF, radius: f32) -> Self {
Self { center, radius }
}
#[inline]
pub const fn from_coords(cx: f32, cy: f32, radius: f32) -> Self {
Self {
center: PointF::new(cx, cy),
radius,
}
}
pub const ZERO: Self = Self {
center: PointF::ZERO,
radius: 0.0,
};
#[inline]
pub fn diameter(&self) -> f32 {
self.radius * 2.0
}
#[inline]
pub fn area(&self) -> f32 {
core::f32::consts::PI * self.radius * self.radius
}
#[inline]
pub fn circumference(&self) -> f32 {
2.0 * core::f32::consts::PI * self.radius
}
#[inline]
pub fn bounds(&self) -> RectF {
RectF::new(
self.center.x - self.radius,
self.center.y - self.radius,
self.diameter(),
self.diameter(),
)
}
#[inline]
pub fn contains_point(&self, p: PointF) -> bool {
self.center.distance_squared(&p) <= self.radius * self.radius
}
#[inline]
pub fn intersects(&self, other: &Circle) -> bool {
let dist = self.center.distance(&other.center);
dist < self.radius + other.radius
}
#[inline]
pub fn point_at_angle(&self, angle: f32) -> PointF {
PointF::new(
self.center.x + self.radius * rdsmath::cosf(angle),
self.center.y + self.radius * rdsmath::sinf(angle),
)
}
#[inline]
pub fn is_empty(&self) -> bool {
self.radius <= 0.0
}
#[inline]
pub fn offset(&self, dx: f32, dy: f32) -> Self {
Self {
center: self.center.offset(dx, dy),
radius: self.radius,
}
}
#[inline]
pub fn scale(&self, factor: f32) -> Self {
Self {
center: self.center,
radius: self.radius * factor,
}
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Ellipse {
pub center: PointF,
pub radius_x: f32,
pub radius_y: f32,
}
impl Ellipse {
#[inline]
pub const fn new(center: PointF, radius_x: f32, radius_y: f32) -> Self {
Self {
center,
radius_x,
radius_y,
}
}
#[inline]
pub const fn from_coords(cx: f32, cy: f32, rx: f32, ry: f32) -> Self {
Self {
center: PointF::new(cx, cy),
radius_x: rx,
radius_y: ry,
}
}
#[inline]
pub fn inscribed(rect: RectF) -> Self {
Self {
center: rect.center(),
radius_x: rect.width * 0.5,
radius_y: rect.height * 0.5,
}
}
#[inline]
pub fn bounds(&self) -> RectF {
RectF::new(
self.center.x - self.radius_x,
self.center.y - self.radius_y,
self.radius_x * 2.0,
self.radius_y * 2.0,
)
}
#[inline]
pub fn area(&self) -> f32 {
core::f32::consts::PI * self.radius_x * self.radius_y
}
#[inline]
pub fn is_circle(&self) -> bool {
let diff = self.radius_x - self.radius_y;
(if diff < 0.0 { -diff } else { diff }) < 0.0001
}
#[inline]
pub fn to_circle(&self) -> Circle {
Circle {
center: self.center,
radius: (self.radius_x + self.radius_y) * 0.5,
}
}
#[inline]
pub fn contains_point(&self, p: PointF) -> bool {
if self.radius_x <= 0.0 || self.radius_y <= 0.0 {
return false;
}
let dx = (p.x - self.center.x) / self.radius_x;
let dy = (p.y - self.center.y) / self.radius_y;
dx * dx + dy * dy <= 1.0
}
#[inline]
pub fn is_empty(&self) -> bool {
self.radius_x <= 0.0 || self.radius_y <= 0.0
}
#[inline]
pub fn offset(&self, dx: f32, dy: f32) -> Self {
Self {
center: self.center.offset(dx, dy),
radius_x: self.radius_x,
radius_y: self.radius_y,
}
}
}