-
Notifications
You must be signed in to change notification settings - Fork 12
/
beztoy.js
112 lines (96 loc) · 2.85 KB
/
beztoy.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
// Copyright 2018 Raph Levien
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! A simple interactive visualizer for 2-parameter spline curves based
//! on cubic Beziers.
class Ui {
constructor() {
let svg = document.getElementById("s");
svg.addEventListener("pointermove", e => this.mousemove(e));
svg.addEventListener("pointerup", e => this.mouseup(e));
this.mousehandler = null;
this.attach_handler("left_th", this.left_th_handler);
this.attach_handler("right_th", this.right_th_handler);
this.coords = new Float64Array(8);
this.coords[4] = 1;
this.coords[6] = 1;
}
attach_handler(id, handler) {
let element = document.getElementById(id);
let svg = document.getElementById("s");
element.addEventListener("pointerdown", e => {
svg.setPointerCapture(e.pointerId);
this.mousehandler = handler;
});
}
mousemove(e) {
if (this.mousehandler != null) {
this.mousehandler(e);
}
}
mouseup(e) {
e.target.releasePointerCapture(e.pointerId);
this.mousehandler = null;
}
left_th_handler(e) {
let x = e.offsetX;
let y = e.offsetY;
this.coords[2] = (x - 100) / 200;
this.coords[3] = (200 - y) / 200;
let el = document.getElementById("left_th");
el.setAttribute("cx", x);
el.setAttribute("cy", y);
this.redraw();
}
right_th_handler(e) {
let x = e.offsetX;
let y = e.offsetY;
this.coords[4] = (x - 100) / 200;
this.coords[5] = (200 - y) / 200;
let el = document.getElementById("right_th");
el.setAttribute("cx", x);
el.setAttribute("cy", y);
this.redraw();
}
redraw() {
let th0 = Math.atan2(this.coords[3], this.coords[2]);
let th1 = Math.atan2(this.coords[5], 1 - this.coords[4]);
//let coords = this.coords;
let coords = myCubic(th0, th1);
// Draw the bezier
var path = "";
for (var i = 0; i < 4; i ++) {
let x = 100 + 200 * coords[i * 2];
let y = 200 - 200 * coords[i * 2 + 1];
let cmd = ['M', ' C', ' ', ' '][i];
path += `${cmd}${x} ${y}`;
}
document.getElementById("bez").setAttribute("d", path);
// Draw the graph of curvature vs arclength.
let cb = new CubicBez(coords);
path = "";
var cmd = "M";
var last = new Vec2(0, 0);
var s = 0;
for (var i = 0; i <= 100; i++) {
let t = 0.01 * i;
let xy = cb.eval(t);
s += Math.hypot(xy.x - last.x, xy.y - last.y);
last = xy;
let x = 100 + 200 * s;
let k = cb.curvature(t);
if (!isNaN(k)) {
let scale = -0.05;
let y = 300 - 200 * scale * k;
path += `${cmd}${x} ${y}`;
cmd = " L";
}
}
document.getElementById("curv").setAttribute("d", path);
document.getElementById("curv-base").setAttribute("x2", 100 + 200 * s);
}
}
let ui = new Ui();