StackGenVis: Alignment of Data, Algorithms, and Models for Stacking Ensemble Learning Using Performance Metrics
https://doi.org/10.1109/TVCG.2020.3030352
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
312 lines
8.2 KiB
312 lines
8.2 KiB
'use strict';
|
|
|
|
module.exports = Point;
|
|
|
|
/**
|
|
* A standalone point geometry with useful accessor, comparison, and
|
|
* modification methods.
|
|
*
|
|
* @class Point
|
|
* @param {Number} x the x-coordinate. this could be longitude or screen
|
|
* pixels, or any other sort of unit.
|
|
* @param {Number} y the y-coordinate. this could be latitude or screen
|
|
* pixels, or any other sort of unit.
|
|
* @example
|
|
* var point = new Point(-77, 38);
|
|
*/
|
|
function Point(x, y) {
|
|
this.x = x;
|
|
this.y = y;
|
|
}
|
|
|
|
Point.prototype = {
|
|
|
|
/**
|
|
* Clone this point, returning a new point that can be modified
|
|
* without affecting the old one.
|
|
* @return {Point} the clone
|
|
*/
|
|
clone: function() { return new Point(this.x, this.y); },
|
|
|
|
/**
|
|
* Add this point's x & y coordinates to another point,
|
|
* yielding a new point.
|
|
* @param {Point} p the other point
|
|
* @return {Point} output point
|
|
*/
|
|
add: function(p) { return this.clone()._add(p); },
|
|
|
|
/**
|
|
* Subtract this point's x & y coordinates to from point,
|
|
* yielding a new point.
|
|
* @param {Point} p the other point
|
|
* @return {Point} output point
|
|
*/
|
|
sub: function(p) { return this.clone()._sub(p); },
|
|
|
|
/**
|
|
* Multiply this point's x & y coordinates by point,
|
|
* yielding a new point.
|
|
* @param {Point} p the other point
|
|
* @return {Point} output point
|
|
*/
|
|
multByPoint: function(p) { return this.clone()._multByPoint(p); },
|
|
|
|
/**
|
|
* Divide this point's x & y coordinates by point,
|
|
* yielding a new point.
|
|
* @param {Point} p the other point
|
|
* @return {Point} output point
|
|
*/
|
|
divByPoint: function(p) { return this.clone()._divByPoint(p); },
|
|
|
|
/**
|
|
* Multiply this point's x & y coordinates by a factor,
|
|
* yielding a new point.
|
|
* @param {Point} k factor
|
|
* @return {Point} output point
|
|
*/
|
|
mult: function(k) { return this.clone()._mult(k); },
|
|
|
|
/**
|
|
* Divide this point's x & y coordinates by a factor,
|
|
* yielding a new point.
|
|
* @param {Point} k factor
|
|
* @return {Point} output point
|
|
*/
|
|
div: function(k) { return this.clone()._div(k); },
|
|
|
|
/**
|
|
* Rotate this point around the 0, 0 origin by an angle a,
|
|
* given in radians
|
|
* @param {Number} a angle to rotate around, in radians
|
|
* @return {Point} output point
|
|
*/
|
|
rotate: function(a) { return this.clone()._rotate(a); },
|
|
|
|
/**
|
|
* Rotate this point around p point by an angle a,
|
|
* given in radians
|
|
* @param {Number} a angle to rotate around, in radians
|
|
* @param {Point} p Point to rotate around
|
|
* @return {Point} output point
|
|
*/
|
|
rotateAround: function(a,p) { return this.clone()._rotateAround(a,p); },
|
|
|
|
/**
|
|
* Multiply this point by a 4x1 transformation matrix
|
|
* @param {Array<Number>} m transformation matrix
|
|
* @return {Point} output point
|
|
*/
|
|
matMult: function(m) { return this.clone()._matMult(m); },
|
|
|
|
/**
|
|
* Calculate this point but as a unit vector from 0, 0, meaning
|
|
* that the distance from the resulting point to the 0, 0
|
|
* coordinate will be equal to 1 and the angle from the resulting
|
|
* point to the 0, 0 coordinate will be the same as before.
|
|
* @return {Point} unit vector point
|
|
*/
|
|
unit: function() { return this.clone()._unit(); },
|
|
|
|
/**
|
|
* Compute a perpendicular point, where the new y coordinate
|
|
* is the old x coordinate and the new x coordinate is the old y
|
|
* coordinate multiplied by -1
|
|
* @return {Point} perpendicular point
|
|
*/
|
|
perp: function() { return this.clone()._perp(); },
|
|
|
|
/**
|
|
* Return a version of this point with the x & y coordinates
|
|
* rounded to integers.
|
|
* @return {Point} rounded point
|
|
*/
|
|
round: function() { return this.clone()._round(); },
|
|
|
|
/**
|
|
* Return the magitude of this point: this is the Euclidean
|
|
* distance from the 0, 0 coordinate to this point's x and y
|
|
* coordinates.
|
|
* @return {Number} magnitude
|
|
*/
|
|
mag: function() {
|
|
return Math.sqrt(this.x * this.x + this.y * this.y);
|
|
},
|
|
|
|
/**
|
|
* Judge whether this point is equal to another point, returning
|
|
* true or false.
|
|
* @param {Point} other the other point
|
|
* @return {boolean} whether the points are equal
|
|
*/
|
|
equals: function(other) {
|
|
return this.x === other.x &&
|
|
this.y === other.y;
|
|
},
|
|
|
|
/**
|
|
* Calculate the distance from this point to another point
|
|
* @param {Point} p the other point
|
|
* @return {Number} distance
|
|
*/
|
|
dist: function(p) {
|
|
return Math.sqrt(this.distSqr(p));
|
|
},
|
|
|
|
/**
|
|
* Calculate the distance from this point to another point,
|
|
* without the square root step. Useful if you're comparing
|
|
* relative distances.
|
|
* @param {Point} p the other point
|
|
* @return {Number} distance
|
|
*/
|
|
distSqr: function(p) {
|
|
var dx = p.x - this.x,
|
|
dy = p.y - this.y;
|
|
return dx * dx + dy * dy;
|
|
},
|
|
|
|
/**
|
|
* Get the angle from the 0, 0 coordinate to this point, in radians
|
|
* coordinates.
|
|
* @return {Number} angle
|
|
*/
|
|
angle: function() {
|
|
return Math.atan2(this.y, this.x);
|
|
},
|
|
|
|
/**
|
|
* Get the angle from this point to another point, in radians
|
|
* @param {Point} b the other point
|
|
* @return {Number} angle
|
|
*/
|
|
angleTo: function(b) {
|
|
return Math.atan2(this.y - b.y, this.x - b.x);
|
|
},
|
|
|
|
/**
|
|
* Get the angle between this point and another point, in radians
|
|
* @param {Point} b the other point
|
|
* @return {Number} angle
|
|
*/
|
|
angleWith: function(b) {
|
|
return this.angleWithSep(b.x, b.y);
|
|
},
|
|
|
|
/*
|
|
* Find the angle of the two vectors, solving the formula for
|
|
* the cross product a x b = |a||b|sin(θ) for θ.
|
|
* @param {Number} x the x-coordinate
|
|
* @param {Number} y the y-coordinate
|
|
* @return {Number} the angle in radians
|
|
*/
|
|
angleWithSep: function(x, y) {
|
|
return Math.atan2(
|
|
this.x * y - this.y * x,
|
|
this.x * x + this.y * y);
|
|
},
|
|
|
|
_matMult: function(m) {
|
|
var x = m[0] * this.x + m[1] * this.y,
|
|
y = m[2] * this.x + m[3] * this.y;
|
|
this.x = x;
|
|
this.y = y;
|
|
return this;
|
|
},
|
|
|
|
_add: function(p) {
|
|
this.x += p.x;
|
|
this.y += p.y;
|
|
return this;
|
|
},
|
|
|
|
_sub: function(p) {
|
|
this.x -= p.x;
|
|
this.y -= p.y;
|
|
return this;
|
|
},
|
|
|
|
_mult: function(k) {
|
|
this.x *= k;
|
|
this.y *= k;
|
|
return this;
|
|
},
|
|
|
|
_div: function(k) {
|
|
this.x /= k;
|
|
this.y /= k;
|
|
return this;
|
|
},
|
|
|
|
_multByPoint: function(p) {
|
|
this.x *= p.x;
|
|
this.y *= p.y;
|
|
return this;
|
|
},
|
|
|
|
_divByPoint: function(p) {
|
|
this.x /= p.x;
|
|
this.y /= p.y;
|
|
return this;
|
|
},
|
|
|
|
_unit: function() {
|
|
this._div(this.mag());
|
|
return this;
|
|
},
|
|
|
|
_perp: function() {
|
|
var y = this.y;
|
|
this.y = this.x;
|
|
this.x = -y;
|
|
return this;
|
|
},
|
|
|
|
_rotate: function(angle) {
|
|
var cos = Math.cos(angle),
|
|
sin = Math.sin(angle),
|
|
x = cos * this.x - sin * this.y,
|
|
y = sin * this.x + cos * this.y;
|
|
this.x = x;
|
|
this.y = y;
|
|
return this;
|
|
},
|
|
|
|
_rotateAround: function(angle, p) {
|
|
var cos = Math.cos(angle),
|
|
sin = Math.sin(angle),
|
|
x = p.x + cos * (this.x - p.x) - sin * (this.y - p.y),
|
|
y = p.y + sin * (this.x - p.x) + cos * (this.y - p.y);
|
|
this.x = x;
|
|
this.y = y;
|
|
return this;
|
|
},
|
|
|
|
_round: function() {
|
|
this.x = Math.round(this.x);
|
|
this.y = Math.round(this.y);
|
|
return this;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Construct a point from an array if necessary, otherwise if the input
|
|
* is already a Point, or an unknown type, return it unchanged
|
|
* @param {Array<Number>|Point|*} a any kind of input value
|
|
* @return {Point} constructed point, or passed-through value.
|
|
* @example
|
|
* // this
|
|
* var point = Point.convert([0, 1]);
|
|
* // is equivalent to
|
|
* var point = new Point(0, 1);
|
|
*/
|
|
Point.convert = function (a) {
|
|
if (a instanceof Point) {
|
|
return a;
|
|
}
|
|
if (Array.isArray(a)) {
|
|
return new Point(a[0], a[1]);
|
|
}
|
|
return a;
|
|
};
|
|
|