-
Notifications
You must be signed in to change notification settings - Fork 0
/
TwoSpaceRenderEngine.js
125 lines (110 loc) · 3.38 KB
/
TwoSpaceRenderEngine.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
113
114
115
116
117
118
119
120
121
122
123
124
125
class TwoSpaceRenderEngine {
constructor(field) {
this.field = field;
}
line(x1, y1, x2, y2) {
let start = this.field.mapPoint(x1, y1);
let end = this.field.mapPoint(x2, y2);
line(start.x, start.y, end.x, end.y);
}
vector(xMagnitude, yMagnitude, x, y) {
let start = createVector(x, y);
let end = createVector(x+xMagnitude, y+yMagnitude);
let t = atan((end.y - start.y) / (end.x - start.x));
if (start.x > end.x) {
t += PI;
}
let forwardAngle = t + 19*PI/16;
let backwardAngle = t - 19*PI/16;
let magnitude = sqrt(yMagnitude**2 + xMagnitude**2);
let headRatio = 12;
this.shape([
end,
createVector(
end.x + (cos(forwardAngle) * magnitude / headRatio),
end.y + (sin(forwardAngle) * magnitude / headRatio)
),
createVector(
end.x + (cos(backwardAngle) * magnitude / headRatio),
end.y + (sin(backwardAngle) * magnitude / headRatio)
)
]);
this.line(start.x, start.y, end.x, end.y);
}
pointer(xMagnitude, yMagnitude, x, y) {
let start = createVector(x - xMagnitude, y - yMagnitude);
let end = createVector(x, y);
let t = atan((end.y - start.y) / (end.x - start.x));
if (xMagnitude < 0) {
t += PI;
}
let forwardAngle = t + 19*PI/16;
let backwardAngle = t - 19*PI/16;
let magnitude = sqrt(yMagnitude**2 + xMagnitude**2);
let headRatio = 6;
this.line(end.x + (cos(forwardAngle) * magnitude / headRatio), end.y + (sin(forwardAngle) * magnitude / headRatio), end.x, end.y);
this.line(end.x + (cos(backwardAngle) * magnitude / headRatio), end.y + (sin(backwardAngle) * magnitude / headRatio), end.x, end.y);
}
point(x1, y1) {
let pos = this.field.mapPoint(x1, y1);
point(pos.x,pos.y)
}
shape(points) {
beginShape();
points.forEach(point => {
let mapped = this.field.mapPoint(point.x, point.y);
vertex(mapped.x, mapped.y);
});
endShape();
let max = points.length-1;
this.line(points[0].x, points[0].y, points[max].x, points[max].y);
}
graph(func) {
noFill();
beginShape();
this.#samplePoints().forEach(x => {
let y = func(x);
let mapped = this.field.mapPoint(x, y)
vertex(mapped.x, mapped.y);
});
endShape();
}
#samplePoints() {
let acc = [];
for (let x = this.field.xWindow.start; x < this.field.xWindow.end; x+=this.field.windowWidth() / 1000) {
acc.push(x);
}
return acc;
}
vectorField(xFunc, yFunc) {
this.#sample2DPoints().forEach(pt => {
// <h(x, y), k(x, y)>
// pick your poison
// this.vector(xFunc(pt.x, pt.y), yFunc(pt.x, pt.y), pt.x, pt.y);
this.pointer(xFunc(pt.x, pt.y), yFunc(pt.x, pt.y), pt.x, pt.y);
});
}
gradient(func) {
this.#sample2DPoints().forEach(pt => {
// f(x, y)
let f = func(pt.x, pt.y);
// Δ
let d = 2**-24;
// ∂f/∂x
let Fx = (func(pt.x+d, pt.y)-f) / d;
// ∂f/∂y
let Fy = (func(pt.x, pt.y+d)-f) / d;
// <∂f/∂x, ∂f/∂y>
this.vector(Fx, Fy, pt.x, pt.y);
});
}
#sample2DPoints() {
let acc = [];
for (let x = this.field.xWindow.start; x < this.field.xWindow.end; x+=this.field.windowWidth() / 33) {
for (let y = this.field.yWindow.start; y < this.field.yWindow.end; y+=this.field.windowHeight() / 33) {
acc.push(createVector(x, y));
}
}
return acc;
}
}