@dominicstop/utils
Version:
Yet another event emitter written in typescript.
206 lines (205 loc) • 6.25 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Point = void 0;
const helpers_1 = require("../helpers");
const Line_1 = require("./Line");
const Rect_1 = require("./Rect");
const Vector2D_1 = require("./Vector2D");
class Point {
constructor(args) {
this.epsilon = 1e-10;
this.x = args.x;
this.y = args.y;
}
;
get asValue() {
return {
x: this.x,
y: this.y,
};
}
;
get asVector() {
return new Vector2D_1.Vector2D({
dx: this.x,
dy: this.y,
});
}
;
get magnitude() {
return this.asVector.magnitude;
}
get normalized() {
return this.asVector.normalized;
}
;
// MARK: - Methods
// ---------------
clone() {
return new Point({
x: this.x,
y: this.y
});
}
isEqualToOtherPoint(otherPoint) {
return (Math.abs(this.x - otherPoint.x) < this.epsilon &&
Math.abs(this.y - otherPoint.y) < this.epsilon);
}
get isZero() {
return (Math.abs(this.x) < this.epsilon &&
Math.abs(this.y) < this.epsilon);
}
;
get isNaN() {
return (Number.isNaN(this.x)
|| Number.isNaN(this.y));
}
;
toString() {
return `Point(${this.x}, ${this.y})`;
}
createLine(otherPoint) {
return new Line_1.Line({
startPoint: this,
endPoint: otherPoint
});
}
;
getDistance(otherPoint) {
return Point.getDistanceBetweenTwoPoints(this, otherPoint);
}
;
getDelta(otherPoint) {
return new Point({
x: this.x - otherPoint.x,
y: this.y - otherPoint.y,
});
}
;
getSum(...otherPoints) {
return Point.sumOfAllPoints(this, ...otherPoints);
}
;
getMidpointBetweenOtherPoint(otherPoint) {
const line = this.createLine(otherPoint);
return line.midPoint;
}
;
rotateRelativeToCenterPoint(args) {
const angleRad = args.angle.radians;
const translatedX = this.x - args.center.x;
const translatedY = this.y - args.center.y;
// 2d rotation matrix:
// * sin wave and cos wave can be used to modulate x and y axis
// * as they wobble back and forth, combined they can be used trace a circlular path
// * these two equations trace a circular path as the angle increases
//
// cos and sin on the unit:
// * the unit circle is a circle with radius 1, centered at the
// origin (x: 0, y: 0).
//
// * for any angle theta (in radians), a point on the unit circle is:
// `(x: cos(theta), y: sin(theta))`.
//
// * innother words, if you plot `(cos(angle), sin(angle))`,
// you get points around a circle.
//
// * the resulting point is a direction vector (normalized vector), i.e.
// a unit-length arrow pointing in the direction of angle.
//
// * note: for this function, we define a specific center; as such
// the point is first translated to be relative to the center.
//
const rotatedX = translatedX * Math.cos(angleRad) - translatedY * Math.sin(angleRad);
const rotatedY = translatedX * Math.sin(angleRad) + translatedY * Math.cos(angleRad);
this.x = rotatedX + args.center.x;
this.y = rotatedY + args.center.y;
}
;
rotatedRelativeToCenterPoint(args) {
const copy = this.clone();
copy.rotateRelativeToCenterPoint(args);
return copy;
}
;
// MARK: - Static Alias
// --------------------
static get zero() {
return new Point({ x: 0, y: 0 });
}
;
// MARK: - Static Methods
// ----------------------
static lerp(valueStart, valueEnd, percent) {
const nextX = helpers_1.InterpolationHelpers.lerp(valueStart.x, valueEnd.x, percent);
const nextY = helpers_1.InterpolationHelpers.lerp(valueStart.y, valueEnd.y, percent);
return new Point({
x: nextX,
y: nextY
});
}
;
static getBoundingBoxForPoints(points) {
const valuesX = points.map(point => point.x);
const valuesY = points.map(point => point.y);
const sortedValuesX = valuesX.sort((a, b) => a - b);
const sortedValuesY = valuesY.sort((a, b) => a - b);
const minX = sortedValuesX[0] ?? 0;
const maxX = sortedValuesX[valuesX.length - 1] ?? 0;
const minY = sortedValuesY[0] ?? 0;
const maxY = sortedValuesY[valuesY.length - 1] ?? 0;
return new Rect_1.Rect({
mode: 'corners',
minX,
maxX,
minY,
maxY,
});
}
;
static translatePoints(args) {
const boundingBox = this.getBoundingBoxForPoints(args.points);
// calc the translation for the derived bounding box
const translatedOrigin = new Point({
x: boundingBox.origin.x + args.dx,
y: boundingBox.origin.y + args.dy
});
// adj each point by translation
return args.points.map(point => {
const adjX = translatedOrigin.x - boundingBox.origin.x;
const adjY = translatedOrigin.y - boundingBox.origin.y;
return new Point({
x: point.x + adjX,
y: point.y + adjY
});
});
}
;
static sumOfAllPoints(...points) {
let sumX = 0;
let sumY = 0;
for (const point of points) {
sumX += point.x;
sumY += point.y;
}
;
return new Point({ x: sumX, y: sumY });
}
;
static getDistanceBetweenTwoPoints(pointA, pointB) {
const line = pointA.createLine(pointB);
return line.distance;
}
;
static rotatePointsRelativeToCenter(args) {
if (args.points.length === 0)
return [];
return args.points.map(point => point.rotatedRelativeToCenterPoint({
angle: args.rotationAmount,
center: args.center
}));
}
;
}
exports.Point = Point;
;