Files
astro/basic/topocentric_horizontal.go
T

91 lines
4.0 KiB
Go
Raw Normal View History

package basic
import (
"math"
"b612.me/astro/internal/ephem"
. "b612.me/astro/tools"
)
// topocentricHourAngleDec 由地心视赤经、视赤纬(度)与地心距(AU)给出观测者处的站心时角与站心视赤纬(度)。
// 恒星时只算一次,视差修正与时角共用;观测者取海拔 0,海拔对太阳系天体视差的影响可忽略。
func topocentricHourAngleDec(utcJD, lon, lat, ra, dec, distanceAU float64) (hourAngle, topocentricDec float64) {
gast := ApparentSiderealTime(UTC2UT1(utcJD)) * 15
topocentricRA, topocentricDec := topocentricRaDecWithSidereal(ra, dec, lat, lon, gast, distanceAU, 0)
return Limit360(gast + lon - topocentricRA), topocentricDec
}
// horizontalAltitude 时角、赤纬、纬度(度)转高度角 / altitude from hour angle, declination and latitude.
func horizontalAltitude(hourAngle, dec, lat float64) float64 {
return ArcSin(Sin(lat)*Sin(dec) + Cos(dec)*Cos(lat)*Cos(hourAngle))
}
// horizontalAzimuth 时角、赤纬、纬度(度)转方位角,北起向东 / azimuth from north through east.
func horizontalAzimuth(hourAngle, dec, lat float64) float64 {
tanAzimuth := Sin(hourAngle) / (Cos(hourAngle)*Sin(lat) - Tan(dec)*Cos(lat))
azimuth := ArcTan(tanAzimuth)
if azimuth < 0 {
if hourAngle/15 < 12 {
return azimuth + 360
}
return azimuth + 180
}
if hourAngle/15 < 12 {
return azimuth + 180
}
return azimuth
}
// planetApparentRaDecDistanceNWithInstance 行星地心视赤经、视赤纬与几何地心距,三者取自同一次求值。
func planetApparentRaDecDistanceNWithInstance(index int, jde float64, n int, inst *Instance) (ra, dec, distanceAU float64) {
geo, _, distanceAU, ok := planetApparentPositionWithInstance(index, jde, n, inst)
if !ok || math.IsNaN(geo.lo) || math.IsNaN(geo.bo) {
return math.NaN(), math.NaN(), math.NaN()
}
ra, dec = planetApparentRaDecFromLoBo(jde, geo.lo, geo.bo)
return ra, dec, distanceAU
}
func planetTopocentricHourAngleDecN(index int, localJD, lon, lat, timezone float64, n int, inst *Instance) (float64, float64) {
utcJD := localJD - timezone/24.0
ra, dec, distanceAU := planetApparentRaDecDistanceNWithInstance(index, UTC2TT(utcJD), n, inst)
return topocentricHourAngleDec(utcJD, lon, lat, ra, dec, distanceAU)
}
// planetHeightN 行星站心视高度角(度,不含折射)/ topocentric planet altitude without refraction.
func planetHeightN(index int, localJD, lon, lat, timezone float64, n int, inst *Instance) float64 {
hourAngle, dec := planetTopocentricHourAngleDecN(index, localJD, lon, lat, timezone, n, inst)
return horizontalAltitude(hourAngle, dec, lat)
}
// planetAzimuthN 行星站心方位角(度)/ topocentric planet azimuth.
func planetAzimuthN(index int, localJD, lon, lat, timezone float64, n int, inst *Instance) float64 {
hourAngle, dec := planetTopocentricHourAngleDecN(index, localJD, lon, lat, timezone, n, inst)
return horizontalAzimuth(hourAngle, dec, lat)
}
// sunTopocentricHourAngleDecN 太阳站心时角、站心视赤纬与地日距 / topocentric solar hour angle, declination and distance.
func sunTopocentricHourAngleDecN(jd, lon, lat, tz float64, n int, inst *Instance) (hourAngle, dec, distanceAU float64) {
utcJD := jd - tz/24.0
ra, dec, distanceAU := hSunApparentRaDecDistanceN(UTC2TT(utcJD), n, inst)
hourAngle, dec = topocentricHourAngleDec(utcJD, lon, lat, ra, dec, distanceAU)
return hourAngle, dec, distanceAU
}
// sunAzimuthN 地距只用于视差,矢量视位置可用时直接取其距离,省去一次地距求值。
func sunAzimuthN(jd, lon, lat, tz float64, n int, inst *Instance) float64 {
utcJD := jd - tz/24.0
tt := UTC2TT(utcJD)
var ra, dec, distanceAU float64
if lo, bo, _, dist, ok, err := vectorApparentWithInstance(ephem.Sun, tt, n, inst); err != nil {
return math.NaN()
} else if ok {
ra, dec = LoBoToRaDec(tt, lo, bo)
distanceAU = dist
} else {
ra, dec, distanceAU = hSunApparentRaDecDistanceN(tt, n, inst)
}
hourAngle, topocentricDec := topocentricHourAngleDec(utcJD, lon, lat, ra, dec, distanceAU)
return horizontalAzimuth(hourAngle, topocentricDec, lat)
}