fast image operations
add Image::poly
bendn 2023-09-29
parent c33594e · commit e405062
-rw-r--r--Cargo.toml2
-rw-r--r--src/drawing/poly.rs59
-rw-r--r--src/drawing/tri.rs10
-rw-r--r--tdata/enneagon.imgbufbin0 -> 90000 bytes
4 files changed, 67 insertions, 4 deletions
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 <[email protected]>"]
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<T: DerefMut<Target = [u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
) {
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<T: DerefMut<Target = [u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
/// ```
/// # 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
--- /dev/null
+++ b/tdata/enneagon.imgbuf
Binary files differ