summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lerp.rs8
-rw-r--r--src/lib.rs21
-rw-r--r--src/main.rs61
-rw-r--r--src/poly.rs (renamed from src/lerp/poly.rs)52
-rw-r--r--src/poly/iter.rs (renamed from src/lerp/poly/iter.rs)0
5 files changed, 90 insertions, 52 deletions
diff --git a/src/lerp.rs b/src/lerp.rs
index b613620..4c829a1 100644
--- a/src/lerp.rs
+++ b/src/lerp.rs
@@ -1,6 +1,4 @@
-pub mod poly;
-
-use poly::Poly;
+use crate::poly::Poly;
pub enum Lerp {
Node(Box<Lerp>, Box<Lerp>),
@@ -9,7 +7,7 @@ pub enum Lerp {
}
impl Lerp {
- pub fn new(v: Vec<f32>) -> Box<Lerp> {
+ pub fn new(v: &Vec<f32>) -> Box<Lerp> {
Lerp::new_s(&v[..])
}
@@ -33,7 +31,7 @@ impl Lerp {
let a = a.to_poly();
let b = b.to_poly();
let c = &b - &a;
- &a + &(&c * &Poly::new(vec![0.0, 1.0]))
+ &a + &c.shift()
}
}
}
diff --git a/src/lib.rs b/src/lib.rs
index cadef3c..6f26672 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,14 +1,17 @@
mod lerp;
+mod poly;
use lerp::Lerp;
-use lerp::poly::Poly;
+use poly::Poly;
pub struct Bezier {
+ pub degree: usize,
pub vx: Vec<f32>,
pub vy: Vec<f32>,
pub px: Poly,
pub py: Poly,
- pub degree: usize
+ pub dpx: Poly,
+ pub dpy: Poly
}
impl Bezier {
@@ -18,6 +21,8 @@ impl Bezier {
vy: Vec::<f32>::new(),
px: Poly::new(vec![]),
py: Poly::new(vec![]),
+ dpy: Poly::new(vec![]),
+ dpx: Poly::new(vec![]),
degree: 0,
}
}
@@ -25,16 +30,20 @@ impl Bezier {
pub fn push(&mut self, x: i32, y: i32) {
self.vx.push(x as f32);
self.vy.push(y as f32);
- self.px = Lerp::new(self.vx.clone()).to_poly();
- self.py = Lerp::new(self.vy.clone()).to_poly();
+ self.px = Lerp::new(&self.vx).to_poly();
+ self.py = Lerp::new(&self.vy).to_poly();
+ self.dpx = self.px.deriv();
+ self.dpy = self.py.deriv();
self.degree += 1;
}
pub fn remove(&mut self, index: usize) {
self.vx.remove(index);
self.vy.remove(index);
- self.px = Lerp::new(self.vx.clone()).to_poly();
- self.py = Lerp::new(self.vy.clone()).to_poly();
+ self.px = Lerp::new(&self.vx).to_poly();
+ self.py = Lerp::new(&self.vy).to_poly();
+ self.dpx = self.px.deriv();
+ self.dpy = self.py.deriv();
self.degree -= 1;
}
diff --git a/src/main.rs b/src/main.rs
index f01526b..a61478f 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -37,25 +37,47 @@ fn compile_bezier_shader(c: &Bezier) -> GLuint {
#version 410 core
out vec4 FragColor;
- float inf = 1000000;
float vx[{s}] = float[{s}]({vx});
float vy[{s}] = float[{s}]({vy});
+
float px[{sx}] = float[{sx}]({px});
float py[{sy}] = float[{sy}]({py});
+
+ float dpx[{dsx}] = float[{dsx}]({dpx});
+ float dpy[{dsy}] = float[{dsy}]({dpy});
+
float thr = 32;
+ float step_size = 10;
+ float inf = 1000000;
- float eval_a(float[{sx}] v, float t) {{
+ float eval_px(float t) {{
float result = 0.0;
for (int i = 0; i < {sx}; i++) {{
- result += v[i] * pow(t, i);
+ result += px[i] * pow(t, i);
}}
return result;
}}
- float eval_b(float[{sy}] v, float t) {{
+ float eval_py(float t) {{
float result = 0.0;
for (int i = 0; i < {sy}; i++) {{
- result += v[i] * pow(t, i);
+ result += py[i] * pow(t, i);
+ }}
+ return result;
+ }}
+
+ float eval_dpx(float t) {{
+ float result = 0.0;
+ for (int i = 0; i < {dsx}; i++) {{
+ result += dpx[i] * pow(t, i);
+ }}
+ return result;
+ }}
+
+ float eval_dpy(float t) {{
+ float result = 0.0;
+ for (int i = 0; i < {dsy}; i++) {{
+ result += dpy[i] * pow(t, i);
}}
return result;
}}
@@ -72,13 +94,14 @@ fn compile_bezier_shader(c: &Bezier) -> GLuint {
}}
float inside(vec2 pos) {{
- float res = 100;
float closest = inf;
float t = 0.0;
- while (t < 1.0 - 1.0 / res) {{
- float step = t + 1.0 / res;
- vec2 a = vec2(eval_a(px, t), eval_b(py, t));
- vec2 b = vec2(eval_a(px, step), eval_b(py, step));
+ float dstep = 0.0;
+ while (t < 1.0 - dstep) {{
+ dstep = step_size / length(vec2(eval_dpx(t), eval_dpy(t)));
+ float step = t + dstep;
+ vec2 a = vec2(eval_px(t), eval_py(t));
+ vec2 b = vec2(eval_px(step), eval_py(step));
float c = pow(length(a - b), 2);
float d = distance(pos, a + clamp(dot(pos - a, b - a) / c, 0, 1) * (b - a));
if (d < closest) {{
@@ -95,13 +118,17 @@ fn compile_bezier_shader(c: &Bezier) -> GLuint {
FragColor = vec4(r, c, 0.0, 1.0);
}}
",
- sx = c.px.degree() + 1,
- sy = c.py.degree() + 1,
- px = &c.px,
- py = &c.py,
- s = c.degree,
- vx = c.show_x(),
- vy = c.show_y(),
+ s = c.degree,
+ vx = c.show_x(),
+ vy = c.show_y(),
+ px = &c.px,
+ py = &c.py,
+ sx = c.px.degree() + 1,
+ sy = c.py.degree() + 1,
+ dpx = &c.dpx,
+ dpy = &c.dpy,
+ dsx = c.dpx.degree() + 1,
+ dsy = c.dpy.degree() + 1,
)
.into_bytes();
diff --git a/src/lerp/poly.rs b/src/poly.rs
index 961c56c..35e85d8 100644
--- a/src/lerp/poly.rs
+++ b/src/poly.rs
@@ -2,7 +2,7 @@ mod iter;
use iter::Iter;
use std::fmt;
-use std::ops::{Add, Mul, Sub};
+use std::ops::{Add, Sub};
#[derive(PartialEq, Debug, Clone)]
pub struct Poly {
@@ -12,7 +12,7 @@ pub struct Poly {
impl Poly {
pub fn new(data: Vec<f32>) -> Poly {
- if data.len() > 0 {
+ if data.len() > 1 {
let mut i = data.len() - 1;
while data[i] == 0.0 && i > 0 {
i -= 1;
@@ -30,6 +30,24 @@ impl Poly {
fn iter(&self) -> Iter {
Iter::new(self.data.clone(), self.degree())
}
+
+ pub fn shift(self) -> Poly {
+ let mut r = vec![0.0];
+ r.append(&mut self.data.clone());
+ Poly::new(r)
+ }
+
+ pub fn deriv(&self) -> Poly {
+ let mut data = vec![0.0; self.degree()];
+ if self.degree() > 0 {
+ for i in 0..self.degree() {
+ data[i] = self.data[i + 1] * (i + 1) as f32;
+ }
+ Poly::new(data)
+ } else {
+ Poly::new(vec![0.0])
+ }
+ }
}
impl Add for &Poly {
@@ -48,25 +66,6 @@ impl Sub for &Poly {
}
}
-impl Mul for &Poly {
- type Output = Poly;
-
- fn mul(self, other: Self) -> Poly {
- let mut r = Vec::new();
- for i in 0..other.degree() + 1 {
- let mut prefix = vec![0.0; i];
- let mut suffix: Vec<f32> = self
- .iter()
- .take(self.degree() + 1)
- .map(|x| x * other.data[i])
- .collect();
- prefix.append(&mut suffix);
- r.push(Poly::new(prefix));
- }
- r.iter().fold(Poly::new(vec![0.0]), |acc, x| &acc + x)
- }
-}
-
impl fmt::Display for &Poly {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut s = String::new();
@@ -85,10 +84,9 @@ mod tests {
use super::*;
#[test]
- fn mul_test() {
+ fn shift_test() {
let a = Poly::new(vec![1.0, 2.0, 3.0]);
- let b = Poly::new(vec![1.0, 2.0]);
- assert_eq!(&a * &b, Poly::new(vec![1.0, 4.0, 7.0, 6.0]));
+ assert_eq!(a.shift(), Poly::new(vec![0.0, 1.0, 2.0, 3.0]));
}
#[test]
@@ -106,6 +104,12 @@ mod tests {
}
#[test]
+ fn deriv_test() {
+ let p = Poly::new(vec![1.0, 2.0, 3.0, 4.0]);
+ assert_eq!(p.deriv(), Poly::new(vec![2.0, 6.0, 12.0]));
+ }
+
+ #[test]
fn degree_is_five() {
let p = Poly::new(vec![0.0, 0.0, 0.0, 0.0, 0.0, 2.0]);
assert_eq!(p.degree(), 5);
diff --git a/src/lerp/poly/iter.rs b/src/poly/iter.rs
index 90cc4b5..90cc4b5 100644
--- a/src/lerp/poly/iter.rs
+++ b/src/poly/iter.rs