mirror of
https://github.com/ricoriedel/wipe.git
synced 2024-11-26 01:46:36 +00:00
Add patterns
This commit is contained in:
parent
afe3dc4122
commit
2bdd88a7e8
58
src/pattern/circle.rs
Normal file
58
src/pattern/circle.rs
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
use crate::pattern::{Config, Pattern, PatternFactory};
|
||||||
|
use crate::vec::Vector;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct CircleFactory;
|
||||||
|
pub struct Circle {
|
||||||
|
center: Vector,
|
||||||
|
radius: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PatternFactory for CircleFactory {
|
||||||
|
fn name(&self) -> String {
|
||||||
|
stringify!(Circle).to_lowercase()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create(&self, config: &Config) -> Box<dyn Pattern> {
|
||||||
|
Box::new(Circle::new(config))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Circle {
|
||||||
|
pub fn new(config: &Config) -> Self {
|
||||||
|
let center = config.size.center();
|
||||||
|
let radius = center.len();
|
||||||
|
|
||||||
|
Self { center, radius }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Pattern for Circle {
|
||||||
|
fn sample(&self, pos: Vector) -> f32 {
|
||||||
|
(pos - self.center).len() / self.radius
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
use approx::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn name() {
|
||||||
|
assert_eq!("circle", CircleFactory::default().name());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sample() {
|
||||||
|
let config = Config {
|
||||||
|
size: Vector::new(10.0, 20.0),
|
||||||
|
step: 0.0,
|
||||||
|
};
|
||||||
|
let pattern = Circle::new(&config);
|
||||||
|
|
||||||
|
assert_abs_diff_eq!(1.0, pattern.sample(Vector::new(0.0, 0.0)), epsilon = 0.1);
|
||||||
|
assert_abs_diff_eq!(0.0, pattern.sample(Vector::new(5.0, 10.0)), epsilon = 0.1);
|
||||||
|
assert_abs_diff_eq!(0.5, pattern.sample(Vector::new(7.5, 15.0)), epsilon = 0.1);
|
||||||
|
}
|
||||||
|
}
|
57
src/pattern/line.rs
Normal file
57
src/pattern/line.rs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
use crate::pattern::{Config, Pattern, PatternFactory};
|
||||||
|
use crate::vec::Vector;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct LineFactory;
|
||||||
|
pub struct Line {
|
||||||
|
width: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PatternFactory for LineFactory {
|
||||||
|
fn name(&self) -> String {
|
||||||
|
stringify!(Line).to_lowercase()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create(&self, config: &Config) -> Box<dyn Pattern> {
|
||||||
|
Box::new(Line::new(config))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Line {
|
||||||
|
pub fn new(config: &Config) -> Self {
|
||||||
|
let width = config.size.x;
|
||||||
|
|
||||||
|
Self { width }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Pattern for Line {
|
||||||
|
fn sample(&self, pos: Vector) -> f32 {
|
||||||
|
pos.x / self.width
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
use approx::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn name() {
|
||||||
|
assert_eq!("line", LineFactory::default().name());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sample() {
|
||||||
|
let config = Config {
|
||||||
|
size: Vector::new(20.0, 0.0),
|
||||||
|
step: 0.0,
|
||||||
|
};
|
||||||
|
let pattern = Line::new(&config);
|
||||||
|
|
||||||
|
assert_abs_diff_eq!(0.0, pattern.sample(Vector::new(0.0, 4.0)), epsilon = 0.1);
|
||||||
|
assert_abs_diff_eq!(0.4, pattern.sample(Vector::new(8.0, 8.0)), epsilon = 0.1);
|
||||||
|
assert_abs_diff_eq!(0.8, pattern.sample(Vector::new(16.0, 7.0)), epsilon = 0.1);
|
||||||
|
assert_abs_diff_eq!(1.0, pattern.sample(Vector::new(20.0, 3.0)), epsilon = 0.1);
|
||||||
|
}
|
||||||
|
}
|
22
src/pattern/mod.rs
Normal file
22
src/pattern/mod.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
mod circle;
|
||||||
|
mod line;
|
||||||
|
mod rhombus;
|
||||||
|
mod wheel;
|
||||||
|
|
||||||
|
use crate::vec::Vector;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct Config {
|
||||||
|
pub size: Vector,
|
||||||
|
pub step: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait PatternFactory {
|
||||||
|
fn name(&self) -> String;
|
||||||
|
|
||||||
|
fn create(&self, config: &Config) -> Box<dyn Pattern>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Pattern {
|
||||||
|
fn sample(&self, pos: Vector) -> f32;
|
||||||
|
}
|
59
src/pattern/rhombus.rs
Normal file
59
src/pattern/rhombus.rs
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
use crate::pattern::{Config, Pattern, PatternFactory};
|
||||||
|
use crate::vec::Vector;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct RhombusFactory;
|
||||||
|
pub struct Rhombus {
|
||||||
|
center: Vector,
|
||||||
|
distance: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PatternFactory for RhombusFactory {
|
||||||
|
fn name(&self) -> String {
|
||||||
|
stringify!(Rhombus).to_lowercase()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create(&self, config: &Config) -> Box<dyn Pattern> {
|
||||||
|
Box::new(Rhombus::new(config))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Rhombus {
|
||||||
|
pub fn new(config: &Config) -> Rhombus {
|
||||||
|
let center = config.size.center();
|
||||||
|
let distance = center.sum();
|
||||||
|
|
||||||
|
Self { center, distance }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Pattern for Rhombus {
|
||||||
|
fn sample(&self, pos: Vector) -> f32 {
|
||||||
|
(pos - self.center).abs().sum() / self.distance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
use approx::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn name() {
|
||||||
|
assert_eq!("rhombus", RhombusFactory::default().name());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sample() {
|
||||||
|
let config = Config {
|
||||||
|
size: Vector::new(10.0, 5.0),
|
||||||
|
step: 0.0,
|
||||||
|
};
|
||||||
|
let pattern = Rhombus::new(&config);
|
||||||
|
|
||||||
|
assert_abs_diff_eq!(1.0, pattern.sample(Vector::new(0.0, 0.0)), epsilon = 0.1);
|
||||||
|
assert_abs_diff_eq!(1.0, pattern.sample(Vector::new(10.0, 5.0)), epsilon = 0.1);
|
||||||
|
assert_abs_diff_eq!(0.0, pattern.sample(Vector::new(5.0, 2.5)), epsilon = 0.1);
|
||||||
|
assert_abs_diff_eq!(0.5, pattern.sample(Vector::new(7.0, 0.5)), epsilon = 0.1);
|
||||||
|
}
|
||||||
|
}
|
58
src/pattern/wheel.rs
Normal file
58
src/pattern/wheel.rs
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
use crate::pattern::{Config, Pattern, PatternFactory};
|
||||||
|
use crate::vec::Vector;
|
||||||
|
use std::f32::consts::PI;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct WheelFactory;
|
||||||
|
pub struct Wheel {
|
||||||
|
center: Vector,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PatternFactory for WheelFactory {
|
||||||
|
fn name(&self) -> String {
|
||||||
|
stringify!(Wheel).to_lowercase()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create(&self, config: &Config) -> Box<dyn Pattern> {
|
||||||
|
Box::new(Wheel::new(config))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Wheel {
|
||||||
|
pub fn new(config: &Config) -> Self {
|
||||||
|
let center = config.size.center();
|
||||||
|
|
||||||
|
Self { center }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Pattern for Wheel {
|
||||||
|
fn sample(&self, pos: Vector) -> f32 {
|
||||||
|
((pos - self.center).angle() + PI) / PI / 2.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
use approx::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn name() {
|
||||||
|
assert_eq!("wheel", WheelFactory::default().name());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sample() {
|
||||||
|
let config = Config {
|
||||||
|
size: Vector::new(10.0, 20.0),
|
||||||
|
step: 0.0,
|
||||||
|
};
|
||||||
|
let pattern = Wheel::new(&config);
|
||||||
|
|
||||||
|
assert_abs_diff_eq!(0.0, pattern.sample(Vector::new(0.0, 9.0)), epsilon = 0.1);
|
||||||
|
assert_abs_diff_eq!(1.0, pattern.sample(Vector::new(0.0, 10.0)), epsilon = 0.1);
|
||||||
|
assert_abs_diff_eq!(0.5, pattern.sample(Vector::new(10.0, 10.0)), epsilon = 0.1);
|
||||||
|
assert_abs_diff_eq!(0.75, pattern.sample(Vector::new(5.0, 20.0)), epsilon = 0.1);
|
||||||
|
}
|
||||||
|
}
|
18
src/vec.rs
18
src/vec.rs
@ -15,6 +15,14 @@ impl Vector {
|
|||||||
(self.x * self.x + self.y * self.y).sqrt()
|
(self.x * self.x + self.y * self.y).sqrt()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn abs(&self) -> Vector {
|
||||||
|
Self::new(self.x.abs(), self.y.abs())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sum(&self) -> f32 {
|
||||||
|
self.x + self.y
|
||||||
|
}
|
||||||
|
|
||||||
pub fn center(&self) -> Vector {
|
pub fn center(&self) -> Vector {
|
||||||
Self::new(self.x / 2.0, self.y / 2.0)
|
Self::new(self.x / 2.0, self.y / 2.0)
|
||||||
}
|
}
|
||||||
@ -49,6 +57,16 @@ mod test {
|
|||||||
assert_abs_diff_eq!(8.5, Vector::new(3.0, 8.0).len(), epsilon = 0.1);
|
assert_abs_diff_eq!(8.5, Vector::new(3.0, 8.0).len(), epsilon = 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn abs() {
|
||||||
|
assert_eq!(Vector::new(3.0, 7.0), Vector::new(-3.0, -7.0).abs());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sum() {
|
||||||
|
assert_eq!(11.0, Vector::new(3.0, 8.0).sum());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn center() {
|
fn center() {
|
||||||
assert_eq!(Vector::new(4.0, 9.0), Vector::new(8.0, 18.0).center());
|
assert_eq!(Vector::new(4.0, 9.0), Vector::new(8.0, 18.0).center());
|
||||||
|
Loading…
Reference in New Issue
Block a user