mirror of
https://github.com/belsabbagh/dotfiles.git
synced 2026-04-11 17:47:09 +00:00
178 lines
3.5 KiB
JavaScript
178 lines
3.5 KiB
JavaScript
.pragma library
|
|
|
|
/**
|
|
* @param {number} x
|
|
* @param {number} y
|
|
* @returns {Offset}
|
|
*/
|
|
function createOffset(x, y) {
|
|
return new Offset(x, y);
|
|
}
|
|
|
|
class Offset {
|
|
/**
|
|
* @param {number} x
|
|
* @param {number} y
|
|
*/
|
|
constructor(x, y) {
|
|
this.x = x;
|
|
this.y = y;
|
|
}
|
|
|
|
/**
|
|
* @param {number} x
|
|
* @param {number} y
|
|
* @returns {Offset}
|
|
*/
|
|
copy(x = this.x, y = this.y) {
|
|
return new Offset(x, y);
|
|
}
|
|
|
|
/**
|
|
* @returns {number}
|
|
*/
|
|
getDistance() {
|
|
return Math.sqrt(this.x * this.x + this.y * this.y);
|
|
}
|
|
|
|
/**
|
|
* @returns {number}
|
|
*/
|
|
getDistanceSquared() {
|
|
return this.x * this.x + this.y * this.y;
|
|
}
|
|
|
|
/**
|
|
* @returns {boolean}
|
|
*/
|
|
isValid() {
|
|
return isFinite(this.x) && isFinite(this.y);
|
|
}
|
|
|
|
/**
|
|
* @returns {boolean}
|
|
*/
|
|
get isFinite() {
|
|
return isFinite(this.x) && isFinite(this.y);
|
|
}
|
|
|
|
/**
|
|
* @returns {boolean}
|
|
*/
|
|
get isSpecified() {
|
|
return !this.isUnspecified;
|
|
}
|
|
|
|
/**
|
|
* @returns {boolean}
|
|
*/
|
|
get isUnspecified() {
|
|
return Object.is(this.x, NaN) && Object.is(this.y, NaN);
|
|
}
|
|
|
|
/**
|
|
* @returns {Offset}
|
|
*/
|
|
negate() {
|
|
return new Offset(-this.x, -this.y);
|
|
}
|
|
|
|
/**
|
|
* @param {Offset} other
|
|
* @returns {Offset}
|
|
*/
|
|
minus(other) {
|
|
return new Offset(this.x - other.x, this.y - other.y);
|
|
}
|
|
|
|
/**
|
|
* @param {Offset} other
|
|
* @returns {Offset}
|
|
*/
|
|
plus(other) {
|
|
return new Offset(this.x + other.x, this.y + other.y);
|
|
}
|
|
|
|
/**
|
|
* @param {number} operand
|
|
* @returns {Offset}
|
|
*/
|
|
times(operand) {
|
|
return new Offset(this.x * operand, this.y * operand);
|
|
}
|
|
|
|
/**
|
|
* @param {number} operand
|
|
* @returns {Offset}
|
|
*/
|
|
div(operand) {
|
|
return new Offset(this.x / operand, this.y / operand);
|
|
}
|
|
|
|
/**
|
|
* @param {number} operand
|
|
* @returns {Offset}
|
|
*/
|
|
rem(operand) {
|
|
return new Offset(this.x % operand, this.y % operand);
|
|
}
|
|
|
|
/**
|
|
* @returns {string}
|
|
*/
|
|
toString() {
|
|
if (this.isSpecified) {
|
|
return `Offset(${this.x.toFixed(1)}, ${this.y.toFixed(1)})`;
|
|
} else {
|
|
return 'Offset.Unspecified';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {Offset} start
|
|
* @param {Offset} stop
|
|
* @param {number} fraction
|
|
* @returns {Offset}
|
|
*/
|
|
static lerp(start, stop, fraction) {
|
|
return new Offset(
|
|
start.x + (stop.x - start.x) * fraction,
|
|
start.y + (stop.y - start.y) * fraction
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param {function(): Offset} block
|
|
* @returns {Offset}
|
|
*/
|
|
takeOrElse(block) {
|
|
return this.isSpecified ? this : block();
|
|
}
|
|
|
|
/**
|
|
* @returns {number}
|
|
*/
|
|
angleDegrees() {
|
|
return Math.atan2(this.y, this.x) * 180 / Math.PI;
|
|
}
|
|
|
|
/**
|
|
* @param {number} angle
|
|
* @param {Offset} center
|
|
* @returns {Offset}
|
|
*/
|
|
rotateDegrees(angle, center = Offset.Zero) {
|
|
const a = angle * Math.PI / 180;
|
|
const off = this.minus(center);
|
|
const cosA = Math.cos(a);
|
|
const sinA = Math.sin(a);
|
|
const newX = off.x * cosA - off.y * sinA;
|
|
const newY = off.x * sinA + off.y * cosA;
|
|
return new Offset(newX, newY).plus(center);
|
|
}
|
|
}
|
|
|
|
Offset.Zero = new Offset(0, 0);
|
|
Offset.Infinite = new Offset(Infinity, Infinity);
|
|
Offset.Unspecified = new Offset(NaN, NaN);
|