react-force-graph-ar
Version:
React component for AR force directed graphs
992 lines (981 loc) • 815 kB
JavaScript
// Version 1.9.0 react-force-graph-ar - https://github.com/vasturiano/react-force-graph
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('react')) :
typeof define === 'function' && define.amd ? define(['react'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.ForceGraphAR = factory(global.React));
})(this, (function (React) { 'use strict';
function _iterableToArrayLimit$5(arr, i) {
var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"];
if (null != _i) {
var _s,
_e,
_x,
_r,
_arr = [],
_n = true,
_d = false;
try {
if (_x = (_i = _i.call(arr)).next, 0 === i) {
if (Object(_i) !== _i) return;
_n = !1;
} else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0);
} catch (err) {
_d = true, _e = err;
} finally {
try {
if (!_n && null != _i.return && (_r = _i.return(), Object(_r) !== _r)) return;
} finally {
if (_d) throw _e;
}
}
return _arr;
}
}
function _defineProperty$2(obj, key, value) {
key = _toPropertyKey$3(key);
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function _slicedToArray$5(arr, i) {
return _arrayWithHoles$5(arr) || _iterableToArrayLimit$5(arr, i) || _unsupportedIterableToArray$5(arr, i) || _nonIterableRest$5();
}
function _toConsumableArray$4(arr) {
return _arrayWithoutHoles$4(arr) || _iterableToArray$4(arr) || _unsupportedIterableToArray$5(arr) || _nonIterableSpread$4();
}
function _arrayWithoutHoles$4(arr) {
if (Array.isArray(arr)) return _arrayLikeToArray$5(arr);
}
function _arrayWithHoles$5(arr) {
if (Array.isArray(arr)) return arr;
}
function _iterableToArray$4(iter) {
if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
}
function _unsupportedIterableToArray$5(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray$5(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$5(o, minLen);
}
function _arrayLikeToArray$5(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
return arr2;
}
function _nonIterableSpread$4() {
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _nonIterableRest$5() {
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _toPrimitive$3(input, hint) {
if (typeof input !== "object" || input === null) return input;
var prim = input[Symbol.toPrimitive];
if (prim !== undefined) {
var res = prim.call(input, hint);
if (typeof res !== "object") return res;
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return (hint === "string" ? String : Number)(input);
}
function _toPropertyKey$3(arg) {
var key = _toPrimitive$3(arg, "string");
return typeof key === "symbol" ? key : String(key);
}
var omit = function omit(obj, keys) {
var keySet = new Set(keys);
return Object.assign.apply(Object, [{}].concat(_toConsumableArray$4(Object.entries(obj).filter(function (_ref2) {
var _ref3 = _slicedToArray$5(_ref2, 1),
key = _ref3[0];
return !keySet.has(key);
}).map(function (_ref4) {
var _ref5 = _slicedToArray$5(_ref4, 2),
key = _ref5[0],
val = _ref5[1];
return _defineProperty$2({}, key, val);
}))));
};
function _arrayLikeToArray$4(r, a) {
(null == a || a > r.length) && (a = r.length);
for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
return n;
}
function _arrayWithHoles$4(r) {
if (Array.isArray(r)) return r;
}
function _arrayWithoutHoles$3(r) {
if (Array.isArray(r)) return _arrayLikeToArray$4(r);
}
function _iterableToArray$3(r) {
if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r);
}
function _iterableToArrayLimit$4(r, l) {
var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
if (null != t) {
var e,
n,
i,
u,
a = [],
f = true,
o = false;
try {
if (i = (t = t.call(r)).next, 0 === l) ; else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
} catch (r) {
o = true, n = r;
} finally {
try {
if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
} finally {
if (o) throw n;
}
}
return a;
}
}
function _nonIterableRest$4() {
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _nonIterableSpread$3() {
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _slicedToArray$4(r, e) {
return _arrayWithHoles$4(r) || _iterableToArrayLimit$4(r, e) || _unsupportedIterableToArray$4(r, e) || _nonIterableRest$4();
}
function _toConsumableArray$3(r) {
return _arrayWithoutHoles$3(r) || _iterableToArray$3(r) || _unsupportedIterableToArray$4(r) || _nonIterableSpread$3();
}
function _unsupportedIterableToArray$4(r, a) {
if (r) {
if ("string" == typeof r) return _arrayLikeToArray$4(r, a);
var t = {}.toString.call(r).slice(8, -1);
return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray$4(r, a) : void 0;
}
}
function index$3 (kapsuleComponent) {
var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
_ref$wrapperElementTy = _ref.wrapperElementType,
wrapperElementType = _ref$wrapperElementTy === void 0 ? 'div' : _ref$wrapperElementTy,
_ref$nodeMapper = _ref.nodeMapper,
nodeMapper = _ref$nodeMapper === void 0 ? function (node) {
return node;
} : _ref$nodeMapper,
_ref$methodNames = _ref.methodNames,
methodNames = _ref$methodNames === void 0 ? [] : _ref$methodNames,
_ref$initPropNames = _ref.initPropNames,
initPropNames = _ref$initPropNames === void 0 ? [] : _ref$initPropNames;
return /*#__PURE__*/React.forwardRef(function (props, ref) {
var domEl = React.useRef();
// instantiate the inner kapsule component with the defined initPropNames
var comp = React.useMemo(function () {
var configOptions = Object.fromEntries(initPropNames.filter(function (p) {
return props.hasOwnProperty(p);
}).map(function (prop) {
return [prop, props[prop]];
}));
return kapsuleComponent(configOptions);
}, []);
useEffectOnce(function () {
comp(nodeMapper(domEl.current)); // mount kapsule synchronously on this element ref, optionally mapped into an object that the kapsule understands
}, React.useLayoutEffect);
useEffectOnce(function () {
// invoke destructor on unmount, if it exists
return comp._destructor instanceof Function ? comp._destructor : undefined;
});
// Call a component method
var _call = React.useCallback(function (method) {
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
return comp[method] instanceof Function ? comp[method].apply(comp, args) : undefined;
} // method not found
, [comp]);
// propagate component props that have changed
var prevPropsRef = React.useRef({});
Object.keys(omit(props, [].concat(_toConsumableArray$3(methodNames), _toConsumableArray$3(initPropNames)))) // initPropNames or methodNames should not be called
.filter(function (p) {
return prevPropsRef.current[p] !== props[p];
}).forEach(function (p) {
return _call(p, props[p]);
});
prevPropsRef.current = props;
// bind external methods to parent ref
React.useImperativeHandle(ref, function () {
return Object.fromEntries(methodNames.map(function (method) {
return [method, function () {
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
}
return _call.apply(void 0, [method].concat(args));
}];
}));
}, [_call]);
return /*#__PURE__*/React.createElement(wrapperElementType, {
ref: domEl
});
});
}
//
// Handle R18 strict mode double mount at init
function useEffectOnce(effect) {
var useEffectFn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : React.useEffect;
var destroyFunc = React.useRef();
var effectCalled = React.useRef(false);
var renderAfterCalled = React.useRef(false);
var _useState = React.useState(0),
_useState2 = _slicedToArray$4(_useState, 2);
_useState2[0];
var setVal = _useState2[1];
if (effectCalled.current) {
renderAfterCalled.current = true;
}
useEffectFn(function () {
// only execute the effect first time around
if (!effectCalled.current) {
destroyFunc.current = effect();
effectCalled.current = true;
}
// this forces one render after the effect is run
setVal(function (val) {
return val + 1;
});
return function () {
// if the comp didn't render since the useEffect was called,
// we know it's the dummy React cycle
if (!renderAfterCalled.current) return;
if (destroyFunc.current) destroyFunc.current();
};
}, []);
}
/**
* @license
* Copyright 2010-2025 Three.js Authors
* SPDX-License-Identifier: MIT
*/const REVISION='178';/**
* Only front faces are rendered.
*
* @type {number}
* @constant
*/const FrontSide=0;/**
* Only back faces are rendered.
*
* @type {number}
* @constant
*/const BackSide=1;/**
* The default blending.
*
* @type {number}
* @constant
*/const NormalBlending=1;/**
* A `source + destination` blending equation.
*
* @type {number}
* @constant
*/const AddEquation=100;/**
* Multiplies all colors by the source alpha value.
*
* @type {number}
* @constant
*/const SrcAlphaFactor=204;/**
* Multiplies all colors by 1 minus the source alpha value.
*
* @type {number}
* @constant
*/const OneMinusSrcAlphaFactor=205;/**
* Pass if the incoming value is less than or equal to the depth buffer value.
*
* @type {number}
* @constant
*/const LessEqualDepth=3;/**
* Multiplies the environment map color with the surface color.
*
* @type {number}
* @constant
*/const MultiplyOperation=0;/**
* Maps textures using the geometry's UV coordinates.
*
* @type {number}
* @constant
*/const UVMapping=300;/**
* The texture will simply repeat to infinity.
*
* @type {number}
* @constant
*/const RepeatWrapping=1000;/**
* The last pixel of the texture stretches to the edge of the mesh.
*
* @type {number}
* @constant
*/const ClampToEdgeWrapping=1001;/**
* The texture will repeats to infinity, mirroring on each repeat.
*
* @type {number}
* @constant
*/const MirroredRepeatWrapping=1002;/**
* Returns the weighted average of the four texture elements that are closest to the specified
* texture coordinates, and can include items wrapped or repeated from other parts of a texture,
* depending on the values of `wrapS` and `wrapT`, and on the exact mapping.
*
* @type {number}
* @constant
*/const LinearFilter=1006;/**
* Chooses the two mipmaps that most closely match the size of the pixel being textured and uses
* the `LinearFilter` criterion to produce a texture value from each mipmap. The final texture value
* is a weighted average of those two values.
*
* @type {number}
* @constant
*/const LinearMipmapLinearFilter=1008;/**
* An unsigned byte data type for textures.
*
* @type {number}
* @constant
*/const UnsignedByteType=1009;/**
* A float data type for textures.
*
* @type {number}
* @constant
*/const FloatType=1015;/**
* Reads the red, green, blue and alpha components.
*
* @type {number}
* @constant
*/const RGBAFormat=1023;/**
* Normal information is relative to the underlying surface.
*
* @type {number}
* @constant
*/const TangentSpaceNormalMap=0;/**
* No color space.
*
* @type {string}
* @constant
*/const NoColorSpace='';/**
* sRGB color space.
*
* @type {string}
* @constant
*/const SRGBColorSpace='srgb';/**
* sRGB-linear color space.
*
* @type {string}
* @constant
*/const LinearSRGBColorSpace='srgb-linear';/**
* Linear transfer function.
*
* @type {string}
* @constant
*/const LinearTransfer='linear';/**
* sRGB transfer function.
*
* @type {string}
* @constant
*/const SRGBTransfer='srgb';/**
* Keeps the current value.
*
* @type {number}
* @constant
*/const KeepStencilOp=7680;/**
* Will always return true.
*
* @type {number}
* @constant
*/const AlwaysStencilFunc=519;/**
* The contents are intended to be specified once by the application, and used many
* times as the source for drawing and image specification commands.
*
* @type {number}
* @constant
*/const StaticDrawUsage=35044;/**
* WebGL coordinate system.
*
* @type {number}
* @constant
*/const WebGLCoordinateSystem=2000;/**
* WebGPU coordinate system.
*
* @type {number}
* @constant
*/const WebGPUCoordinateSystem=2001;/**
* This type represents mouse buttons and interaction types in context of controls.
*
* @typedef {Object} ConstantsMouse
* @property {number} MIDDLE - The left mouse button.
* @property {number} LEFT - The middle mouse button.
* @property {number} RIGHT - The right mouse button.
* @property {number} ROTATE - A rotate interaction.
* @property {number} DOLLY - A dolly interaction.
* @property {number} PAN - A pan interaction.
**//**
* This type represents touch interaction types in context of controls.
*
* @typedef {Object} ConstantsTouch
* @property {number} ROTATE - A rotate interaction.
* @property {number} PAN - A pan interaction.
* @property {number} DOLLY_PAN - The dolly-pan interaction.
* @property {number} DOLLY_ROTATE - A dolly-rotate interaction.
**//**
* This type represents the different timestamp query types.
*
* @typedef {Object} ConstantsTimestampQuery
* @property {string} COMPUTE - A `compute` timestamp query.
* @property {string} RENDER - A `render` timestamp query.
**//**
* Represents the different interpolation sampling types.
*
* @typedef {Object} ConstantsInterpolationSamplingType
* @property {string} PERSPECTIVE - Perspective-correct interpolation.
* @property {string} LINEAR - Linear interpolation.
* @property {string} FLAT - Flat interpolation.
*//**
* Represents the different interpolation sampling modes.
*
* @typedef {Object} ConstantsInterpolationSamplingMode
* @property {string} NORMAL - Normal sampling mode.
* @property {string} CENTROID - Centroid sampling mode.
* @property {string} SAMPLE - Sample-specific sampling mode.
* @property {string} FLAT_FIRST - Flat interpolation using the first vertex.
* @property {string} FLAT_EITHER - Flat interpolation using either vertex.
*//**
* This modules allows to dispatch event objects on custom JavaScript objects.
*
* Main repository: [eventdispatcher.js]{@link https://github.com/mrdoob/eventdispatcher.js/}
*
* Code Example:
* ```js
* class Car extends EventDispatcher {
* start() {
* this.dispatchEvent( { type: 'start', message: 'vroom vroom!' } );
* }
*};
*
* // Using events with the custom object
* const car = new Car();
* car.addEventListener( 'start', function ( event ) {
* alert( event.message );
* } );
*
* car.start();
* ```
*/class EventDispatcher{/**
* Adds the given event listener to the given event type.
*
* @param {string} type - The type of event to listen to.
* @param {Function} listener - The function that gets called when the event is fired.
*/addEventListener(type,listener){if(this._listeners===undefined)this._listeners={};const listeners=this._listeners;if(listeners[type]===undefined){listeners[type]=[];}if(listeners[type].indexOf(listener)===-1){listeners[type].push(listener);}}/**
* Returns `true` if the given event listener has been added to the given event type.
*
* @param {string} type - The type of event.
* @param {Function} listener - The listener to check.
* @return {boolean} Whether the given event listener has been added to the given event type.
*/hasEventListener(type,listener){const listeners=this._listeners;if(listeners===undefined)return false;return listeners[type]!==undefined&&listeners[type].indexOf(listener)!==-1;}/**
* Removes the given event listener from the given event type.
*
* @param {string} type - The type of event.
* @param {Function} listener - The listener to remove.
*/removeEventListener(type,listener){const listeners=this._listeners;if(listeners===undefined)return;const listenerArray=listeners[type];if(listenerArray!==undefined){const index=listenerArray.indexOf(listener);if(index!==-1){listenerArray.splice(index,1);}}}/**
* Dispatches an event object.
*
* @param {Object} event - The event that gets fired.
*/dispatchEvent(event){const listeners=this._listeners;if(listeners===undefined)return;const listenerArray=listeners[event.type];if(listenerArray!==undefined){event.target=this;// Make a copy, in case listeners are removed while iterating.
const array=listenerArray.slice(0);for(let i=0,l=array.length;i<l;i++){array[i].call(this,event);}event.target=null;}}}const _lut=['00','01','02','03','04','05','06','07','08','09','0a','0b','0c','0d','0e','0f','10','11','12','13','14','15','16','17','18','19','1a','1b','1c','1d','1e','1f','20','21','22','23','24','25','26','27','28','29','2a','2b','2c','2d','2e','2f','30','31','32','33','34','35','36','37','38','39','3a','3b','3c','3d','3e','3f','40','41','42','43','44','45','46','47','48','49','4a','4b','4c','4d','4e','4f','50','51','52','53','54','55','56','57','58','59','5a','5b','5c','5d','5e','5f','60','61','62','63','64','65','66','67','68','69','6a','6b','6c','6d','6e','6f','70','71','72','73','74','75','76','77','78','79','7a','7b','7c','7d','7e','7f','80','81','82','83','84','85','86','87','88','89','8a','8b','8c','8d','8e','8f','90','91','92','93','94','95','96','97','98','99','9a','9b','9c','9d','9e','9f','a0','a1','a2','a3','a4','a5','a6','a7','a8','a9','aa','ab','ac','ad','ae','af','b0','b1','b2','b3','b4','b5','b6','b7','b8','b9','ba','bb','bc','bd','be','bf','c0','c1','c2','c3','c4','c5','c6','c7','c8','c9','ca','cb','cc','cd','ce','cf','d0','d1','d2','d3','d4','d5','d6','d7','d8','d9','da','db','dc','dd','de','df','e0','e1','e2','e3','e4','e5','e6','e7','e8','e9','ea','eb','ec','ed','ee','ef','f0','f1','f2','f3','f4','f5','f6','f7','f8','f9','fa','fb','fc','fd','fe','ff'];/**
* Generate a [UUID]{@link https://en.wikipedia.org/wiki/Universally_unique_identifier}
* (universally unique identifier).
*
* @return {string} The UUID.
*/function generateUUID(){// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136
const d0=Math.random()*0xffffffff|0;const d1=Math.random()*0xffffffff|0;const d2=Math.random()*0xffffffff|0;const d3=Math.random()*0xffffffff|0;const uuid=_lut[d0&0xff]+_lut[d0>>8&0xff]+_lut[d0>>16&0xff]+_lut[d0>>24&0xff]+'-'+_lut[d1&0xff]+_lut[d1>>8&0xff]+'-'+_lut[d1>>16&0x0f|0x40]+_lut[d1>>24&0xff]+'-'+_lut[d2&0x3f|0x80]+_lut[d2>>8&0xff]+'-'+_lut[d2>>16&0xff]+_lut[d2>>24&0xff]+_lut[d3&0xff]+_lut[d3>>8&0xff]+_lut[d3>>16&0xff]+_lut[d3>>24&0xff];// .toLowerCase() here flattens concatenated strings to save heap memory space.
return uuid.toLowerCase();}/**
* Clamps the given value between min and max.
*
* @param {number} value - The value to clamp.
* @param {number} min - The min value.
* @param {number} max - The max value.
* @return {number} The clamped value.
*/function clamp(value,min,max){return Math.max(min,Math.min(max,value));}/**
* Computes the Euclidean modulo of the given parameters that
* is `( ( n % m ) + m ) % m`.
*
* @param {number} n - The first parameter.
* @param {number} m - The second parameter.
* @return {number} The Euclidean modulo.
*/function euclideanModulo(n,m){// https://en.wikipedia.org/wiki/Modulo_operation
return (n%m+m)%m;}/**
* Returns a value linearly interpolated from two known points based on the given interval -
* `t = 0` will return `x` and `t = 1` will return `y`.
*
* @param {number} x - The start point
* @param {number} y - The end point.
* @param {number} t - The interpolation factor in the closed interval `[0, 1]`.
* @return {number} The interpolated value.
*/function lerp(x,y,t){return (1-t)*x+t*y;}/**
* Denormalizes the given value according to the given typed array.
*
* @param {number} value - The value to denormalize.
* @param {TypedArray} array - The typed array that defines the data type of the value.
* @return {number} The denormalize (float) value in the range `[0,1]`.
*/function denormalize(value,array){switch(array.constructor){case Float32Array:return value;case Uint32Array:return value/4294967295.0;case Uint16Array:return value/65535.0;case Uint8Array:return value/255.0;case Int32Array:return Math.max(value/2147483647.0,-1);case Int16Array:return Math.max(value/32767.0,-1);case Int8Array:return Math.max(value/127.0,-1);default:throw new Error('Invalid component type.');}}/**
* Normalizes the given value according to the given typed array.
*
* @param {number} value - The float value in the range `[0,1]` to normalize.
* @param {TypedArray} array - The typed array that defines the data type of the value.
* @return {number} The normalize value.
*/function normalize(value,array){switch(array.constructor){case Float32Array:return value;case Uint32Array:return Math.round(value*4294967295.0);case Uint16Array:return Math.round(value*65535.0);case Uint8Array:return Math.round(value*255.0);case Int32Array:return Math.round(value*2147483647.0);case Int16Array:return Math.round(value*32767.0);case Int8Array:return Math.round(value*127.0);default:throw new Error('Invalid component type.');}}/**
* Class representing a 2D vector. A 2D vector is an ordered pair of numbers
* (labeled x and y), which can be used to represent a number of things, such as:
*
* - A point in 2D space (i.e. a position on a plane).
* - A direction and length across a plane. In three.js the length will
* always be the Euclidean distance(straight-line distance) from `(0, 0)` to `(x, y)`
* and the direction is also measured from `(0, 0)` towards `(x, y)`.
* - Any arbitrary ordered pair of numbers.
*
* There are other things a 2D vector can be used to represent, such as
* momentum vectors, complex numbers and so on, however these are the most
* common uses in three.js.
*
* Iterating through a vector instance will yield its components `(x, y)` in
* the corresponding order.
* ```js
* const a = new THREE.Vector2( 0, 1 );
*
* //no arguments; will be initialised to (0, 0)
* const b = new THREE.Vector2( );
*
* const d = a.distanceTo( b );
* ```
*/class Vector2{/**
* Constructs a new 2D vector.
*
* @param {number} [x=0] - The x value of this vector.
* @param {number} [y=0] - The y value of this vector.
*/constructor(x=0,y=0){/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/Vector2.prototype.isVector2=true;/**
* The x value of this vector.
*
* @type {number}
*/this.x=x;/**
* The y value of this vector.
*
* @type {number}
*/this.y=y;}/**
* Alias for {@link Vector2#x}.
*
* @type {number}
*/get width(){return this.x;}set width(value){this.x=value;}/**
* Alias for {@link Vector2#y}.
*
* @type {number}
*/get height(){return this.y;}set height(value){this.y=value;}/**
* Sets the vector components.
*
* @param {number} x - The value of the x component.
* @param {number} y - The value of the y component.
* @return {Vector2} A reference to this vector.
*/set(x,y){this.x=x;this.y=y;return this;}/**
* Sets the vector components to the same value.
*
* @param {number} scalar - The value to set for all vector components.
* @return {Vector2} A reference to this vector.
*/setScalar(scalar){this.x=scalar;this.y=scalar;return this;}/**
* Sets the vector's x component to the given value
*
* @param {number} x - The value to set.
* @return {Vector2} A reference to this vector.
*/setX(x){this.x=x;return this;}/**
* Sets the vector's y component to the given value
*
* @param {number} y - The value to set.
* @return {Vector2} A reference to this vector.
*/setY(y){this.y=y;return this;}/**
* Allows to set a vector component with an index.
*
* @param {number} index - The component index. `0` equals to x, `1` equals to y.
* @param {number} value - The value to set.
* @return {Vector2} A reference to this vector.
*/setComponent(index,value){switch(index){case 0:this.x=value;break;case 1:this.y=value;break;default:throw new Error('index is out of range: '+index);}return this;}/**
* Returns the value of the vector component which matches the given index.
*
* @param {number} index - The component index. `0` equals to x, `1` equals to y.
* @return {number} A vector component value.
*/getComponent(index){switch(index){case 0:return this.x;case 1:return this.y;default:throw new Error('index is out of range: '+index);}}/**
* Returns a new vector with copied values from this instance.
*
* @return {Vector2} A clone of this instance.
*/clone(){return new this.constructor(this.x,this.y);}/**
* Copies the values of the given vector to this instance.
*
* @param {Vector2} v - The vector to copy.
* @return {Vector2} A reference to this vector.
*/copy(v){this.x=v.x;this.y=v.y;return this;}/**
* Adds the given vector to this instance.
*
* @param {Vector2} v - The vector to add.
* @return {Vector2} A reference to this vector.
*/add(v){this.x+=v.x;this.y+=v.y;return this;}/**
* Adds the given scalar value to all components of this instance.
*
* @param {number} s - The scalar to add.
* @return {Vector2} A reference to this vector.
*/addScalar(s){this.x+=s;this.y+=s;return this;}/**
* Adds the given vectors and stores the result in this instance.
*
* @param {Vector2} a - The first vector.
* @param {Vector2} b - The second vector.
* @return {Vector2} A reference to this vector.
*/addVectors(a,b){this.x=a.x+b.x;this.y=a.y+b.y;return this;}/**
* Adds the given vector scaled by the given factor to this instance.
*
* @param {Vector2} v - The vector.
* @param {number} s - The factor that scales `v`.
* @return {Vector2} A reference to this vector.
*/addScaledVector(v,s){this.x+=v.x*s;this.y+=v.y*s;return this;}/**
* Subtracts the given vector from this instance.
*
* @param {Vector2} v - The vector to subtract.
* @return {Vector2} A reference to this vector.
*/sub(v){this.x-=v.x;this.y-=v.y;return this;}/**
* Subtracts the given scalar value from all components of this instance.
*
* @param {number} s - The scalar to subtract.
* @return {Vector2} A reference to this vector.
*/subScalar(s){this.x-=s;this.y-=s;return this;}/**
* Subtracts the given vectors and stores the result in this instance.
*
* @param {Vector2} a - The first vector.
* @param {Vector2} b - The second vector.
* @return {Vector2} A reference to this vector.
*/subVectors(a,b){this.x=a.x-b.x;this.y=a.y-b.y;return this;}/**
* Multiplies the given vector with this instance.
*
* @param {Vector2} v - The vector to multiply.
* @return {Vector2} A reference to this vector.
*/multiply(v){this.x*=v.x;this.y*=v.y;return this;}/**
* Multiplies the given scalar value with all components of this instance.
*
* @param {number} scalar - The scalar to multiply.
* @return {Vector2} A reference to this vector.
*/multiplyScalar(scalar){this.x*=scalar;this.y*=scalar;return this;}/**
* Divides this instance by the given vector.
*
* @param {Vector2} v - The vector to divide.
* @return {Vector2} A reference to this vector.
*/divide(v){this.x/=v.x;this.y/=v.y;return this;}/**
* Divides this vector by the given scalar.
*
* @param {number} scalar - The scalar to divide.
* @return {Vector2} A reference to this vector.
*/divideScalar(scalar){return this.multiplyScalar(1/scalar);}/**
* Multiplies this vector (with an implicit 1 as the 3rd component) by
* the given 3x3 matrix.
*
* @param {Matrix3} m - The matrix to apply.
* @return {Vector2} A reference to this vector.
*/applyMatrix3(m){const x=this.x,y=this.y;const e=m.elements;this.x=e[0]*x+e[3]*y+e[6];this.y=e[1]*x+e[4]*y+e[7];return this;}/**
* If this vector's x or y value is greater than the given vector's x or y
* value, replace that value with the corresponding min value.
*
* @param {Vector2} v - The vector.
* @return {Vector2} A reference to this vector.
*/min(v){this.x=Math.min(this.x,v.x);this.y=Math.min(this.y,v.y);return this;}/**
* If this vector's x or y value is less than the given vector's x or y
* value, replace that value with the corresponding max value.
*
* @param {Vector2} v - The vector.
* @return {Vector2} A reference to this vector.
*/max(v){this.x=Math.max(this.x,v.x);this.y=Math.max(this.y,v.y);return this;}/**
* If this vector's x or y value is greater than the max vector's x or y
* value, it is replaced by the corresponding value.
* If this vector's x or y value is less than the min vector's x or y value,
* it is replaced by the corresponding value.
*
* @param {Vector2} min - The minimum x and y values.
* @param {Vector2} max - The maximum x and y values in the desired range.
* @return {Vector2} A reference to this vector.
*/clamp(min,max){// assumes min < max, componentwise
this.x=clamp(this.x,min.x,max.x);this.y=clamp(this.y,min.y,max.y);return this;}/**
* If this vector's x or y values are greater than the max value, they are
* replaced by the max value.
* If this vector's x or y values are less than the min value, they are
* replaced by the min value.
*
* @param {number} minVal - The minimum value the components will be clamped to.
* @param {number} maxVal - The maximum value the components will be clamped to.
* @return {Vector2} A reference to this vector.
*/clampScalar(minVal,maxVal){this.x=clamp(this.x,minVal,maxVal);this.y=clamp(this.y,minVal,maxVal);return this;}/**
* If this vector's length is greater than the max value, it is replaced by
* the max value.
* If this vector's length is less than the min value, it is replaced by the
* min value.
*
* @param {number} min - The minimum value the vector length will be clamped to.
* @param {number} max - The maximum value the vector length will be clamped to.
* @return {Vector2} A reference to this vector.
*/clampLength(min,max){const length=this.length();return this.divideScalar(length||1).multiplyScalar(clamp(length,min,max));}/**
* The components of this vector are rounded down to the nearest integer value.
*
* @return {Vector2} A reference to this vector.
*/floor(){this.x=Math.floor(this.x);this.y=Math.floor(this.y);return this;}/**
* The components of this vector are rounded up to the nearest integer value.
*
* @return {Vector2} A reference to this vector.
*/ceil(){this.x=Math.ceil(this.x);this.y=Math.ceil(this.y);return this;}/**
* The components of this vector are rounded to the nearest integer value
*
* @return {Vector2} A reference to this vector.
*/round(){this.x=Math.round(this.x);this.y=Math.round(this.y);return this;}/**
* The components of this vector are rounded towards zero (up if negative,
* down if positive) to an integer value.
*
* @return {Vector2} A reference to this vector.
*/roundToZero(){this.x=Math.trunc(this.x);this.y=Math.trunc(this.y);return this;}/**
* Inverts this vector - i.e. sets x = -x and y = -y.
*
* @return {Vector2} A reference to this vector.
*/negate(){this.x=-this.x;this.y=-this.y;return this;}/**
* Calculates the dot product of the given vector with this instance.
*
* @param {Vector2} v - The vector to compute the dot product with.
* @return {number} The result of the dot product.
*/dot(v){return this.x*v.x+this.y*v.y;}/**
* Calculates the cross product of the given vector with this instance.
*
* @param {Vector2} v - The vector to compute the cross product with.
* @return {number} The result of the cross product.
*/cross(v){return this.x*v.y-this.y*v.x;}/**
* Computes the square of the Euclidean length (straight-line length) from
* (0, 0) to (x, y). If you are comparing the lengths of vectors, you should
* compare the length squared instead as it is slightly more efficient to calculate.
*
* @return {number} The square length of this vector.
*/lengthSq(){return this.x*this.x+this.y*this.y;}/**
* Computes the Euclidean length (straight-line length) from (0, 0) to (x, y).
*
* @return {number} The length of this vector.
*/length(){return Math.sqrt(this.x*this.x+this.y*this.y);}/**
* Computes the Manhattan length of this vector.
*
* @return {number} The length of this vector.
*/manhattanLength(){return Math.abs(this.x)+Math.abs(this.y);}/**
* Converts this vector to a unit vector - that is, sets it equal to a vector
* with the same direction as this one, but with a vector length of `1`.
*
* @return {Vector2} A reference to this vector.
*/normalize(){return this.divideScalar(this.length()||1);}/**
* Computes the angle in radians of this vector with respect to the positive x-axis.
*
* @return {number} The angle in radians.
*/angle(){const angle=Math.atan2(-this.y,-this.x)+Math.PI;return angle;}/**
* Returns the angle between the given vector and this instance in radians.
*
* @param {Vector2} v - The vector to compute the angle with.
* @return {number} The angle in radians.
*/angleTo(v){const denominator=Math.sqrt(this.lengthSq()*v.lengthSq());if(denominator===0)return Math.PI/2;const theta=this.dot(v)/denominator;// clamp, to handle numerical problems
return Math.acos(clamp(theta,-1,1));}/**
* Computes the distance from the given vector to this instance.
*
* @param {Vector2} v - The vector to compute the distance to.
* @return {number} The distance.
*/distanceTo(v){return Math.sqrt(this.distanceToSquared(v));}/**
* Computes the squared distance from the given vector to this instance.
* If you are just comparing the distance with another distance, you should compare
* the distance squared instead as it is slightly more efficient to calculate.
*
* @param {Vector2} v - The vector to compute the squared distance to.
* @return {number} The squared distance.
*/distanceToSquared(v){const dx=this.x-v.x,dy=this.y-v.y;return dx*dx+dy*dy;}/**
* Computes the Manhattan distance from the given vector to this instance.
*
* @param {Vector2} v - The vector to compute the Manhattan distance to.
* @return {number} The Manhattan distance.
*/manhattanDistanceTo(v){return Math.abs(this.x-v.x)+Math.abs(this.y-v.y);}/**
* Sets this vector to a vector with the same direction as this one, but
* with the specified length.
*
* @param {number} length - The new length of this vector.
* @return {Vector2} A reference to this vector.
*/setLength(length){return this.normalize().multiplyScalar(length);}/**
* Linearly interpolates between the given vector and this instance, where
* alpha is the percent distance along the line - alpha = 0 will be this
* vector, and alpha = 1 will be the given one.
*
* @param {Vector2} v - The vector to interpolate towards.
* @param {number} alpha - The interpolation factor, typically in the closed interval `[0, 1]`.
* @return {Vector2} A reference to this vector.
*/lerp(v,alpha){this.x+=(v.x-this.x)*alpha;this.y+=(v.y-this.y)*alpha;return this;}/**
* Linearly interpolates between the given vectors, where alpha is the percent
* distance along the line - alpha = 0 will be first vector, and alpha = 1 will
* be the second one. The result is stored in this instance.
*
* @param {Vector2} v1 - The first vector.
* @param {Vector2} v2 - The second vector.
* @param {number} alpha - The interpolation factor, typically in the closed interval `[0, 1]`.
* @return {Vector2} A reference to this vector.
*/lerpVectors(v1,v2,alpha){this.x=v1.x+(v2.x-v1.x)*alpha;this.y=v1.y+(v2.y-v1.y)*alpha;return this;}/**
* Returns `true` if this vector is equal with the given one.
*
* @param {Vector2} v - The vector to test for equality.
* @return {boolean} Whether this vector is equal with the given one.
*/equals(v){return v.x===this.x&&v.y===this.y;}/**
* Sets this vector's x value to be `array[ offset ]` and y
* value to be `array[ offset + 1 ]`.
*
* @param {Array<number>} array - An array holding the vector component values.
* @param {number} [offset=0] - The offset into the array.
* @return {Vector2} A reference to this vector.
*/fromArray(array,offset=0){this.x=array[offset];this.y=array[offset+1];return this;}/**
* Writes the components of this vector to the given array. If no array is provided,
* the method returns a new instance.
*
* @param {Array<number>} [array=[]] - The target array holding the vector components.
* @param {number} [offset=0] - Index of the first element in the array.
* @return {Array<number>} The vector components.
*/toArray(array=[],offset=0){array[offset]=this.x;array[offset+1]=this.y;return array;}/**
* Sets the components of this vector from the given buffer attribute.
*
* @param {BufferAttribute} attribute - The buffer attribute holding vector data.
* @param {number} index - The index into the attribute.
* @return {Vector2} A reference to this vector.
*/fromBufferAttribute(attribute,index){this.x=attribute.getX(index);this.y=attribute.getY(index);return this;}/**
* Rotates this vector around the given center by the given angle.
*
* @param {Vector2} center - The point around which to rotate.
* @param {number} angle - The angle to rotate, in radians.
* @return {Vector2} A reference to this vector.
*/rotateAround(center,angle){const c=Math.cos(angle),s=Math.sin(angle);const x=this.x-center.x;const y=this.y-center.y;this.x=x*c-y*s+center.x;this.y=x*s+y*c+center.y;return this;}/**
* Sets each component of this vector to a pseudo-random value between `0` and
* `1`, excluding `1`.
*
* @return {Vector2} A reference to this vector.
*/random(){this.x=Math.random();this.y=Math.random();return this;}*[Symbol.iterator](){yield this.x;yield this.y;}}/**
* Class for representing a Quaternion. Quaternions are used in three.js to represent rotations.
*
* Iterating through a vector instance will yield its components `(x, y, z, w)` in
* the corresponding order.
*
* Note that three.js expects Quaternions to be normalized.
* ```js
* const quaternion = new THREE.Quaternion();
* quaternion.setFromAxisAngle( new THREE.Vector3( 0, 1, 0 ), Math.PI / 2 );
*
* const vector = new THREE.Vector3( 1, 0, 0 );
* vector.applyQuaternion( quaternion );
* ```
*/class Quaternion{/**
* Constructs a new quaternion.
*
* @param {number} [x=0] - The x value of this quaternion.
* @param {number} [y=0] - The y value of this quaternion.
* @param {number} [z=0] - The z value of this quaternion.
* @param {number} [w=1] - The w value of this quaternion.
*/constructor(x=0,y=0,z=0,w=1){/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/this.isQuaternion=true;this._x=x;this._y=y;this._z=z;this._w=w;}/**
* Interpolates between two quaternions via SLERP. This implementation assumes the
* quaternion data are managed in flat arrays.
*
* @param {Array<number>} dst - The destination array.
* @param {number} dstOffset - An offset into the destination array.
* @param {Array<number>} src0 - The source array of the first quaternion.
* @param {number} srcOffset0 - An offset into the first source array.
* @param {Array<number>} src1 - The source array of the second quaternion.
* @param {number} srcOffset1 - An offset into the second source array.
* @param {number} t - The interpolation factor in the range `[0,1]`.
* @see {@link Quaternion#slerp}
*/static slerpFlat(dst,dstOffset,src0,srcOffset0,src1,srcOffset1,t){// fuzz-free, array-based Quaternion SLERP operation
let x0=src0[srcOffset0+0],y0=src0[srcOffset0+1],z0=src0[srcOffset0+2],w0=src0[srcOffset0+3];const x1=src1[srcOffset1+0],y1=src1[srcOffset1+1],z1=src1[srcOffset1+2],w1=src1[srcOffset1+3];if(t===0){dst[dstOffset+0]=x0;dst[dstOffset+1]=y0;dst[dstOffset+2]=z0;dst[dstOffset+3]=w0;return;}if(t===1){dst[dstOffset+0]=x1;dst[dstOffset+1]=y1;dst[dstOffset+2]=z1;dst[dstOffset+3]=w1;return;}if(w0!==w1||x0!==x1||y0!==y1||z0!==z1){let s=1-t;const cos=x0*x1+y0*y1+z0*z1+w0*w1,dir=cos>=0?1:-1,sqrSin=1-cos*cos;// Skip the Slerp for tiny steps to avoid numeric problems:
if(sqrSin>Number.EPSILON){const sin=Math.sqrt(sqrSin),len=Math.atan2(sin,cos*dir);s=Math.sin(s*len)/sin;t=Math.sin(t*len)/sin;}const tDir=t*dir;x0=x0*s+x1*tDir;y0=y0*s+y1*tDir;z0=z0*s+z1*tDir;w0=w0*s+w1*tDir;// Normalize in case we just did a lerp:
if(s===1-t){const f=1/Math.sqrt(x0*x0+y0*y0+z0*z0+w0*w0);x0*=f;y0*=f;z0*=f;w0*=f;}}dst[dstOffset]=x0;dst[dstOffset+1]=y0;dst[dstOffset+2]=z0;dst[dstOffset+3]=w0;}/**
* Multiplies two quaternions. This implementation assumes the quaternion data are managed
* in flat arrays.
*
* @param {Array<number>} dst - The destination array.
* @param {number} dstOffset - An offset into the destination array.
* @param {Array<number>} src0 - The source array of the first quaternion.
* @param {number} srcOffset0 - An offset into the first source array.
* @param {Array<number>} src1 - The source array of the second quaternion.
* @param {number} srcOffset1 - An offset into the second source array.
* @return {Array<number>} The destination array.
* @see {@link Quaternion#multiplyQuaternions}.
*/static multiplyQuaternionsFlat(dst,dstOffset,src0,srcOffset0,src1,srcOffset1){const x0=src0[srcOffset0];const y0=src0[srcOffset0+1];const z0=src0[srcOffset0+2];const w0=src0[srcOffset0+3];const x1=src1[srcOffset1];const y1=src1[srcOffset1+1];const z1=src1[srcOffset1+2];const w1=src1[srcOffset1+3];dst[dstOffset]=x0*w1+w0*x1+y0*z1-z0*y1;dst[dstOffset+1]=y0*w1+w0*y1+z0*x1-x0*z1;dst[dstOffset+2]=z0*w1+w0*z1+x0*y1-y0*x1;dst[dstOffset+3]=w0*w1-x0*x1-y0*y1-z0*z1;return dst;}/**
* The x value of this quaternion.
*
* @type {number}
* @default 0
*/get x(){return this._x;}set x(value){this._x=value;this._onChangeCallback();}/**
* The y value of this quaternion.
*
* @type {number}
* @default 0
*/get y(){return this._y;}set y(value){this._y=value;this._onChangeCallback();}/**
* The z value of this quaternion.
*
* @type {number}
* @default 0
*/get z(){return this._z;}set z(value){this._z=value;this._onChangeCallback();}/**
* The w value of this quaternion.
*
* @type {number}
* @default 1
*/get w(){return this._w;}set w(value){this._w=value;this._onChangeCallback();}/**
* Sets the quaternion components.
*
* @param {number} x - The x value of this quaternion.
* @param {number} y - The y value of this quaternion.
* @param {number} z - The z value of this quaternion.
* @param {number} w - The w value of this quaternion.
* @return {Quaternion} A reference to this quaternion.
*/set(x,y,z,w){this._x=x;this._y=y;this._z=z;this._w=w;this._onChangeCallback();return this;}/**
* Returns a new quaternion with copied values from this instance.
*
* @return {Quaternion} A clone of this instance.
*/clone(){return new this.constructor(this._x,this._y,this._z,this._w);}/**
* Copies the values of the given quaternion to this instance.
*
* @param {Quaternion} quaternion - The quaternion to copy.
* @return {Quaternion} A reference to this quaternion.
*/copy(quaternion){this._x=quaternion.x;this._y=quaternion.y;this._z=quaternion.z;this._w=quaternion.w;this._onChangeCallback();return this;}/**
* Sets this quaternion from the rotation specified by the given
* Euler angles.
*
* @param {Euler} euler - The Euler angles.
* @param {boolean} [update=true] - Whether the internal `onChange` callback should be executed or not.
* @return {Quaternion} A reference to this quaternion.
*/setFromEuler(euler,update=true){const x=euler._x,y=euler._y,z=euler._z,order=euler._order;// http://www.mathworks.com/matlabcentral/fileexchange/
// 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/
// content/SpinCalc.m
const cos=Math.cos;const sin=Math.sin;const c1=cos(x/2);const c2=cos(y/2);const c3=cos(z/2);const s1=sin(x/2);const s2=sin(y/2);const s3=sin(z/2);switch(order){case 'XYZ':this._x=s1*c2*c3+c1*s2*s3;this._y=c1*s2*c3-s1*c2*s3;this._z=c1*c2*s3+s1*s2*c3;this._w=c1*c2*c3-s1*s2*s3;break;case 'YXZ':this._x=s1*c2*c3+c1*s2*s3;this._y=c1*s2*c3-s1*c2*s3;this._z=c1*c2*s3-s1*s2*c3;this._w=c1*c2*c3+s1*s2*s3;break;case 'ZXY':this._x=s1*c2*c3-c1*s2*s3;this._y=c1*s2*c3+s1*c2*s3;this._z=c1*c2*s3+s1*s2*c3;this._w=c1*c2*c3-s1*s2*s3;break;case 'ZYX':this._x=s1*c2*c3-c1*s2*s3;this._y=c1*s2*c3+s1*c2*s3;this._z=c1*c2*s3-s1*s2*c3;this._w=c1*c2*c3+s1*s2*s3;break;case 'YZX':this._x=s1*c2*c3+c1*s2*s3;this._y=c1*s2*c3+s1*c2*s3;this._z=c1*c2*s3-s1*s2*c3;this._w=c1*c2*c3-s1*s2*s3;break;case 'XZY':this._x=s1*c2*c3-c1*s2*s3;this._y=c1*s2*c3-s1*c2*s3;this._z=c1*c2*s3+s1*s2*c3;this._w=c1*c2*c3+s1*s2*s3;break;default:console.warn('THREE.Quaternion: .setFromEuler() encountered an unknown order: '+order);}if(update===true)this._onChangeCallback();return this;}/**
* Sets this quaternion from the given axis and angle.
*
* @param {Vector3} axis - The normalized axis.
* @param {number} angle - The angle in radians.
* @return {Quaternion} A reference to this quaternion.
*/setFromAxisAngle(axis,angle){// http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm
const halfAngle=angle/2,s=Math.sin(halfAngle);this._x=axis.x*s;this._y=axis.y*s;this._z=axis.z*s;this._w=Math.cos(halfAngle);this._onChangeCallback();return this;}/**
* Sets this quaternion from the given rotation matrix.
*
* @param {Matrix4} m - A 4x4 matrix of which the upper 3x3 of matrix is a pure rotation matrix (i.e. unscaled).
* @return {Quaternion} A reference to this quaternion.
*/setFromRotationMatrix(m){// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
const te=m.elements,m11=te[0],m12=te[4],m13=te[8],m21=te[1],m22=te[5],m23=te[9],m31=te[2],m32=te[6],m33=te[10],trace=m11+m22+m33;if(trace>0){const s=0.5/Math.sqrt(trace+1.0);this._w=0.25/s;this._x=(m32-m23)*s;this._y=(m13-m31)*s;this._z=(m21-m12)*s;}else if(m11>m22&&m11>m33){const s=2.0*Math.sqrt(1.0+m11-m22-m33);this._w=(m32-m23)/s;this._x=0.25*s;this._y=(m12+m21)/s;this._z=(m13+m31)/s;}else if(m22>m33){const s=2.0*Math.sqrt(1.0+m22-m11-m33);this._w=(m13-m31)/s;this._x=(m12+m21)/s;this._y=0.25*s;this._z=(m23+m32)/s;}else {const s=2.0*Math.sqrt(1.0+m33-m11-m22);this._w=(m21-m12)/s;this._x=(m13+m31)/s;this._y=(m23+m32)/s;this._z=