diff --git a/src/body/Earth.ts b/src/body/Earth.ts index d6bb288..57870f4 100644 --- a/src/body/Earth.ts +++ b/src/body/Earth.ts @@ -153,8 +153,8 @@ export class Earth { /** * Calculates the diameter of the Earth based on the satellite position. - * @param satPos The position of the satellite. - * @returns The diameter of the Earth. + * @param satPos The position of the satellite. @returns The diameter of the + * Earth. */ static diameter(satPos: Vector3D): number { return angularDiameter(Earth.radiusEquator * 2, satPos.magnitude(), AngularDiameterMethod.Sphere); diff --git a/src/body/Moon.ts b/src/body/Moon.ts index 99652d8..7593bb2 100644 --- a/src/body/Moon.ts +++ b/src/body/Moon.ts @@ -1,41 +1,43 @@ /** * @author Theodore Kruczek. - * @description Orbital Object ToolKit Core (ootk-core) is a collection of tools for working - * with satellites and other orbital objects. + * @description Orbital Object ToolKit Core (ootk-core) is a collection of tools + * for working with satellites and other orbital objects. * * Some of the math in this file was originally created by Vladimir Agafonkin. - * Robert Gester's update was referenced for documentation. There were a couple of - * bugs in both versions so there will be some differences if you are migrating from - * either to this library. + * Robert Gester's update was referenced for documentation. There were a couple + * of bugs in both versions so there will be some differences if you are + * migrating from either to this library. * - * @Copyright (c) 2011-2015, Vladimir Agafonkin - * SunCalc is a JavaScript library for calculating sun/moon position and light phases. + * @Copyright (c) 2011-2015, Vladimir Agafonkin SunCalc is a JavaScript library + * for calculating sun/moon position and light phases. * https://github.com/mourner/suncalc * - * Reworked and enhanced by Robert Gester - * @Copyright (c) 2022 Robert Gester + * Reworked and enhanced by Robert Gester @Copyright (c) 2022 Robert Gester * https://github.com/hypnos3/suncalc3 * - * moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + * moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html + * formulas * * @license MIT License * - * @Copyright (c) 2022-2024 Theodore Kruczek - * Permission is hereby granted, free of charge, to any person obtaining a copy of this - * software and associated documentation files (the "Software"), to deal in the Software - * without restriction, including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons - * to whom the Software is furnished to do so, subject to the following conditions: + * @Copyright (c) 2022-2024 Theodore Kruczek Permission is hereby granted, free + * of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: * - * The above copyright notice and this permission notice shall be included in all copies or - * substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE - * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. */ import { AngularDiameterMethod, Celestial, Degrees, Kilometers, RaDec, Radians } from '../main'; @@ -96,7 +98,7 @@ export class Moon { static radiusEquator = 1738.0; // / Calculate the Moon's ECI position _(km)_ for a given UTC [epoch]. - static eci(epoch: EpochUTC = EpochUTC.fromDateTime(new Date())): Vector3D { + static eci(epoch: EpochUTC = EpochUTC.fromDateTime(new Date())): Vector3D { const jc = epoch.toJulianCenturies(); const dtr = DEG2RAD; const lamEcl = @@ -133,18 +135,21 @@ export class Moon { const rMOD = r.scale(Earth.radiusEquator); const p = Earth.precession(epoch); - return rMOD.rotZ(p.zed).rotY(-p.theta).rotZ(p.zeta); + return rMOD + .rotZ(p.zed) + .rotY(-p.theta as Radians) + .rotZ(p.zeta) as Vector3D; } /** * Calculates the illumination of the Moon at a given epoch. * * @param epoch - The epoch in UTC. - * @param origin - The origin vector. Defaults to the origin vector if not provided. - * @returns The illumination of the Moon, ranging from 0 to 1. + * @param origin - The origin vector. Defaults to the origin vector if not + * provided. @returns The illumination of the Moon, ranging from 0 to 1. */ - static illumination(epoch: EpochUTC, origin?: Vector3D): number { - const orig = origin ?? Vector3D.origin; + static illumination(epoch: EpochUTC, origin?: Vector3D): number { + const orig = origin ?? (Vector3D.origin as Vector3D); const sunPos = Sun.position(epoch).subtract(orig); const moonPos = this.eci(epoch).subtract(orig); const phaseAngle = sunPos.angle(moonPos); @@ -156,19 +161,21 @@ export class Moon { * Calculates the diameter of the Moon. * * @param obsPos - The position of the observer. - * @param moonPos - The position of the Moon. - * @returns The diameter of the Moon. + * @param moonPos - The position of the Moon. @returns The diameter of the + * Moon. */ static diameter(obsPos: Vector3D, moonPos: Vector3D): number { return angularDiameter(this.radiusEquator * 2, obsPos.subtract(moonPos).magnitude(), AngularDiameterMethod.Sphere); } /** - * calculations for illumination parameters of the moon, - * based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and - * Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. - * @param {number | Date} date Date object or timestamp for calculating moon-illumination - * @return {MoonIlluminationData} result object of moon-illumination + * calculations for illumination parameters of the moon, based on + * http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and Chapter + * 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, + * Richmond) 1998. + * @param {number | Date} date Date object or timestamp for calculating + * moon-illumination @return {MoonIlluminationData} result object of + * moon-illumination */ // eslint-disable-next-line max-statements static getMoonIllumination(date: number | Date): MoonIlluminationData { @@ -191,7 +198,10 @@ export class Moon { ); const phaseValue = 0.5 + (0.5 * inc * (angle < 0 ? -1 : 1)) / Math.PI; - // calculates the difference in ms between the sirst fullMoon 2000 and given Date + /* + * calculates the difference in ms between the sirst fullMoon 2000 and given + * Date + */ const diffBase = dateValue - firstNewMoon2000; // Calculate modulus to drop completed cycles let cycleModMs = diffBase % lunarDaysMs; @@ -218,8 +228,8 @@ export class Moon { nextThirdQuarter += lunarDaysMs; } /* - * Calculate the fraction of the moon cycle - * const currentfrac = cycleModMs / lunarDaysMs; + * Calculate the fraction of the moon cycle const currentfrac = cycleModMs / + * lunarDaysMs; */ const next = Math.min(nextNewMoon, nextFirstQuarter, nextFullMoon, nextThirdQuarter); // eslint-disable-next-line init-declarations @@ -293,7 +303,10 @@ export class Moon { const c = Moon.moonCoords(d); const H = Sun.siderealTime(d, lw) - c.ra; let h = Celestial.elevation(H, phi, c.dec); - // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + /* + * formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus + * (Willmann-Bell, Richmond) 1998. + */ const pa = Math.atan2(Math.sin(H), Math.tan(phi) * Math.cos(c.dec) - Math.sin(c.dec) * Math.cos(H)); h = (h + Celestial.atmosphericRefraction(h)); // altitude correction for refraction @@ -307,7 +320,8 @@ export class Moon { } /** - * calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + * calculations for moon rise/set times are based on + * http://www.stargazing.net/kepler/moonrise.html article */ static getMoonTimes(date: Date, lat: Degrees, lon: Degrees, isUtc = false) { // Clone the date so we don't change the original @@ -366,7 +380,8 @@ export class Moon { * Calculates the geocentric ecliptic coordinates of the moon. * * @param d - The number of days since year 2000. - * @returns An object containing the right ascension, declination, and distance to the moon. + * @returns An object containing the right ascension, declination, and + * distance to the moon. */ static moonCoords(d: number): RaDec { const L = DEG2RAD * (218.316 + 13.176396 * d); // ecliptic longitude @@ -400,7 +415,10 @@ export class Moon { let x2 = 0; let dx = 0; - // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + /* + * go in 2-hour chunks, each time seeing if a 3-point quadratic curve + * crosses zero (which means rise or set) + */ for (let i = 1; i <= 24; i += 2) { h1 = Moon.rae(Moon.hoursLater_(t, i), lat, lon).el - hc; h2 = Moon.rae(Moon.hoursLater_(t, i + 1), lat, lon).el - hc; diff --git a/src/body/Sun.ts b/src/body/Sun.ts index 60c4e80..cf6d77d 100644 --- a/src/body/Sun.ts +++ b/src/body/Sun.ts @@ -30,8 +30,8 @@ export class Sun { static readonly e = DEG2RAD * 23.4397; /** - * Array representing the times for different phases of the sun. - * Each element in the array contains: + * Array representing the times for different phases of the sun. Each element + * in the array contains: * - The angle in degrees representing the time offset from solar noon. * - The name of the start time for the phase. * - The name of the end time for the phase. @@ -66,8 +66,8 @@ export class Sun { */ static readonly solarFlux = 1367.0; /** - * The solar pressure exerted by the Sun. (N/m²) - * It is calculated as the solar flux divided by the speed of light. + * The solar pressure exerted by the Sun. (N/m²) It is calculated as the solar + * flux divided by the speed of light. */ static readonly solarPressure = Sun.solarFlux / (cKmPerSec * 1000); /** @@ -80,12 +80,13 @@ export class Sun { } /** - * Calculates the azimuth and elevation of the Sun for a given date, latitude, and longitude. + * Calculates the azimuth and elevation of the Sun for a given date, latitude, + * and longitude. * @param date - The date for which to calculate the azimuth and elevation. - * @param lat - The latitude in degrees. - * @param lon - The longitude in degrees. - * @param c - The right ascension and declination of the target. Defaults to the Sun's right ascension and declination - * @returns An object containing the azimuth and elevation of the Sun in radians. + * @param lat - The latitude in degrees. @param lon - The longitude in + * degrees. @param c - The right ascension and declination of the target. + * Defaults to the Sun's right ascension and declination @returns An object + * containing the azimuth and elevation of the Sun in radians. */ static azEl(date: Date, lat: Degrees, lon: Degrees, c?: RaDec): AzEl { const lw = (-lon * DEG2RAD); @@ -114,16 +115,16 @@ export class Sun { } /** - * Calculate the Sun's angular diameter _(rad)_ from an ECI observer - * position [obsPos] and Sun position [sunPos] _(km)_. + * Calculate the Sun's angular diameter _(rad)_ from an ECI observer position + * [obsPos] and Sun position [sunPos] _(km)_. */ static diameter(obsPos: Vector3D, sunPos: Vector3D): number { return angularDiameter(this.radius * 2, obsPos.subtract(sunPos).magnitude(), AngularDiameterMethod.Sphere); } /** - * Calculate eclipse angles given a satellite ECI position [satPos] _(km)_ - * and Sun ECI position [sunPos] _(km)_. + * Calculate eclipse angles given a satellite ECI position [satPos] _(km)_ and + * Sun ECI position [sunPos] _(km)_. * * Returns a tuple containing the following three values: * - central body angle _(rad)_ @@ -145,8 +146,9 @@ export class Sun { } /** - * Ecliptic latitude measures the distance north or south of the ecliptic, attaining +90° at the north ecliptic - * pole (NEP) and -90° at the south ecliptic pole (SEP). The ecliptic itself is 0° latitude. + * Ecliptic latitude measures the distance north or south of the ecliptic, + * attaining +90° at the north ecliptic pole (NEP) and -90° at the south + * ecliptic pole (SEP). The ecliptic itself is 0° latitude. * * @param {number} B - ? * @returns {number} ecliptic latitude @@ -159,14 +161,14 @@ export class Sun { } /** - * Ecliptic longitude, also known as celestial longitude, measures the angular distance of an - * object along the ecliptic from the primary direction. It is measured positive eastwards in - * the fundamental plane (the ecliptic) from 0° to 360°. The primary direction - * (0° ecliptic longitude) points from the Earth towards the Sun at the vernal equinox of the - * Northern Hemisphere. Due to axial precession, the ecliptic longitude of most "fixed stars" - * increases by about 50.3 arcseconds per year, or 83.8 arcminutes per century. - * @param {number} M - solar mean anomaly - * @returns {number} ecliptic longitude + * Ecliptic longitude, also known as celestial longitude, measures the angular + * distance of an object along the ecliptic from the primary direction. It is + * measured positive eastwards in the fundamental plane (the ecliptic) from 0° + * to 360°. The primary direction (0° ecliptic longitude) points from the + * Earth towards the Sun at the vernal equinox of the Northern Hemisphere. Due + * to axial precession, the ecliptic longitude of most "fixed stars" increases + * by about 50.3 arcseconds per year, or 83.8 arcminutes per century. + * @param {number} M - solar mean anomaly @returns {number} ecliptic longitude */ static eclipticLongitude(M: number): Radians { const C = DEG2RAD * (1.9148 * Math.sin(M) + 0.02 * Math.sin(2 * M) + 0.0003 * Math.sin(3 * M)); @@ -177,14 +179,10 @@ export class Sun { /** * returns set time for the given sun altitude - * @param {number} h - height at 0 - * @param {number} lw - rad * -lng - * @param {number} phi - rad * lat; - * @param {number} dec - declination - * @param {number} n - Julian cycle - * @param {number} M - solar mean anomal - * @param {number} L - ecliptic longitude - * @returns {number} set time + * @param {number} h - height at 0 @param {number} lw - rad * -lng @param + * {number} phi - rad * lat; @param {number} dec - declination @param + * {number} n - Julian cycle @param {number} M - solar mean anomal @param + * {number} L - ecliptic longitude @returns {number} set time */ static getSetJulian(h: Meters, lw: number, phi: number, dec: number, n: number, M: number, L: number): number { const w = Sun.hourAngle(h, phi, dec); @@ -196,7 +194,8 @@ export class Sun { /** * Convert Date to Solar Date/Time * - * Based on https://www.pveducation.org/pvcdrom/properties-of-sunlight/solar-time + * Based on + * https://www.pveducation.org/pvcdrom/properties-of-sunlight/solar-time * * See: https://github.com/mourner/suncalc/pull/156 */ @@ -218,7 +217,8 @@ export class Sun { } /** - * Calculates time for a given azimuth angle for a given date and latitude/longitude + * Calculates time for a given azimuth angle for a given date and + * latitude/longitude */ static getSunTimeByAz( dateValue: number | Date, @@ -270,8 +270,8 @@ export class Sun { /** * Calculates sun times for a given date and latitude/longitude * - * Default altitude is 0 meters. - * If `isUtc` is `true`, the times are returned as UTC, otherwise in local time. + * Default altitude is 0 meters. If `isUtc` is `true`, the times are returned + * as UTC, otherwise in local time. */ static getTimes(dateVal: Date | number, lat: Degrees, lon: Degrees, alt: Meters = 0, isUtc = false): SunTime { if (isNaN(lat)) { @@ -322,10 +322,8 @@ export class Sun { /** * hour angle - * @param {number} h - heigh at 0 - * @param {number} phi - rad * lat; - * @param {number} dec - declination - * @returns {number} hour angle + * @param {number} h - heigh at 0 @param {number} phi - rad * lat; @param + * {number} dec - declination @returns {number} hour angle */ static hourAngle(h: number, phi: number, dec: number): number { return Math.acos((Math.sin(h) - Math.sin(phi) * Math.sin(dec)) / (Math.cos(phi) * Math.cos(dec))); @@ -333,8 +331,8 @@ export class Sun { /** * convert Julian calendar to date object - * @param {number} julian day number in Julian calendar to convert - * @return {number} result date as timestamp + * @param {number} julian day number in Julian calendar to convert @return + * {number} result date as timestamp */ static julian2date(julian: number): Date { return new Date((julian - Sun.J1970_) * MS_PER_DAY); @@ -347,19 +345,20 @@ export class Sun { * Sun, Moon, and planets repeat. It is used in astronomical calculations to * determine the position of celestial bodies. * - * The Julian Period starts at noon on January 1, 4713 B.C.E. (Julian calendar) and - * lasts for 7980 years. This was determined because it is a time period long enough - * to include all of recorded history and includes some time in the future that would - * incorporate the three important calendrical cycles, the Golden Number Cycle, the - * Solar Cycle, and the Roman Indiction. + * The Julian Period starts at noon on January 1, 4713 B.C.E. (Julian + * calendar) and lasts for 7980 years. This was determined because it is a + * time period long enough to include all of recorded history and includes + * some time in the future that would incorporate the three important + * calendrical cycles, the Golden Number Cycle, the Solar Cycle, and the Roman + * Indiction. * - * The Golden Number Cycle is a cycle of 19 years, while the Solar Cycle is a cycle of - * 28 years and the Roman Indiction repeats every 15 years. Thus the Julian Period is - * calculated to be 7980 years long or 2,914,695 days because 19*28*15 = 7980. + * The Golden Number Cycle is a cycle of 19 years, while the Solar Cycle is a + * cycle of 28 years and the Roman Indiction repeats every 15 years. Thus the + * Julian Period is calculated to be 7980 years long or 2,914,695 days because + * 19*28*15 = 7980. * * @param {Date} date - Date object for calculating julian cycle - * @param {Degrees} lon - Degrees longitude - * @returns {number} julian cycle + * @param {Degrees} lon - Degrees longitude @returns {number} julian cycle */ static julianCycle(date: Date, lon: Degrees): number { const lw = (-lon * DEG2RAD); @@ -369,11 +368,11 @@ export class Sun { } /** - * Calculate the lighting ratio given a satellite ECI position [satPos] - * _(km)_ and Sun ECI position [sunPos] _(km)_. + * Calculate the lighting ratio given a satellite ECI position [satPos] _(km)_ + * and Sun ECI position [sunPos] _(km)_. * - * Returns `1.0` if the satellite is fully illuminated and `0.0` when - * fully eclipsed. + * Returns `1.0` if the satellite is fully illuminated and `0.0` when fully + * eclipsed. */ static lightingRatio(satPos: Vector3D, sunPos: Vector3D): number { const [sunSatAngle, aCent, aSun] = Sun.eclipseAngles(satPos, sunPos); @@ -402,14 +401,15 @@ export class Sun { } /** - * Calculates the lighting factor based on the position of the satellite and the sun. + * Calculates the lighting factor based on the position of the satellite and + * the sun. * * @deprecated - * This method was previously used. It is now deprecated and will be removed in a future release. + * This method was previously used. It is now deprecated and will be removed + * in a future release. * * @param satPos The position of the satellite. - * @param sunPos The position of the sun. - * @returns The lighting factor. + * @param sunPos The position of the sun. @returns The lighting factor. */ static sunlightLegacy(satPos: Vector3D, sunPos: Vector3D): number { let lighting = 1.0; @@ -450,11 +450,12 @@ export class Sun { } /** - * Calculates the position vector of the Sun at a given epoch in the Earth-centered inertial (ECI) coordinate system. - * @param epoch - The epoch in UTC. - * @returns The position vector of the Sun in meters. + * Calculates the position vector of the Sun at a given epoch in the + * Earth-centered inertial (ECI) coordinate system. + * @param epoch - The epoch in UTC. @returns The position vector of the Sun in + * Kilometers. */ - static position(epoch: EpochUTC): Vector3D { + static position(epoch: EpochUTC): Vector3D { const jc = epoch.toJulianCenturies(); const dtr = DEG2RAD; const lamSun = 280.46 + 36000.77 * jc; @@ -470,11 +471,15 @@ export class Sun { const rMOD = r.scale(astronomicalUnit); const p = Earth.precession(epoch); - return rMOD.rotZ(p.zed).rotY(-p.theta).rotZ(p.zeta) as Vector3D; + return rMOD + .rotZ(p.zed) + .rotY(-p.theta as Radians) + .rotZ(p.zeta) as Vector3D; } /** - * Calculate the Sun's apparent ECI position _(km)_ from Earth for a given UTC [epoch]. + * Calculate the Sun's apparent ECI position _(km)_ from Earth for a given UTC + * [epoch]. */ static positionApparent(epoch: EpochUTC): Vector3D { const distance = Sun.position(epoch).magnitude(); @@ -486,8 +491,10 @@ export class Sun { /** * Calculates the right ascension and declination of the Sun for a given date. * - * @param date - The date for which to calculate the right ascension and declination. - * @returns An object containing the declination and right ascension of the Sun. + * @param date - The date for which to calculate the right ascension and + * declination. + * @returns An object containing the declination and right ascension of the + * Sun. */ static raDec(date: Date): RaDec { const d = Sun.date2jSince2000(date); @@ -502,7 +509,8 @@ export class Sun { } /** - * Return `true` if the ECI satellite position [posSat] is in eclipse at the given UTC [epoch]. + * Return `true` if the ECI satellite position [posSat] is in eclipse at the + * given UTC [epoch]. */ static shadow(epoch: EpochUTC, posSat: Vector3D): boolean { const posSun = Sun.positionApparent(epoch); @@ -525,9 +533,8 @@ export class Sun { /** * side real time - * @param {number} d - julian day - * @param {Radians} lw - longitude of the observer - * @returns {number} sidereal time + * @param {number} d - julian day @param {Radians} lw - longitude of the + * observer @returns {number} sidereal time */ static siderealTime(d: number, lw: Radians): number { return DEG2RAD * (280.16 + 360.9856235 * d) - lw; @@ -535,10 +542,9 @@ export class Sun { /** * solar transit in Julian - * @param {number} ds - approxTransit - * @param {number} M - solar mean anomal - * @param {number} L - ecliptic longitude - * @returns {number} solar transit in Julian + * @param {number} ds - approxTransit @param {number} M - solar mean anomal + * @param {number} L - ecliptic longitude @returns {number} solar transit in + * Julian */ static solarTransitJulian(ds: number, M: number, L: number): number { return Sun.J2000_ + ds + 0.0053 * Math.sin(M) - 0.0069 * Math.sin(2 * L); @@ -546,10 +552,8 @@ export class Sun { /** * The approximate transit time - * @param {number} Ht - hourAngle - * @param {number} lw - rad * -lng - * @param {number} n - Julian cycle - * @returns {number} approx transit + * @param {number} Ht - hourAngle @param {number} lw - rad * -lng @param + * {number} n - Julian cycle @returns {number} approx transit */ private static approxTransit_(Ht: number, lw: number, n: number): number { return Sun.J0_ + (Ht + lw) / TAU + n; @@ -573,14 +577,10 @@ export class Sun { /** * returns set time for the given sun altitude - * @param {Meters} alt - altitude at 0 - * @param {Radians} lw - -lng - * @param {Radians} phi - lat; - * @param {Radians} dec - declination - * @param {number} n - Julian cycle - * @param {number} M - solar mean anomal - * @param {number} L - ecliptic longitude - * @return {number} sunset time in days since 2000 + * @param {Meters} alt - altitude at 0 @param {Radians} lw - -lng @param + * {Radians} phi - lat; @param {Radians} dec - declination @param {number} n - + * Julian cycle @param {number} M - solar mean anomal @param {number} L - + * ecliptic longitude @return {number} sunset time in days since 2000 */ private static getSetJ_( alt: Meters, @@ -605,8 +605,8 @@ export class Sun { /** * calculates the obderver angle - * @param {number} alt the observer altitude (in meters) relative to the horizon - * @returns {Degrees} height for further calculations + * @param {number} alt the observer altitude (in meters) relative to the + * horizon @returns {Degrees} height for further calculations */ private static observerAngle_(alt: Meters): Degrees { return ((-2.076 * Math.sqrt(alt)) / 60); @@ -614,8 +614,7 @@ export class Sun { /** * get solar mean anomaly - * @param {number} d - julian day - * @returns {number} solar mean anomaly + * @param {number} d - julian day @returns {number} solar mean anomaly */ private static solarMeanAnomaly_(d: number): number { return DEG2RAD * (357.5291 + 0.98560028 * d); diff --git a/src/coordinate/ClassicalElements.ts b/src/coordinate/ClassicalElements.ts index 249033e..7906c46 100644 --- a/src/coordinate/ClassicalElements.ts +++ b/src/coordinate/ClassicalElements.ts @@ -227,10 +227,16 @@ export class ClassicalElements { ); const vVec = new Vector3D(-Math.sin(this.trueAnomaly), this.eccentricity + Math.cos(this.trueAnomaly), 0.0); const vPQW = vVec.scale(Math.sqrt(this.mu / (this.semimajorAxis * (1 - this.eccentricity ** 2)))); - const position = rPQW.rotZ(-this.argPerigee).rotX(-this.inclination).rotZ(-this.rightAscension); - const velocity = vPQW.rotZ(-this.argPerigee).rotX(-this.inclination).rotZ(-this.rightAscension); + const position = rPQW + .rotZ(-this.argPerigee as Radians) + .rotX(-this.inclination) + .rotZ(-this.rightAscension as Radians); + const velocity = vPQW + .rotZ(-this.argPerigee as Radians) + .rotX(-this.inclination) + .rotZ(-this.rightAscension as Radians); - return { position, velocity }; + return { position: position as Vector3D, velocity: velocity as Vector3D }; } /** diff --git a/src/coordinate/Geodetic.ts b/src/coordinate/Geodetic.ts index 60733b2..e55f90a 100644 --- a/src/coordinate/Geodetic.ts +++ b/src/coordinate/Geodetic.ts @@ -110,13 +110,13 @@ export class Geodetic { const sLat = Math.sin(this.lat); const cLat = Math.cos(this.lat); const nVal = Earth.radiusEquator / Math.sqrt(1 - Earth.eccentricitySquared * sLat * sLat); - const r = new Vector3D( - (nVal + this.alt) * cLat * Math.cos(this.lon), - (nVal + this.alt) * cLat * Math.sin(this.lon), - (nVal * (1 - Earth.eccentricitySquared) + this.alt) * sLat, + const r = new Vector3D( + ((nVal + this.alt) * cLat * Math.cos(this.lon)) as Kilometers, + ((nVal + this.alt) * cLat * Math.sin(this.lon)) as Kilometers, + ((nVal * (1 - Earth.eccentricitySquared) + this.alt) * sLat) as Kilometers, ); - return new ITRF(epoch, r, Vector3D.origin); + return new ITRF(epoch, r, Vector3D.origin as Vector3D); } /** diff --git a/src/coordinate/ITRF.ts b/src/coordinate/ITRF.ts index 3468997..25f7ce0 100644 --- a/src/coordinate/ITRF.ts +++ b/src/coordinate/ITRF.ts @@ -1,5 +1,5 @@ /* eslint-disable class-methods-use-this */ -import { Kilometers, Radians } from 'src/main'; +import { Kilometers, Radians, Vector3D } from 'src/main'; import { Earth } from '../body/Earth'; import { Geodetic } from './Geodetic'; import { J2000 } from './J2000'; @@ -79,12 +79,18 @@ export class ITRF extends StateVector { const p = Earth.precession(this.epoch); const n = Earth.nutation(this.epoch); const ast = this.epoch.gmstAngle() + n.eqEq; - const rTOD = this.position.rotZ(-ast); - const vTOD = this.velocity.add(Earth.rotation.cross(this.position)).rotZ(-ast); + const rTOD = this.position.rotZ(-ast as Radians); + const vTOD = this.velocity.add(Earth.rotation.cross(this.position) as Vector3D).rotZ(-ast as Radians); const rMOD = rTOD.rotX(n.eps).rotZ(n.dPsi).rotX(-n.mEps); const vMOD = vTOD.rotX(n.eps).rotZ(n.dPsi).rotX(-n.mEps); - const rJ2000 = rMOD.rotZ(p.zed).rotY(-p.theta).rotZ(p.zeta); - const vJ2000 = vMOD.rotZ(p.zed).rotY(-p.theta).rotZ(p.zeta); + const rJ2000 = rMOD + .rotZ(p.zed) + .rotY(-p.theta as Radians) + .rotZ(p.zeta) as Vector3D; + const vJ2000 = vMOD + .rotZ(p.zed) + .rotY(-p.theta as Radians) + .rotZ(p.zeta) as Vector3D; return new J2000(this.epoch, rJ2000, vJ2000); } diff --git a/src/coordinate/J2000.ts b/src/coordinate/J2000.ts index 2792025..3e6fa38 100644 --- a/src/coordinate/J2000.ts +++ b/src/coordinate/J2000.ts @@ -1,4 +1,5 @@ /* eslint-disable class-methods-use-this */ +import { Kilometers, Radians, Vector3D } from '../main'; import { Earth } from '../body/Earth'; import { ClassicalElements } from './ClassicalElements'; import { ITRF } from './ITRF'; @@ -57,13 +58,25 @@ export class J2000 extends StateVector { toITRF(): ITRF { const p = Earth.precession(this.epoch); const n = Earth.nutation(this.epoch); - const ast = this.epoch.gmstAngle() + n.eqEq; - const rMOD = this.position.rotZ(-p.zeta).rotY(p.theta).rotZ(-p.zed); - const vMOD = this.velocity.rotZ(-p.zeta).rotY(p.theta).rotZ(-p.zed); - const rTOD = rMOD.rotX(n.mEps).rotZ(-n.dPsi).rotX(-n.eps); - const vTOD = vMOD.rotX(n.mEps).rotZ(-n.dPsi).rotX(-n.eps); - const rPEF = rTOD.rotZ(ast); - const vPEF = vTOD.rotZ(ast).add(Earth.rotation.negate().cross(rPEF)); + const ast = (this.epoch.gmstAngle() + n.eqEq) as Radians; + const rMOD = this.position + .rotZ(-p.zeta as Radians) + .rotY(p.theta) + .rotZ(-p.zed as Radians); + const vMOD = this.velocity + .rotZ(-p.zeta as Radians) + .rotY(p.theta) + .rotZ(-p.zed as Radians); + const rTOD = rMOD + .rotX(n.mEps) + .rotZ(-n.dPsi as Radians) + .rotX(-n.eps); + const vTOD = vMOD + .rotX(n.mEps) + .rotZ(-n.dPsi as Radians) + .rotX(-n.eps); + const rPEF = rTOD.rotZ(ast) as Vector3D; + const vPEF = vTOD.rotZ(ast).add(Earth.rotation.negate().cross(rPEF)) as Vector3D; return new ITRF(this.epoch, rPEF, vPEF); } @@ -77,11 +90,25 @@ export class J2000 extends StateVector { const p = Earth.precession(this.epoch); const n = Earth.nutation(this.epoch); const eps = n.mEps + n.dEps; - const dPsiCosEps = n.dPsi * Math.cos(eps); - const rMOD = this.position.rotZ(-p.zeta).rotY(p.theta).rotZ(-p.zed); - const vMOD = this.velocity.rotZ(-p.zeta).rotY(p.theta).rotZ(-p.zed); - const rTEME = rMOD.rotX(n.mEps).rotZ(-n.dPsi).rotX(-eps).rotZ(dPsiCosEps); - const vTEME = vMOD.rotX(n.mEps).rotZ(-n.dPsi).rotX(-eps).rotZ(dPsiCosEps); + const dPsiCosEps = (n.dPsi * Math.cos(eps)) as Radians; + const rMOD = this.position + .rotZ(-p.zeta as Radians) + .rotY(p.theta) + .rotZ(-p.zed as Radians); + const vMOD = this.velocity + .rotZ(-p.zeta as Radians) + .rotY(p.theta) + .rotZ(-p.zed as Radians); + const rTEME = rMOD + .rotX(n.mEps) + .rotZ(-n.dPsi as Radians) + .rotX(-eps) + .rotZ(dPsiCosEps) as Vector3D; + const vTEME = vMOD + .rotX(n.mEps) + .rotZ(-n.dPsi as Radians) + .rotX(-eps) + .rotZ(dPsiCosEps) as Vector3D; return new TEME(this.epoch, rTEME, vTEME); } diff --git a/src/coordinate/RIC.ts b/src/coordinate/RIC.ts index 472ac02..14d5789 100644 --- a/src/coordinate/RIC.ts +++ b/src/coordinate/RIC.ts @@ -4,16 +4,19 @@ import { J2000 } from './J2000'; import { RelativeState } from './RelativeState'; /** - * Represents a Radial-Intrack-Crosstrack (RIC) coordinate. - * - * RIC coordinates are created from J2000 state vectors and can be transformed to the J2000 coordinate system. + * Represents a Radial-Intrack-Crosstrack (RIC) coordinates. */ export class RIC extends RelativeState { /** - * Creates a new RIC (Radial-Intrack-Crosstrack) coordinate from the J2000 state vectors. - * @param state The J2000 state vector. - * @param origin The J2000 state vector of the origin. - * @param transform The transformation matrix. + * Creates a new RIC (Radial-Intrack-Crosstrack) coordinate from the J2000 + * state vectors. + * + * @param state - The J2000 state vector. + * + * @param origin - The J2000 state vector of the origin. + * + * @param transform - The transformation matrix. + * * @returns The RIC coordinate. */ static fromJ2000Matrix(state: J2000, origin: J2000, transform: Matrix): RIC { @@ -24,9 +27,12 @@ export class RIC extends RelativeState { } /** - * Creates a RIC (Radial-Intrack-Crosstrack) coordinate system from a J2000 state and origin. + * Creates a RIC (Radial-Intrack-Crosstrack) coordinate system from a J2000 + * state and origin. * @param state The J2000 state. + * * @param origin The J2000 origin. + * * @returns The RIC coordinate system. */ static fromJ2000(state: J2000, origin: J2000): RIC { @@ -42,9 +48,12 @@ export class RIC extends RelativeState { } /** - * Transforms the current RIC coordinate to the J2000 coordinate system using the provided origin and transform matrix + * Transforms the current RIC coordinate to the J2000 coordinate system using + * the provided origin and transform matrix * @param origin The origin J2000 coordinate. + * * @param transform The transformation matrix. + * * @returns The transformed J2000 coordinate. */ toJ2000Matrix(origin: J2000, transform: Matrix): J2000 { @@ -56,8 +65,10 @@ export class RIC extends RelativeState { } /** - * Transforms the current RIC coordinate to the J2000 coordinate system using the provided origin. + * Transforms the current RIC coordinate to the J2000 coordinate system using + * the provided origin. * @param origin The origin J2000 coordinate. + * * @returns The transformed J2000 coordinate. */ toJ2000(origin: J2000): J2000 { diff --git a/src/coordinate/RelativeState.ts b/src/coordinate/RelativeState.ts index 7063221..3c7dc21 100644 --- a/src/coordinate/RelativeState.ts +++ b/src/coordinate/RelativeState.ts @@ -1,17 +1,32 @@ +import { Kilometers } from 'src/main'; import { Matrix } from '../operations/Matrix'; import { Vector3D } from '../operations/Vector3D'; import { J2000 } from './J2000'; -// / Base class for relative states. +/** + * Represents the relative state of an object in 3D space. + */ export abstract class RelativeState { - // / Create a new [RelativeState] object. - constructor(public position: Vector3D, public velocity: Vector3D) { - // Nothing to do here. + position: Vector3D; + velocity: Vector3D; + constructor(position: Vector3D, velocity: Vector3D) { + this.position = position; + this.velocity = velocity; } - // / Return the name of this coordinate frame. + /** + * Gets the name of the coordinate system. + * + * @returns The name of the coordinate system. + */ abstract get name(): string; + /** + * Returns a string representation of the RelativeState object. The string + * includes the name, position, and velocity of the object. + * + * @returns A string representation of the RelativeState object. + */ toString(): string { return [ `[${this.name}]`, @@ -20,15 +35,22 @@ export abstract class RelativeState { ].join('\n'); } - // / Convert this to a [J2000] state vector object. + /** + * Transforms the current RelativeState coordinate to the J2000 coordinate + * @param origin The origin J2000 coordinate. + * + * @returns The transformed J2000 coordinate. + */ abstract toJ2000(origin: J2000): J2000; /** - * Creates a matrix based on the given position and velocity vectors. - * The matrix represents the relative state of an object in 3D space. + * Creates a matrix based on the given position and velocity vectors. The + * matrix represents the relative state of an object in 3D space. * * @param position - The position vector. + * * @param velocity - The velocity vector. + * * @returns The matrix representing the relative state. */ static createMatrix(position: Vector3D, velocity: Vector3D): Matrix { @@ -43,12 +65,20 @@ export abstract class RelativeState { ]); } - // / Return the relative range _(km)_. - range(): number { - return this.position.magnitude(); + /** + * Calculates the range of the relative state. + * @returns The range in kilometers. + */ + range(): Kilometers { + return this.position.magnitude() as Kilometers; } - // / Return the relative range rate _(km/s)_. + /** + * Calculates the range rate of the relative state. Range rate is the dot + * product of the position and velocity divided by the range. + * + * @returns The range rate in Kilometers per second. + */ rangeRate(): number { return this.position.dot(this.velocity) / this.range(); } diff --git a/src/coordinate/StateVector.ts b/src/coordinate/StateVector.ts index 2ad561f..cc9c42d 100644 --- a/src/coordinate/StateVector.ts +++ b/src/coordinate/StateVector.ts @@ -1,3 +1,4 @@ +import { Kilometers } from 'src/main'; import { Earth } from '../body/Earth'; import type { Vector3D } from '../operations/Vector3D'; import type { EpochUTC } from '../time/EpochUTC'; @@ -6,16 +7,16 @@ import { ClassicalElements } from './ClassicalElements'; // / Position and velocity [Vector3D] container. export type PositionVelocity = { - position: Vector3D; - velocity: Vector3D; + position: Vector3D; + velocity: Vector3D; }; // / Base class for state vectors. export abstract class StateVector { constructor( public epoch: EpochUTC, - public position: Vector3D, - public velocity: Vector3D, + public position: Vector3D, + public velocity: Vector3D, ) { // Nothing to do here. } diff --git a/src/coordinate/TEME.ts b/src/coordinate/TEME.ts index ad7cbca..7eb2178 100644 --- a/src/coordinate/TEME.ts +++ b/src/coordinate/TEME.ts @@ -1,4 +1,5 @@ /* eslint-disable class-methods-use-this */ +import { Kilometers, Radians, Vector3D } from '../main'; import { Earth } from '../body/Earth'; import type { ClassicalElements } from './ClassicalElements'; import { J2000 } from './J2000'; @@ -38,10 +39,24 @@ export class TEME extends StateVector { const n = Earth.nutation(this.epoch); const eps = n.mEps + n.dEps; const dPsiCosEps = n.dPsi * Math.cos(eps); - const rMOD = this.position.rotZ(-dPsiCosEps).rotX(eps).rotZ(n.dPsi).rotX(-n.mEps); - const vMOD = this.velocity.rotZ(-dPsiCosEps).rotX(eps).rotZ(n.dPsi).rotX(-n.mEps); - const rJ2K = rMOD.rotZ(p.zed).rotY(-p.theta).rotZ(p.zeta); - const vJ2K = vMOD.rotZ(p.zed).rotY(-p.theta).rotZ(p.zeta); + const rMOD = this.position + .rotZ(-dPsiCosEps as Radians) + .rotX(eps) + .rotZ(n.dPsi) + .rotX(-n.mEps); + const vMOD = this.velocity + .rotZ(-dPsiCosEps as Radians) + .rotX(eps) + .rotZ(n.dPsi) + .rotX(-n.mEps); + const rJ2K = rMOD + .rotZ(p.zed) + .rotY(-p.theta as Radians) + .rotZ(p.zeta) as Vector3D; + const vJ2K = vMOD + .rotZ(p.zed) + .rotY(-p.theta as Radians) + .rotZ(p.zeta) as Vector3D; return new J2000(this.epoch, rJ2K, vJ2K); } diff --git a/src/coordinate/Tle.ts b/src/coordinate/Tle.ts index c0738bb..325e1b2 100644 --- a/src/coordinate/Tle.ts +++ b/src/coordinate/Tle.ts @@ -36,6 +36,7 @@ import { EpochUTC } from '../time/EpochUTC'; import { Degrees, EciVec3, + Kilometers, Line1Data, Line2Data, Minutes, @@ -203,7 +204,11 @@ export class Tle { Tle.sv2rv_(stateVector, r, v); - return new TEME(epoch, new Vector3D(r[0], r[1], r[2]), new Vector3D(v[0], v[1], v[2])); + return new TEME( + epoch, + new Vector3D(r[0], r[1], r[2]), + new Vector3D(v[0], v[1], v[2]), + ); } private static sv2rv_(stateVector: StateVectorSgp4, r: Float64Array, v: Float64Array) { @@ -226,7 +231,11 @@ export class Tle { Tle.sv2rv_(stateVector, r, v); - return new TEME(this.epoch, new Vector3D(r[0], r[1], r[2]), new Vector3D(v[0], v[1], v[2])); + return new TEME( + this.epoch, + new Vector3D(r[0], r[1], r[2]), + new Vector3D(v[0], v[1], v[2]), + ); } get state(): TEME { diff --git a/src/observation/RAE.ts b/src/observation/RAE.ts index b93deca..62d00ab 100644 --- a/src/observation/RAE.ts +++ b/src/observation/RAE.ts @@ -2,7 +2,7 @@ import { ITRF } from '../coordinate/ITRF'; import { J2000 } from '../coordinate/J2000'; import { AngularDistanceMethod } from '../enums/AngularDistanceMethod'; -import { Radians } from '../main'; +import { Degrees, Kilometers, Radians } from '../main'; import { Vector3D } from '../operations/Vector3D'; import { EpochUTC } from '../time/EpochUTC'; import { DEG2RAD, halfPi, RAD2DEG, TAU } from '../utils/constants'; @@ -13,19 +13,22 @@ export class RAE { // / Create a new [Razel] object. constructor( public epoch: EpochUTC, - public range: number, + public range: Kilometers, public azimuth: Radians, public elevation: Radians, /** - * The range rate of the satellite relative to the observer in kilometers per second. + * The range rate of the satellite relative to the observer in kilometers + * per second. */ public rangeRate?: number, /** - * The azimuth rate of the satellite relative to the observer in radians per second. + * The azimuth rate of the satellite relative to the observer in radians per + * second. */ public azimuthRate?: number, /** - * The elevation rate of the satellite relative to the observer in radians per second. + * The elevation rate of the satellite relative to the observer in radians + * per second. */ public elevationRate?: number, ) { @@ -35,9 +38,9 @@ export class RAE { // / Create a new [Razel] object, using degrees for the angular values. static fromDegrees( epoch: EpochUTC, - range: number, - azimuthDegrees: number, - elevationDegrees: number, + range: Kilometers, + azimuthDegrees: Degrees, + elevationDegrees: Degrees, rangeRate?: number, azimuthRateDegrees?: number, elevationRateDegrees?: number, @@ -57,8 +60,7 @@ export class RAE { } /** - * Create a [Razel] object from an inertial [state] and - * [site] vector. + * Create a [Razel] object from an inertial [state] and [site] vector. */ static fromStateVectors(state: J2000, site: J2000): RAE { const stateEcef = state.toITRF(); @@ -67,8 +69,8 @@ export class RAE { const r = stateEcef.position.subtract(siteEcef.position); const rDot = stateEcef.velocity; const geo = siteEcef.toGeodetic(); - const p = r.rotZ(geo.lon).rotY(po2 - geo.lat); - const pDot = rDot.rotZ(geo.lon).rotY(po2 - geo.lat); + const p = r.rotZ(geo.lon).rotY((po2 - geo.lat) as Radians); + const pDot = rDot.rotZ(geo.lon).rotY((po2 - geo.lat) as Radians); const pS = p.x; const pE = p.y; const pZ = p.z; @@ -135,7 +137,7 @@ export class RAE { * An optional azimuth [az] _(rad)_ and elevation [el] _(rad)_ value can be * passed to override the values contained in this observation. */ - position(site: J2000, az?: number, el?: number): Vector3D { + position(site: J2000, az?: Radians, el?: Radians): Vector3D { const ecef = site.toITRF(); const geo = ecef.toGeodetic(); const po2 = halfPi; @@ -145,13 +147,17 @@ export class RAE { const cAz = Math.cos(newAz); const sEl = Math.sin(newEl); const cEl = Math.cos(newEl); - const pSez = new Vector3D(-this.range * cEl * cAz, this.range * cEl * sAz, this.range * sEl); + const pSez = new Vector3D( + (-this.range * cEl * cAz) as Kilometers, + (this.range * cEl * sAz) as Kilometers, + (this.range * sEl) as Kilometers, + ); const rEcef = pSez - .rotY(-(po2 - geo.lat)) - .rotZ(-geo.lon) + .rotY(-(po2 - geo.lat) as Radians) + .rotZ(-geo.lon as Radians) .add(ecef.position); - return new ITRF(this.epoch, rEcef, Vector3D.origin).toJ2000().position; + return new ITRF(this.epoch, rEcef, Vector3D.origin as Vector3D).toJ2000().position; } /** @@ -171,34 +177,38 @@ export class RAE { const cAz = Math.cos(this.azimuth); const sEl = Math.sin(this.elevation); const cEl = Math.cos(this.elevation); - const pSez = new Vector3D(-this.range * cEl * cAz, this.range * cEl * sAz, this.range * sEl); - const pDotSez = new Vector3D( - -this.rangeRate * cEl * cAz + + const pSez = new Vector3D( + (-this.range * cEl * cAz) as Kilometers, + (this.range * cEl * sAz) as Kilometers, + (this.range * sEl) as Kilometers, + ); + const pDotSez = new Vector3D( + (-this.rangeRate * cEl * cAz + this.range * sEl * cAz * this.elevationRate + - this.range * cEl * sAz * this.azimuthRate, - this.rangeRate * cEl * sAz - + this.range * cEl * sAz * this.azimuthRate) as Kilometers, + (this.rangeRate * cEl * sAz - this.range * sEl * sAz * this.elevationRate + - this.range * cEl * cAz * this.azimuthRate, - this.rangeRate * sEl + this.range * cEl * this.elevationRate, + this.range * cEl * cAz * this.azimuthRate) as Kilometers, + (this.rangeRate * sEl + this.range * cEl * this.elevationRate) as Kilometers, ); - const pEcef = pSez.rotY(-(po2 - geo.lat)).rotZ(-geo.lon); - const pDotEcef = pDotSez.rotY(-(po2 - geo.lat)).rotZ(-geo.lon); + const pEcef = pSez.rotY(-(po2 - geo.lat) as Radians).rotZ(-geo.lon as Radians); + const pDotEcef = pDotSez.rotY(-(po2 - geo.lat) as Radians).rotZ(-geo.lon as Radians); const rEcef = pEcef.add(ecef.position); return new ITRF(this.epoch, rEcef, pDotEcef).toJ2000(); } /** - * Calculate the angular distance _(rad)_ between this and another - * [Razel] object. + * Calculate the angular distance _(rad)_ between this and another [Razel] + * object. */ angle(razel: RAE, method: AngularDistanceMethod = AngularDistanceMethod.Cosine): number { return angularDistance(this.azimuth, this.elevation, razel.azimuth, razel.elevation, method); } /** - * Calculate the angular distance _(°)_ between this and another - * [Razel] object. + * Calculate the angular distance _(°)_ between this and another [Razel] + * object. */ angleDegrees(razel: RAE, method: AngularDistanceMethod = AngularDistanceMethod.Cosine): number { return this.angle(razel, method) * RAD2DEG; diff --git a/src/operations/Matrix.ts b/src/operations/Matrix.ts index dabb99f..7141fd9 100644 --- a/src/operations/Matrix.ts +++ b/src/operations/Matrix.ts @@ -192,8 +192,8 @@ export class Matrix { return new Vector(result); } - public multiplyVector3D(v: Vector3D): Vector3D { - const result: number[] = []; + public multiplyVector3D(v: Vector3D): Vector3D { + const result: T[] = []; for (let i = 0; i < this.rows; i++) { let total = 0.0; @@ -213,10 +213,10 @@ export class Matrix { break; } } - result[i] = total; + result[i] = total as T; } - return new Vector3D(result[0], result[1], result[2]); + return new Vector3D(result[0], result[1], result[2]); } public reciprocal(): Matrix { diff --git a/src/operations/Vector3D.ts b/src/operations/Vector3D.ts index a833c1f..3484860 100644 --- a/src/operations/Vector3D.ts +++ b/src/operations/Vector3D.ts @@ -1,4 +1,4 @@ -import { linearDistance } from '../main'; +import { Radians, linearDistance } from '../main'; import { Matrix } from './Matrix'; import { Vector } from './Vector'; @@ -13,33 +13,33 @@ export class Vector3D { } /** - * Create a new [Vector3D] object from the first three elements of a - * [Vector] object. + * Create a new [Vector3D] object from the first three elements of a [Vector] + * object. */ - static fromVector(v: Vector): Vector3D { - return new Vector3D(v.x, v.y, v.z); + static fromVector(v: Vector): Vector3D { + return new Vector3D(v.x as U, v.y as U, v.z as U); } // / Origin vector. - static origin = new Vector3D(0, 0, 0) as Vector3D; + static origin = new Vector3D(0, 0, 0); // / X-axis unit vector. - static xAxis = new Vector3D(1, 0, 0); + static xAxis = new Vector3D(1, 0, 0); // / Y-axis unit vector. - static yAxis = new Vector3D(0, 1, 0); + static yAxis = new Vector3D(0, 1, 0); // / Z-axis unit vector. - static zAxis = new Vector3D(0, 0, 1); + static zAxis = new Vector3D(0, 0, 1); // / Negative x-axis unit vector. - static xAxisNeg = new Vector3D(-1, 0, 0); + static xAxisNeg = new Vector3D(-1, 0, 0); // / Negative y-axis unit vector. - static yAxisNeg = new Vector3D(0, -1, 0); + static yAxisNeg = new Vector3D(0, -1, 0); // / Negative z-axis unit vector. - static zAxisNeg = new Vector3D(0, 0, -1); + static zAxisNeg = new Vector3D(0, 0, -1); // / Convert this to a [List] of doubles. toList() { @@ -84,18 +84,18 @@ export class Vector3D { } // / Return the magnitude of this vector. - magnitude(): number { - return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); + magnitude(): T { + return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z) as T; } // / Return the result of adding this to another [Vector3D]. - add(v: Vector3D): Vector3D { - return new Vector3D(this.x + v.x, this.y + v.y, this.z + v.z); + add(v: Vector3D): Vector3D { + return new Vector3D((this.x + v.x) as T, (this.y + v.y) as T, (this.z + v.z) as T); } // / Return the result of subtracting this and another [Vector3D]. - subtract(v: Vector3D): Vector3D { - return new Vector3D(this.x - v.x, this.y - v.y, this.z - v.z); + subtract(v: Vector3D): Vector3D { + return new Vector3D((this.x - v.x) as T, (this.y - v.y) as T, (this.z - v.z) as T); } // / Return a copy of this [Vector3D] scaled by [n]; @@ -143,8 +143,12 @@ export class Vector3D { } // Calculate the cross product of this and another [Vector3D]. - cross(v: Vector3D): Vector3D { - return new Vector3D(this.y * v.z - this.z * v.y, this.z * v.x - this.x * v.z, this.x * v.y - this.y * v.x); + cross(v: Vector3D): Vector3D { + return new Vector3D( + (this.y * v.z - this.z * v.y) as T, + (this.z * v.x - this.x * v.z) as T, + (this.x * v.y - this.y * v.x) as T, + ); } // Calculate the skew-symmetric matrix for this [Vector3D]. @@ -156,7 +160,10 @@ export class Vector3D { ]); } - // Create a copy of this [Vector3D] rotated in the x-axis by angle [theta] _(rad)_. + /* + * Create a copy of this [Vector3D] rotated in the x-axis by angle [theta] + * _(rad)_. + */ rotX(theta: number): Vector3D { const cosT = Math.cos(theta); const sinT = Math.sin(theta); @@ -164,31 +171,37 @@ export class Vector3D { return new Vector3D(this.x, cosT * this.y + sinT * this.z, -sinT * this.y + cosT * this.z); } - // Create a copy of this [Vector3D] rotated in the y-axis by angle [theta] _(rad)_. - rotY(theta: number): Vector3D { + /* + * Create a copy of this [Vector3D] rotated in the y-axis by angle [theta] + * _(rad)_. + */ + rotY(theta: Radians): Vector3D { const cosT = Math.cos(theta); const sinT = Math.sin(theta); - return new Vector3D(cosT * this.x + -sinT * this.z, this.y, sinT * this.x + cosT * this.z); + return new Vector3D((cosT * this.x + -sinT * this.z) as T, this.y as T, (sinT * this.x + cosT * this.z) as T); } - // Create a copy of this [Vector3D] rotated in the z-axis by angle [theta] _(rad)_. - rotZ(theta: number): Vector3D { + /* + * Create a copy of this [Vector3D] rotated in the z-axis by angle [theta] + * _(rad)_. + */ + rotZ(theta: Radians): Vector3D { const cosT = Math.cos(theta); const sinT = Math.sin(theta); - return new Vector3D(cosT * this.x + sinT * this.y, -sinT * this.x + cosT * this.y, this.z); + return new Vector3D((cosT * this.x + sinT * this.y) as T, (-sinT * this.x + cosT * this.y) as T, this.z); } // Calculate the angle _(rad)_ between this and another [Vector3D]. - angle(v: Vector3D): number { + angle(v: Vector3D): number { const theta = Math.atan2(this.cross(v).magnitude(), this.dot(v)); return isNaN(theta) ? 0 : theta; } // Calculate the angle _(°)_ between this and another [Vector3D]. - angleDegrees(v: Vector3D): number { + angleDegrees(v: Vector3D): number { return this.angle(v) * (180 / Math.PI); }