use crate::{
geometry::{Angle, Dimensions, Point, Size},
primitives::{Circle, PointsIter, Primitive, Rectangle},
transform::Transform,
};
mod points;
mod styled;
pub use points::Points;
pub use styled::StyledPixelsIterator;
#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
#[cfg_attr(feature = "defmt", derive(::defmt::Format))]
pub struct Arc {
pub top_left: Point,
pub diameter: u32,
pub angle_start: Angle,
pub angle_sweep: Angle,
}
impl Arc {
pub const fn new(
top_left: Point,
diameter: u32,
angle_start: Angle,
angle_sweep: Angle,
) -> Self {
Arc {
top_left,
diameter,
angle_start,
angle_sweep,
}
}
pub const fn with_center(
center: Point,
diameter: u32,
angle_start: Angle,
angle_sweep: Angle,
) -> Self {
Self::from_circle(
Circle::with_center(center, diameter),
angle_start,
angle_sweep,
)
}
pub const fn from_circle(circle: Circle, angle_start: Angle, angle_sweep: Angle) -> Self {
Self {
top_left: circle.top_left,
diameter: circle.diameter,
angle_start,
angle_sweep,
}
}
pub const fn to_circle(&self) -> Circle {
Circle::new(self.top_left, self.diameter)
}
pub fn center(&self) -> Point {
self.bounding_box().center()
}
}
impl Primitive for Arc {}
impl PointsIter for Arc {
type Iter = Points;
fn points(&self) -> Self::Iter {
Points::new(self)
}
}
impl Dimensions for Arc {
fn bounding_box(&self) -> Rectangle {
Rectangle::new(self.top_left, Size::new(self.diameter, self.diameter))
}
}
impl Transform for Arc {
fn translate(&self, by: Point) -> Self {
Self {
top_left: self.top_left + by,
..*self
}
}
fn translate_mut(&mut self, by: Point) -> &mut Self {
self.top_left += by;
self
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::geometry::AngleUnit;
#[test]
fn negative_dimensions() {
let arc = Arc::new(Point::new(-15, -15), 10, 0.0.deg(), 90.0.deg());
assert_eq!(
arc.bounding_box(),
Rectangle::new(Point::new(-15, -15), Size::new(10, 10))
);
}
#[test]
fn dimensions() {
let arc = Arc::new(Point::new(5, 15), 10, 0.0.deg(), 90.0.deg());
assert_eq!(
arc.bounding_box(),
Rectangle::new(Point::new(5, 15), Size::new(10, 10))
);
}
#[test]
fn it_handles_negative_coordinates() {
let positive = Arc::new(Point::new(10, 10), 5, 0.0.deg(), 90.0.deg()).points();
let negative = Arc::new(Point::new(-10, -10), 5, 0.0.deg(), 90.0.deg()).points();
assert!(negative.eq(positive.map(|p| p - Point::new(20, 20))));
}
#[test]
fn center_is_correct() {
let arc = Arc::new(Point::new(10, 10), 5, 0.0.deg(), 90.0.deg());
assert_eq!(arc.center(), Point::new(12, 12));
let arc = Arc::new(Point::new(10, 10), 6, 0.0.deg(), 90.0.deg());
assert_eq!(arc.center(), Point::new(12, 12));
let arc = Arc::with_center(Point::new(10, 10), 5, 0.0.deg(), 90.0.deg());
assert_eq!(arc.center(), Point::new(10, 10));
let arc = Arc::with_center(Point::new(10, 10), 6, 0.0.deg(), 90.0.deg());
assert_eq!(arc.center(), Point::new(10, 10));
}
}