mirror of
https://github.com/bend-n/fimg.git
synced 2024-12-22 10:28:21 -06:00
use vec2's
This commit is contained in:
parent
cd17b4860f
commit
c264f735ce
|
@ -11,6 +11,7 @@ exclude = ["tdata", "benches/", ".gitignore"]
|
||||||
[dependencies]
|
[dependencies]
|
||||||
mattr = "0.0.2"
|
mattr = "0.0.2"
|
||||||
png = { version = "0.17", features = ["unstable"], optional = true }
|
png = { version = "0.17", features = ["unstable"], optional = true }
|
||||||
|
vecto = "0.1.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
iai = { version = "0.1.1", features = [
|
iai = { version = "0.1.1", features = [
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#![allow(clippy::missing_docs_in_private_items)]
|
#![allow(clippy::missing_docs_in_private_items)]
|
||||||
use crate::Image;
|
use crate::Image;
|
||||||
use std::iter::Iterator;
|
use std::iter::Iterator;
|
||||||
|
use vecto::Vec2;
|
||||||
|
|
||||||
/// taken from [bresenham-rs](https://github.com/mbr/bresenham-rs)
|
/// taken from [bresenham-rs](https://github.com/mbr/bresenham-rs)
|
||||||
pub struct Bresenham {
|
pub struct Bresenham {
|
||||||
|
@ -156,20 +157,18 @@ impl<T: AsMut<[u8]> + AsRef<[u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
|
||||||
/// ```
|
/// ```
|
||||||
pub fn thick_line(
|
pub fn thick_line(
|
||||||
&mut self,
|
&mut self,
|
||||||
(x1, y1): (f32, f32),
|
a: impl Into<Vec2>,
|
||||||
(x2, y2): (f32, f32),
|
b: impl Into<Vec2>,
|
||||||
stroke: f32,
|
stroke: f32,
|
||||||
color: [u8; CHANNELS],
|
color: [u8; CHANNELS],
|
||||||
) {
|
) {
|
||||||
let (wx, wy) = {
|
let a = a.into();
|
||||||
let (x, y) = (y1 - y2, -(x1 - x2));
|
let b = b.into();
|
||||||
let l = (x * x + y * y).sqrt();
|
let w = (a - b).orthogonal().normalized() * (stroke / 2.0);
|
||||||
((x / l) * (stroke / 2.0), (y / l) * (stroke / 2.0))
|
|
||||||
};
|
|
||||||
macro_rules! p {
|
macro_rules! p {
|
||||||
($x:expr,$y:expr) => {
|
($x:expr) => {
|
||||||
#[allow(clippy::cast_possible_truncation)]
|
#[allow(clippy::cast_possible_truncation)]
|
||||||
($x.round() as i32, $y.round() as i32)
|
($x.x.round() as i32, $x.y.round() as i32)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
// order:
|
// order:
|
||||||
|
@ -177,10 +176,10 @@ impl<T: AsMut<[u8]> + AsRef<[u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
|
||||||
// [ ]
|
// [ ]
|
||||||
// ^ x3 ^ x4
|
// ^ x3 ^ x4
|
||||||
self.quad(
|
self.quad(
|
||||||
p!(x1 - wx, y1 - wy), // x1
|
p!(a - w), // x1
|
||||||
p!(x2 - wx, y2 - wy), // x2
|
p!(b - w), // x2
|
||||||
p!(x2 + wx, y2 + wy), // x3
|
p!(b + w), // x3
|
||||||
p!(x1 + wx, y1 + wy), // x4
|
p!(a + w), // x4
|
||||||
color,
|
color,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
use crate::math::{madd, FExt};
|
use crate::math::{madd, FExt};
|
||||||
use std::cmp::{max, min};
|
use std::cmp::{max, min};
|
||||||
use std::f32::consts::TAU;
|
use std::f32::consts::TAU;
|
||||||
|
use vecto::Vec2;
|
||||||
|
|
||||||
use crate::Image;
|
use crate::Image;
|
||||||
|
|
||||||
|
@ -97,22 +98,22 @@ impl<T: AsMut<[u8]> + AsRef<[u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
|
||||||
/// ```
|
/// ```
|
||||||
pub fn poly(
|
pub fn poly(
|
||||||
&mut self,
|
&mut self,
|
||||||
(x, y): (f32, f32),
|
pos: impl Into<Vec2>,
|
||||||
sides: usize,
|
sides: usize,
|
||||||
radius: f32,
|
radius: f32,
|
||||||
rotation: f32,
|
rotation: f32,
|
||||||
c: [u8; CHANNELS],
|
c: [u8; CHANNELS],
|
||||||
) {
|
) {
|
||||||
let trans = |a: f32| (a.cos() * radius, a.sin() * radius);
|
let pos = pos.into();
|
||||||
let r = |(a, b): (f32, f32)| (a.round() as i32, b.round() as i32);
|
let trans = |a: f32| Vec2::from_angle(a) * radius;
|
||||||
let add = |(a, b)| (a + x, b + y);
|
let r = |v: Vec2| (v.x.round() as i32, v.y.round() as i32);
|
||||||
match sides {
|
match sides {
|
||||||
3 => {
|
3 => {
|
||||||
let space = TAU / 3.0;
|
let space = TAU / 3.0;
|
||||||
self.tri(
|
self.tri(
|
||||||
add(trans(space + rotation)),
|
trans(space + rotation) + pos,
|
||||||
add(trans(rotation)),
|
trans(rotation) + pos,
|
||||||
add(trans(madd(space, 2.0, rotation))),
|
trans(madd(space, 2.0, rotation)) + pos,
|
||||||
c,
|
c,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -120,10 +121,10 @@ impl<T: AsMut<[u8]> + AsRef<[u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
|
||||||
let space = TAU / sides as f32;
|
let space = TAU / sides as f32;
|
||||||
for i in (0..sides - 1).step_by(2).map(|i| i as f32) {
|
for i in (0..sides - 1).step_by(2).map(|i| i as f32) {
|
||||||
self.quad(
|
self.quad(
|
||||||
r((x, y)),
|
r(pos),
|
||||||
r(add(trans(madd(space, i, rotation)))),
|
r(trans(madd(space, i, rotation)) + pos),
|
||||||
r(add(trans(madd(space, i + 1., rotation)))),
|
r(trans(madd(space, i + 1., rotation)) + pos),
|
||||||
r(add(trans(madd(space, i + 2., rotation)))),
|
r(trans(madd(space, i + 2., rotation)) + pos),
|
||||||
c,
|
c,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -132,9 +133,9 @@ impl<T: AsMut<[u8]> + AsRef<[u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
|
||||||
let i = (sides - 1) as f32;
|
let i = (sides - 1) as f32;
|
||||||
// the missing piece
|
// the missing piece
|
||||||
self.tri(
|
self.tri(
|
||||||
(x, y),
|
pos,
|
||||||
add(trans(madd(space, i, rotation))),
|
trans(madd(space, i, rotation)) + pos,
|
||||||
add(trans(madd(space, i + 1., rotation))),
|
trans(madd(space, i + 1., rotation)) + pos,
|
||||||
c,
|
c,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -152,13 +153,14 @@ impl<T: AsMut<[u8]> + AsRef<[u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
|
||||||
/// ```
|
/// ```
|
||||||
pub fn border_poly(
|
pub fn border_poly(
|
||||||
&mut self,
|
&mut self,
|
||||||
(x, y): (f32, f32),
|
pos: impl Into<Vec2>,
|
||||||
sides: usize,
|
sides: usize,
|
||||||
radius: f32,
|
radius: f32,
|
||||||
rotation: f32,
|
rotation: f32,
|
||||||
stroke: f32,
|
stroke: f32,
|
||||||
c: [u8; CHANNELS],
|
c: [u8; CHANNELS],
|
||||||
) {
|
) {
|
||||||
|
let pos = pos.into();
|
||||||
let space = TAU / sides as f32;
|
let space = TAU / sides as f32;
|
||||||
let step = stroke / 2.0 / (space / 2.0).cos();
|
let step = stroke / 2.0 / (space / 2.0).cos();
|
||||||
let r1 = radius - step;
|
let r1 = radius - step;
|
||||||
|
@ -167,10 +169,16 @@ impl<T: AsMut<[u8]> + AsRef<[u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
|
||||||
for i in 0..sides {
|
for i in 0..sides {
|
||||||
let a = space.madd(i as f32, rotation);
|
let a = space.madd(i as f32, rotation);
|
||||||
self.quad(
|
self.quad(
|
||||||
r(r1.madd(a.cos(), x), r1.madd(a.sin(), y)),
|
r(r1.madd(a.cos(), pos.x), r1.madd(a.sin(), pos.y)),
|
||||||
r(r1.madd((a + space).cos(), x), r1.madd((a + space).sin(), y)),
|
r(
|
||||||
r(r2.madd((a + space).cos(), x), r2.madd((a + space).sin(), y)),
|
r1.madd((a + space).cos(), pos.x),
|
||||||
r(r2.madd(a.cos(), x), r2.madd(a.sin(), y)),
|
r1.madd((a + space).sin(), pos.y),
|
||||||
|
),
|
||||||
|
r(
|
||||||
|
r2.madd((a + space).cos(), pos.x),
|
||||||
|
r2.madd((a + space).sin(), pos.y),
|
||||||
|
),
|
||||||
|
r(r2.madd(a.cos(), pos.x), r2.madd(a.sin(), pos.y)),
|
||||||
c,
|
c,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
//! trongle drawing
|
//! trongle drawing
|
||||||
|
use vecto::Vec2;
|
||||||
|
|
||||||
use crate::math::madd;
|
use crate::math::madd;
|
||||||
use crate::Image;
|
use crate::Image;
|
||||||
use std::cmp::{max, min};
|
use std::cmp::{max, min};
|
||||||
|
@ -19,11 +21,14 @@ impl<T: AsMut<[u8]> + AsRef<[u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
|
||||||
/// ```
|
/// ```
|
||||||
pub fn tri(
|
pub fn tri(
|
||||||
&mut self,
|
&mut self,
|
||||||
(x2, y2): (f32, f32),
|
b: impl Into<Vec2>,
|
||||||
(x1, y1): (f32, f32),
|
a: impl Into<Vec2>,
|
||||||
(x3, y3): (f32, f32),
|
c: impl Into<Vec2>,
|
||||||
c: [u8; CHANNELS],
|
col: [u8; CHANNELS],
|
||||||
) {
|
) {
|
||||||
|
let Vec2 { x: x1, y: y1 } = a.into();
|
||||||
|
let Vec2 { x: x2, y: y2 } = b.into();
|
||||||
|
let Vec2 { x: x3, y: y3 } = c.into();
|
||||||
let ymin = max(y1.min(y2).min(y3) as u32, 0);
|
let ymin = max(y1.min(y2).min(y3) as u32, 0);
|
||||||
let ymax = min(y1.max(y2).max(y3) as u32, self.height());
|
let ymax = min(y1.max(y2).max(y3) as u32, self.height());
|
||||||
let xmin = max(x1.min(x2).min(x3) as u32, 0);
|
let xmin = max(x1.min(x2).min(x3) as u32, 0);
|
||||||
|
@ -36,7 +41,7 @@ impl<T: AsMut<[u8]> + AsRef<[u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
|
||||||
&& madd(x3 - x1, y as f32 - y3, -(y3 - y1) * (x as f32 - x3)) > 0.
|
&& madd(x3 - x1, y as f32 - y3, -(y3 - y1) * (x as f32 - x3)) > 0.
|
||||||
{
|
{
|
||||||
// SAFETY: x, y are bounded
|
// SAFETY: x, y are bounded
|
||||||
unsafe { self.set_pixel(x, y, c) };
|
unsafe { self.set_pixel(x, y, col) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -254,6 +254,7 @@ impl<const CHANNELS: usize, const N: usize> Image<[u8; N], CHANNELS> {
|
||||||
impl<const CHANNELS: usize> Image<&[u8], CHANNELS> {
|
impl<const CHANNELS: usize> Image<&[u8], CHANNELS> {
|
||||||
/// Box this image.
|
/// Box this image.
|
||||||
pub fn boxed(self) -> Image<Box<[u8]>, CHANNELS> {
|
pub fn boxed(self) -> Image<Box<[u8]>, CHANNELS> {
|
||||||
|
// SAFETY: ctor
|
||||||
unsafe { Image::new(self.width, self.height, self.buffer.into()) }
|
unsafe { Image::new(self.width, self.height, self.buffer.into()) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue