'use strict';
/**
* The Point2D class stores and operates on 2-dimensional points, represented as
* x and y coordinates.
*
* @memberof westures-core
*
* @param {number} [ x=0 ] - The x coordinate of the point.
* @param {number} [ y=0 ] - The y coordinate of the point.
*/
class Point2D {
constructor(x = 0, y = 0) {
/**
* The x coordinate of the point.
*
* @type {number}
*/
this.x = x;
/**
* The y coordinate of the point.
*
* @type {number}
*/
this.y = y;
}
/**
* Calculates the angle between this point and the given point.
*
* @param {!westures-core.Point2D} point - Projected point for calculating the
* angle.
*
* @return {number} Radians along the unit circle where the projected
* point lies.
*/
angleTo(point) {
return Math.atan2(point.y - this.y, point.x - this.x);
}
/**
* Determine the angle from the centroid to each of the points.
*
* @param {!westures-core.Point2D[]} points - the Point2D objects to calculate
* the angles to.
*
* @returns {number[]}
*/
anglesTo(points) {
return points.map(point => this.angleTo(point));
}
/**
* Determine the average distance from this point to the provided array of
* points.
*
* @param {!westures-core.Point2D[]} points - the Point2D objects to calculate
* the average distance to.
*
* @return {number} The average distance from this point to the provided
* points.
*/
averageDistanceTo(points) {
return this.totalDistanceTo(points) / points.length;
}
/**
* Clone this point.
*
* @return {westures-core.Point2D} A new Point2D, identical to this point.
*/
clone() {
return new Point2D(this.x, this.y);
}
/**
* Calculates the distance between two points.
*
* @param {!westures-core.Point2D} point - Point to which the distance is
* calculated.
*
* @return {number} The distance between the two points, a.k.a. the
* hypoteneuse.
*/
distanceTo(point) {
return Math.hypot(point.x - this.x, point.y - this.y);
}
/**
* Subtract the given point from this point.
*
* @param {!westures-core.Point2D} point - Point to subtract from this point.
*
* @return {westures-core.Point2D} A new Point2D, which is the result of (this
* - point).
*/
minus(point) {
return new Point2D(
this.x - point.x,
this.y - point.y,
);
}
/**
* Return the summation of this point to the given point.
*
* @param {!westures-core.Point2D} point - Point to add to this point.
*
* @return {westures-core.Point2D} A new Point2D, which is the addition of the
* two points.
*/
plus(point) {
return new Point2D(
this.x + point.x,
this.y + point.y,
);
}
/**
* Calculates the total distance from this point to an array of points.
*
* @param {!westures-core.Point2D[]} points - The array of Point2D objects to
* calculate the total distance to.
*
* @return {number} The total distance from this point to the provided points.
*/
totalDistanceTo(points) {
return points.reduce((d, p) => d + this.distanceTo(p), 0);
}
/**
* Calculates the centroid of a list of points.
*
* @param {westures-core.Point2D[]} points - The array of Point2D objects for
* which to calculate the centroid.
*
* @return {westures-core.Point2D} The centroid of the provided points.
*/
static centroid(points = []) {
if (points.length === 0) return null;
const total = Point2D.sum(points);
total.x /= points.length;
total.y /= points.length;
return total;
}
/**
* Calculates the sum of the given points.
*
* @param {westures-core.Point2D[]} points - The Point2D objects to sum up.
*
* @return {westures-core.Point2D} A new Point2D representing the sum of the
* given points.
*/
static sum(points = []) {
return points.reduce(
(total, pt) => {
total.x += pt.x;
total.y += pt.y;
return total;
},
new Point2D(0, 0),
);
}
}
module.exports = Point2D;