mirror of
https://github.com/ricoriedel/wipe.git
synced 2024-11-22 16:06:38 +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()
|
||||
}
|
||||
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
|
||||
#[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]
|
||||
fn center() {
|
||||
assert_eq!(Vector::new(4.0, 9.0), Vector::new(8.0, 18.0).center());
|
||||
|
Loading…
Reference in New Issue
Block a user