'use strict' ; let _add , _angle , _azimuth , _cross , _dot , _equals , _magnitude , _multiply , _plunge , _unit , _rotate , _subtract , _x , _y , _z ; param v1 { Array < Number > } param v2 { Array < Number > } return { Array < Number > } throws _add = function ( v1 , v2 ) : Array < number > { let i , v ; if ( v1 . length !== v2 . length ) { throw new Error ( 'vectors must be same length' ) ; } v = [ ] ; for ( i = 0 ; i < v1 . length ; i ++ ) { v . push ( v1 [ i ] + v2 [ i ] ) ; } return v ; } ; param v1 { Array < Number > } param v2 { Array < Number > } return { Number } _angle = function ( v1 , v2 ) : number { return Math . acos ( _dot ( v1 , v2 ) / ( _magnitude ( v1 ) * _magnitude ( v2 ) ) ) ; } ; param v1 { Array < Number > } param v2 { Array < Number > } return { Number } _azimuth = function ( v1 ) : number { if ( v1 . length < 2 ) { throw new Error ( 'azimuth requires at least 2 dimensions' ) ; } if ( v1 [ 0 ] === 0 && v1 [ 1 ] === 0 ) { return 0 ; } return Math . PI / 2 - Math . atan2 ( v1 [ 1 ] , v1 [ 0 ] ) ; } ; param v1 { Array < Number > } param v2 { Array < Number > } return { Array < Number > } _cross = function ( v1 , v2 ) : Array < number > { if ( v1 . length !== v2 . length || v1 . length < 3 ) { throw new Error ( 'cross product requires at least 3 dimensions' ) ; } return [ v1 [ 1 ] * v2 [ 2 ] - v2 [ 1 ] * v1 [ 2 ] , v1 [ 2 ] * v2 [ 0 ] - v2 [ 2 ] * v1 [ 0 ] , v1 [ 0 ] * v2 [ 1 ] - v2 [ 0 ] * v1 [ 1 ] ] ; } ; param v1 { Array < Number } param v2 { Array < Number > } return { Number } _dot = function ( v1 , v2 ) : number { let i , sum ; sum = 0 ; for ( i = 0 ; i < v1 . length ; i ++ ) { sum += v1 [ i ] * v2 [ i ] ; } return sum ; } ; param v1 { Array < Number > } param v2 { Array < Number > } return { Boolean } _equals = function ( v1 , v2 ) : boolean { let i ; if ( v1 . length !== v2 . length ) { return false ; } for ( i = 0 ; i < v1 . length ; i ++ ) { if ( v1 [ i ] !== v2 [ i ] ) { return false ; } } return true ; } ; param v1 { Array < Number > } return { Number } _magnitude = function ( v1 ) : number { let i , sum ; sum = 0 ; for ( i = 0 ; i < v1 . length ; i ++ ) { sum += v1 [ i ] * v1 [ i ] ; } return Math . sqrt ( sum ) ; } ; param v1 { Array < Number > } param n { Number } return { Array < Number } _multiply = function ( v1 , n ) : Array < number > { let i , v ; v = [ ] ; for ( i = 0 ; i < v1 . length ; i ++ ) { v . push ( v1 [ i ] * n ) ; } return v ; } ; param v { Array < Number > } return { Number } _plunge = function ( v ) : number { if ( v . length < 3 ) { throw new Error ( '__azimuth: vector must have at least 3 dimensions' ) ; } return Math . asin ( v [ 2 ] / _magnitude ( v ) ) ; } ; param v1 { Array < Number > } param axis { Array < Number > } param theta { Number } param origin { Array < Number > } _rotate = function ( v1 , axis , theta , origin = [ 0 , 0 , 0 ] ) : Array < number > { let a , au , av , aw , b , bu , bv , bw , c , cu , cv , cw , cosT , sinT , u , uu , ux , uy , uz , v , vv , vx , vy , vz , w , ww , wx , wy , wz , x , y , z ; a = origin [ 0 ] ; b = origin [ 1 ] ; c = origin [ 2 ] ; u = axis [ 0 ] ; v = axis [ 1 ] ; w = axis [ 2 ] ; x = v1 [ 0 ] ; y = v1 [ 1 ] ; z = v1 [ 2 ] ; cosT = Math . cos ( theta ) ; sinT = Math . sin ( theta ) ; au = a * u ; av = a * v ; aw = a * w ; bu = b * u ; bv = b * v ; bw = b * w ; cu = c * u ; cv = c * v ; cw = c * w ; uu = u * u ; ux = u * x ; uy = u * y ; uz = u * z ; vv = v * v ; vx = v * x ; vy = v * y ; vz = v * z ; ww = w * w ; wx = w * x ; wy = w * y ; wz = w * z ; return [ ( a * ( vv + ww ) - u * ( bv + cw - ux - vy - wz ) ) * ( 1 - cosT ) + x * cosT + ( - cv + bw - wy + vz ) * sinT , ( b * ( uu + ww ) - v * ( au + cw - ux - vy - wz ) ) * ( 1 - cosT ) + y * cosT + ( cu - aw + wx - uz ) * sinT , ( c * ( uu + vv ) - w * ( au + bv - ux - vy - wz ) ) * ( 1 - cosT ) + z * cosT + ( - bu + av - vx + uy ) * sinT ] ; } ; param v1 { Array < Number > } param v2 { Array < Number > } return { Array < Number > } throws _subtract = function ( v1 , v2 ) : Array < number > { let i , v ; if ( v1 . length !== v2 . length ) { throw new Error ( '__subtract: vectors must be same length' ) ; } v = [ ] ; for ( i = 0 ; i < v1 . length ; i ++ ) { v . push ( v1 [ i ] - v2 [ i ] ) ; } return v ; } ; param v1 { Array < Number > } throws return { Array < Number > } _unit = function ( v1 ) : Array < number > { const mag = _magnitude ( v1 ) ; if ( mag === 0 ) { throw new Error ( '__unit: cannot convert zero vector to unit vector' ) ; } return _multiply ( v1 , 1 / mag ) ; } ; param v { Array < Number > } param value { Number } return { Number } _x = function ( v , value ? ) : number { if ( typeof value === 'number' ) { v [ 0 ] = value ; } return v [ 0 ] ; } ; param v { Array < Number > } param value { Number } return { Number } _y = function ( v , value ) : number { if ( typeof value === 'number' ) { v [ 1 ] = value ; } return v [ 1 ] ; } ; param v { Array < Number > } param value { Number } return { Number } _z = function ( v , value ) : number { if ( typeof value === 'number' ) { v [ 2 ] = value ; } return v [ 2 ] ; } ; param data { Array < Number > } export class Vector { static add = _add ; static angle = _angle ; static azimuth = _azimuth ; static cross = _cross ; static dot = _dot ; static magnitude = _magnitude ; static multiply = _multiply ; static plunge = _plunge ; static rotate = _rotate ; static subtract = _subtract ; static unit = _unit ; static x = _x ; static y = _y ; static z = _z ; constructor ( public data ) { } param that { Vector | Array < Number > } return { Vector } add ( that ) { return new Vector ( _add ( this . data , that instanceof Vector ? that . data : that ) ) ; } param that { Vector | Array < Number > } return { Number } angle ( that ) { return _angle ( this . data , that instanceof Vector ? that . data : that ) ; } return { Number } azimuth ( ) { return _azimuth ( this . data ) ; } param that { Vector | Array < Number > } return { Vector } cross ( that ) { return new Vector ( _cross ( this . data , that instanceof Vector ? that . data : that ) ) ; } param that { Vector | Array < Number > } return { Number } dot ( that ) { return _dot ( this . data , that instanceof Vector ? that . data : that ) ; } param that { Vector | Array < Number > } return { Boolean } equals ( that ) { return _equals ( this . data , that instanceof Vector ? that . data : that ) ; } return { Number } magnitude ( ) { return _magnitude ( this . data ) ; } param n { Number } return { Vector } multiply ( n ) { return new Vector ( _multiply ( this . data , n ) ) ; } return { Number } plunge ( ) { return _plunge ( this . data ) ; } param axis { Vector | Array < Number > } param theta { Number } param origin { Vector | Array < Number > } return { Vector } rotate ( axis , theta , origin = [ 0 , 0 , 0 ] ) { return new Vector ( _rotate ( this . data , axis instanceof Vector ? axis . data : axis , theta , origin instanceof Vector ? origin . data : origin ) ) ; } param that { Vector | Array < Number > } return { Vector } subtract ( that ) { return new Vector ( _subtract ( this . data , that instanceof Vector ? that . data : that ) ) ; } return { String } toString ( ) { return '' + this . data ; } return { Vector } unit ( ) { return new Vector ( _unit ( this . data ) ) ; } param value { Number } return { Number } x ( value ? ) { return _x ( this . data , value ) ; } param value { Number } return { Number } y ( value ? ) { return _y ( this . data , value ) ; } param value { Number } return { Number } z ( value ? ) { return _z ( this . data , value ) ; } }