From e4050629473b2e91e6259d74c251ee68126efdfa Mon Sep 17 00:00:00 2001 From: bendn Date: Fri, 29 Sep 2023 07:04:26 +0700 Subject: [PATCH] add Image::poly --- Cargo.toml | 2 +- src/drawing/poly.rs | 59 ++++++++++++++++++++++++++++++++++++++++++ src/drawing/tri.rs | 10 ++++--- tdata/enneagon.imgbuf | Bin 0 -> 90000 bytes 4 files changed, 67 insertions(+), 4 deletions(-) create mode 100644 tdata/enneagon.imgbuf 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 0000000000000000000000000000000000000000..cf4a7972e41b6180ccd43f1dc29e1e07e4e2b46e GIT binary patch literal 90000 zcmeI*!E)P55JOS_|4%y`my+0~*x+EgLFs1Yh&?^PF`X)J-uw9A4+01vfB*srAbdmiAzLeG#0O`!@Xi2p%4!?-j#rEQ{*T51>Umkw}t;^l@gLl``8?T(W zwbn}UOK0z^b*b*!p}S(OwZ3}#o?2JiuAaN0)@tR2^LNu)sJediURdjW*EZZpYptl| z^j)+pWtW%SLu$kQpo~V$3jB^=}1Mb*q{GI-8I$X>{bpN&--_OkgSbl4h~0e>bqITTT4yE~LvE z9eA;_0E9GHMPmu!!bbaFtS|r}4pzxnLbkNg_7^J+K*`gMrDRK+#j5@t!K!Z6{d^D{&U9`gaAZx>e`z zIYO$;(Z&}m6F^9XRV0=WDs;5(#R>&bVzpr@p+aY|s()j!DqFQtt^c3i%AIx%VpW&L zs%+Iqb^o71tjezyzdJ`#-Tr5=@kbCV0lWUTM@|Y&*GD4->Y>&FgbnpriIYN6!)T&F zJ(B@ISW(ZFI4Kl0j3x?{Ga33TE6TYN2bH3R*+hbJCPRN^MLAdCpwiPZ8%R)&xZ(#EusuIV&| zS{_$>aZfE=*p%4OH6Er=isR}o?&}M8-QQym{N31Q^Qr-y|F7KK&$|Bq zR@uI+Tj$^VwwH5X@Nf9muiZsD_O$~2y{w~}|Bk=;`@ZtGXxi9E^mS8HuPxW~ zVr{9=wzSo%t<|QB`mi=`)mdrZT^(5a(l>A3j@8^}>vfy4wr1~MzSXL`%d E0Icc0b^rhX literal 0 HcmV?d00001