import Kernel from '../Kernel' ; import Utils from '../Utils' ; import Vertice from './Vertice' ; import Vector from './Vector' ; import Line from './Line' ; import Plan from './Plan' ; import Matrix from './Matrix' ; if ( ! ( < any > Math ) . log2 ) { ( < any > Math ) . log2 = ( value ) => ( Math . log ( value ) / Math . log ( 2 ) ) ; } const pow2Cache = { } ; ( function ( cache ) { cache [ 0 ] = 1 ; for ( var i = 1 ; i <= 20 ; i ++ ) { cache [ i ] = cache [ i - 1 ] << 1 ; cache [ - i ] = 1 / cache [ i ] ; } } ) ( pow2Cache ) ; const ONE_RADIAN_EQUAL_DEGREE = 57.29577951308232 ; const ONE_DEGREE_EQUAL_RADIAN = 0.017453292519943295 ; export default class MathUtils { static getRealValueInWorld ( virtualValue ) { return virtualValue / Kernel . SCALE_FACTOR ; } static pow2 ( v ) { var s = v . toString ( ) ; if ( pow2Cache . hasOwnProperty ( s ) ) { return pow2Cache [ s ] ; } else { return Math . pow ( 2 , v ) ; } } static log2 ( value ) { return ( < any > Math ) . log2 ( value ) ; } static izZero ( value ) { if ( ! Utils . isNumber ( value ) ) { throw "invalid value" ; } return Math . abs ( value ) < 0.000001 ; } static isPowerOfTwo ( value ) { return ( value & ( value - 1 ) ) === 0 && value !== 0 ; } static asinSafely ( value ) { if ( value > 1 ) { value = 1 ; } if ( value < - 1 ) { value = - 1 ; } return Math . asin ( value ) ; } static acosSafely ( value ) { if ( value > 1 ) { value = 1 ; } if ( value < - 1 ) { value = - 1 ; } return Math . acos ( value ) ; } param numSys param strNum returns { number } static numerationSystemTo10 ( numSys , strNum ) { var sum = 0 ; for ( var i = 0 ; i < strNum . length ; i ++ ) { var level = strNum . length - 1 - i ; var key = parseInt ( strNum [ i ] ) ; sum += key * Math . pow ( numSys , level ) ; } return sum ; } param numSys param num returns { string } static numerationSystemFrom10 ( numSys , num ) { return num . toString ( numSys ) ; } param numSysFrom param numSysTo param strNumFrom returns { string } static numerationSystemChange ( numSysFrom , numSysTo , strNumFrom ) { var temp10 = this . numerationSystemTo10 ( numSysFrom , strNumFrom ) ; var strResult = this . numerationSystemFrom10 ( numSysTo , temp10 ) ; return strResult ; } /**
     * 计算三角形的面积
     */ static getTriangleArea ( v1 , v2 , v3 ) { var v1Copy = v1 . clone ( ) ; var v2Copy = v2 . clone ( ) ; var v3Copy = v3 . clone ( ) ; var direction = Vector . verticeMinusVertice ( v3Copy , v2Copy ) ; var line = new Line ( v2Copy , direction ) ; var h = this . getLengthFromVerticeToLine ( v1Copy , line ) ; var w = this . getLengthFromVerticeToVertice ( v2Copy , v3Copy ) ; var area = 0.5 * w * h ; return area ; } param vertice1 param vertice2 return { Number } static getLengthFromVerticeToVertice ( vertice1 , vertice2 ) { var vertice1Copy = vertice1 . clone ( ) ; var vertice2Copy = vertice2 . clone ( ) ; var length2 = Math . pow ( vertice1Copy . x - vertice2Copy . x , 2 ) + Math . pow ( vertice1Copy . y - vertice2Copy . y , 2 ) + Math . pow ( vertice1Copy . z - vertice2Copy . z , 2 ) ; var length = Math . sqrt ( length2 ) ; return length ; } param vertice param line return { Number } static getLengthFromVerticeToLine ( vertice , line ) { var verticeCopy = vertice . clone ( ) ; var lineCopy = line . clone ( ) ; var x0 = verticeCopy . x ; var y0 = verticeCopy . y ; var z0 = verticeCopy . z ; var verticeOnLine = lineCopy . vertice ; var x1 = verticeOnLine . x ; var y1 = verticeOnLine . y ; var z1 = verticeOnLine . z ; var lineVector = lineCopy . vector ; lineVector . normalize ( ) ; var a = lineVector . x ; var b = lineVector . y ; var c = lineVector . z ; var A = ( y0 - y1 ) * c - b * ( z0 - z1 ) ; var B = ( z0 - z1 ) * a - c * ( x0 - x1 ) ; var C = ( x0 - x1 ) * b - a * ( y0 - y1 ) ; return Math . sqrt ( A * A + B * B + C * C ) ; } param vertice param plan return { Number } static getLengthFromVerticeToPlan ( vertice , plan ) { var verticeCopy = vertice . clone ( ) ; var planCopy = plan . clone ( ) ; var x = verticeCopy . x ; var y = verticeCopy . y ; var z = verticeCopy . z ; var A = planCopy . A ; var B = planCopy . B ; var C = planCopy . C ; var D = planCopy . D ; var numerator = Math . abs ( A * x + B * y + C * z + D ) ; var denominator = Math . sqrt ( A * A + B * B + C * C ) ; var length = numerator / denominator ; return length ; } param vertice param plan return { World . Vertice } static getVerticeVerticalIntersectPointWidthPlan ( vertice , plan ) { var verticeCopy = vertice . clone ( ) ; var planCopy = plan . clone ( ) ; var x0 = verticeCopy . x ; var y0 = verticeCopy . y ; var z0 = verticeCopy . z ; var normalVector = new Vector ( planCopy . A , planCopy . B , planCopy . C ) ; normalVector . normalize ( ) ; var a = normalVector . x ; var b = normalVector . y ; var c = normalVector . z ; var d = planCopy . D * a / planCopy . A ; var k = - ( a * x0 + b * y0 + c * z0 + d ) ; var x = k * a + x0 ; var y = k * b + y0 ; var z = k * c + z0 ; var intersectVertice = new Vertice ( x , y , z ) ; return intersectVertice ; } static getIntersectPointByLineAdPlan ( line , plan ) { var lineCopy = line . clone ( ) ; var planCopy = plan . clone ( ) ; lineCopy . vector . normalize ( ) ; var A = planCopy . A ; var B = planCopy . B ; var C = planCopy . C ; var D = planCopy . D ; var x0 = lineCopy . vertice . x ; var y0 = lineCopy . vertice . y ; var z0 = lineCopy . vertice . z ; var a = lineCopy . vector . x ; var b = lineCopy . vector . y ; var c = lineCopy . vector . z ; var k = - ( A * x0 + B * y0 + C * z0 + D ) / ( A * a + B * b + C * c ) ; var x = k * a + x0 ; var y = k * b + y0 ; var z = k * c + z0 ; var intersectVertice = new Vertice ( x , y , z ) ; return intersectVertice ; } param line return { Array } static getLineIntersectPointWithEarth ( line ) { var result = [ ] ; var lineCopy = line . clone ( ) ; var vertice = lineCopy . vertice ; var direction = lineCopy . vector ; direction . normalize ( ) ; var r = Kernel . EARTH_RADIUS ; var a = direction . x ; var b = direction . y ; var c = direction . z ; var x0 = vertice . x ; var y0 = vertice . y ; var z0 = vertice . z ; var a2 = a * a ; var b2 = b * b ; var c2 = c * c ; var r2 = r * r ; var ay0 = a * y0 ; var az0 = a * z0 ; var bx0 = b * x0 ; var bz0 = b * z0 ; var cx0 = c * x0 ; var cy0 = c * y0 ; var deltaA = ay0 * bx0 + az0 * cx0 + bz0 * cy0 ; var deltaB = ay0 * ay0 + az0 * az0 + bx0 * bx0 + bz0 * bz0 + cx0 * cx0 + cy0 * cy0 ; var deltaC = a2 + b2 + c2 ; var delta = 8 * deltaA - 4 * deltaB + 4 * r2 * deltaC ; if ( delta < 0 ) { result = [ ] ; } else { var t = a * x0 + b * y0 + c * z0 ; var A = a2 + b2 + c2 ; if ( delta == 0 ) { var k = - t / A ; var x = k * a + x0 ; var y = k * b + y0 ; var z = k * c + z0 ; var p = new Vertice ( x , y , z ) ; result . push ( p ) ; } else if ( delta > 0 ) { var sqrtDelta = Math . sqrt ( delta ) ; var k1 = ( - 2 * t + sqrtDelta ) / ( 2 * A ) ; var x1 = k1 * a + x0 ; var y1 = k1 * b + y0 ; var z1 = k1 * c + z0 ; var p1 = new Vertice ( x1 , y1 , z1 ) ; result . push ( p1 ) ; var k2 = ( - 2 * t - sqrtDelta ) / ( 2 * A ) ; var x2 = k2 * a + x0 ; var y2 = k2 * b + y0 ; var z2 = k2 * c + z0 ; var p2 = new Vertice ( x2 , y2 , z2 ) ; result . push ( p2 ) ; } } return result ; } param vertice param direction return { Object } static getCrossPlaneByLine ( vertice , direction ) { var verticeCopy = vertice . clone ( ) ; var directionCopy = direction . clone ( ) ; directionCopy . normalize ( ) ; var a = directionCopy . x ; var b = directionCopy . y ; var c = directionCopy . z ; var x0 = verticeCopy . x ; var y0 = verticeCopy . y ; var z0 = verticeCopy . z ; var d = - ( a * x0 + b * y0 + c * z0 ) ; var plan = new Plan ( a , b , c , d ) ; return plan ; } static convertPointFromCanvasToNDC ( canvasWidth , canvasHeight , canvasX , canvasY ) { if ( ! ( Utils . isNumber ( canvasX ) ) ) { throw "invalid canvasX" ; } if ( ! ( Utils . isNumber ( canvasY ) ) ) { throw "invalid canvasY" ; } var ndcX = 2 * canvasX / canvasWidth - 1 ; var ndcY = 1 - 2 * canvasY / canvasHeight ; return [ ndcX , ndcY ] ; } static convertPointFromNdcToCanvas ( canvasWidth , canvasHeight , ndcX , ndcY ) { if ( ! ( Utils . isNumber ( ndcX ) ) ) { throw "invalid ndcX" ; } if ( ! ( Utils . isNumber ( ndcY ) ) ) { throw "invalid ndcY" ; } var canvasX = ( 1 + ndcX ) * canvasWidth / 2.0 ; var canvasY = ( 1 - ndcY ) * canvasHeight / 2.0 ; return [ canvasX , canvasY ] ; } lon lat r p static geographicToCartesianCoord ( lon , lat , r = Kernel . EARTH_RADIUS ) { if ( ! ( lon >= - ( 180 + 0.001 ) && lon <= ( 180 + 0.001 ) ) ) { throw "invalid lon" ; } if ( ! ( lat >= - ( 90 + 0.001 ) && lat <= ( 90 + 0.001 ) ) ) { throw "invalid lat" ; } var radianLon = this . degreeToRadian ( lon ) ; var radianLat = this . degreeToRadian ( lat ) ; var sin1 = Math . sin ( radianLon ) ; var cos1 = Math . cos ( radianLon ) ; var sin2 = Math . sin ( radianLat ) ; var cos2 = Math . cos ( radianLat ) ; var x = r * sin1 * cos2 ; var y = r * sin2 ; var z = r * cos1 * cos2 ; return new Vertice ( x , y , z ) ; } param vertice return { Array } static cartesianCoordToGeographic ( vertice ) { var verticeCopy = vertice . clone ( ) ; var x = verticeCopy . x ; var y = verticeCopy . y ; var z = verticeCopy . z ; var sin2 = y / Kernel . EARTH_RADIUS ; var radianLat = this . asinSafely ( sin2 ) ; var cos2 = Math . cos ( radianLat ) ; var sin1 = x / ( Kernel . EARTH_RADIUS * cos2 ) ; if ( sin1 > 1 ) { sin1 = 1 ; } if ( sin1 < - 1 ) { sin1 = - 1 ; } var cos1 = z / ( Kernel . EARTH_RADIUS * cos2 ) ; if ( cos1 > 1 ) { cos1 = 1 ; } if ( cos1 < - 1 ) { cos1 = - 1 ; } var radianLog = this . asinSafely ( sin1 ) ; if ( sin1 >= 0 ) { if ( cos1 >= 0 ) { radianLog = radianLog ; } else { radianLog = Math . PI - radianLog ; } } else { if ( cos1 >= 0 ) { radianLog = radianLog ; } else { radianLog = - radianLog - Math . PI ; } } var degreeLat = this . radianToDegree ( radianLat ) ; var degreeLog = this . radianToDegree ( radianLog ) ; return [ degreeLog , degreeLat ] ; } param degree return { * } static degreeToRadian ( degree ) { return degree * ONE_DEGREE_EQUAL_RADIAN ; } param radian return { * } static radianToDegree ( radian ) { return radian * ONE_RADIAN_EQUAL_DEGREE ; } static getRealArcDistanceBetweenLonLats ( lon1 , lat1 , lon2 , lat2 ) { var φ1 = this . degreeToRadian ( lat1 ) ; var φ2 = this . degreeToRadian ( lat2 ) ; var Δφ = φ2 - φ1 ; var Δλ = this . degreeToRadian ( lon2 - lon1 ) ; var a = Math . sin ( Δφ / 2 ) ; var b = Math . sin ( Δλ / 2 ) ; var c = a * a + Math . cos ( φ1 ) * Math . cos ( φ2 ) * b * b ; var d = 2 * Math . atan2 ( Math . sqrt ( c ) , Math . sqrt ( 1 - c ) ) ; var distance = Kernel . REAL_EARTH_RADIUS * d ; return distance ; } param x return { Number } static webMercatorXToRadianLon ( x ) { return x / Kernel . EARTH_RADIUS ; } param x return { * } static webMercatorXToDegreeLon ( x ) { var radianLog = this . webMercatorXToRadianLon ( x ) ; return this . radianToDegree ( radianLog ) ; } param y return { Number } static webMercatorYToRadianLat ( y ) { if ( ! ( Utils . isNumber ( y ) ) ) { throw "invalid y" ; } var a = y / Kernel . EARTH_RADIUS ; var b = Math . pow ( Math . E , a ) ; var c = Math . atan ( b ) ; var radianLat = 2 * c - Math . PI / 2 ; return radianLat ; } param y return { * } static webMercatorYToDegreeLat ( y ) { var radianLat = this . webMercatorYToRadianLat ( y ) ; return this . radianToDegree ( radianLat ) ; } param x param y return { Array } static webMercatorToRadianGeographic ( x , y ) { var radianLog = this . webMercatorXToRadianLon ( x ) ; var radianLat = this . webMercatorYToRadianLat ( y ) ; return [ radianLog , radianLat ] ; } param x param y return { Array } static webMercatorToDegreeGeographic ( x , y ) { var degreeLog = this . webMercatorXToDegreeLon ( x ) ; var degreeLat = this . webMercatorYToDegreeLat ( y ) ; return [ degreeLog , degreeLat ] ; } param radianLog return { * } static radianLonToWebMercatorX ( radianLog , real = false ) { if ( ! ( Utils . isNumber ( radianLog ) && radianLog <= ( Math . PI + 0.001 ) && radianLog >= - ( Math . PI + 0.001 ) ) ) { throw "invalid radianLog" ; } if ( real ) { return Kernel . REAL_EARTH_RADIUS * radianLog ; } else { return Kernel . EARTH_RADIUS * radianLog ; } } param degreeLog return { * } static degreeLonToWebMercatorX ( degreeLog , real = false ) { if ( ! ( Utils . isNumber ( degreeLog ) && degreeLog <= ( 180 + 0.001 ) && degreeLog >= - ( 180 + 0.001 ) ) ) { throw "invalid degreeLog" ; } var radianLog = this . degreeToRadian ( degreeLog ) ; return this . radianLonToWebMercatorX ( radianLog , real ) ; } param radianLat return { Number } static radianLatToWebMercatorY ( radianLat , real = false ) { if ( ! ( radianLat <= ( Math . PI / 2 + 0.001 ) && radianLat >= - ( Math . PI / 2 + 0.001 ) ) ) { throw "invalid radianLat" ; } var a = Math . PI / 4 + radianLat / 2 ; var b = Math . tan ( a ) ; var c = Math . log ( b ) ; if ( real ) { return Kernel . REAL_EARTH_RADIUS * c ; } else { return Kernel . EARTH_RADIUS * c ; } } param degreeLat return { Number } static degreeLatToWebMercatorY ( degreeLat , real = false ) { if ( ! ( degreeLat <= ( 90 + 0.001 ) && degreeLat >= - ( 90 + 0.001 ) ) ) { throw "invalid degreeLat" ; } var radianLat = this . degreeToRadian ( degreeLat ) ; return this . radianLatToWebMercatorY ( radianLat , real ) ; } param radianLog param radianLat return { Array } static radianGeographicToWebMercator ( radianLog , radianLat ) { var x = this . radianLonToWebMercatorX ( radianLog ) ; var y = this . radianLatToWebMercatorY ( radianLat ) ; return [ x , y ] ; } param degreeLog param degreeLat return { Array } static degreeGeographicToWebMercator ( degreeLog , degreeLat ) { var x = this . degreeLonToWebMercatorX ( degreeLog ) ; var y = this . degreeLatToWebMercatorY ( degreeLat ) ; return [ x , y ] ; } static getTileWebMercatorEnvelopeByGrid ( level , row , column ) { var k = Kernel . MAX_PROJECTED_COORD ; var size = 2 * k / Math . pow ( 2 , level ) ; var minX = - k + column * size ; var maxX = minX + size ; var maxY = k - row * size ; var minY = maxY - size ; var Eproj = { "minX" : minX , "minY" : minY , "maxX" : maxX , "maxY" : maxY } ; return Eproj ; } static getTileGeographicEnvelopByGrid ( level , row , column ) { var Eproj = this . getTileWebMercatorEnvelopeByGrid ( level , row , column ) ; var pMin = this . webMercatorToDegreeGeographic ( Eproj . minX , Eproj . minY ) ; var pMax = this . webMercatorToDegreeGeographic ( Eproj . maxX , Eproj . maxY ) ; var Egeo = { "minLon" : pMin [ 0 ] , "minLat" : pMin [ 1 ] , "maxLon" : pMax [ 0 ] , "maxLat" : pMax [ 1 ] } ; return Egeo ; } static getTileCartesianEnvelopByGrid ( level , row , column ) { var Egeo = this . getTileGeographicEnvelopByGrid ( level , row , column ) ; var minLon = Egeo . minLon ; var minLat = Egeo . minLat ; var maxLon = Egeo . maxLon ; var maxLat = Egeo . maxLat ; var pLeftBottom = this . geographicToCartesianCoord ( minLon , minLat ) ; var pLeftTop = this . geographicToCartesianCoord ( minLon , maxLat ) ; var pRightTop = this . geographicToCartesianCoord ( maxLon , maxLat ) ; var pRightBottom = this . geographicToCartesianCoord ( maxLon , minLat ) ; var Ecar = { "pLeftBottom" : pLeftBottom , "pLeftTop" : pLeftTop , "pRightTop" : pRightTop , "pRightBottom" : pRightBottom , "minLon" : minLon , "minLat" : minLat , "maxLon" : maxLon , "maxLat" : maxLat } ; return Ecar ; } param level param row param column return { Array } static getGeographicTileCenter ( level , row , column ) { var Egeo = this . getTileGeographicEnvelopByGrid ( level , row , column ) ; var minLon = Egeo . minLon ; var minLat = Egeo . minLat ; var maxLon = Egeo . maxLon ; var maxLat = Egeo . maxLat ; var centerLon = ( minLon + maxLon ) / 2 ; var centerLat = ( minLat + maxLat ) / 2 ; var lonlatTileCenter = [ centerLon , centerLat ] ; return lonlatTileCenter ; } static getCartesianTileCenter ( level , row , column ) { var lonLat = this . getGeographicTileCenter ( level , row , column ) ; var vertice = this . geographicToCartesianCoord ( lonLat [ 0 ] , lonLat [ 1 ] ) ; return vertice ; } param p0 param p1 param p2 param count static quad ( p0 , p1 , p2 , count ) { const points = [ ] ; for ( var i = 0 ; i < count ; i ++ ) { if ( i === 0 ) { points . push ( p0 ) ; } else if ( i === count - 1 ) { points . push ( p2 ) ; } else { const t = i / count ; const a = ( 1 - t ) * ( 1 - t ) ; const b = 2 * t * ( 1 - t ) ; const c = t * t ; const x = a * p0 [ 0 ] + b * p1 [ 0 ] + c * p2 [ 0 ] ; const y = a * p0 [ 1 ] + b * p1 [ 1 ] + c * p2 [ 1 ] ; points . push ( [ x , y ] ) ; } } return points ; } param vs param ind return { Array } static calculateNormals ( vs , ind ) { var x = 0 ; var y = 1 ; var z = 2 ; var ns = [ ] ; for ( var i = 0 ; i < vs . length ; i = i + 3 ) { ns [ i + x ] = 0.0 ; ns [ i + y ] = 0.0 ; ns [ i + z ] = 0.0 ; } for ( var i = 0 ; i < ind . length ; i = i + 3 ) { var v1 = [ ] ; var v2 = [ ] ; var normal = [ ] ; v1 [ x ] = vs [ 3 * ind [ i + 2 ] + x ] - vs [ 3 * ind [ i + 1 ] + x ] ; v1 [ y ] = vs [ 3 * ind [ i + 2 ] + y ] - vs [ 3 * ind [ i + 1 ] + y ] ; v1 [ z ] = vs [ 3 * ind [ i + 2 ] + z ] - vs [ 3 * ind [ i + 1 ] + z ] ; v2 [ x ] = vs [ 3 * ind [ i ] + x ] - vs [ 3 * ind [ i + 1 ] + x ] ; v2 [ y ] = vs [ 3 * ind [ i ] + y ] - vs [ 3 * ind [ i + 1 ] + y ] ; v2 [ z ] = vs [ 3 * ind [ i ] + z ] - vs [ 3 * ind [ i + 1 ] + z ] ; normal [ x ] = v1 [ y ] * v2 [ z ] - v1 [ z ] * v2 [ y ] ; normal [ y ] = v1 [ z ] * v2 [ x ] - v1 [ x ] * v2 [ z ] ; normal [ z ] = v1 [ x ] * v2 [ y ] - v1 [ y ] * v2 [ x ] ; for ( var j = 0 ; j < 3 ; j ++ ) { ns [ 3 * ind [ i + j ] + x ] = ns [ 3 * ind [ i + j ] + x ] + normal [ x ] ; ns [ 3 * ind [ i + j ] + y ] = ns [ 3 * ind [ i + j ] + y ] + normal [ y ] ; ns [ 3 * ind [ i + j ] + z ] = ns [ 3 * ind [ i + j ] + z ] + normal [ z ] ; } } for ( var i = 0 ; i < vs . length ; i = i + 3 ) { var nn = [ ] ; nn [ x ] = ns [ i + x ] ; nn [ y ] = ns [ i + y ] ; nn [ z ] = ns [ i + z ] ; var len = Math . sqrt ( ( nn [ x ] * nn [ x ] ) + ( nn [ y ] * nn [ y ] ) + ( nn [ z ] * nn [ z ] ) ) ; if ( len == 0 ) len = 1.0 ; nn [ x ] = nn [ x ] / len ; nn [ y ] = nn [ y ] / len ; nn [ z ] = nn [ z ] / len ; ns [ i + x ] = nn [ x ] ; ns [ i + y ] = nn [ y ] ; ns [ i + z ] = nn [ z ] ; } return ns ; } param orig param dir param v0 param v1 param v2 static intersectTriangle ( orig , dir , v0 , v1 , v2 ) { var t , u , v ; var E1 = Vector . verticeMinusVertice ( v1 , v0 ) ; var E2 = Vector . verticeMinusVertice ( v2 , v0 ) ; var P = dir . cross ( E2 ) ; var det = E1 . dot ( P ) ; var T = null ; if ( det > 0 ) { T = Vector . verticeMinusVertice ( orig , v0 ) ; } else { T = Vector . verticeMinusVertice ( v0 , orig ) ; det = - det ; } if ( det < 0.0001 ) { return false ; } u = T . dot ( P ) ; if ( u < 0 || u > det ) { return false ; } var Q = T . cross ( E1 ) ; v = dir . dot ( Q ) ; if ( v < 0 || ( u + v ) > det ) { return false ; } return true ; } param worldVertice param localMatrix param inverseLocalMatrix static convertWorldVerticeToLocalVertice ( worldVertice , localMatrix , inverseLocalMatrix ? ) { if ( ! inverseLocalMatrix ) { inverseLocalMatrix = localMatrix . getInverseMatrix ( ) ; } const inputColumn = worldVertice . getArray ( ) ; inputColumn . push ( 1 ) ; const column = inverseLocalMatrix . multiplyColumn ( inputColumn ) ; const localVertice = new Vertice ( column [ 0 ] , column [ 1 ] , column [ 2 ] ) ; return localVertice ; } param worldVector param localMatrix param inverseLocalMatrix static convertWorldVectorToLocalVector ( worldVector , localMatrix , inverseLocalMatrix ? ) { if ( ! inverseLocalMatrix ) { inverseLocalMatrix = localMatrix . getInverseMatrix ( ) ; } const worldVertice1 = new Vertice ( 0 , 0 , 0 ) ; const worldVertice2 = worldVector . getVertice ( ) ; const localVertice1 = this . convertWorldVerticeToLocalVertice ( worldVertice1 , localMatrix , inverseLocalMatrix ) ; const localVertice2 = this . convertWorldVerticeToLocalVertice ( worldVertice2 , localMatrix , inverseLocalMatrix ) ; const localVector = Vector . verticeMinusVertice ( localVertice2 , localVertice1 ) ; localVector . normalize ( ) ; return localVector ; } param worldLine param localMatrix param inverseLocalMatrix static convertWorldLineToLocalLine ( worldLine , localMatrix , inverseLocalMatrix ? ) { if ( ! inverseLocalMatrix ) { inverseLocalMatrix = localMatrix . getInverseMatrix ( ) ; } const localVertice = this . convertWorldVerticeToLocalVertice ( worldLine . vertice , localMatrix , inverseLocalMatrix ) ; const localVector = this . convertWorldVectorToLocalVector ( worldLine . vector , localMatrix , inverseLocalMatrix ) ; const localLine = new Line ( localVertice , localVector ) ; return localLine ; } } ;