vec = ({
len([dx, dy]) {
return Math.sqrt(dx ** 2 + dy ** 2);
},
arg([dx, dy]) {
return radiansToDegrees(Math.atan2(dy, dx));
},
mul([dx, dy], s) {
return [s * dx, s * dy];
},
add([dx1, dy1], [dx2, dy2]) {
return [dx1 + dx2, dy1 + dy2];
},
sub([dx1, dy1], [dx2, dy2]) {
return [dx1 - dx2, dy1 - dy2];
},
vec([dx1, dy1], [dx2, dy2]) {
return [dx2 - dx1, dy2 - dy1];
},
inv([dx, dy]) {
return [-dx, -dy];
},
unit(vec, len=1) {
return this.mul(vec, len / this.len(vec));
},
rotate([dx, dy], degrees) {
const a = degreesToRadians(degrees);
const [c, s] = [Math.cos(a), Math.sin(a)];
return [c * dx - s * dy, c * dy + s * dx];
},
lin(source, target, prop) {
return this.add(source, this.mul(this.vec(source, target), prop));
},
pad(source, target, dist) {
return this.add(source, this.unit(this.vec(source, target), dist));
},
})