Source

coordinates/equatorial2horizontal.ts

import { Degree, EquatorialCoordinates, GeographicCoordinates, HorizontalCoordinates, JulianDay } from '@/types'
import { getLocalSiderealTime } from '@/juliandays'
import { fmod360, fmod90 } from '@/utils'
import { DEG2RAD, H2DEG, RAD2DEG } from '@/constants'

/**
 * Horizontal (local) altitude (where horizon is zero degrees)
 * @param {JulianDay} jd The julian day
 * @param {GeographicCoordinates} geoCoords The geographic coordinates of the observer's location.
 * @param {EquatorialCoordinates } equCoords The equatorial coordinates of the target
 * @returns {Degree}
 */
export function getHorizontalAltitude (jd: JulianDay, equCoords: EquatorialCoordinates, geoCoords: GeographicCoordinates): Degree {
  const lmst = getLocalSiderealTime(jd, geoCoords.longitude) * H2DEG
  const hourAngle = (lmst - equCoords.rightAscension) * DEG2RAD
  const rEquCoords = {
    rightAscension: equCoords.rightAscension * DEG2RAD,
    declination: equCoords.declination * DEG2RAD
  }
  const rGeoCoords = {
    longitude: geoCoords.longitude * DEG2RAD,
    latitude: geoCoords.latitude * DEG2RAD
  }
  const value = Math.asin(
    Math.sin(rGeoCoords.latitude) * Math.sin(rEquCoords.declination)
    + Math.cos(rGeoCoords.latitude) * Math.cos(rEquCoords.declination) * Math.cos(hourAngle)
  )
  return fmod90(value * RAD2DEG)
}

/**
 * Horizontal (local) azimuth.
 * @param {JulianDay} jd The julian day
 * @param {GeographicCoordinates} geoCoords The geographic coordinates of the observer's location.
 * @param {EquatorialCoordinates } equCoords The equatorial coordinates of the target
 * @returns {Degree}
 */
export function getHorizontalAzimuth (jd: JulianDay, equCoords: EquatorialCoordinates, geoCoords: GeographicCoordinates): Degree {
  const lmst = getLocalSiderealTime(jd, geoCoords.longitude) * H2DEG
  const hourAngle = (lmst - equCoords.rightAscension) * DEG2RAD
  const rEquCoords = {
    rightAscension: equCoords.rightAscension * DEG2RAD,
    declination: equCoords.declination * DEG2RAD
  }
  const rGeoCoords = {
    longitude: geoCoords.longitude * DEG2RAD,
    latitude: geoCoords.latitude * DEG2RAD
  }
  const value = Math.atan2(
    Math.sin(hourAngle),
    Math.cos(hourAngle) * Math.sin(rGeoCoords.latitude) - Math.tan(rEquCoords.declination) * Math.cos(rGeoCoords.latitude))
  return fmod360(value * RAD2DEG)
}


/**
 * Transform equatorial coordinates to horizontal coordinates.
 * @param {JulianDay} jd The julian day
 * @param {GeographicCoordinates} geoCoords The geographic coordinates of the observer's location.
 * @param {EquatorialCoordinates } equCoords The equatorial coordinates of the target
 * @returns {HorizontalCoordinates}
 */
export function transformEquatorialToHorizontal (jd: JulianDay, equCoords: EquatorialCoordinates, geoCoords: GeographicCoordinates): HorizontalCoordinates {
  return {
    azimuth: getHorizontalAzimuth(jd, equCoords, geoCoords),
    altitude: getHorizontalAltitude(jd, equCoords, geoCoords)
  }
}