mirror of
https://github.com/bend-n/fimg.git
synced 2024-12-22 02:28:19 -06:00
add Image::circle
This commit is contained in:
parent
e405062947
commit
ac3f07c797
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "fimg"
|
||||
version = "0.4.10"
|
||||
version = "0.4.11"
|
||||
authors = ["bend-n <bend.n@outlook.com>"]
|
||||
license = "MIT"
|
||||
edition = "2021"
|
||||
|
|
|
@ -188,9 +188,7 @@ unsafe fn transpose_non_power_of_two<const CHANNELS: usize, T: DerefMut<Target =
|
|||
for i in 0..size {
|
||||
for j in i..size {
|
||||
// SAFETY: caller ensures squarity
|
||||
unsafe {
|
||||
b.swap_unchecked(i * size + j, j * size + i);
|
||||
};
|
||||
unsafe { b.swap_unchecked(i * size + j, j * size + i) };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
67
src/drawing/circle.rs
Normal file
67
src/drawing/circle.rs
Normal file
|
@ -0,0 +1,67 @@
|
|||
//! draw 2d circles
|
||||
use crate::Image;
|
||||
use std::ops::DerefMut;
|
||||
|
||||
impl<T: DerefMut<Target = [u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
|
||||
/// Draws a circle, using the [Bresenham's circle](https://en.wikipedia.org/wiki/Midpoint_circle_algorithm) algorithm.
|
||||
/// ```
|
||||
/// # use fimg::Image;
|
||||
/// let mut i = Image::alloc(50, 50);
|
||||
/// i.border_circle((25, 25), 20, [255]);
|
||||
/// # assert_eq!(i.buffer(), include_bytes!("../../tdata/circle.imgbuf"));
|
||||
/// ```
|
||||
pub fn border_circle(&mut self, (xc, yc): (i32, i32), radius: i32, c: [u8; CHANNELS]) {
|
||||
let mut x = 0;
|
||||
let mut y = radius;
|
||||
let mut p = 1 - radius;
|
||||
/// bounds the pixels
|
||||
macro_rules! bound {
|
||||
($($x:expr,$y:expr);+;) => {
|
||||
$(if $x >= 0 && $x < self.width() as i32 && $y >= 0 && $y < self.height() as i32 {
|
||||
// SAFETY: ^
|
||||
unsafe { self.set_pixel($x as u32, $y as u32, c) };
|
||||
})+
|
||||
};
|
||||
}
|
||||
while x <= y {
|
||||
bound! {
|
||||
xc + x, yc + y;
|
||||
xc + y, yc + x;
|
||||
xc - y, yc + x;
|
||||
xc - x, yc + y;
|
||||
xc - x, yc - y;
|
||||
xc - y, yc - x;
|
||||
xc + y, yc - x;
|
||||
xc + x, yc - y;
|
||||
};
|
||||
x += 1;
|
||||
if p < 0 {
|
||||
p += 2 * x + 1;
|
||||
} else {
|
||||
y -= 1;
|
||||
p += 2 * (x - y) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw a filled circle.
|
||||
/// ```
|
||||
/// # use fimg::Image;
|
||||
/// let mut i = Image::alloc(50, 50);
|
||||
/// i.circle((25, 25), 20, [255]);
|
||||
/// # assert_eq!(i.buffer(), include_bytes!("../../tdata/circle2.imgbuf"));
|
||||
/// ```
|
||||
pub fn circle(&mut self, (xc, yc): (i32, i32), radius: i32, c: [u8; CHANNELS]) {
|
||||
for x in -radius..radius {
|
||||
let h = ((radius * radius - x * x) as f32).sqrt().round() as i32;
|
||||
for y in -h..h {
|
||||
let x = x + xc;
|
||||
let y = y + yc;
|
||||
if x >= 0 && x < self.width() as i32 && y >= 0 && y < self.height() as i32 {
|
||||
// SAFETY: ^
|
||||
unsafe { self.set_pixel(x as u32, y as u32, c) };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
//! contains drawing operations, like {line, box, triangle, polygon} drawing
|
||||
//! contains drawing operations, like {line, box, triangle, polygon, circle} drawing
|
||||
mod r#box;
|
||||
mod circle;
|
||||
mod line;
|
||||
mod poly;
|
||||
mod tri;
|
||||
|
|
|
@ -86,6 +86,7 @@ impl<T: DerefMut<Target = [u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
|
|||
}
|
||||
|
||||
/// Draws a regular convex polygon with a specified number of sides, a radius, and a rotation (radians).
|
||||
/// Prefer [`Image::circle`] over `poly(.., 600, ..)`.
|
||||
/// Calls into [`Image::tri`] and [`Image::quad`].
|
||||
/// ```
|
||||
/// # use fimg::Image;
|
||||
|
@ -113,7 +114,7 @@ impl<T: DerefMut<Target = [u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
|
|||
self.tri(
|
||||
add(trans(space + rotation)),
|
||||
add(trans(rotation)),
|
||||
add(trans(space * 2.0 + rotation)),
|
||||
add(trans(space.mul_add(2.0, rotation))),
|
||||
c,
|
||||
);
|
||||
}
|
||||
|
@ -122,9 +123,9 @@ impl<T: DerefMut<Target = [u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
|
|||
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))),
|
||||
r(add(trans(space.mul_add(i, rotation)))),
|
||||
r(add(trans(space.mul_add(i + 1., rotation)))),
|
||||
r(add(trans(space.mul_add(i + 2., rotation)))),
|
||||
c,
|
||||
);
|
||||
}
|
||||
|
@ -134,8 +135,8 @@ impl<T: DerefMut<Target = [u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
|
|||
// the missing piece
|
||||
self.tri(
|
||||
(x, y),
|
||||
add(trans(space * i + rotation)),
|
||||
add(trans(space * (i + 1.) + rotation)),
|
||||
add(trans(space.mul_add(i, rotation))),
|
||||
add(trans(space.mul_add(i + 1., rotation))),
|
||||
c,
|
||||
);
|
||||
}
|
||||
|
|
BIN
tdata/circle.imgbuf
Normal file
BIN
tdata/circle.imgbuf
Normal file
Binary file not shown.
BIN
tdata/circle2.imgbuf
Normal file
BIN
tdata/circle2.imgbuf
Normal file
Binary file not shown.
Loading…
Reference in a new issue