const HALF_CIRC = 180 ; const ACCURACY = 1e6 ; export class Vector { constructor ( x = 0 , y = 0 ) { this . x = x ; this . y = y ; } x : number ; y : number ; private get _modulo ( ) : number { return Math . sqrt ( this . x * this . x + this . y * this . y ) ; } get modulo ( ) : number { return Vector . Rounding ( Math . sqrt ( this . x * this . x + this . y * this . y ) ) ; } set modulo ( m ) { this . normalize ( ) ; this . x *= m ; this . y *= m ; } rotate ( arc ) { const _x = this . x ; const _y = this . y ; this . x = _x * Math . cos ( arc ) - _y * Math . sin ( arc ) ; this . y = _x * Math . sin ( arc ) + _y * Math . cos ( arc ) ; return this ; } valueOf ( ) { return this . modulo ; } toString ( ) { return `[${ this . x },${ this . y }]` ; } normalize ( ) { const modulo = this . _modulo ; if ( modulo !== 0 ) { this . x /= modulo ; this . y /= modulo ; } else { throw new Error ( '零向量无法标准化！' ) ; } return this ; } zero ( ) { this . x = 0 ; this . y = 0 ; return this ; } add ( v ) { this . x += v . x ; this . y += v . y ; return this ; } substract ( v ) { this . x -= v . x ; this . y -= v . y ; return this ; } multiplied ( n ) ; multiplied ( n ) ; multiplied ( n ) { if ( typeof n === 'number' ) { this . x *= n ; this . y *= n ; return this ; } else { return this . x * n . x + this . y * n . y ; } } radian ( v ) { return Vector . radian ( this , v ) ; } angel ( v ) { return Vector . angel ( this , v ) ; } get isZero ( ) { return this . x === 0 && this . y === 0 ; } get isNormalize ( ) { return this . modulo === 1 ; } static add ( v1 , v2 ) { return new Vector ( v1 . x + v2 . x , v1 . y + v2 . y ) ; } static substract ( v1 , v2 ) { return new Vector ( v1 . x - v2 . x , v1 . y - v2 . y ) ; } static multiplied ( v1 , v2 ) ; static multiplied ( v1 , n ) ; static multiplied ( v1 , n ) { if ( typeof n === 'number' ) { return new Vector ( v1 . x * n , v1 . y * n ) ; } else { return v1 . x * n . x + v1 . y * n . y ; } } static radian ( v1 , v2 ) { if ( v1 . isZero || v2 . isZero ) { return NaN ; } return Math . acos ( Vector . multiplied ( v1 , v2 ) / v1 . _modulo / v2 . _modulo ) ; } static angel ( v1 , v2 ) { if ( v1 . isZero || v2 . isZero ) { return NaN ; } return Vector . Rounding ( HALF_CIRC * Vector . radian ( v1 , v2 ) / Math . PI ) ; } static projected ( v1 , v2 ) { if ( v1 . isZero || v2 . isZero ) { return new Vector ( 0 , 0 ) ; } return Vector . multiplied ( v2 , Vector . multiplied ( v1 , v2 ) / Math . pow ( v2 . _modulo , 2 ) ) ; } static plumb ( v1 , v2 ) { if ( v1 . isZero ) { return new Vector ( 0 , 0 ) ; } if ( v2 . isZero ) { return new Vector ( v1 . x , v1 . y ) ; } return Vector . substract ( v1 , Vector . projected ( v1 , v2 ) ) ; } static Rounding ( n ) { return Math . round ( n * ACCURACY ) / ACCURACY ; } static distance ( v1 , v2 ) { return Vector . substract ( v1 , v2 ) . modulo ; } }