Skip to content

Commit

Permalink
refactor: 🏷️ improve type support for radec observations
Browse files Browse the repository at this point in the history
  • Loading branch information
thkruz committed Jan 16, 2024
1 parent 88474ee commit 942f204
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 65 deletions.
25 changes: 13 additions & 12 deletions src/observation/ObservationUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,33 +21,34 @@
* SOFTWARE.
*/

import { Kilometers, KilometersPerSecond, Radians, RadiansPerSecond } from '../main';
import { Vector3D } from '../operations/Vector3D';

export const radecToPosition = (ra: number, dec: number, r: number): Vector3D => {
export const radecToPosition = (ra: Radians, dec: Radians, r: Kilometers): Vector3D<Kilometers> => {
const ca = Math.cos(ra);
const sa = Math.sin(ra);
const cd = Math.cos(dec);
const sd = Math.sin(dec);

return new Vector3D(r * cd * ca, r * cd * sa, r * sd);
return new Vector3D(r * cd * ca as Kilometers, r * cd * sa as Kilometers, r * sd as Kilometers);
};

export const radecToVelocity = (
ra: number,
dec: number,
r: number,
raDot: number,
decDot: number,
rDot: number,
): Vector3D => {
ra: Radians,
dec: Radians,
r: Kilometers,
raDot: RadiansPerSecond,
decDot: RadiansPerSecond,
rDot: KilometersPerSecond,
): Vector3D<KilometersPerSecond> => {
const ca = Math.cos(ra);
const sa = Math.sin(ra);
const cd = Math.cos(dec);
const sd = Math.sin(dec);

return new Vector3D(
rDot * cd * ca - r * sd * ca * decDot - r * cd * sa * raDot,
rDot * cd * sa - r * sd * sa * decDot + r * cd * ca * raDot,
rDot * sd + r * cd * decDot,
rDot * cd * ca - r * sd * ca * decDot - r * cd * sa * raDot as KilometersPerSecond,
rDot * cd * sa - r * sd * sa * decDot + r * cd * ca * raDot as KilometersPerSecond,
rDot * sd + r * cd * decDot as KilometersPerSecond,
);
};
36 changes: 19 additions & 17 deletions src/observation/RadecGeocentric.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
*/

/* eslint-disable no-undefined */
import { Degrees, Kilometers, Radians } from 'src/main';
import { Degrees, Kilometers, KilometersPerSecond, Radians, RadiansPerSecond } from 'src/main';
import { J2000 } from '../coordinate/J2000';
import { AngularDistanceMethod } from '../enums/AngularDistanceMethod';
import { Vector3D } from '../operations/Vector3D';
Expand All @@ -39,9 +39,9 @@ export class RadecGeocentric {
public rightAscension: Radians,
public declination: Radians,
public range?: Kilometers,
public rightAscensionRate?: Radians,
public declinationRate?: Radians,
public rangeRate?: number,
public rightAscensionRate?: RadiansPerSecond,
public declinationRate?: RadiansPerSecond,
public rangeRate?: KilometersPerSecond,
) {
// Nothing to do here.
}
Expand All @@ -65,18 +65,20 @@ export class RadecGeocentric {
range?: Kilometers,
rightAscensionRateDegrees?: Degrees,
declinationRateDegrees?: Degrees,
rangeRate?: number,
rangeRate?: KilometersPerSecond,
): RadecGeocentric {
const rightAscensionRate = rightAscensionRateDegrees && rightAscensionRateDegrees * DEG2RAD;
const declinationRate = declinationRateDegrees && declinationRateDegrees * DEG2RAD;
const rightAscensionRate = rightAscensionRateDegrees
? rightAscensionRateDegrees * DEG2RAD as RadiansPerSecond
: undefined;
const declinationRate = declinationRateDegrees ? declinationRateDegrees * DEG2RAD as RadiansPerSecond : undefined;

return new RadecGeocentric(
epoch,
rightAscensionDegrees * DEG2RAD as Radians,
declinationDegrees * DEG2RAD as Radians,
range,
rightAscensionRate as Radians,
declinationRate as Radians,
rightAscensionRate,
declinationRate,
rangeRate,
);
}
Expand All @@ -99,7 +101,7 @@ export class RadecGeocentric {
} else {
rightAscension = Math.atan2(vJ, vI);
}
const rangeRate = state.position.dot(state.velocity) / rMag;
const rangeRate = state.position.dot(state.velocity) / rMag as KilometersPerSecond;
const rightAscensionRate = (vI * rJ - vJ * rI) / (-(rJ * rJ) - rI * rI);
const declinationRate = (vK - rangeRate * (rK / rMag)) / rIJMag;

Expand All @@ -108,8 +110,8 @@ export class RadecGeocentric {
rightAscension % TAU as Radians,
declination as Radians,
rMag,
rightAscensionRate as Radians,
declinationRate as Radians,
rightAscensionRate as RadiansPerSecond,
declinationRate as RadiansPerSecond,
rangeRate,
);
}
Expand Down Expand Up @@ -142,8 +144,8 @@ export class RadecGeocentric {
* @param range Range _(km)_.
* @returns A [Vector3D] object.
*/
position(range?: number): Vector3D {
const r = range ?? this.range ?? 1.0;
position(range?: Kilometers): Vector3D<Kilometers> {
const r = range ?? this.range ?? 1.0 as Kilometers;

return radecToPosition(this.rightAscension, this.declination, r);
}
Expand All @@ -157,12 +159,12 @@ export class RadecGeocentric {
* @param rangeRate Range rate _(km/s)_.
* @returns A [Vector3D] object.
*/
velocity(range?: number, rangeRate?: number): Vector3D {
velocity(range?: Kilometers, rangeRate?: KilometersPerSecond): Vector3D<KilometersPerSecond> {
if (!this.rightAscensionRate || !this.declinationRate) {
throw new Error('Velocity unsolvable, missing ra/dec rates.');
}
const r = range ?? this.range ?? 1.0;
const rd = rangeRate ?? this.rangeRate ?? 0.0;
const r = range ?? this.range ?? 1.0 as Kilometers;
const rd = rangeRate ?? this.rangeRate ?? 0.0 as KilometersPerSecond;

return radecToVelocity(this.rightAscension, this.declination, r, this.rightAscensionRate, this.declinationRate, rd);
}
Expand Down
77 changes: 43 additions & 34 deletions src/observation/RadecTopocentric.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
*/

/* eslint-disable no-undefined */
import { Degrees, DegreesPerSecond, Kilometers, KilometersPerSecond, Radians, RadiansPerSecond } from 'src/main';
import { J2000 } from '../coordinate/J2000';
import { AngularDistanceMethod } from '../enums/AngularDistanceMethod';
import { Vector3D } from '../operations/Vector3D';
Expand All @@ -35,12 +36,12 @@ export class RadecTopocentric {
// / Create a new [RadecTopocentric] object.
constructor(
public epoch: EpochUTC,
public rightAscension: number,
public declination: number,
public range?: number,
public rightAscensionRate?: number,
public declinationRate?: number,
public rangeRate?: number,
public rightAscension: Radians,
public declination: Radians,
public range?: Kilometers,
public rightAscensionRate?: RadiansPerSecond,
public declinationRate?: RadiansPerSecond,
public rangeRate?: KilometersPerSecond,
) {
// Nothing to do here.
}
Expand All @@ -59,20 +60,24 @@ export class RadecTopocentric {
*/
static fromDegrees(
epoch: EpochUTC,
rightAscensionDegrees: number,
declinationDegrees: number,
range?: number,
rightAscensionRateDegrees?: number,
declinationRateDegrees?: number,
rangeRate?: number,
rightAscensionDegrees: Degrees,
declinationDegrees: Degrees,
range?: Kilometers,
rightAscensionRateDegrees?: DegreesPerSecond,
declinationRateDegrees?: DegreesPerSecond,
rangeRate?: KilometersPerSecond,
): RadecTopocentric {
const rightAscensionRate = rightAscensionRateDegrees ? rightAscensionRateDegrees * DEG2RAD : undefined;
const declinationRate = declinationRateDegrees ? declinationRateDegrees * DEG2RAD : undefined;
const rightAscensionRate = rightAscensionRateDegrees
? rightAscensionRateDegrees * DEG2RAD as RadiansPerSecond
: undefined;
const declinationRate = declinationRateDegrees
? declinationRateDegrees * DEG2RAD as RadiansPerSecond
: undefined;

return new RadecTopocentric(
epoch,
rightAscensionDegrees * DEG2RAD,
declinationDegrees * DEG2RAD,
rightAscensionDegrees * DEG2RAD as Radians,
declinationDegrees * DEG2RAD as Radians,
range,
rightAscensionRate,
declinationRate,
Expand Down Expand Up @@ -112,33 +117,37 @@ export class RadecTopocentric {

return new RadecTopocentric(
state.epoch,
rightAscension % TAU,
declination,
rightAscension % TAU as Radians,
declination as Radians,
pMag,
rightAscensionRate,
declinationRate,
rangeRate,
rightAscensionRate as RadiansPerSecond,
declinationRate as RadiansPerSecond,
rangeRate as KilometersPerSecond,
);
}

// / Right-ascension _(°)_.
get rightAscensionDegrees(): number {
return this.rightAscension * RAD2DEG;
get rightAscensionDegrees(): Degrees {
return this.rightAscension * RAD2DEG as Degrees;
}

// / Declination _(°)_.
get declinationDegrees(): number {
return this.declination * RAD2DEG;
get declinationDegrees(): Degrees {
return this.declination * RAD2DEG as Degrees;
}

// / Right-ascension rate _(°/s)_.
get rightAscensionRateDegrees(): number | undefined {
return this.rightAscensionRate ? this.rightAscensionRate * RAD2DEG : undefined;
get rightAscensionRateDegrees(): DegreesPerSecond | null {
return this.rightAscensionRate
? this.rightAscensionRate * RAD2DEG as DegreesPerSecond
: null;
}

// / Declination rate _(°/s)_.
get declinationRateDegrees(): number | undefined {
return this.declinationRate ? this.declinationRate * RAD2DEG : undefined;
get declinationRateDegrees(): DegreesPerSecond | null {
return this.declinationRate
? this.declinationRate * RAD2DEG as DegreesPerSecond
: null;
}

/**
Expand All @@ -150,8 +159,8 @@ export class RadecTopocentric {
* @param range Range _(km)_.
* @returns A [Vector3D] object.
*/
position(site: J2000, range?: number): Vector3D {
const r = range ?? this.range ?? 1.0;
position(site: J2000, range?: Kilometers): Vector3D {
const r = range ?? this.range ?? 1.0 as Kilometers;

return radecToPosition(this.rightAscension, this.declination, r).add(site.position);
}
Expand All @@ -166,12 +175,12 @@ export class RadecTopocentric {
* @param rangeRate Range rate _(km/s)_.
* @returns A [Vector3D] object.
*/
velocity(site: J2000, range?: number, rangeRate?: number): Vector3D {
velocity(site: J2000, range?: Kilometers, rangeRate?: KilometersPerSecond): Vector3D {
if (!this.rightAscensionRate || !this.declinationRate) {
throw new Error('Velocity unsolvable, missing ra/dec rates.');
}
const r = range ?? this.range ?? 1.0;
const rd = rangeRate ?? this.rangeRate ?? 0.0;
const r = range ?? this.range ?? 1.0 as Kilometers;
const rd = rangeRate ?? this.rangeRate ?? 0.0 as KilometersPerSecond;

return radecToVelocity(
this.rightAscension,
Expand Down
5 changes: 5 additions & 0 deletions src/types/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,11 @@ export type KilometersPerSecond = Distinct<number, 'KilometersPerSecond'>;
*/
export type RadiansPerSecond = Distinct<number, 'RadiansPerSecond'>;

/**
* Represents a value in degrees per second.
*/
export type DegreesPerSecond = Distinct<number, 'DegreesPerSecond'>;

/**
* Represents a value in meters per second.
*/
Expand Down
4 changes: 2 additions & 2 deletions test/observation/__snapshots__/RadecTopocentric.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ exports[`RadecTopocentric should return the angle in degrees 1`] = `0.9999999999

exports[`RadecTopocentric should return the declination in degrees 1`] = `0`;

exports[`RadecTopocentric should return the declination rate in degrees 1`] = `undefined`;
exports[`RadecTopocentric should return the declination rate in degrees 1`] = `null`;

exports[`RadecTopocentric should return the position 1`] = `
Vector3D {
Expand All @@ -60,7 +60,7 @@ Vector3D {

exports[`RadecTopocentric should return the right ascension in degrees 1`] = `25`;

exports[`RadecTopocentric should return the right ascension rate in degrees 1`] = `undefined`;
exports[`RadecTopocentric should return the right ascension rate in degrees 1`] = `null`;

exports[`RadecTopocentric should return the velocity 1`] = `
Vector3D {
Expand Down

0 comments on commit 942f204

Please sign in to comment.