Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Visualization of lowering cubic Beziers to arcs #106

Draft
wants to merge 11 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions _config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,7 @@ plugins:
# - vendor/cache/
# - vendor/gems/
# - vendor/ruby/

exclude:
- Cargo.toml
- Cargo.lock
2 changes: 2 additions & 0 deletions _figures/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/target
/dist
2 changes: 2 additions & 0 deletions _figures/beztoy/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/target
/dist
11 changes: 11 additions & 0 deletions _figures/beztoy/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "beztoy"
license = "Apache-2.0"
version = "0.1.0"
edition = "2021"

[dependencies]
console_error_panic_hook = "0.1"
wasm-bindgen = "0.2.87"
web-sys = "0.3.64"
xilem_web = { git = "https://github.com/linebender/xilem", rev = "1ef39fc562d969cfc8548d16b2b72202a5d2196d" }
5 changes: 5 additions & 0 deletions _figures/beztoy/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# beztoy

A toy for experimenting with Bézier curves, intended to become a testbed for Euler spiral based stroke expansion.

Run with `trunk serve`, then navigate to the webpage.
4 changes: 4 additions & 0 deletions _figures/beztoy/Trunk.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[build]
#public_url = "https://levien.com/tmp/beztoy/"


Binary file added _figures/beztoy/beztoy.tar.gz
Binary file not shown.
14 changes: 14 additions & 0 deletions _figures/beztoy/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<head>
<style>
svg {
touch-action: pinch-zoom;
}
svg circle {
pointer-events: all;
}
</style>
</head>
<body>
<p>See <a href="https://github.com/raphlinus/raphlinus.github.io/pull/100">raphlinus#100</a> for more context.</p>
</body>
71 changes: 71 additions & 0 deletions _figures/beztoy/src/arc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Copyright 2023 the raphlinus.github.io Authors
// SPDX-License-Identifier: Apache-2.0

//! Convert an Euler spiral to a series of arcs.

use xilem_web::svg::kurbo::{SvgArc, Vec2};

use crate::euler::EulerSeg;

#[allow(unused)]
pub fn euler_to_arcs(es: &EulerSeg, tol: f64) -> Vec<SvgArc> {
let arclen = es.p0.distance(es.p1) / es.params.ch;
let n_subdiv = ((1. / 120.) * arclen / tol * es.params.k1.abs()).cbrt();
web_sys::console::log_1(&format!("n_subdiv = {n_subdiv}").into());
let n = (n_subdiv.ceil() as usize).max(1);
let dt = 1.0 / n as f64;
let mut p0 = es.p0;
(0..n)
.map(|i| {
let t0 = i as f64 * dt;
let t1 = t0 + dt;
let p1 = if i + 1 == n { es.p1 } else { es.eval(t1) };
let t = t0 + 0.5 * dt - 0.5;
let k = es.params.k0 + t * es.params.k1;
web_sys::console::log_1(&format!("{i}: k = {k} t = {t}").into());
let r = arclen / k;
let arc = SvgArc {
from: p0,
to: p1,
radii: Vec2::new(r, r),
x_rotation: 0.0,
large_arc: false,
sweep: k < 0.0,
};
p0 = p1;
arc
})
.collect()
}

pub fn espc_to_arcs(es: &EulerSeg, d: f64, tol: f64) -> Vec<SvgArc> {
let arclen = es.p0.distance(es.p1) / es.params.ch;
let est_err =
(1. / 120.) / tol * es.params.k1.abs() * (arclen + 0.4 * (es.params.k1 * d).abs());
let n_subdiv = est_err.cbrt();
web_sys::console::log_1(&format!("n_subdiv = {n_subdiv}").into());
let n = (n_subdiv.ceil() as usize).max(1);
let dt = 1.0 / n as f64;
let mut p0 = es.eval_with_offset(0.0, d);
(0..n)
.map(|i| {
let t0 = i as f64 * dt;
let t1 = t0 + dt;
let p1 = es.eval_with_offset(t1, d);
let t = t0 + 0.5 * dt - 0.5;
let k = es.params.k0 + t * es.params.k1;
let arclen_offset = arclen + d * k;
let r = arclen_offset / k;
let arc = SvgArc {
from: p0,
to: p1,
radii: Vec2::new(r, r),
x_rotation: 0.0,
large_arc: false,
sweep: k < 0.0,
};
p0 = p1;
arc
})
.collect()
}
Loading