diff --git a/Cargo.toml b/Cargo.toml index fae1c2d..7bfa3f1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fimg" -version = "0.4.9" +version = "0.4.10" authors = ["bend-n "] license = "MIT" edition = "2021" diff --git a/src/drawing/poly.rs b/src/drawing/poly.rs index ae20914..e0dd017 100644 --- a/src/drawing/poly.rs +++ b/src/drawing/poly.rs @@ -1,6 +1,7 @@ //! draw polygons use std::{ cmp::{max, min}, + f32::consts::TAU, ops::DerefMut, }; @@ -83,4 +84,62 @@ impl, const CHANNELS: usize> Image { ) { self.points(&[a, b, c, d, a], col); } + + /// Draws a regular convex polygon with a specified number of sides, a radius, and a rotation (radians). + /// Calls into [`Image::tri`] and [`Image::quad`]. + /// ``` + /// # use fimg::Image; + /// let mut i = Image::alloc(300, 300); + /// // draw a enneagon + /// // at x150, y150 │ unrotated white + /// // with a radius of ─┼──╮ │ │ + /// i.poly((150., 150.), 9, 100.0, 0.0, [255]); + /// # assert_eq!(i.buffer(), include_bytes!("../../tdata/enneagon.imgbuf")); + /// ``` + pub fn poly( + &mut self, + (x, y): (f32, f32), + sides: usize, + radius: f32, + rotation: f32, + c: [u8; CHANNELS], + ) { + let trans = |a: f32| (a.cos() * radius, a.sin() * radius); + let r = |(a, b): (f32, f32)| (a.round() as i32, b.round() as i32); + let add = |(a, b)| (a + x, b + y); + match sides { + 3 => { + let space = TAU / 3.0; + self.tri( + add(trans(space + rotation)), + add(trans(rotation)), + add(trans(space * 2.0 + rotation)), + c, + ); + } + _ => { + let space = TAU / sides as f32; + for i in (0..sides - 1).step_by(2).map(|i| i as f32) { + self.quad( + r((x, y)), + r(add(trans(space * i + rotation))), + r(add(trans(space * (i + 1.) + rotation))), + r(add(trans(space * (i + 2.) + rotation))), + c, + ); + } + + if sides % 2 != 0 && sides > 4 { + let i = (sides - 1) as f32; + // the missing piece + self.tri( + (x, y), + add(trans(space * i + rotation)), + add(trans(space * (i + 1.) + rotation)), + c, + ); + } + } + } + } } diff --git a/src/drawing/tri.rs b/src/drawing/tri.rs index e141f94..c29ad1d 100644 --- a/src/drawing/tri.rs +++ b/src/drawing/tri.rs @@ -8,9 +8,13 @@ impl, const CHANNELS: usize> Image { /// ``` /// # use fimg::*; /// let mut a = Image::alloc(10, 10); - /// // draw a triangle from point a v point b v point c v - /// // with color white - /// a.as_mut().tri((3.0, 2.0), (8.0, 7.0), (1.0, 8.0), [255]); + /// // draw a triangle + /// a.as_mut().tri( + /// (3.0, 2.0), // point a + /// (8.0, 7.0), // point b + /// (1.0, 8.0), // point c + /// [255] // white + /// ); /// # assert_eq!(a.buffer(), b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"); /// ``` pub fn tri( diff --git a/tdata/enneagon.imgbuf b/tdata/enneagon.imgbuf new file mode 100644 index 0000000..cf4a797 Binary files /dev/null and b/tdata/enneagon.imgbuf differ