UNPKG

@nekobird/vector2

Version:
1,059 lines (962 loc) 26.2 kB
function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function (obj) { return typeof obj; }; } else { _typeof = function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } } function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); } function isPointLike(point) { return _typeof(point) === 'object' && typeof point.x === 'number' && typeof point.y === 'number'; } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } function _toConsumableArray$1(arr) { return _arrayWithoutHoles$1(arr) || _iterableToArray$1(arr) || _nonIterableSpread$1(); } function _arrayWithoutHoles$1(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _iterableToArray$1(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); } function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _nonIterableSpread$1() { throw new TypeError("Invalid attempt to spread non-iterable instance"); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } function isNumber(value) { return typeof value === 'number' && !isNaN(value); } function clamp(value, a, b) { var range; if (isNumber(a) && isNumber(b)) { range = orderRangeArray([a, b]); } else if (isNumberOrRange(a) && typeof b === 'undefined') { range = getRangeFromNumberOrRange(a); } else { return value; } var _orderRangeArray = orderRangeArray(range), _orderRangeArray2 = _slicedToArray(_orderRangeArray, 2), min = _orderRangeArray2[0], max = _orderRangeArray2[1]; return Math.max(min, Math.min(value, max)); } function cubicBezier(t, p1, cp1, cp2, p2) { return Math.pow(1 - t, 3) * p1 + 3 * t * Math.pow(1 - t, 2) * cp1 + 3 * t * t * (1 - t) * cp2 + t * t * t * p2; } function cycleNumber(value, range) { var _range = getRangeFromNumberOrRange(range); var _orderRangeArray3 = orderRangeArray(_range), _orderRangeArray4 = _slicedToArray(_orderRangeArray3, 2), min = _orderRangeArray4[0], max = _orderRangeArray4[1]; if (min === 0 && max === 0) { return 0; } var da = getEuclideanDistance(min, max); if (value > max) { var db = getEuclideanDistance(value, max); var c = db % da + min; return c === min ? max : c; } else if (value < min) { var _db = getEuclideanDistance(value, min); var _c = max - _db % da; return _c === max ? min : _c; } return value; } function getEuclideanDistance(a, b) { return a === b ? 0 : Math.sqrt(Math.abs((a - b) * (b - a))); } function hypotenuse(x, y) { if (Math.hypot) { return Math.hypot(x, y); } var max = Math.max(Math.abs(x), Math.abs(y)); if (max === 0) { max = 1; } var min = Math.min(Math.abs(x), Math.abs(y)); var n = min / max; return max * Math.sqrt(1 + n * n); } function transform(value, from, to) { var clampResult = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; var _from = getRangeFromNumberOrRange(from); var _to = getRangeFromNumberOrRange(to); var result = (value - _from[0]) * ((_to[1] - _to[0]) / (_from[1] - _from[0])) + _to[0]; if (clampResult) { return clamp(result, _to); } return result; } function getRangeFromNumberOrRange(range) { return isNumber(range) ? [0, range] : [range[0], range[1]]; } function isNumberOrRange(thing) { return isNumber(thing) || isRangeArray(thing); } function isRangeArray(thing) { return Array.isArray(thing) && thing.length === 2 && thing.every(isNumber); } function orderRangeArray(range) { return [Math.min.apply(Math, _toConsumableArray$1(range)), Math.max.apply(Math, _toConsumableArray$1(range))]; } function toDegrees(radians) { return radians * (180 / Math.PI); } function toRadians(degrees) { return degrees * (Math.PI / 180); } function deltaClockwise(from, to) { var direction = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; var sign = 1; var range = from - Math.PI; if (range < 0) { var offset = cycleNumber(range, Math.PI * 2); if (to < from || to >= offset) { sign = -1; } } else if (to < from && to >= range) { sign = -1; } if (direction === false) { sign = 1; } var result = 0; if (from > to) { result = from - to; } else if (to > from) { result = to - from; } return result * sign; } function deltaCounterclockwise(from, to) { var direction = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; var sign = 1; var range = from + Math.PI; if (range > Math.PI * 2) { var offset = cycleNumber(range, Math.PI * 2); if (to > from || to <= offset) { sign = -1; } } else if (to > from && to <= range) { sign = -1; } if (direction === false) { sign = 1; } var result = 0; if (from > to) { result = from - to; } else if (to > from) { result = to - from; } return result * sign; } function differenceClockwise(from, to) { var result = 0; if (from > to) { result = Math.PI * 2 - from + to; } else if (to > from) { result = to - from; } return result; } function differenceCounterclockwise(from, to) { var result = 0; if (from > to) { result = from - to; } else if (to > from) { result = from + Math.PI * 2 - to; } return result; } var Vector2 = /*#__PURE__*/ function () { function Vector2(a, b) { _classCallCheck(this, Vector2); this.x = 0; this.y = 0; if (isNumber(a) && isNumber(b)) { this.x = a; this.y = b; } else if (isNumber(a) && !isNumber(b)) { this.x = a; this.y = a; } else if (isPointLike(a)) { this.x = a.x; this.y = a.y; } return this; } _createClass(Vector2, [{ key: "equals", value: function equals(a, b) { if (isNumber(a) && isNumber(b)) { this.x = a; this.y = b; } else if (isNumber(a) && !isNumber(b)) { this.x = a; this.y = a; } else if (isPointLike(a)) { this.x = a.x; this.y = a.y; } return this; } }, { key: "isEqual", value: function isEqual() { var _this = this; for (var _len = arguments.length, v = new Array(_len), _key = 0; _key < _len; _key++) { v[_key] = arguments[_key]; } return v.every(function (p) { return _this.x === p.x && _this.y === p.y; }); } }, { key: "negative", value: function negative() { this.x = -this.x; this.y = -this.y; return this; } }, { key: "absolute", value: function absolute() { this.x = Math.abs(this.x); this.y = Math.abs(this.y); return this; } }, { key: "clamp", value: function clamp$1(by) { this.x = clamp(this.x, by); this.y = clamp(this.y, by); return this; } }, { key: "limit", value: function limit(by) { if (this.magnitude > by) { this.normalize().multiply(by); } return this; } }, { key: "normalize", value: function normalize() { var magnitude = Math.abs(this.magnitude); if (magnitude === 0) { magnitude = 1; } this.x /= magnitude; this.y /= magnitude; return this; } }, { key: "dot", value: function dot(point) { return this.x * point.x + this.y * point.y; } }, { key: "round", value: function round() { var to = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; this.x = parseFloat(this.x.toFixed(to)); this.y = parseFloat(this.y.toFixed(to)); return this; } }, { key: "zero", value: function zero() { this.x = this.y = 0; return this; } }, { key: "clone", value: function clone() { return Vector2.clone(this); } }, { key: "add", value: function add(a, b) { if (isPointLike(a)) { this.x += a.x; this.y += a.y; } else if (isNumber(a) && isNumber(b)) { this.x += a; this.y += b; } else if (isNumber(a) && !isNumber(b)) { this.x += a; this.y += a; } return this; } }, { key: "addX", value: function addX(a) { if (isNumber(a)) { this.x += a; } else if (_typeof(a) === 'object' && isNumber(a.x)) { this.x += a.x; } return this; } }, { key: "addY", value: function addY(a) { if (isNumber(a)) { this.y += a; } else if (_typeof(a) === 'object' && isNumber(a.y)) { this.y += a.y; } return this; } }, { key: "subtract", value: function subtract(a, b) { if (isPointLike(a)) { this.x -= a.x; this.y -= a.y; } else if (isNumber(a) && !isNumber(b)) { this.x -= a; this.y -= a; } else if (isNumber(a) && isNumber(b)) { this.x -= a; this.y -= b; } return this; } }, { key: "subtractX", value: function subtractX(a) { if (isNumber(a)) { this.x -= a; } else if (_typeof(a) === 'object' && !isNumber(a.x)) { this.x -= a.x; } return this; } }, { key: "subtractY", value: function subtractY(a) { if (isNumber(a)) { this.y -= a; } else if (_typeof(a) === 'object' && !isNumber(a.y)) { this.y -= a.y; } return this; } }, { key: "multiply", value: function multiply(a, b) { if (isPointLike(a)) { this.x *= a.x; this.y *= a.y; } else if (isNumber(a) && !isNumber(b)) { this.x *= a; this.y *= a; } else if (isNumber(a) && isNumber(b)) { this.x *= a; this.y *= b; } return this; } }, { key: "multiplyX", value: function multiplyX(a) { if (isNumber(a)) { this.x *= a; } else if (isPointLike(a)) { this.x *= a.x; } return this; } }, { key: "multiplyY", value: function multiplyY(a) { if (isNumber(a)) { this.y *= a; } else if (isPointLike(a)) { this.y *= a.y; } return this; } }, { key: "divide", value: function divide(a, b) { if (isNumber(a) && !isNumber(b)) { if (a === 0) { throw new Error('Vector2: Division by zero.'); } else { this.x /= a; this.y /= a; } } else if (isNumber(a) && isNumber(b)) { if (a === 0 || b === 0) { throw new Error('Vector2: Division by zero.'); } else { this.x /= a; this.y /= b; } } else if (isPointLike(a)) { if (a.x === 0 || a.y === 0) { throw new Error('Vector2: Division by zero.'); } else { this.x /= a.x; this.y /= a.y; } } return this; } }, { key: "divideX", value: function divideX(a) { if (isNumber(a)) { if (a === 0) { throw new Error('Vector2: Division by zero.'); } else { this.x /= a; } } else if (isPointLike(a)) { if (a.x === 0) { throw new Error('Vector2: Division by zero.'); } else { this.x /= a.x; } } return this; } }, { key: "divideY", value: function divideY(a) { if (isNumber(a)) { if (a === 0) { throw new Error('Vector2: Division by zero.'); } else { this.y /= a; } } else if (isPointLike(a)) { if (a.y === 0) { throw new Error('Vector2: Division by zero.'); } else { this.y /= a.y; } } return this; } }, { key: "getDistanceTo", value: function getDistanceTo(to) { return Vector2.subtract(this, to).magnitude; } }, { key: "getAngleFrom", value: function getAngleFrom(from) { var x = this.x - from.x; var y = this.y - from.y; var m = hypotenuse(x, y); var angle = Math.acos(x / m); return y < 0 ? Math.PI + (Math.PI - angle) : angle; } }, { key: "getAngleTo", value: function getAngleTo(to) { var x = to.x - this.x; var y = to.y - this.y; var m = hypotenuse(x, y); var angle = Math.acos(x / m); return y < 0 ? Math.PI + (Math.PI - angle) : angle; } }, { key: "moveBy", value: function moveBy(a, b) { if (isNumber(a) && isNumber(b)) { this.x += a; this.y += b; } else if (isPointLike(a)) { this.add(a); } return this; } }, { key: "moveTo", value: function moveTo(a, b) { if (isNumber(a) && isNumber(b)) { this.x = a; this.y = b; } else if (isPointLike(a)) { this.equals(a); } return this; } }, { key: "polarTranslate", value: function polarTranslate(angle, length) { angle = cycleNumber(angle, Math.PI * 2); this.x += Math.cos(angle) * length; this.y += Math.sin(angle) * length; return this; } }, { key: "polarTranslateBy", value: function polarTranslateBy(by, length) { var angle = cycleNumber(this.angle + by, Math.PI * 2); this.x += Math.cos(angle) * length; this.y += Math.sin(angle) * length; return this; } }, { key: "moveRadiallyBy", value: function moveRadiallyBy(angle, by) { angle = cycleNumber(angle, Math.PI * 2); this.x += Math.cos(angle) * by; this.y += Math.sin(angle) * by; return this; } }, { key: "moveRadiallyTo", value: function moveRadiallyTo(angle, to) { angle = cycleNumber(angle, Math.PI * 2); this.x = Math.cos(angle) * to; this.y = Math.sin(angle) * to; return this; } }, { key: "rotateBy", value: function rotateBy(by) { var angle = this.angle + by; this.x = Math.cos(angle) * this.magnitude; this.y = Math.sin(angle) * this.magnitude; return this; } }, { key: "rotateTo", value: function rotateTo(angle) { angle = cycleNumber(angle, Math.PI * 2); this.x = Math.cos(angle) * this.magnitude; this.y = Math.sin(angle) * this.magnitude; return this; } }, { key: "rotateByFrom", value: function rotateByFrom(by, from) { by = cycleNumber(by, Math.PI * 2); var x = this.x - from.x; var y = this.y - from.y; var m = hypotenuse(x, y); var a = Math.acos(x / m); if (y < 0) { a = Math.PI + (Math.PI - a); } var angle = cycleNumber(a + by, Math.PI * 2); this.x = from.x + Math.cos(angle) * m; this.y = from.y + Math.sin(angle) * m; return this; } }, { key: "rotateToFrom", value: function rotateToFrom(to, from) { to = cycleNumber(to, Math.PI * 2); var x = this.x - from.x; var y = this.y - from.y; var m = hypotenuse(x, y); this.x = from.x + Math.cos(to) * m; this.y = from.y + Math.sin(to) * m; return this; } }, { key: "scaleBy", value: function scaleBy(by) { var magnitude = this.magnitude; if (magnitude === 0) { magnitude = 1; } this.x /= magnitude; this.y /= magnitude; this.x *= by; this.y *= by; return this; } }, { key: "scaleByFrom", value: function scaleByFrom(by, from) { var difference = Vector2.subtract(this, from); var magnitude = difference.magnitude; difference.normalize().multiply(magnitude * by).add(from); this.equals(difference); return this; } }, { key: "applyLerp", value: function applyLerp(t, point) { this.x = transform(t, 1, [this.x, point.x], false); this.y = transform(t, 1, [this.y, point.y], false); return this; } }, { key: "applyCubicBezier", value: function applyCubicBezier(t, p1, cp1, cp2, p2) { this.x = cubicBezier(t, p1.x, cp1.x, cp2.x, p2.x); this.y = cubicBezier(t, p1.y, cp1.y, cp2.y, p2.y); return this; } }, { key: "magnitude", get: function get() { return hypotenuse(this.x, this.y); }, set: function set(magnitude) { this.normalize().multiply(magnitude); } }, { key: "isZero", get: function get() { return this.x === 0 && this.y === 0; } }, { key: "array", get: function get() { return [this.x, this.y]; } }, { key: "string", get: function get() { return "x: ".concat(this.x, ", y: ").concat(this.y); } }, { key: "average", get: function get() { return (Math.abs(this.x) + Math.abs(this.y)) / 2; } }, { key: "angle", get: function get() { var angle = Math.acos(this.x / this.magnitude); return this.y < 0 ? Math.PI + (Math.PI - angle) : angle; } }], [{ key: "clone", value: function clone(point) { return new Vector2(point.x, point.y); } }, { key: "unit", value: function unit(v) { return Vector2.clone(v).normalize(); } }, { key: "add", value: function add(a, b) { return Vector2.clone(a).add(b); } }, { key: "subtract", value: function subtract(a, b) { return Vector2.clone(a).subtract(b); } }, { key: "multiply", value: function multiply(v, n) { return Vector2.clone(v).multiply(n); } }, { key: "divide", value: function divide(v, n) { return Vector2.clone(v).divide(n); } }, { key: "projectFrom", value: function projectFrom(from, direction, by) { var to = Vector2.clone(direction).normalize().multiply(by); return Vector2.add(from, to); } }, { key: "splitAtAngle", value: function splitAtAngle(target, angle, by) { var results = []; results[0] = Vector2.clone(target).moveRadiallyBy(angle, -by); results[1] = Vector2.clone(target).moveRadiallyBy(angle, by); return results; } }, { key: "getMidPointBetween", value: function getMidPointBetween(a, b) { var x = a.x - b.x; var y = a.y - b.y; x /= 2; y /= 2; x += b.x; y += b.y; return new Vector2(x, y); } }, { key: "getDistanceBetween", value: function getDistanceBetween(a, b) { return Vector2.subtract(a, b).magnitude; } }, { key: "getLengthBetween", value: function getLengthBetween(a, b) { return Vector2.subtract(a, b).magnitude; } }, { key: "scaleByFrom", value: function scaleByFrom(vector, to, from) { return Vector2.clone(vector).scaleByFrom(to, from); } }, { key: "getDisplacement", value: function getDisplacement(from, to) { return Vector2.subtract(to, from); } }, { key: "getDirection", value: function getDirection(from, to) { return Vector2.subtract(to, from).normalize(); } }, { key: "perpendicular", value: function perpendicular(from) { return from.clone().rotateBy(Math.PI / 2); } }, { key: "angleIsInProximity", value: function angleIsInProximity(a, b, tolerance) { var d1 = differenceClockwise(a, b); var d2 = differenceCounterclockwise(a, b); var d = Math.min(d1, d2); return d <= tolerance; } }, { key: "getAngleBetween2Points", value: function getAngleBetween2Points(a, b) { var a1 = Vector2.clone(a).angle; var a2 = Vector2.clone(b).angle; var b1 = differenceClockwise(a1, a2); var b2 = differenceCounterclockwise(a1, a2); return Math.min(b1, b2); } }, { key: "getAngleBetween3Points", value: function getAngleBetween3Points(a, b, c) { var va = Vector2.clone(a); var vb = Vector2.clone(b); var vc = Vector2.clone(c); var a1 = vb.getAngleTo(va); var a2 = vb.getAngleTo(vc); var b1 = differenceClockwise(a1, a2); var b2 = differenceCounterclockwise(a1, a2); return Math.min(b1, b2); } }, { key: "getBasePointOfTriangle", value: function getBasePointOfTriangle(v1, v2, v3) { var a1 = v1.getAngleTo(v3); var a2 = v1.getAngleTo(v2); var a = Math.abs(a1 - a2); var h = v1.getDistanceTo(v2); var bh = Math.sin(a) * h; var ml = Math.atan(a) / bh; var fv = Vector2.clone(v1); return fv.moveRadiallyBy(a1, ml); } }, { key: "getCenterVector", value: function getCenterVector() { var left = this.minX.apply(this, arguments); var right = this.maxX.apply(this, arguments); var top = this.minY.apply(this, arguments); var bottom = this.maxY.apply(this, arguments); return new Vector2(left + (right - left) / 2, top + (bottom - top) / 2); } }, { key: "one", value: function one() { return new Vector2(1, 1); } }, { key: "up", value: function up() { return new Vector2(0, -1); } }, { key: "down", value: function down() { return new Vector2(0, 1); } }, { key: "left", value: function left() { return new Vector2(-1, 0); } }, { key: "right", value: function right() { return new Vector2(0, 1); } }, { key: "min", value: function min() { for (var _len2 = arguments.length, v = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { v[_key2] = arguments[_key2]; } var magnitudes = v.map(function (vector) { return vector.magnitude; }); var index = magnitudes.indexOf(Math.min.apply(Math, _toConsumableArray(magnitudes))); return v[index]; } }, { key: "max", value: function max() { for (var _len3 = arguments.length, v = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { v[_key3] = arguments[_key3]; } var magnitudes = v.map(function (vector) { return vector.magnitude; }); var index = magnitudes.indexOf(Math.max.apply(Math, _toConsumableArray(magnitudes))); return v[index]; } }, { key: "minX", value: function minX() { for (var _len4 = arguments.length, p = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { p[_key4] = arguments[_key4]; } var x = p.map(function (point) { return point.x; }); var i = x.indexOf(Math.min.apply(Math, _toConsumableArray(x))); return x[i]; } }, { key: "minY", value: function minY() { for (var _len5 = arguments.length, p = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) { p[_key5] = arguments[_key5]; } var y = p.map(function (point) { return point.y; }); var i = y.indexOf(Math.min.apply(Math, _toConsumableArray(y))); return y[i]; } }, { key: "maxX", value: function maxX() { for (var _len6 = arguments.length, p = new Array(_len6), _key6 = 0; _key6 < _len6; _key6++) { p[_key6] = arguments[_key6]; } var x = p.map(function (point) { return point.x; }); var i = x.indexOf(Math.max.apply(Math, _toConsumableArray(x))); return x[i]; } }, { key: "maxY", value: function maxY() { for (var _len7 = arguments.length, p = new Array(_len7), _key7 = 0; _key7 < _len7; _key7++) { p[_key7] = arguments[_key7]; } var y = p.map(function (point) { return point.y; }); var i = y.indexOf(Math.max.apply(Math, _toConsumableArray(y))); return y[i]; } }, { key: "zero", get: function get() { return new Vector2(0, 0); } }, { key: "random", get: function get() { return new Vector2(Math.random(), Math.random()); } }]); return Vector2; }(); export { Vector2, deltaClockwise, deltaCounterclockwise, differenceClockwise, differenceCounterclockwise, isPointLike, toDegrees, toRadians }; //# sourceMappingURL=vector2.js.map