├── .npmignore ├── .prettierrc ├── LICENSE ├── README.md ├── clamp.js ├── constants.js ├── cross.js ├── degToRad.js ├── distance.js ├── fract.js ├── geocentricToPolar.js ├── index.js ├── length.js ├── lerp.js ├── map.js ├── normal.js ├── normalize.js ├── package-lock.json ├── package.json ├── polarToGeocentric.js └── radToDeg.js /.npmignore: -------------------------------------------------------------------------------- 1 | .npmignore 2 | index.html -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "tabWidth": 4, 4 | "useTabs": true, 5 | "singleQuote": true, 6 | "printWidth": 80, 7 | "bracketSpacing": true, 8 | "trailingComma": "all" 9 | } 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Raphaël Améaume 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # lemonade-math 2 | 3 | Math utility functions 4 | 5 | ## Installation 6 | 7 | ``` 8 | npm install lemonade-math 9 | ``` 10 | 11 | ### Usage 12 | 13 | ```js 14 | import { lerp } from 'lemonade-math'; 15 | 16 | console.log(lerp(0, 2, 0.5)); // 1 17 | ``` 18 | 19 | ## Constants 20 | 21 | #### `PI` 22 | 23 | #### `TAU` 24 | 25 | #### `HALF_PI` 26 | 27 | #### `RAD2DEG` 28 | 29 | #### `DEG2RAD` 30 | 31 | ## Functions 32 | 33 | #### `clamp` 34 | 35 | - Type: `(value: number, min:number, max:number) => number` 36 | 37 | Constrain a value to lie between two further values 38 | 39 | #### `cross` 40 | 41 | - Type: `(a: number[3], b: number[3]) => number[3]` 42 | 43 | Compute the cross product of two 3D vectors 44 | 45 | #### `degToRad` 46 | 47 | - Type: `(angle: number) => number` 48 | 49 | Convert an angle in degrees to radians 50 | 51 | #### `distance` 52 | 53 | - Type: `(a: number[2|3], b: number[2|3]) => number` 54 | 55 | Compute the Euclidian distance between two vectors 56 | 57 | #### `distance2D` 58 | 59 | - Type: `(a: number[2], b: number[2]) => number` 60 | 61 | Compute the Euclidian distance between two 2D vectors 62 | 63 | #### `distance3D` 64 | 65 | - Type: `(a: number[3], b: number[3]) => number` 66 | 67 | Compute the Euclidian distance between two 3D vectors 68 | 69 | #### `squaredDistance` 70 | 71 | - Type: `(a: number[2|3], b: number[2|3]) => number` 72 | 73 | Compute the square of the Euclidian distance between two vectors 74 | 75 | #### `squaredDistance2D` 76 | 77 | - Type: `(a: number[2], b: number[2]) => number` 78 | 79 | Compute the square of the Euclidian distance between two 2D vectors 80 | 81 | #### `squaredDistance3D` 82 | 83 | - Type: `(a: number[3], b: number[3]) => number` 84 | 85 | Compute the square of the Euclidian distance between two 3D vectors 86 | 87 | #### `fract` 88 | 89 | - Type: `(value: number) => number` 90 | 91 | Compute the fractional part of a value 92 | 93 | #### `geocentricToPolar` 94 | 95 | - Type: `({ x: number, y: number, z: number }) => { latitude: number, longitude: number }` 96 | 97 | Convert geocentric coordinates (x, y, z) to polar coordinates (latitude, longitude) 98 | 99 | #### `length` 100 | 101 | - Type: `(a: number[2|3|4], b: number[2|3|4]) => number` 102 | 103 | Compute the Euclidian length between two vectors 104 | 105 | #### `length2D` 106 | 107 | - Type: `(a: number[2], b: number[2]) => number` 108 | 109 | Compute the Euclidian length between two 2D vectors 110 | 111 | #### `length3D` 112 | 113 | - Type: `(a: number[3], b: number[3]) => number` 114 | 115 | Compute the Euclidian length between two 3D vectors 116 | 117 | #### `length4D` 118 | 119 | - Type: `(a: number[4], b: number[4]) => number` 120 | 121 | Compute the Euclidian length between two 4D vectors 122 | 123 | #### `squaredLength` 124 | 125 | - Type: `(a: number[2|3|4], b: number[2|3|4]) => number` 126 | 127 | Compute the square of the Euclidian length between two vectors 128 | 129 | #### `squaredLength2D` 130 | 131 | - Type: `(a: number[2], b: number[2]) => number` 132 | 133 | Compute the square of the Euclidian length between two 2D vectors 134 | 135 | #### `squaredLength3D` 136 | 137 | - Type: `(a: number[3], b: number[3]) => number` 138 | 139 | Compute the square of the Euclidian length between two 3D vectors 140 | 141 | #### `squaredLength4D` 142 | 143 | - Type: `(a: number[4], b: number[4]) => number` 144 | 145 | Compute the square of the Euclidian length between two 4D vectors 146 | 147 | #### `lerp` 148 | 149 | - Type: `(a: number, b: number) => number` 150 | 151 | Linearly interpolate between two values 152 | 153 | #### `lerp2D` 154 | 155 | - Type: `(a: number[2], b: number[2]) => number[2]` 156 | 157 | Linearly interpolate between two 2D vectors 158 | 159 | #### `lerp3D` 160 | 161 | - Type: `(a: number[3], b: number[3]) => number[3]` 162 | 163 | Linearly interpolate between two 3D vectors 164 | 165 | #### `lerp4D` 166 | 167 | - Type: `(a: number[4], b: number[4]) => number[4]` 168 | 169 | Linearly interpolate between two 4D vectors 170 | 171 | #### `map` 172 | 173 | - Type: `(value: number, min: number, max: number, nmin: number, nmax: number) => number` 174 | 175 | Convert a number from one range to an other 176 | 177 | #### `normal` 178 | 179 | - Type: `(a: number[2], b: number[2], direction?: number) => number[2]` 180 | 181 | Compute the normal between two 2D vectors 182 | 183 | #### `normalize` 184 | 185 | - Type: `(a: number[2|3|4], b: number[2|3|4]) => number[2|3|4]` 186 | 187 | Compute the unit vector of a vector 188 | 189 | #### `normalize2D` 190 | 191 | - Type: `(a: number[2], b: number[2]) => number[2]` 192 | 193 | Compute the unit vector of a 2D vector 194 | 195 | #### `normalize3D` 196 | 197 | - Type: `(a: number[3], b: number[3]) => number[3]` 198 | 199 | Compute the unit vector of a 3D vector 200 | 201 | #### `normalize4D` 202 | 203 | - Type: `(a: number[4], b: number[4]) => number[4]` 204 | 205 | Compute the unit vector of a 4D vector 206 | 207 | #### `polarToGeocentric` 208 | 209 | - Type: `({ latitude: number, longitude: number }) => { x: number, y: number, z: number }` 210 | 211 | Convert polar coordinates (latitude, longitude) to geocentric coordinates (x,y,z) 212 | 213 | #### `radToDeg` 214 | 215 | - Type: `(angle: number) => number` 216 | 217 | Convert an angle in radians to degrees 218 | 219 | ## License 220 | 221 | MIT License, see [LICENSE](https://github.com/raphaelameaume/lemonade-helpers/tree/master/LICENSE) for details 222 | -------------------------------------------------------------------------------- /clamp.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Constrain a value to lie between two further values 3 | * @param {number} value 4 | * @param {number} min 5 | * @param {number} max 6 | * @returns {number} 7 | */ 8 | export function clamp(value, min, max) { 9 | return Math.max(min, Math.min(value, max)); 10 | } 11 | -------------------------------------------------------------------------------- /constants.js: -------------------------------------------------------------------------------- 1 | export const PI = Math.PI; 2 | export const TAU = PI * 2; 3 | export const HALF_PI = PI * 0.5; 4 | export const RAD2DEG = 180 / PI; 5 | export const DEG2RAD = PI / 180; 6 | -------------------------------------------------------------------------------- /cross.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Compute the cross product of two 3D vectors 3 | * @param {[number, number, number]} a 4 | * @param {[number, number, number]} b 5 | * @returns {[number, number, number]} 6 | */ 7 | export function cross([ax, ay, az], [bx, by, bz]) { 8 | return [ay * bz - az * by, az * bx - ax * bz, ax * by - ay * bx]; 9 | } 10 | -------------------------------------------------------------------------------- /degToRad.js: -------------------------------------------------------------------------------- 1 | import { DEG2RAD } from './constants.js'; 2 | 3 | /** 4 | * Convert an angle in degrees to radians 5 | * @param {number} angle 6 | * @returns {number} 7 | */ 8 | export function degToRad(angle) { 9 | return angle * DEG2RAD; 10 | } 11 | -------------------------------------------------------------------------------- /distance.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Compute the square of the Euclidian distance between two 2D vectors 3 | * @param {[number, number]|[number, number, number]} a 4 | * @param {[number, number]|[number, number, number]} b 5 | * @returns {number} 6 | */ 7 | export function squaredDistance(a, b) { 8 | if (a.length === b.length && a.length === 2) return squaredDistance2D(a, b); 9 | if (a.length === b.length && a.length === 3) return squaredDistance3D(a, b); 10 | } 11 | 12 | /** 13 | * Compute the square of the Euclidian distance between two 2D vectors 14 | * @param {[number, number]} a 15 | * @param {[number, number]} b 16 | * @returns {number} 17 | */ 18 | export function squaredDistance2D([ax, ay], [bx, by]) { 19 | const dx = bx - ax; 20 | const dy = by - ay; 21 | 22 | return dx * dx + dy * dy + dz * dz; 23 | } 24 | 25 | /** 26 | * Compute the square of the Euclidian distance between two 3D vectors 27 | * @param {[number, number, number]} a 28 | * @param {[number, number, number]} b 29 | * @returns {number} 30 | */ 31 | export function squaredDistance3D([ax, ay, az], [bx, by, bz]) { 32 | const dx = bx - ax; 33 | const dy = by - ay; 34 | const dz = bz - az; 35 | 36 | return dx * dx + dy * dy + dz * dz; 37 | } 38 | 39 | /** 40 | * Compute the Euclidian distance between two vectors 41 | * @param {[number, number]|[number, number, number]} a 42 | * @param {[number, number]|[number, number, number]} b 43 | * @returns {number} 44 | */ 45 | export function distance(a, b) { 46 | if (a.length === b.length && a.length === 2) return distance2D(a, b); 47 | if (a.length === b.length && a.length === 3) return distance3D(a, b); 48 | } 49 | 50 | /** 51 | * Compute the Euclidian distance between two 2D vectors 52 | * @param {[number, number]} a 53 | * @param {[number, number]} b 54 | * @returns {number} 55 | */ 56 | export function distance2D(a, b) { 57 | return Math.sqrt(squaredDistance2D(a, b)); 58 | } 59 | 60 | /** 61 | * Compute the Euclidian distance between two 3D vectors 62 | * @param {[number, number, number]} a 63 | * @param {[number, number, number]} b 64 | * @returns {number} 65 | */ 66 | export function distance3D(a, b) { 67 | return Math.sqrt(squaredDistance3D(a, b)); 68 | } 69 | -------------------------------------------------------------------------------- /fract.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Compute the fractional part of a value 3 | * @param {number} value 4 | * @returns {number} 5 | */ 6 | export function fract(value) { 7 | return value - Math.floor(value); 8 | } 9 | -------------------------------------------------------------------------------- /geocentricToPolar.js: -------------------------------------------------------------------------------- 1 | import { RAD2DEG } from './constants.js'; 2 | import { clamp } from './clamp.js'; 3 | import { map } from './map.js'; 4 | 5 | /** 6 | * Convert geocentric coordinates (x, y, z) to polar coordinates (latitude, longitude) 7 | * @param {Object} geocentricCoordinates 8 | * @param {number} geocentricCoordinates.x 9 | * @param {number} geocentricCoordinates.y 10 | * @param {number} geocentricCoordinates.z 11 | * @returns {Object} polarCoordinates 12 | * @returns {number} polarCoordinates.latitude - In degrees, in range [-90, 90] 13 | * @returns {number} polarCoordinates.longitude - In degrees, in range [-180, 180] 14 | */ 15 | export function geocentricToPolar({ x, y, z }) { 16 | let radius = Math.sqrt(x * x + y * y + z * z); 17 | let theta = 0; 18 | let phi = 0; 19 | 20 | if (radius !== 0) { 21 | theta = Math.atan2(x, z); 22 | phi = Math.acos(clamp(y / radius, -1, 1)); 23 | } 24 | 25 | let longitude = theta * RAD2DEG - 90; 26 | 27 | if (longitude < -180) { 28 | longitude = 180 - (Math.abs(longitude) - 180); 29 | } 30 | 31 | let latitude = map(phi * RAD2DEG, 0, 180, 90, -90); 32 | 33 | return { latitude, longitude }; 34 | } 35 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | export { clamp } from './clamp.js'; 2 | export { PI, TAU, HALF_PI, DEG2RAD, RAD2DEG } from './constants.js'; 3 | export { cross } from './cross.js'; 4 | export { degToRad } from './degToRad.js'; 5 | export { 6 | distance, 7 | distance2D, 8 | distance3D, 9 | squaredDistance, 10 | squaredDistance2D, 11 | squaredDistance3D, 12 | } from './distance.js'; 13 | export { fract } from './fract.js'; 14 | export { geocentricToPolar } from './geocentricToPolar.js'; 15 | export { 16 | length, 17 | length2D, 18 | length3D, 19 | length4D, 20 | squaredLength, 21 | squaredLength2D, 22 | squaredLength3D, 23 | squaredLength4D, 24 | } from './length.js'; 25 | export { lerp, lerp2D, lerp3D, lerp4D } from './lerp.js'; 26 | export { map } from './map.js'; 27 | export { normal } from './normal.js'; 28 | export { 29 | normalize, 30 | normalize2D, 31 | normalize3D, 32 | normalize4D, 33 | } from './normalize.js'; 34 | export { polarToGeocentric } from './polarToGeocentric.js'; 35 | export { radToDeg } from './radToDeg.js'; 36 | -------------------------------------------------------------------------------- /length.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Compute the square of the Euclidian length of a vector 3 | * @param {[number, number]|[number, number, number]|[number, number, number, number]} a 4 | * @returns {number} 5 | */ 6 | export function squaredLength(a) { 7 | if (a.length === 2) return squaredLength2D(a); 8 | if (a.length === 3) return squaredLength3D(a); 9 | if (a.length === 4) return squaredLength4D(a); 10 | } 11 | 12 | /** 13 | * Compute the square of the Euclidian length of a 2D vector 14 | * @param {[number, number]} a 15 | * @returns {number} 16 | */ 17 | export function squaredLength2D([x, y]) { 18 | return x * x + y * y; 19 | } 20 | 21 | /** 22 | * Compute the square of the Euclidian length of a 3D vector 23 | * @param {[number, number, number]} a 24 | * @returns {number} 25 | */ 26 | export function squaredLength3D([x, y, z]) { 27 | return x * x + y * y + z * z; 28 | } 29 | 30 | /** 31 | * Compute the square of the Euclidian length of a 4D vector 32 | * @param {[number, number, number, number]} a 33 | * @returns {number} 34 | */ 35 | export function squaredLength4D([x, y, z, w]) { 36 | return x * x + y * y + z * z + w * w; 37 | } 38 | 39 | /** 40 | * Compute the Euclidian length of a vector 41 | * @param {[number, number]|[number, number, number]|[number, number, number, number]} a 42 | * @returns {number} 43 | */ 44 | export function length(a) { 45 | if (a.length === 2) return length2D(a); 46 | if (a.length === 3) return length3D(a); 47 | if (a.length === 4) return length4D(a); 48 | } 49 | 50 | /** 51 | * Compute the Euclidian length of a 2D vector 52 | * @param {[number, number]} a 53 | * @returns {number} 54 | */ 55 | export function length2D(a) { 56 | return Math.sqrt(squaredLength2D(a)); 57 | } 58 | 59 | /** 60 | * Compute the Euclidian length of a 3D vector 61 | * @param {[number, number, number]} a 62 | * @returns {number} 63 | */ 64 | export function length3D(a) { 65 | return Math.sqrt(squaredLength3D(a)); 66 | } 67 | 68 | /** 69 | * Compute the Euclidian length of a 4D vector 70 | * @param {[number, number, number, number]} a 71 | * @returns {number} 72 | */ 73 | export function length4D(a) { 74 | return Math.sqrt(squaredLength4D(a)); 75 | } 76 | -------------------------------------------------------------------------------- /lerp.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Linearly interpolate between two values 3 | * @param {number} x - Specify the start of the range in which to interpolate 4 | * @param {number} y - Specify the end of the range in which to interpolate. 5 | * @param {number} t - Specify the value to use to interpolate between x and y 6 | * @returns {number} 7 | */ 8 | export function lerp(x, y, t) { 9 | return (1 - t) * x + t * y; 10 | } 11 | 12 | /** 13 | * Linearly interpolate between two 2D vectors 14 | * @param {[number, number]} a 15 | * @param {[number, number]} b 16 | * @param {number} t 17 | * @returns {[number, number]} 18 | */ 19 | export function lerp2D([ax, ay], [bx, by], t) { 20 | return [lerp(ax, bx, t), lerp(ay, by, t)]; 21 | } 22 | 23 | /** 24 | * Linearly interpolate between two 3D vectors 25 | * @param {[number, number, number]} a 26 | * @param {[number, number, number]} b 27 | * @param {number} t 28 | * @returns {[number, number, number]} 29 | */ 30 | export function lerp3D([ax, ay, az], [bx, by, bz], t) { 31 | return [lerp(ax, bx, t), lerp(ay, by, t), lerp(az, bz, t)]; 32 | } 33 | 34 | /** 35 | * Linearly interpolate between two 4D vectors 36 | * @param {[number, number, number, number]} a 37 | * @param {[number, number, number, number]} b 38 | * @param {number} t 39 | * @returns {[number, number, number, number]} 40 | */ 41 | export function lerp4D([ax, ay, az, aw], [bx, by, bz, bw], t) { 42 | return [lerp(ax, bx, t), lerp(ay, by, t), lerp(az, bz, t), lerp(aw, bw, t)]; 43 | } 44 | -------------------------------------------------------------------------------- /map.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Convert a number from one range to an other 3 | * @param {number} value 4 | * @param {number} min 5 | * @param {number} max 6 | * @param {number} nmin 7 | * @param {number} nmax 8 | * @returns {number} 9 | */ 10 | export function map(value, min, max, nmin, nmax) { 11 | return ((value - min) / (max - min)) * (nmax - nmin) + nmin; 12 | } 13 | -------------------------------------------------------------------------------- /normal.js: -------------------------------------------------------------------------------- 1 | import { normalize2D } from './normalize.js'; 2 | 3 | /** 4 | * Compute the normal between two 2D vectors 5 | * @param {[number, number]} a 6 | * @param {[number, number]} b 7 | * @param {number} direction 8 | * @returns {[number, number]} 9 | */ 10 | export function normal([ax, ay], [bx, by], direction = 1) { 11 | const dx = bx - ax; 12 | const dy = by - ay; 13 | 14 | return direction > 0 ? normalize2D([-dy, dx]) : normalize2D([dy, -dx]); 15 | } 16 | -------------------------------------------------------------------------------- /normalize.js: -------------------------------------------------------------------------------- 1 | import { length2D, length3D, length4D } from './length.js'; 2 | 3 | /** 4 | * Compute the unit vector of a vector 5 | * @param {[number, number]|[number, number, number]|[number, number, number, number]} a 6 | * @returns {[number, number]|[number, number, number]|[number, number, number, number]} 7 | */ 8 | export function normalize(a) { 9 | if (a.length === 2) return normalize2D(a); 10 | if (a.length === 3) return normalize3D(a); 11 | if (a.length === 4) return normalize4D(a); 12 | } 13 | 14 | /** 15 | * Compute the unit vector of a 2D vector 16 | * @param {[number, number]} a 17 | * @returns {[number, number]} 18 | */ 19 | export function normalize2D(a) { 20 | let len = length2D(a); 21 | 22 | return [a[0] * len, a[1] * len]; 23 | } 24 | 25 | /** 26 | * Compute the unit vector of a 3D vector 27 | * @param {[number, number, number]} a 28 | * @returns {[number, number, number]} 29 | */ 30 | export function normalize3D(a) { 31 | let len = length3D(a); 32 | 33 | return [a[0] * len, a[1] * len, a[2] * len]; 34 | } 35 | 36 | /** 37 | * Compute the unit vector of a 4D vector 38 | * @param {[number, number, number, number]} a 39 | * @returns {[number, number, number, number]} 40 | */ 41 | export function normalize4D(a) { 42 | let len = length4D(a); 43 | 44 | return [a[0] * len, a[1] * len, a[2] * len, a[3] * len]; 45 | } 46 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lemonade-math", 3 | "version": "1.1.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "lemonade-math", 9 | "version": "1.1.0", 10 | "license": "MIT" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lemonade-math", 3 | "version": "1.2.0", 4 | "description": "Math utility functions", 5 | "main": "./index.js", 6 | "module": "./index.js", 7 | "type": "module", 8 | "repository": { 9 | "type": "git", 10 | "url": "git+https://github.com/raphaelameaume/lemonade-math.git" 11 | }, 12 | "keywords": [ 13 | "math", 14 | "geometry", 15 | "utils" 16 | ], 17 | "author": "Raphaël Améaume", 18 | "license": "MIT", 19 | "bugs": { 20 | "url": "https://github.com/raphaelameaume/lemonade-math/issues" 21 | }, 22 | "homepage": "https://github.com/raphaelameaume/lemonade-math#readme" 23 | } 24 | -------------------------------------------------------------------------------- /polarToGeocentric.js: -------------------------------------------------------------------------------- 1 | import { DEG2RAD } from './constants.js'; 2 | 3 | /** 4 | * Convert polar coordinates (latitude, longitude) to geocentric coordinates (x,y,z) 5 | * @param {Object} options 6 | * @param {number} options.latitude - In degrees, in range [-90, 90] 7 | * @param {number} options.longitude - In degrees, in range [-180, 180] 8 | * @param {number} [options.radius=1] 9 | * @returns {Object} geocentricCoordinates 10 | * @returns {number} geocentricCoordinates.x 11 | * @returns {number} geocentricCoordinates.y 12 | * @returns {number} geocentricCoordinates.z 13 | */ 14 | export function polarToGeocentric({ latitude, longitude, radius = 1 }) { 15 | const phi = (90 - latitude) * DEG2RAD; 16 | const theta = (longitude + 180) * DEG2RAD; 17 | 18 | const x = -(radius * Math.sin(phi) * Math.cos(theta)); 19 | const z = radius * Math.sin(phi) * Math.sin(theta); 20 | const y = radius * Math.cos(phi); 21 | 22 | return { x, y, z }; 23 | } 24 | -------------------------------------------------------------------------------- /radToDeg.js: -------------------------------------------------------------------------------- 1 | import { RAD2DEG } from './constants.js'; 2 | 3 | /** 4 | * Convert an angle in radians to degrees 5 | * @param {number} angle 6 | * @returns {number} 7 | */ 8 | export function radToDeg(angle) { 9 | return angle * RAD2DEG; 10 | } 11 | --------------------------------------------------------------------------------