feat: 引入可切换星历模型并扩展天象观测链路

- 新增半解析、旧模型、自定义与多源堆叠星历实例,提供 Context、Instance、SPK 读取及状态与视位置计算
- 统一太阳、月球和行星实例接口,扩展黄经穿越、留、相位、最近角距、偕日可见、任意高度升落、轨道节点及凌日等天象查询
- 完善日月食、月掩与凌日的月缘剖面、有限盘面接触、站心修正、局地可见性、全球路径和地图输出
- 新增 SVG、GeoJSON、KML 天象输出及凌日、月掩和月缘地形相关缓存与几何求解
- 新增恒星星表导入与查询,支持 CSV、Hipparcos、BSC5、Stellarium 等格式及名称、交叉标识、锥面检索和星等过滤
- 补充 IAU 2006、地球定向、折射消光、大气观测、轨道传播及半解析行星/月球数据支持
- 将默认未来民用时标切换为 TimeScaleLeapHour,更新 2027–2400 农历速查表、中文日期解析和时区边界处理
- 增加事件基线、跨模型回归、几何边界、月缘地形和输出契约测试,完善中英文手册、示例资源、NOTICE 与忽略规则
This commit is contained in:
2026-10-15 23:54:15 +08:00
parent 16c62a97d5
commit 044f2f4381
674 changed files with 62983 additions and 8396 deletions
+302
View File
@@ -0,0 +1,302 @@
package mercury
import (
"time"
)
// Altitude 站心视高度角,不含大气折射 / topocentric apparent altitude without refraction.
func Altitude(date time.Time, lon, lat float64) float64 {
return defaultModule.Altitude(date, lon, lat)
}
// AltitudeN 站心视高度角(n 变体) / n-parameterised topocentric apparent altitude.
func AltitudeN(date time.Time, lon, lat float64, n int) float64 {
return defaultModule.AltitudeN(date, lon, lat, n)
}
// ApparentBo 视黄纬 / apparent ecliptic latitude.
func ApparentBo(date time.Time) float64 { return defaultModule.ApparentBo(date) }
// ApparentBoN 视黄纬(n 变体) / n-parameterised apparent ecliptic latitude.
func ApparentBoN(date time.Time, n int) float64 { return defaultModule.ApparentBoN(date, n) }
// ApparentDec 视赤纬 / apparent declination.
func ApparentDec(date time.Time) float64 { return defaultModule.ApparentDec(date) }
// ApparentDecN 视赤纬(n 变体) / n-parameterised apparent declination.
func ApparentDecN(date time.Time, n int) float64 { return defaultModule.ApparentDecN(date, n) }
// ApparentLo 视黄经 / apparent ecliptic longitude.
func ApparentLo(date time.Time) float64 { return defaultModule.ApparentLo(date) }
// ApparentLoN 视黄经(n 变体) / n-parameterised apparent ecliptic longitude.
func ApparentLoN(date time.Time, n int) float64 { return defaultModule.ApparentLoN(date, n) }
// ApparentMagnitude 视星等 / apparent magnitude.
func ApparentMagnitude(date time.Time) float64 { return defaultModule.ApparentMagnitude(date) }
// ApparentMagnitudeN 视星等(n 变体) / n-parameterised apparent magnitude.
func ApparentMagnitudeN(date time.Time, n int) float64 {
return defaultModule.ApparentMagnitudeN(date, n)
}
// ApparentRa 视赤经 / apparent right ascension.
func ApparentRa(date time.Time) float64 { return defaultModule.ApparentRa(date) }
// ApparentRaDec 视赤经、视赤纬 / apparent right ascension and declination.
func ApparentRaDec(date time.Time) (float64, float64) { return defaultModule.ApparentRaDec(date) }
// ApparentRaDecN 视赤经赤纬(n 变体) / n-parameterised apparent right ascension and declination.
func ApparentRaDecN(date time.Time, n int) (float64, float64) {
return defaultModule.ApparentRaDecN(date, n)
}
// ApparentRaN 视赤经(n 变体) / n-parameterised apparent right ascension.
func ApparentRaN(date time.Time, n int) float64 { return defaultModule.ApparentRaN(date, n) }
// AscendingNode 水星升交点黄经 / ascending node longitude of Mercury.
func AscendingNode(date time.Time) float64 { return defaultModule.AscendingNode(date) }
// AscendingNodeN 水星升交点黄经(n 变体) / n-parameterised ascending node longitude of Mercury.
func AscendingNodeN(date time.Time, n int) float64 { return defaultModule.AscendingNodeN(date, n) }
// Azimuth 站心方位角,自正北向东量 / topocentric azimuth, measured from north through east.
func Azimuth(date time.Time, lon, lat float64) float64 { return defaultModule.Azimuth(date, lon, lat) }
// AzimuthN 站心方位角(n 变体) / n-parameterised topocentric azimuth.
func AzimuthN(date time.Time, lon, lat float64, n int) float64 {
return defaultModule.AzimuthN(date, lon, lat, n)
}
// BrightLimbPositionAngle 亮面中心位置角,单位度 / bright limb position angle in degrees.
func BrightLimbPositionAngle(date time.Time) float64 {
return defaultModule.BrightLimbPositionAngle(date)
}
// BrightLimbPositionAngleN 亮面中心位置角(n 变体),单位度 / n-parameterised bright limb position angle in degrees.
func BrightLimbPositionAngleN(date time.Time, n int) float64 {
return defaultModule.BrightLimbPositionAngleN(date, n)
}
// ClosestTransit 最近一次地心水星凌日 / closest geocentric Mercury transit.
func ClosestTransit(date time.Time) TransitInfo { return defaultModule.ClosestTransit(date) }
// CulminationTime 中天时刻,取 date 所在当地民用日 / culmination time, on the local civil day of date.
func CulminationTime(date time.Time, lon float64) time.Time {
return defaultModule.CulminationTime(date, lon)
}
// CulminationTimeN 中天时间(n 变体) / n-parameterised culmination time.
func CulminationTimeN(date time.Time, lon float64, n int) time.Time {
return defaultModule.CulminationTimeN(date, lon, n)
}
// DescendingNode 水星降交点黄经 / descending node longitude of Mercury.
func DescendingNode(date time.Time) float64 { return defaultModule.DescendingNode(date) }
// DescendingNodeN 水星降交点黄经(n 变体) / n-parameterised descending node longitude of Mercury.
func DescendingNodeN(date time.Time, n int) float64 { return defaultModule.DescendingNodeN(date, n) }
// Diameter 水星视直径,单位角秒 / apparent Mercury diameter in arcseconds.
func Diameter(date time.Time) float64 { return defaultModule.Diameter(date) }
// DiameterN 水星视直径(n 变体),单位角秒 / n-parameterised apparent Mercury diameter in arcseconds.
func DiameterN(date time.Time, n int) float64 { return defaultModule.DiameterN(date, n) }
// DownTime 落下时间别名 / deprecated set-time alias.
//
// Deprecated: use SetTime instead.
func DownTime(date time.Time, lon, lat, height float64, aero bool) (time.Time, error) {
return defaultModule.DownTime(date, lon, lat, height, aero)
}
// DownTimeN 落下时间别名(n 变体) / n-parameterised down-time alias.
func DownTimeN(date time.Time, lon, lat, height float64, aero bool, n int) (time.Time, error) {
return defaultModule.DownTimeN(date, lon, lat, height, aero, n)
}
// EarthDistance 地心距离 / Earth distance.
func EarthDistance(date time.Time) float64 { return defaultModule.EarthDistance(date) }
// EarthDistanceN 地球距离(n 变体) / n-parameterised Earth distance.
func EarthDistanceN(date time.Time, n int) float64 { return defaultModule.EarthDistanceN(date, n) }
// HourAngle 地心视时角,不含站心视差 / geocentric apparent hour angle without topocentric parallax.
func HourAngle(date time.Time, lon float64) float64 { return defaultModule.HourAngle(date, lon) }
// HourAngleN 时角(n 变体) / n-parameterised hour angle.
func HourAngleN(date time.Time, lon float64, n int) float64 {
return defaultModule.HourAngleN(date, lon, n)
}
// IlluminatedFraction 被照亮比例 / illuminated fraction.
func IlluminatedFraction(date time.Time) float64 { return defaultModule.IlluminatedFraction(date) }
// IlluminatedFractionN 被照亮比例(n 变体) / n-parameterised illuminated fraction.
func IlluminatedFractionN(date time.Time, n int) float64 {
return defaultModule.IlluminatedFractionN(date, n)
}
// LastConjunction 上一次合日,取 date 所在当地民用日 / previous conjunction with the Sun, on the local civil day of date.
func LastConjunction(date time.Time) time.Time { return defaultModule.LastConjunction(date) }
// LastGreatestElongation 上一次大距,取 date 所在当地民用日 / previous greatest elongation, on the local civil day of date.
func LastGreatestElongation(date time.Time) time.Time {
return defaultModule.LastGreatestElongation(date)
}
// LastGreatestElongationEast 上一次东大距,取 date 所在当地民用日 / previous greatest eastern elongation, on the local civil day of date.
func LastGreatestElongationEast(date time.Time) time.Time {
return defaultModule.LastGreatestElongationEast(date)
}
// LastGreatestElongationWest 上一次西大距,取 date 所在当地民用日 / previous greatest western elongation, on the local civil day of date.
func LastGreatestElongationWest(date time.Time) time.Time {
return defaultModule.LastGreatestElongationWest(date)
}
// LastInferiorConjunction 上一次下合,取 date 所在当地民用日 / previous inferior conjunction, on the local civil day of date.
func LastInferiorConjunction(date time.Time) time.Time {
return defaultModule.LastInferiorConjunction(date)
}
// LastProgradeToRetrograde 上一次顺行转逆行留,取 date 所在当地民用日 / previous station from prograde to retrograde, on the local civil day of date.
func LastProgradeToRetrograde(date time.Time) time.Time {
return defaultModule.LastProgradeToRetrograde(date)
}
// LastRetrograde 上一次留,取 date 所在当地民用日 / previous stationary point, on the local civil day of date.
func LastRetrograde(date time.Time) time.Time { return defaultModule.LastRetrograde(date) }
// LastRetrogradeToPrograde 上一次逆行转顺行留,取 date 所在当地民用日 / previous station from retrograde to prograde, on the local civil day of date.
func LastRetrogradeToPrograde(date time.Time) time.Time {
return defaultModule.LastRetrogradeToPrograde(date)
}
// LastSuperiorConjunction 上一次上合,取 date 所在当地民用日 / previous superior conjunction, on the local civil day of date.
func LastSuperiorConjunction(date time.Time) time.Time {
return defaultModule.LastSuperiorConjunction(date)
}
// LastTransit 上一次地心水星凌日 / previous geocentric Mercury transit.
func LastTransit(date time.Time) TransitInfo { return defaultModule.LastTransit(date) }
// LocalTransit 地心凌日在观测地的站心接触与凌甚 / topocentric contacts of a transit seen from the site.
func LocalTransit(transit TransitInfo, lon, lat, height float64) LocalTransitInfo {
return defaultModule.LocalTransit(transit, lon, lat, height)
}
// NextConjunction 下一次合日,取 date 所在当地民用日 / next conjunction with the Sun, on the local civil day of date.
func NextConjunction(date time.Time) time.Time { return defaultModule.NextConjunction(date) }
// NextGreatestElongation 下一次大距,取 date 所在当地民用日 / next greatest elongation, on the local civil day of date.
func NextGreatestElongation(date time.Time) time.Time {
return defaultModule.NextGreatestElongation(date)
}
// NextGreatestElongationEast 下一次东大距,取 date 所在当地民用日 / next greatest eastern elongation, on the local civil day of date.
func NextGreatestElongationEast(date time.Time) time.Time {
return defaultModule.NextGreatestElongationEast(date)
}
// NextGreatestElongationWest 下一次西大距,取 date 所在当地民用日 / next greatest western elongation, on the local civil day of date.
func NextGreatestElongationWest(date time.Time) time.Time {
return defaultModule.NextGreatestElongationWest(date)
}
// NextInferiorConjunction 下一次下合,取 date 所在当地民用日 / next inferior conjunction, on the local civil day of date.
func NextInferiorConjunction(date time.Time) time.Time {
return defaultModule.NextInferiorConjunction(date)
}
// NextProgradeToRetrograde 下一次顺行转逆行留,取 date 所在当地民用日 / next station from prograde to retrograde, on the local civil day of date.
func NextProgradeToRetrograde(date time.Time) time.Time {
return defaultModule.NextProgradeToRetrograde(date)
}
// NextRetrograde 下一次留,取 date 所在当地民用日 / next stationary point, on the local civil day of date.
func NextRetrograde(date time.Time) time.Time { return defaultModule.NextRetrograde(date) }
// NextRetrogradeToPrograde 下一次逆行转顺行留,取 date 所在当地民用日 / next station from retrograde to prograde, on the local civil day of date.
func NextRetrogradeToPrograde(date time.Time) time.Time {
return defaultModule.NextRetrogradeToPrograde(date)
}
// NextSuperiorConjunction 下一次上合,取 date 所在当地民用日 / next superior conjunction, on the local civil day of date.
func NextSuperiorConjunction(date time.Time) time.Time {
return defaultModule.NextSuperiorConjunction(date)
}
// NextTransit 下一次地心水星凌日 / next geocentric Mercury transit.
func NextTransit(date time.Time) TransitInfo { return defaultModule.NextTransit(date) }
// ParallacticAngle 水星视差角(天顶方向角) / Mercury parallactic angle.
func ParallacticAngle(date time.Time, lon, lat float64) float64 {
return defaultModule.ParallacticAngle(date, lon, lat)
}
// ParallacticAngleN 水星视差角(天顶方向角)(n 变体) / n-parameterised Mercury parallactic angle.
func ParallacticAngleN(date time.Time, lon, lat float64, n int) float64 {
return defaultModule.ParallacticAngleN(date, lon, lat, n)
}
// Phase 相位,被照亮比例 / phase, illuminated fraction.
func Phase(date time.Time) float64 { return defaultModule.Phase(date) }
// PhaseAngle 相位角,单位度 / phase angle in degrees.
func PhaseAngle(date time.Time) float64 { return defaultModule.PhaseAngle(date) }
// PhaseAngleN 相位角(n 变体),单位度 / n-parameterised phase angle in degrees.
func PhaseAngleN(date time.Time, n int) float64 { return defaultModule.PhaseAngleN(date, n) }
// PhaseN 相位(n 变体),被照亮比例 / n-parameterised phase, illuminated fraction.
func PhaseN(date time.Time, n int) float64 { return defaultModule.PhaseN(date, n) }
// Physical 水星物理观测参数 / physical observing parameters of Mercury.
func Physical(date time.Time) PhysicalInfo { return defaultModule.Physical(date) }
// PhysicalN 水星物理观测参数(n 变体) / n-parameterised physical observing parameters of Mercury.
func PhysicalN(date time.Time, n int) PhysicalInfo { return defaultModule.PhysicalN(date, n) }
// RiseTime 升起时间,取 date 所在当地民用日 / rise time, on the local civil day of date.
func RiseTime(date time.Time, lon, lat, height float64, aero bool) (time.Time, error) {
return defaultModule.RiseTime(date, lon, lat, height, aero)
}
// RiseTimeN 升起时间(n 变体) / n-parameterised rise time.
func RiseTimeN(date time.Time, lon, lat, height float64, aero bool, n int) (time.Time, error) {
return defaultModule.RiseTimeN(date, lon, lat, height, aero, n)
}
// Semidiameter 水星视半径,单位角秒 / apparent Mercury semidiameter in arcseconds.
func Semidiameter(date time.Time) float64 { return defaultModule.Semidiameter(date) }
// SemidiameterN 水星视半径(n 变体),单位角秒 / n-parameterised apparent Mercury semidiameter in arcseconds.
func SemidiameterN(date time.Time, n int) float64 { return defaultModule.SemidiameterN(date, n) }
// SetTime 落下时间,取 date 所在当地民用日 / set time, on the local civil day of date.
func SetTime(date time.Time, lon, lat, height float64, aero bool) (time.Time, error) {
return defaultModule.SetTime(date, lon, lat, height, aero)
}
// SetTimeN 落下时间(n 变体) / n-parameterised set time.
func SetTimeN(date time.Time, lon, lat, height float64, aero bool, n int) (time.Time, error) {
return defaultModule.SetTimeN(date, lon, lat, height, aero, n)
}
// SunDistance 日心距离 / Sun distance.
func SunDistance(date time.Time) float64 { return defaultModule.SunDistance(date) }
// SunDistanceN 太阳距离(n 变体) / n-parameterised Sun distance.
func SunDistanceN(date time.Time, n int) float64 { return defaultModule.SunDistanceN(date, n) }
// Zenith 天顶距 / zenith distance.
func Zenith(date time.Time, lon, lat float64) float64 { return defaultModule.Zenith(date, lon, lat) }
// ZenithN 天顶距(n 变体) / n-parameterised zenith distance.
func ZenithN(date time.Time, lon, lat float64, n int) float64 {
return defaultModule.ZenithN(date, lon, lat, n)
}
// ApparentMagnitude2018 视星等(Mallama & Hilton 2018 模型)/ apparent magnitude, Mallama & Hilton 2018 model.
func ApparentMagnitude2018(date time.Time) float64 { return defaultModule.ApparentMagnitude2018(date) }
+13
View File
@@ -0,0 +1,13 @@
package mercury
import (
"b612.me/astro/internal/ephem"
)
// Mercury 指定星历实例的计算模块 / computation module bound to an ephemeris instance.
type Mercury struct{ inst *ephem.Instance }
// NewWithInstance 创建指定星历实例的模块,nil 使用全局模型 / create a module; nil uses the global model.
func NewWithInstance(inst *ephem.Instance) *Mercury { return &Mercury{inst: inst} }
var defaultModule Mercury
+102
View File
@@ -0,0 +1,102 @@
package mercury
import (
"b612.me/astro/basic"
"b612.me/astro/internal/ephem"
"testing"
"time"
)
type contextAPI interface {
Altitude(date time.Time, lon, lat float64) float64
AltitudeN(date time.Time, lon, lat float64, n int) float64
ApparentBo(date time.Time) float64
ApparentBoN(date time.Time, n int) float64
ApparentDec(date time.Time) float64
ApparentDecN(date time.Time, n int) float64
ApparentLo(date time.Time) float64
ApparentLoN(date time.Time, n int) float64
ApparentMagnitude(date time.Time) float64
ApparentMagnitudeN(date time.Time, n int) float64
ApparentRa(date time.Time) float64
ApparentRaDec(date time.Time) (float64, float64)
ApparentRaDecN(date time.Time, n int) (float64, float64)
ApparentRaN(date time.Time, n int) float64
AscendingNode(date time.Time) float64
AscendingNodeN(date time.Time, n int) float64
Azimuth(date time.Time, lon, lat float64) float64
AzimuthN(date time.Time, lon, lat float64, n int) float64
BrightLimbPositionAngle(date time.Time) float64
BrightLimbPositionAngleN(date time.Time, n int) float64
ClosestTransit(date time.Time) TransitInfo
CulminationTime(date time.Time, lon float64) time.Time
CulminationTimeN(date time.Time, lon float64, n int) time.Time
DescendingNode(date time.Time) float64
DescendingNodeN(date time.Time, n int) float64
Diameter(date time.Time) float64
DiameterN(date time.Time, n int) float64
DownTime(date time.Time, lon, lat, height float64, aero bool) (time.Time, error)
DownTimeN(date time.Time, lon, lat, height float64, aero bool, n int) (time.Time, error)
EarthDistance(date time.Time) float64
EarthDistanceN(date time.Time, n int) float64
HourAngle(date time.Time, lon float64) float64
HourAngleN(date time.Time, lon float64, n int) float64
IlluminatedFraction(date time.Time) float64
IlluminatedFractionN(date time.Time, n int) float64
LastConjunction(date time.Time) time.Time
LastGreatestElongation(date time.Time) time.Time
LastGreatestElongationEast(date time.Time) time.Time
LastGreatestElongationWest(date time.Time) time.Time
LastInferiorConjunction(date time.Time) time.Time
LastProgradeToRetrograde(date time.Time) time.Time
LastRetrograde(date time.Time) time.Time
LastRetrogradeToPrograde(date time.Time) time.Time
LastSuperiorConjunction(date time.Time) time.Time
LastTransit(date time.Time) TransitInfo
LocalTransit(transit TransitInfo, lon, lat, height float64) LocalTransitInfo
NextConjunction(date time.Time) time.Time
NextGreatestElongation(date time.Time) time.Time
NextGreatestElongationEast(date time.Time) time.Time
NextGreatestElongationWest(date time.Time) time.Time
NextInferiorConjunction(date time.Time) time.Time
NextProgradeToRetrograde(date time.Time) time.Time
NextRetrograde(date time.Time) time.Time
NextRetrogradeToPrograde(date time.Time) time.Time
NextSuperiorConjunction(date time.Time) time.Time
NextTransit(date time.Time) TransitInfo
ParallacticAngle(date time.Time, lon, lat float64) float64
ParallacticAngleN(date time.Time, lon, lat float64, n int) float64
Phase(date time.Time) float64
PhaseAngle(date time.Time) float64
PhaseAngleN(date time.Time, n int) float64
PhaseN(date time.Time, n int) float64
Physical(date time.Time) PhysicalInfo
PhysicalN(date time.Time, n int) PhysicalInfo
RiseTime(date time.Time, lon, lat, height float64, aero bool) (time.Time, error)
RiseTimeN(date time.Time, lon, lat, height float64, aero bool, n int) (time.Time, error)
Semidiameter(date time.Time) float64
SemidiameterN(date time.Time, n int) float64
SetTime(date time.Time, lon, lat, height float64, aero bool) (time.Time, error)
SetTimeN(date time.Time, lon, lat, height float64, aero bool, n int) (time.Time, error)
SunDistance(date time.Time) float64
SunDistanceN(date time.Time, n int) float64
Zenith(date time.Time, lon, lat float64) float64
ZenithN(date time.Time, lon, lat float64, n int) float64
}
var _ contextAPI = (*Mercury)(nil)
func TestContextModuleIsolation(t *testing.T) {
previous := basic.GetEphemerisModel()
t.Cleanup(func() { basic.SetEphemerisModel(previous) })
date := time.Date(2024, 10, 6, 12, 0, 0, 0, time.UTC)
for _, model := range []ephem.Model{ephem.Legacy, ephem.Semianalytic} {
basic.SetEphemerisModel(basic.EphemerisModel(model))
want := ApparentLo(date)
module := NewWithInstance(ephem.NewModelInstance(model))
basic.SetEphemerisModel(basic.EphemerisModel(1 - int(model)))
if got := module.ApparentLo(date); got != want {
t.Fatalf("model %d: longitude %.12f, want %.12f", model, got, want)
}
}
}
+10 -10
View File
@@ -8,23 +8,23 @@ import (
)
// Semidiameter 水星视半径,单位角秒 / apparent Mercury semidiameter in arcseconds.
func Semidiameter(date time.Time) float64 {
return SemidiameterN(date, -1)
func (module *Mercury) Semidiameter(date time.Time) float64 {
return module.SemidiameterN(date, -1)
}
// SemidiameterN 水星视半径(截断版),单位角秒 / truncated apparent Mercury semidiameter in arcseconds.
func SemidiameterN(date time.Time, n int) float64 {
// SemidiameterN 水星视半径(n 变体),单位角秒 / n-parameterised apparent Mercury semidiameter in arcseconds.
func (module *Mercury) SemidiameterN(date time.Time, n int) float64 {
jd := calendar.Date2JD(date.UTC())
return basic.MercurySemidiameterN(basic.UTC2TT(jd), n)
return basic.MercurySemidiameterNWithInstance(basic.UTC2TT(jd), n, module.inst)
}
// Diameter 水星视直径,单位角秒 / apparent Mercury diameter in arcseconds.
func Diameter(date time.Time) float64 {
return DiameterN(date, -1)
func (module *Mercury) Diameter(date time.Time) float64 {
return module.DiameterN(date, -1)
}
// DiameterN 水星视直径(截断版),单位角秒 / truncated apparent Mercury diameter in arcseconds.
func DiameterN(date time.Time, n int) float64 {
// DiameterN 水星视直径(n 变体),单位角秒 / n-parameterised apparent Mercury diameter in arcseconds.
func (module *Mercury) DiameterN(date time.Time, n int) float64 {
jd := calendar.Date2JD(date.UTC())
return basic.MercuryDiameterN(basic.UTC2TT(jd), n)
return basic.MercuryDiameterNWithInstance(basic.UTC2TT(jd), n, module.inst)
}
+4
View File
@@ -1,3 +1,7 @@
// Package mercury 水星位置、升落、合日、留、大距、地心凌日、相位、视直径与物理星历,角度单位为度。
// Package mercury covers Mercury position, rise/set, conjunction, station, elongation, geocentric transit, phase, apparent diameter and physical ephemeris; angles are degrees.
// 求值接口的 N 后缀是 n 变体:n < 0 取完整级数;半解析模型下所有 n >= 0 使用同一张快速表;Legacy 按 n 截断。
// The N suffix marks an n-variant: n < 0 uses the full series, every n >= 0 uses one fast table under the semianalytic model, and Legacy truncates by n.
// 时间参数:位置、距离、星等与物理量接口的 date 是绝对时刻,其所在时区参与地方时换算;升落、中天、晨昏与 Next/Last 事件接口按 date 所在时区的当地民用日求解,返回时刻保持该时区。
// Time arguments: date is an absolute instant for position, distance, magnitude and physical-quantity entry points, and its zone takes part in local-time conversion; rise/set, culmination, twilight and Next/Last event entry points solve for the local civil day in date's zone and return instants keeping that zone.
package mercury
+80 -178
View File
@@ -1,11 +1,11 @@
package mercury
import (
"b612.me/astro/basic"
"b612.me/astro/calendar"
"b612.me/astro/planet"
"errors"
"time"
"b612.me/astro/basic"
"b612.me/astro/calendar"
)
var (
@@ -31,136 +31,94 @@ func riseSetResult(date time.Time, jd float64, err error) (time.Time, error) {
}
// ApparentLo 视黄经 / apparent ecliptic longitude.
//
// 返回水星在 date 对应绝对时刻的瞬时视黄经,单位度。
// Returns the apparent ecliptic longitude of Mercury at the instant represented by date, in degrees.
func ApparentLo(date time.Time) float64 {
func (module *Mercury) ApparentLo(date time.Time) float64 {
jd := calendar.Date2JD(date.UTC())
return basic.MercuryApparentLo(basic.UTC2TT(jd))
return basic.MercuryApparentLoWithInstance(basic.UTC2TT(jd), module.inst)
}
// ApparentBo 视黄纬 / apparent ecliptic latitude.
//
// 返回水星在 date 对应绝对时刻的瞬时视黄纬,单位度。
// Returns the apparent ecliptic latitude of Mercury at the instant represented by date, in degrees.
func ApparentBo(date time.Time) float64 {
func (module *Mercury) ApparentBo(date time.Time) float64 {
jd := calendar.Date2JD(date.UTC())
return basic.MercuryApparentBo(basic.UTC2TT(jd))
return basic.MercuryApparentBoWithInstance(basic.UTC2TT(jd), module.inst)
}
// ApparentRa 视赤经 / apparent right ascension.
//
// 返回水星在 date 对应绝对时刻的瞬时视赤经,单位度。
// Returns the apparent right ascension of Mercury at the instant represented by date, in degrees.
func ApparentRa(date time.Time) float64 {
func (module *Mercury) ApparentRa(date time.Time) float64 {
jd := calendar.Date2JD(date.UTC())
return basic.MercuryApparentRa(basic.UTC2TT(jd))
return basic.MercuryApparentRaWithInstance(basic.UTC2TT(jd), module.inst)
}
// ApparentDec 视赤纬 / apparent declination.
//
// 返回水星在 date 对应绝对时刻的瞬时视赤纬,单位度。
// Returns the apparent declination of Mercury at the instant represented by date, in degrees.
func ApparentDec(date time.Time) float64 {
func (module *Mercury) ApparentDec(date time.Time) float64 {
jd := calendar.Date2JD(date.UTC())
return basic.MercuryApparentDec(basic.UTC2TT(jd))
return basic.MercuryApparentDecWithInstance(basic.UTC2TT(jd), module.inst)
}
// ApparentRaDec 视赤经、视赤纬 / apparent right ascension and declination.
//
// 返回水星在 date 对应绝对时刻的瞬时视赤经与视赤纬,单位度。
// Returns the apparent right ascension and declination of Mercury at the instant represented by date, in degrees.
func ApparentRaDec(date time.Time) (float64, float64) {
func (module *Mercury) ApparentRaDec(date time.Time) (float64, float64) {
jd := calendar.Date2JD(date.UTC())
return basic.MercuryApparentRaDec(basic.UTC2TT(jd))
return basic.MercuryApparentRaDecWithInstance(basic.UTC2TT(jd), module.inst)
}
// ApparentMagnitude 视星等 / apparent magnitude.
//
// 返回水星在 date 对应绝对时刻的视星等。
// Returns the apparent visual magnitude of Mercury at the instant represented by date.
func ApparentMagnitude(date time.Time) float64 {
func (module *Mercury) ApparentMagnitude(date time.Time) float64 {
jd := calendar.Date2JD(date.UTC())
return basic.MercuryMag(basic.UTC2TT(jd))
return basic.MercuryMagWithInstance(basic.UTC2TT(jd), module.inst)
}
// EarthDistance 地心距离 / Earth distance.
//
// 返回水星在 date 对应绝对时刻到地球的距离,单位 AU。
// Returns the distance from Mercury to Earth at the instant represented by date, in astronomical units.
func EarthDistance(date time.Time) float64 {
func (module *Mercury) EarthDistance(date time.Time) float64 {
jd := calendar.Date2JD(date.UTC())
return basic.EarthMercuryAway(basic.UTC2TT(jd))
return basic.EarthMercuryAwayWithInstance(basic.UTC2TT(jd), module.inst)
}
// SunDistance 日心距离 / Sun distance.
//
// 返回水星在 date 对应绝对时刻到太阳的距离,单位 AU。
// Returns the distance from Mercury to the Sun at the instant represented by date, in astronomical units.
func SunDistance(date time.Time) float64 {
func (module *Mercury) SunDistance(date time.Time) float64 {
jd := calendar.Date2JD(date.UTC())
return planet.WherePlanet(1, 2, basic.UTC2TT(jd))
return basic.PlanetCoordinateWithInstance(1, 2, basic.UTC2TT(jd), module.inst)
}
// Altitude 高度角 / altitude.
//
// date 表示观测时刻,会读取其时区参与地方时计算;lon 为观测者经度,东正西负;lat 为观测者纬度,北正南负。返回值单位度。
// date is the observing instant and its zone offset participates in local-time calculations. lon is east-positive longitude, lat is north-positive latitude, and the result is in degrees.
func Altitude(date time.Time, lon, lat float64) float64 {
// Altitude 站心视高度角,不含大气折射 / topocentric apparent altitude without refraction.
func (module *Mercury) Altitude(date time.Time, lon, lat float64) float64 {
localJD := basic.Date2JD(date)
_, loc := date.Zone()
timezone := float64(loc) / 3600.0
return basic.MercuryHeight(localJD, lon, lat, timezone)
return basic.MercuryHeightWithInstance(localJD, lon, lat, timezone, module.inst)
}
// Zenith 天顶距 / zenith distance.
//
// 参数与 Altitude 相同,返回值为对应时刻的天顶距,单位度。
// Uses the same inputs as Altitude and returns the zenith distance in degrees.
func Zenith(date time.Time, lon, lat float64) float64 {
return 90 - Altitude(date, lon, lat)
func (module *Mercury) Zenith(date time.Time, lon, lat float64) float64 {
return 90 - module.Altitude(date, lon, lat)
}
// Azimuth 方位角 / azimuth.
//
// date 表示观测时刻,会读取其时区参与地方时计算;lon 为观测者经度,东正西负;lat 为观测者纬度,北正南负。返回值按正北为 0°、向东增加。
// date is the observing instant and its zone offset participates in local-time calculations. lon is east-positive longitude, lat is north-positive latitude, and azimuth is measured from north toward east.
func Azimuth(date time.Time, lon, lat float64) float64 {
// Azimuth 站心方位角 / topocentric azimuth.
func (module *Mercury) Azimuth(date time.Time, lon, lat float64) float64 {
localJD := basic.Date2JD(date)
_, loc := date.Zone()
timezone := float64(loc) / 3600.0
return basic.MercuryAzimuth(localJD, lon, lat, timezone)
return basic.MercuryAzimuthWithInstance(localJD, lon, lat, timezone, module.inst)
}
// HourAngle 时角 / hour angle.
//
// date 表示观测时刻,会读取其时区参与地方时计算;lon 为观测者经度,东正西负。返回值单位度。
// date is the observing instant and its zone offset participates in local-time calculations. lon is east-positive longitude and the returned hour angle is in degrees.
func HourAngle(date time.Time, lon float64) float64 {
// HourAngle 地心视时角,不含站心视差 / geocentric apparent hour angle without topocentric parallax.
func (module *Mercury) HourAngle(date time.Time, lon float64) float64 {
localJD := basic.Date2JD(date)
_, loc := date.Zone()
timezone := float64(loc) / 3600.0
return basic.MercuryHourAngle(localJD, lon, timezone)
return basic.MercuryHourAngleWithInstance(localJD, lon, timezone, module.inst)
}
// CulminationTime 中天时刻 / culmination time.
//
// date 取其所在时区的当地日期,返回值保持相同时区;lon 为观测者经度,东正西负。
// date is interpreted on its local civil day and the result keeps the same time zone. lon is east-positive longitude.
func CulminationTime(date time.Time, lon float64) time.Time {
func (module *Mercury) CulminationTime(date time.Time, lon float64) time.Time {
date = time.Date(date.Year(), date.Month(), date.Day(), 0, 0, 0, 0, date.Location())
localJD := basic.Date2JD(date)
_, loc := date.Zone()
timezone := float64(loc) / 3600.0
calcJD := basic.MercuryCulminationTime(localJD, lon, timezone) - timezone/24.00
calcJD := basic.MercuryCulminationTimeWithInstance(localJD, lon, timezone, module.inst) - timezone/24.00
return basic.JD2DateByZone(calcJD, date.Location(), false)
}
// RiseTime 升起时间 / rise time.
//
// date 取其所在时区的当地日期,返回值保持相同时区;lon 为东正西负经度,lat 为北正南负纬度;height 为观测点椭球高(大地高,米);aero 为 true 时加入标准大气折射。
// date is interpreted on its local civil day and the result keeps the same time zone. lon is east-positive longitude, lat is north-positive latitude, height is observer elevation in meters, and aero enables standard atmospheric refraction.
func RiseTime(date time.Time, lon, lat, height float64, aero bool) (time.Time, error) {
func (module *Mercury) RiseTime(date time.Time, lon, lat, height float64, aero bool) (time.Time, error) {
var aeroFloat float64
if aero {
aeroFloat = 1
@@ -169,25 +127,17 @@ func RiseTime(date time.Time, lon, lat, height float64, aero bool) (time.Time, e
localJD := basic.Date2JD(date)
_, loc := date.Zone()
timezone := float64(loc) / 3600.0
riseJD, err := basic.MercuryRiseTime(localJD, lon, lat, timezone, aeroFloat, height)
riseJD, err := basic.MercuryRiseTimeWithInstance(localJD, lon, lat, timezone, aeroFloat, height, module.inst)
return riseSetResult(date, riseJD, err)
}
// DownTime 落下时间别名 / deprecated set-time alias.
//
// Deprecated: use SetTime instead.
//
// 参数与 SetTime 相同,仅为兼容旧接口保留。
// Same as SetTime and kept only for backward compatibility.
func DownTime(date time.Time, lon, lat, height float64, aero bool) (time.Time, error) {
return SetTime(date, lon, lat, height, aero)
func (module *Mercury) DownTime(date time.Time, lon, lat, height float64, aero bool) (time.Time, error) {
return module.SetTime(date, lon, lat, height, aero)
}
// SetTime 落下时间 / set time.
//
// 参数与 RiseTime 相同,返回给定当地日期内的落下时刻。
// Uses the same inputs as RiseTime and returns the set time on the corresponding local civil day.
func SetTime(date time.Time, lon, lat, height float64, aero bool) (time.Time, error) {
func (module *Mercury) SetTime(date time.Time, lon, lat, height float64, aero bool) (time.Time, error) {
var aeroFloat float64
if aero {
aeroFloat = 1
@@ -196,168 +146,120 @@ func SetTime(date time.Time, lon, lat, height float64, aero bool) (time.Time, er
localJD := basic.Date2JD(date)
_, loc := date.Zone()
timezone := float64(loc) / 3600.0
riseJD, err := basic.MercurySetTime(localJD, lon, lat, timezone, aeroFloat, height)
riseJD, err := basic.MercurySetTimeWithInstance(localJD, lon, lat, timezone, aeroFloat, height, module.inst)
return riseSetResult(date, riseJD, err)
}
// LastConjunction 上一次合日 / previous conjunction with the Sun.
//
// 返回 date 当前或之前最近一次与太阳的合日时刻,结果保持 date 的时区。
// Returns the nearest conjunction with the Sun at or before date, keeping date's time zone.
func LastConjunction(date time.Time) time.Time {
func (module *Mercury) LastConjunction(date time.Time) time.Time {
jde := basic.UTC2TT(basic.Date2JD(date.UTC()))
return basic.JD2DateByZone(basic.LastMercuryConjunction(jde), date.Location(), false)
return basic.JD2DateByZone(basic.LastMercuryConjunctionWithInstance(jde, module.inst), date.Location(), false)
}
// NextConjunction 下一次合日 / next conjunction with the Sun.
//
// 返回 date 当前或之后最近一次与太阳的合日时刻,结果保持 date 的时区。
// Returns the nearest conjunction with the Sun at or after date, keeping date's time zone.
func NextConjunction(date time.Time) time.Time {
func (module *Mercury) NextConjunction(date time.Time) time.Time {
jde := basic.UTC2TT(basic.Date2JD(date.UTC()))
return basic.JD2DateByZone(basic.NextMercuryConjunction(jde), date.Location(), false)
return basic.JD2DateByZone(basic.NextMercuryConjunctionWithInstance(jde, module.inst), date.Location(), false)
}
// LastInferiorConjunction 上一次下合 / previous inferior conjunction.
//
// 返回 date 当前或之前最近一次下合时刻,结果保持 date 的时区。
// Returns the nearest inferior conjunction at or before date, keeping date's time zone.
func LastInferiorConjunction(date time.Time) time.Time {
func (module *Mercury) LastInferiorConjunction(date time.Time) time.Time {
jde := basic.UTC2TT(basic.Date2JD(date.UTC()))
return basic.JD2DateByZone(basic.LastMercuryInferiorConjunctionInclusive(jde), date.Location(), false)
return basic.JD2DateByZone(basic.LastMercuryInferiorConjunctionInclusiveWithInstance(jde, module.inst), date.Location(), false)
}
// NextInferiorConjunction 下一次下合 / next inferior conjunction.
//
// 返回 date 当前或之后最近一次下合时刻,结果保持 date 的时区。
// Returns the nearest inferior conjunction at or after date, keeping date's time zone.
func NextInferiorConjunction(date time.Time) time.Time {
func (module *Mercury) NextInferiorConjunction(date time.Time) time.Time {
jde := basic.UTC2TT(basic.Date2JD(date.UTC()))
return basic.JD2DateByZone(basic.NextMercuryInferiorConjunctionInclusive(jde), date.Location(), false)
return basic.JD2DateByZone(basic.NextMercuryInferiorConjunctionInclusiveWithInstance(jde, module.inst), date.Location(), false)
}
// LastSuperiorConjunction 上一次上合 / previous superior conjunction.
//
// 返回 date 当前或之前最近一次上合时刻,结果保持 date 的时区。
// Returns the nearest superior conjunction at or before date, keeping date's time zone.
func LastSuperiorConjunction(date time.Time) time.Time {
func (module *Mercury) LastSuperiorConjunction(date time.Time) time.Time {
jde := basic.UTC2TT(basic.Date2JD(date.UTC()))
return basic.JD2DateByZone(basic.LastMercurySuperiorConjunctionInclusive(jde), date.Location(), false)
return basic.JD2DateByZone(basic.LastMercurySuperiorConjunctionInclusiveWithInstance(jde, module.inst), date.Location(), false)
}
// NextSuperiorConjunction 下一次上合 / next superior conjunction.
//
// 返回 date 当前或之后最近一次上合时刻,结果保持 date 的时区。
// Returns the nearest superior conjunction at or after date, keeping date's time zone.
func NextSuperiorConjunction(date time.Time) time.Time {
func (module *Mercury) NextSuperiorConjunction(date time.Time) time.Time {
jde := basic.UTC2TT(basic.Date2JD(date.UTC()))
return basic.JD2DateByZone(basic.NextMercurySuperiorConjunctionInclusive(jde), date.Location(), false)
return basic.JD2DateByZone(basic.NextMercurySuperiorConjunctionInclusiveWithInstance(jde, module.inst), date.Location(), false)
}
// LastRetrograde 上一次留 / previous stationary point.
//
// 返回 date 当前或之前最近一次留时刻,不区分顺转逆还是逆转顺,结果保持 date 的时区。
// Returns the nearest stationary point at or before date, regardless of the direction change, keeping date's time zone.
func LastRetrograde(date time.Time) time.Time {
func (module *Mercury) LastRetrograde(date time.Time) time.Time {
jde := basic.UTC2TT(basic.Date2JD(date.UTC()))
return basic.JD2DateByZone(basic.LastMercuryRetrogradeInclusive(jde), date.Location(), false)
return basic.JD2DateByZone(basic.LastMercuryRetrogradeInclusiveWithInstance(jde, module.inst), date.Location(), false)
}
// NextRetrograde 下一次留 / next stationary point.
//
// 返回 date 当前或之后最近一次留时刻,不区分顺转逆还是逆转顺,结果保持 date 的时区。
// Returns the nearest stationary point at or after date, regardless of the direction change, keeping date's time zone.
func NextRetrograde(date time.Time) time.Time {
func (module *Mercury) NextRetrograde(date time.Time) time.Time {
jde := basic.UTC2TT(basic.Date2JD(date.UTC()))
return basic.JD2DateByZone(basic.NextMercuryRetrogradeInclusive(jde), date.Location(), false)
return basic.JD2DateByZone(basic.NextMercuryRetrogradeInclusiveWithInstance(jde, module.inst), date.Location(), false)
}
// LastProgradeToRetrograde 上一次顺行转逆行留 / previous station from prograde to retrograde.
//
// 返回 date 当前或之前最近一次由顺行转为逆行的留时刻,结果保持 date 的时区。
// Returns the nearest station at or before date where motion changes from prograde to retrograde, keeping date's time zone.
func LastProgradeToRetrograde(date time.Time) time.Time {
func (module *Mercury) LastProgradeToRetrograde(date time.Time) time.Time {
jde := basic.UTC2TT(basic.Date2JD(date.UTC()))
return basic.JD2DateByZone(basic.LastMercuryProgradeToRetrogradeInclusive(jde), date.Location(), false)
return basic.JD2DateByZone(basic.LastMercuryProgradeToRetrogradeInclusiveWithInstance(jde, module.inst), date.Location(), false)
}
// NextProgradeToRetrograde 下一次顺行转逆行留 / next station from prograde to retrograde.
//
// 返回 date 当前或之后最近一次由顺行转为逆行的留时刻,结果保持 date 的时区。
// Returns the nearest station at or after date where motion changes from prograde to retrograde, keeping date's time zone.
func NextProgradeToRetrograde(date time.Time) time.Time {
func (module *Mercury) NextProgradeToRetrograde(date time.Time) time.Time {
jde := basic.UTC2TT(basic.Date2JD(date.UTC()))
return basic.JD2DateByZone(basic.NextMercuryProgradeToRetrogradeInclusive(jde), date.Location(), false)
return basic.JD2DateByZone(basic.NextMercuryProgradeToRetrogradeInclusiveWithInstance(jde, module.inst), date.Location(), false)
}
// LastRetrogradeToPrograde 上一次逆行转顺行留 / previous station from retrograde to prograde.
//
// 返回 date 当前或之前最近一次由逆行转为顺行的留时刻,结果保持 date 的时区。
// Returns the nearest station at or before date where motion changes from retrograde to prograde, keeping date's time zone.
func LastRetrogradeToPrograde(date time.Time) time.Time {
func (module *Mercury) LastRetrogradeToPrograde(date time.Time) time.Time {
jde := basic.UTC2TT(basic.Date2JD(date.UTC()))
return basic.JD2DateByZone(basic.LastMercuryRetrogradeToProgradeInclusive(jde), date.Location(), false)
return basic.JD2DateByZone(basic.LastMercuryRetrogradeToProgradeInclusiveWithInstance(jde, module.inst), date.Location(), false)
}
// NextRetrogradeToPrograde 下一次逆行转顺行留 / next station from retrograde to prograde.
//
// 返回 date 当前或之后最近一次由逆行转为顺行的留时刻,结果保持 date 的时区。
// Returns the nearest station at or after date where motion changes from retrograde to prograde, keeping date's time zone.
func NextRetrogradeToPrograde(date time.Time) time.Time {
func (module *Mercury) NextRetrogradeToPrograde(date time.Time) time.Time {
jde := basic.UTC2TT(basic.Date2JD(date.UTC()))
return basic.JD2DateByZone(basic.NextMercuryRetrogradeToProgradeInclusive(jde), date.Location(), false)
return basic.JD2DateByZone(basic.NextMercuryRetrogradeToProgradeInclusiveWithInstance(jde, module.inst), date.Location(), false)
}
// LastGreatestElongation 上一次大距 / previous greatest elongation.
//
// 返回 date 当前或之前最近一次大距时刻,不区分东西大距,结果保持 date 的时区。
// Returns the nearest greatest elongation at or before date, regardless of east or west, keeping date's time zone.
func LastGreatestElongation(date time.Time) time.Time {
func (module *Mercury) LastGreatestElongation(date time.Time) time.Time {
jde := basic.UTC2TT(basic.Date2JD(date.UTC()))
return basic.JD2DateByZone(basic.LastMercuryGreatestElongationInclusive(jde), date.Location(), false)
return basic.JD2DateByZone(basic.LastMercuryGreatestElongationInclusiveWithInstance(jde, module.inst), date.Location(), false)
}
// NextGreatestElongation 下一次大距 / next greatest elongation.
//
// 返回 date 当前或之后最近一次大距时刻,不区分东西大距,结果保持 date 的时区。
// Returns the nearest greatest elongation at or after date, regardless of east or west, keeping date's time zone.
func NextGreatestElongation(date time.Time) time.Time {
func (module *Mercury) NextGreatestElongation(date time.Time) time.Time {
jde := basic.UTC2TT(basic.Date2JD(date.UTC()))
return basic.JD2DateByZone(basic.NextMercuryGreatestElongationInclusive(jde), date.Location(), false)
return basic.JD2DateByZone(basic.NextMercuryGreatestElongationInclusiveWithInstance(jde, module.inst), date.Location(), false)
}
// LastGreatestElongationEast 上一次东大距 / previous greatest eastern elongation.
//
// 返回 date 当前或之前最近一次东大距时刻,结果保持 date 的时区。
// Returns the nearest eastern greatest elongation at or before date, keeping date's time zone.
func LastGreatestElongationEast(date time.Time) time.Time {
func (module *Mercury) LastGreatestElongationEast(date time.Time) time.Time {
jde := basic.UTC2TT(basic.Date2JD(date.UTC()))
return basic.JD2DateByZone(basic.LastMercuryGreatestElongationEastInclusive(jde), date.Location(), false)
return basic.JD2DateByZone(basic.LastMercuryGreatestElongationEastInclusiveWithInstance(jde, module.inst), date.Location(), false)
}
// NextGreatestElongationEast 下一次东大距 / next greatest eastern elongation.
//
// 返回 date 当前或之后最近一次东大距时刻,结果保持 date 的时区。
// Returns the nearest eastern greatest elongation at or after date, keeping date's time zone.
func NextGreatestElongationEast(date time.Time) time.Time {
func (module *Mercury) NextGreatestElongationEast(date time.Time) time.Time {
jde := basic.UTC2TT(basic.Date2JD(date.UTC()))
return basic.JD2DateByZone(basic.NextMercuryGreatestElongationEastInclusive(jde), date.Location(), false)
return basic.JD2DateByZone(basic.NextMercuryGreatestElongationEastInclusiveWithInstance(jde, module.inst), date.Location(), false)
}
// LastGreatestElongationWest 上一次西大距 / previous greatest western elongation.
//
// 返回 date 当前或之前最近一次西大距时刻,结果保持 date 的时区。
// Returns the nearest western greatest elongation at or before date, keeping date's time zone.
func LastGreatestElongationWest(date time.Time) time.Time {
func (module *Mercury) LastGreatestElongationWest(date time.Time) time.Time {
jde := basic.UTC2TT(basic.Date2JD(date.UTC()))
return basic.JD2DateByZone(basic.LastMercuryGreatestElongationWestInclusive(jde), date.Location(), false)
return basic.JD2DateByZone(basic.LastMercuryGreatestElongationWestInclusiveWithInstance(jde, module.inst), date.Location(), false)
}
// NextGreatestElongationWest 下一次西大距 / next greatest western elongation.
//
// 返回 date 当前或之后最近一次西大距时刻,结果保持 date 的时区。
// Returns the nearest western greatest elongation at or after date, keeping date's time zone.
func NextGreatestElongationWest(date time.Time) time.Time {
func (module *Mercury) NextGreatestElongationWest(date time.Time) time.Time {
jde := basic.UTC2TT(basic.Date2JD(date.UTC()))
return basic.JD2DateByZone(basic.NextMercuryGreatestElongationWestInclusive(jde), date.Location(), false)
return basic.JD2DateByZone(basic.NextMercuryGreatestElongationWestInclusiveWithInstance(jde, module.inst), date.Location(), false)
}
// ApparentMagnitude2018 视星等(Mallama & Hilton 2018 模型)/ apparent magnitude, Mallama & Hilton 2018 model.
func (module *Mercury) ApparentMagnitude2018(date time.Time) float64 {
jd := calendar.Date2JD(date.UTC())
return basic.MercuryMag2018WithInstance(basic.UTC2TT(jd), module.inst)
}
+1 -1
View File
@@ -18,7 +18,7 @@ func TestMercury(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if date.Unix() != 1642636481 {
if date.Unix() != 1642636482 {
t.Fatal(date.Unix())
}
}
+10 -10
View File
@@ -8,23 +8,23 @@ import (
)
// AscendingNode 水星升交点黄经 / ascending node longitude of Mercury.
func AscendingNode(date time.Time) float64 {
return AscendingNodeN(date, -1)
func (module *Mercury) AscendingNode(date time.Time) float64 {
return module.AscendingNodeN(date, -1)
}
// AscendingNodeN 水星升交点黄经(截断版) / truncated ascending node longitude of Mercury.
func AscendingNodeN(date time.Time, n int) float64 {
// AscendingNodeN 水星升交点黄经(n 变体) / n-parameterised ascending node longitude of Mercury.
func (module *Mercury) AscendingNodeN(date time.Time, n int) float64 {
jd := calendar.Date2JD(date.UTC())
return basic.MercuryAscendingNodeN(basic.UTC2TT(jd), n)
return basic.MercuryAscendingNodeNWithInstance(basic.UTC2TT(jd), n, module.inst)
}
// DescendingNode 水星降交点黄经 / descending node longitude of Mercury.
func DescendingNode(date time.Time) float64 {
return DescendingNodeN(date, -1)
func (module *Mercury) DescendingNode(date time.Time) float64 {
return module.DescendingNodeN(date, -1)
}
// DescendingNodeN 水星降交点黄经(截断版) / truncated descending node longitude of Mercury.
func DescendingNodeN(date time.Time, n int) float64 {
// DescendingNodeN 水星降交点黄经(n 变体) / n-parameterised descending node longitude of Mercury.
func (module *Mercury) DescendingNodeN(date time.Time, n int) float64 {
jd := calendar.Date2JD(date.UTC())
return basic.MercuryDescendingNodeN(basic.UTC2TT(jd), n)
return basic.MercuryDescendingNodeNWithInstance(basic.UTC2TT(jd), n, module.inst)
}
+5 -5
View File
@@ -7,11 +7,11 @@ import (
)
// ParallacticAngle 水星视差角(天顶方向角) / Mercury parallactic angle.
func ParallacticAngle(date time.Time, lon, lat float64) float64 {
return basic.ParallacticAngleByHourAngle(HourAngle(date, lon), ApparentDec(date), lat)
func (module *Mercury) ParallacticAngle(date time.Time, lon, lat float64) float64 {
return basic.ParallacticAngleByHourAngle(module.HourAngle(date, lon), module.ApparentDec(date), lat)
}
// ParallacticAngleN 截断项水星视差角(天顶方向角) / truncated Mercury parallactic angle.
func ParallacticAngleN(date time.Time, lon, lat float64, n int) float64 {
return basic.ParallacticAngleByHourAngle(HourAngleN(date, lon, n), ApparentDecN(date, n), lat)
// ParallacticAngleN 水星视差角(天顶方向角)(n 变体) / n-parameterised Mercury parallactic angle.
func (module *Mercury) ParallacticAngleN(date time.Time, lon, lat float64, n int) float64 {
return basic.ParallacticAngleByHourAngle(module.HourAngleN(date, lon, n), module.ApparentDecN(date, n), lat)
}
+20 -20
View File
@@ -8,43 +8,43 @@ import (
)
// PhaseAngle 相位角,单位度 / phase angle in degrees.
func PhaseAngle(date time.Time) float64 {
return PhaseAngleN(date, -1)
func (module *Mercury) PhaseAngle(date time.Time) float64 {
return module.PhaseAngleN(date, -1)
}
// PhaseAngleN 相位角(截断版),单位度 / truncated phase angle in degrees.
func PhaseAngleN(date time.Time, n int) float64 {
return basic.MercuryPhaseAngleN(phaseJD(date), n)
// PhaseAngleN 相位角(n 变体),单位度 / n-parameterised phase angle in degrees.
func (module *Mercury) PhaseAngleN(date time.Time, n int) float64 {
return basic.MercuryPhaseAngleNWithInstance(phaseJD(date), n, module.inst)
}
// IlluminatedFraction 被照亮比例 / illuminated fraction.
func IlluminatedFraction(date time.Time) float64 {
return IlluminatedFractionN(date, -1)
func (module *Mercury) IlluminatedFraction(date time.Time) float64 {
return module.IlluminatedFractionN(date, -1)
}
// IlluminatedFractionN 被照亮比例(截断版) / truncated illuminated fraction.
func IlluminatedFractionN(date time.Time, n int) float64 {
return basic.MercuryIlluminatedFractionN(phaseJD(date), n)
// IlluminatedFractionN 被照亮比例(n 变体) / n-parameterised illuminated fraction.
func (module *Mercury) IlluminatedFractionN(date time.Time, n int) float64 {
return basic.MercuryIlluminatedFractionNWithInstance(phaseJD(date), n, module.inst)
}
// Phase 相位,被照亮比例 / phase, illuminated fraction.
func Phase(date time.Time) float64 {
return IlluminatedFraction(date)
func (module *Mercury) Phase(date time.Time) float64 {
return module.IlluminatedFraction(date)
}
// PhaseN 相位(截断版),被照亮比例 / truncated phase, illuminated fraction.
func PhaseN(date time.Time, n int) float64 {
return IlluminatedFractionN(date, n)
// PhaseN 相位(n 变体),被照亮比例 / n-parameterised phase, illuminated fraction.
func (module *Mercury) PhaseN(date time.Time, n int) float64 {
return module.IlluminatedFractionN(date, n)
}
// BrightLimbPositionAngle 亮面中心位置角,单位度 / bright limb position angle in degrees.
func BrightLimbPositionAngle(date time.Time) float64 {
return BrightLimbPositionAngleN(date, -1)
func (module *Mercury) BrightLimbPositionAngle(date time.Time) float64 {
return module.BrightLimbPositionAngleN(date, -1)
}
// BrightLimbPositionAngleN 亮面中心位置角(截断版),单位度 / truncated bright limb position angle in degrees.
func BrightLimbPositionAngleN(date time.Time, n int) float64 {
return basic.MercuryBrightLimbPositionAngleN(phaseJD(date), n)
// BrightLimbPositionAngleN 亮面中心位置角(n 变体),单位度 / n-parameterised bright limb position angle in degrees.
func (module *Mercury) BrightLimbPositionAngleN(date time.Time, n int) float64 {
return basic.MercuryBrightLimbPositionAngleNWithInstance(phaseJD(date), n, module.inst)
}
func phaseJD(date time.Time) float64 {
+5 -5
View File
@@ -21,14 +21,14 @@ type PhysicalInfo struct {
}
// Physical 水星物理观测参数 / physical observing parameters of Mercury.
func Physical(date time.Time) PhysicalInfo {
return PhysicalN(date, -1)
func (module *Mercury) Physical(date time.Time) PhysicalInfo {
return module.PhysicalN(date, -1)
}
// PhysicalN 水星物理观测参数(截断版) / truncated physical observing parameters of Mercury.
func PhysicalN(date time.Time, n int) PhysicalInfo {
// PhysicalN 水星物理观测参数(n 变体) / n-parameterised physical observing parameters of Mercury.
func (module *Mercury) PhysicalN(date time.Time, n int) PhysicalInfo {
jd := basic.Date2JD(date.UTC())
info := basic.MercuryPhysicalN(basic.UTC2TT(jd), n)
info := basic.MercuryPhysicalNWithInstance(basic.UTC2TT(jd), n, module.inst)
return PhysicalInfo{
SubEarthLongitude: info.SubEarthLongitude,
SubEarthLatitude: info.SubEarthLatitude,
+33
View File
@@ -0,0 +1,33 @@
package mercury
import (
"time"
"b612.me/astro/basic"
)
// RiseTimeWithAtmosphere 水星升起时刻,按给定气压(hPa)与气温(°C)计算大气折射 / rise time with explicit pressure and temperature.
func (module *Mercury) RiseTimeWithAtmosphere(date time.Time, lon, lat, height, pressureHPa, temperatureC float64) (time.Time, error) {
date = time.Date(date.Year(), date.Month(), date.Day(), 0, 0, 0, 0, date.Location())
_, loc := date.Zone()
jd, err := basic.MercuryRiseTimeWithAtmosphere(basic.Date2JD(date), lon, lat, float64(loc)/3600.0, height, pressureHPa, temperatureC, module.inst)
return riseSetResult(date, jd, err)
}
// SetTimeWithAtmosphere 水星落下时刻,按给定气压(hPa)与气温(°C)计算大气折射 / set time with explicit pressure and temperature.
func (module *Mercury) SetTimeWithAtmosphere(date time.Time, lon, lat, height, pressureHPa, temperatureC float64) (time.Time, error) {
date = time.Date(date.Year(), date.Month(), date.Day(), 0, 0, 0, 0, date.Location())
_, loc := date.Zone()
jd, err := basic.MercurySetTimeWithAtmosphere(basic.Date2JD(date), lon, lat, float64(loc)/3600.0, height, pressureHPa, temperatureC, module.inst)
return riseSetResult(date, jd, err)
}
// RiseTimeWithAtmosphere 水星升起时刻,按给定气压(hPa)与气温(°C)计算大气折射 / rise time with explicit pressure and temperature.
func RiseTimeWithAtmosphere(date time.Time, lon, lat, height, pressureHPa, temperatureC float64) (time.Time, error) {
return defaultModule.RiseTimeWithAtmosphere(date, lon, lat, height, pressureHPa, temperatureC)
}
// SetTimeWithAtmosphere 水星落下时刻,按给定气压(hPa)与气温(°C)计算大气折射 / set time with explicit pressure and temperature.
func SetTimeWithAtmosphere(date time.Time, lon, lat, height, pressureHPa, temperatureC float64) (time.Time, error) {
return defaultModule.SetTimeWithAtmosphere(date, lon, lat, height, pressureHPa, temperatureC)
}
+29 -6
View File
@@ -32,18 +32,18 @@ type TransitInfo struct {
}
// NextTransit 下一次地心水星凌日 / next geocentric Mercury transit.
func NextTransit(date time.Time) TransitInfo {
return transitInfoFromBasic(basic.NextMercuryTransit(basic.Date2JD(date.UTC())), date.Location())
func (module *Mercury) NextTransit(date time.Time) TransitInfo {
return transitInfoFromBasic(basic.NextMercuryTransitWithInstance(basic.Date2JD(date.UTC()), module.inst), date.Location())
}
// LastTransit 上一次地心水星凌日 / previous geocentric Mercury transit.
func LastTransit(date time.Time) TransitInfo {
return transitInfoFromBasic(basic.LastMercuryTransit(basic.Date2JD(date.UTC())), date.Location())
func (module *Mercury) LastTransit(date time.Time) TransitInfo {
return transitInfoFromBasic(basic.LastMercuryTransitWithInstance(basic.Date2JD(date.UTC()), module.inst), date.Location())
}
// ClosestTransit 最近一次地心水星凌日 / closest geocentric Mercury transit.
func ClosestTransit(date time.Time) TransitInfo {
return transitInfoFromBasic(basic.ClosestMercuryTransit(basic.Date2JD(date.UTC())), date.Location())
func (module *Mercury) ClosestTransit(date time.Time) TransitInfo {
return transitInfoFromBasic(basic.ClosestMercuryTransitWithInstance(basic.Date2JD(date.UTC()), module.inst), date.Location())
}
func transitInfoFromBasic(result basic.PlanetTransitResult, loc *time.Location) TransitInfo {
@@ -71,3 +71,26 @@ func transitInfoFromBasic(result basic.PlanetTransitResult, loc *time.Location)
}
return info
}
// LocalTransitInfo 站心水星凌日信息 / topocentric Mercury transit information.
//
// 时刻保持调用者传入的 TransitInfo 的时区;太阳高度为几何中心高度,不含折射。
// Times keep the timezone of the supplied TransitInfo; Sun altitudes are geometric centre altitudes without refraction.
type LocalTransitInfo = basic.PlanetTransitLocalInfo
// LocalTransitContact 站心凌日接触 / topocentric transit contact.
type LocalTransitContact = basic.PlanetTransitLocalContactInfo
// LocalTransit 地心凌日 transit 在观测地的站心接触与凌甚 / topocentric contacts of transit seen from the site.
//
// lon、lat 为度,东经、北纬为正;height 为海拔米。
// lon and lat are in degrees, east and north positive; height is in meters.
func (module *Mercury) LocalTransit(transit TransitInfo, lon, lat, height float64) LocalTransitInfo {
if !transit.Valid {
return LocalTransitInfo{}
}
result := basic.PlanetTransitResultFromTimes(1,
transit.Start, transit.InternalStart, transit.Greatest, transit.InternalEnd, transit.End)
local := basic.PlanetTransitLocalWithInstance(result, basic.Observer{Longitude: lon, Latitude: lat, Height: height}, module.inst)
return basic.PlanetTransitLocalInfoFromResult(local, transit.Greatest.Location())
}
+19
View File
@@ -21,3 +21,22 @@ func TestTransitWrappers(t *testing.T) {
t.Fatalf("unexpected durations: %+v", info)
}
}
func TestLocalTransitWrapper(t *testing.T) {
loc := time.FixedZone("CST", 8*3600)
info := NextTransit(time.Date(2019, 1, 1, 0, 0, 0, 0, loc))
local := LocalTransit(info, -77.0, 38.9, 0)
if !local.Valid || !local.HasInternal || !local.Visible {
t.Fatalf("unexpected local transit: %+v", local)
}
if local.Greatest.Time.Location() != loc {
t.Fatalf("timezone mismatch: %v", local.Greatest.Time.Location())
}
// 站心接触与地心接触只差视差引起的几十秒。
if shift := local.Start.Time.Sub(info.Start); shift < -2*time.Minute || shift > 2*time.Minute {
t.Fatalf("C1 shift %v", shift)
}
if LocalTransit(TransitInfo{}, 0, 0, 0).Valid {
t.Fatal("invalid transit must give invalid local result")
}
}
+48 -49
View File
@@ -5,100 +5,99 @@ import (
"b612.me/astro/basic"
"b612.me/astro/calendar"
"b612.me/astro/planet"
)
// N variants keep the same semantics as the non-N APIs; n < 0 means full series.
// ApparentLoN 视黄经(截断版) / truncated apparent ecliptic longitude.
func ApparentLoN(date time.Time, n int) float64 {
// ApparentLoN 视黄经(n 变体) / n-parameterised apparent ecliptic longitude.
func (module *Mercury) ApparentLoN(date time.Time, n int) float64 {
jd := calendar.Date2JD(date.UTC())
return basic.MercuryApparentLoN(basic.UTC2TT(jd), n)
return basic.MercuryApparentLoNWithInstance(basic.UTC2TT(jd), n, module.inst)
}
// ApparentBoN 视黄纬(截断版) / truncated apparent ecliptic latitude.
func ApparentBoN(date time.Time, n int) float64 {
// ApparentBoN 视黄纬(n 变体) / n-parameterised apparent ecliptic latitude.
func (module *Mercury) ApparentBoN(date time.Time, n int) float64 {
jd := calendar.Date2JD(date.UTC())
return basic.MercuryApparentBoN(basic.UTC2TT(jd), n)
return basic.MercuryApparentBoNWithInstance(basic.UTC2TT(jd), n, module.inst)
}
// ApparentRaN 视赤经(截断版) / truncated apparent right ascension.
func ApparentRaN(date time.Time, n int) float64 {
// ApparentRaN 视赤经(n 变体) / n-parameterised apparent right ascension.
func (module *Mercury) ApparentRaN(date time.Time, n int) float64 {
jd := calendar.Date2JD(date.UTC())
return basic.MercuryApparentRaN(basic.UTC2TT(jd), n)
return basic.MercuryApparentRaNWithInstance(basic.UTC2TT(jd), n, module.inst)
}
// ApparentDecN 视赤纬(截断版) / truncated apparent declination.
func ApparentDecN(date time.Time, n int) float64 {
// ApparentDecN 视赤纬(n 变体) / n-parameterised apparent declination.
func (module *Mercury) ApparentDecN(date time.Time, n int) float64 {
jd := calendar.Date2JD(date.UTC())
return basic.MercuryApparentDecN(basic.UTC2TT(jd), n)
return basic.MercuryApparentDecNWithInstance(basic.UTC2TT(jd), n, module.inst)
}
// ApparentRaDecN 视赤经赤纬(截断版) / truncated apparent right ascension and declination.
func ApparentRaDecN(date time.Time, n int) (float64, float64) {
// ApparentRaDecN 视赤经赤纬(n 变体) / n-parameterised apparent right ascension and declination.
func (module *Mercury) ApparentRaDecN(date time.Time, n int) (float64, float64) {
jd := calendar.Date2JD(date.UTC())
return basic.MercuryApparentRaDecN(basic.UTC2TT(jd), n)
return basic.MercuryApparentRaDecNWithInstance(basic.UTC2TT(jd), n, module.inst)
}
// ApparentMagnitudeN 视星等(截断版) / truncated apparent magnitude.
func ApparentMagnitudeN(date time.Time, n int) float64 {
// ApparentMagnitudeN 视星等(n 变体) / n-parameterised apparent magnitude.
func (module *Mercury) ApparentMagnitudeN(date time.Time, n int) float64 {
jd := calendar.Date2JD(date.UTC())
return basic.MercuryMagN(basic.UTC2TT(jd), n)
return basic.MercuryMagNWithInstance(basic.UTC2TT(jd), n, module.inst)
}
// EarthDistanceN 地球距离(截断版) / truncated Earth distance.
func EarthDistanceN(date time.Time, n int) float64 {
// EarthDistanceN 地球距离(n 变体) / n-parameterised Earth distance.
func (module *Mercury) EarthDistanceN(date time.Time, n int) float64 {
jd := calendar.Date2JD(date.UTC())
return basic.EarthMercuryAwayN(basic.UTC2TT(jd), n)
return basic.EarthMercuryAwayNWithInstance(basic.UTC2TT(jd), n, module.inst)
}
// SunDistanceN 太阳距离(截断版) / truncated Sun distance.
func SunDistanceN(date time.Time, n int) float64 {
// SunDistanceN 太阳距离(n 变体) / n-parameterised Sun distance.
func (module *Mercury) SunDistanceN(date time.Time, n int) float64 {
jd := calendar.Date2JD(date.UTC())
return planet.WherePlanetN(1, 2, basic.UTC2TT(jd), n)
return basic.PlanetCoordinateNWithInstance(1, 2, basic.UTC2TT(jd), n, module.inst)
}
// AltitudeN 高度角(截断版) / truncated altitude angle.
func AltitudeN(date time.Time, lon, lat float64, n int) float64 {
// AltitudeN 站心视高度角(n 变体) / n-parameterised topocentric apparent altitude.
func (module *Mercury) AltitudeN(date time.Time, lon, lat float64, n int) float64 {
localJD := basic.Date2JD(date)
_, loc := date.Zone()
timezone := float64(loc) / 3600.0
return basic.MercuryHeightN(localJD, lon, lat, timezone, n)
return basic.MercuryHeightNWithInstance(localJD, lon, lat, timezone, n, module.inst)
}
// ZenithN 天顶距(截断版) / truncated zenith distance.
func ZenithN(date time.Time, lon, lat float64, n int) float64 {
return 90 - AltitudeN(date, lon, lat, n)
// ZenithN 天顶距(n 变体) / n-parameterised zenith distance.
func (module *Mercury) ZenithN(date time.Time, lon, lat float64, n int) float64 {
return 90 - module.AltitudeN(date, lon, lat, n)
}
// AzimuthN 方位角(截断版) / truncated azimuth angle.
func AzimuthN(date time.Time, lon, lat float64, n int) float64 {
// AzimuthN 站心方位角(n 变体) / n-parameterised topocentric azimuth.
func (module *Mercury) AzimuthN(date time.Time, lon, lat float64, n int) float64 {
localJD := basic.Date2JD(date)
_, loc := date.Zone()
timezone := float64(loc) / 3600.0
return basic.MercuryAzimuthN(localJD, lon, lat, timezone, n)
return basic.MercuryAzimuthNWithInstance(localJD, lon, lat, timezone, n, module.inst)
}
// HourAngleN 时角(截断版) / truncated hour angle.
func HourAngleN(date time.Time, lon float64, n int) float64 {
// HourAngleN 时角(n 变体) / n-parameterised hour angle.
func (module *Mercury) HourAngleN(date time.Time, lon float64, n int) float64 {
localJD := basic.Date2JD(date)
_, loc := date.Zone()
timezone := float64(loc) / 3600.0
return basic.MercuryHourAngleN(localJD, lon, timezone, n)
return basic.MercuryHourAngleNWithInstance(localJD, lon, timezone, n, module.inst)
}
// CulminationTimeN 中天时间(截断版) / truncated culmination time.
func CulminationTimeN(date time.Time, lon float64, n int) time.Time {
// CulminationTimeN 中天时间(n 变体) / n-parameterised culmination time.
func (module *Mercury) CulminationTimeN(date time.Time, lon float64, n int) time.Time {
date = time.Date(date.Year(), date.Month(), date.Day(), 0, 0, 0, 0, date.Location())
localJD := basic.Date2JD(date)
_, loc := date.Zone()
timezone := float64(loc) / 3600.0
calcJD := basic.MercuryCulminationTimeN(localJD, lon, timezone, n) - timezone/24.0
calcJD := basic.MercuryCulminationTimeNWithInstance(localJD, lon, timezone, n, module.inst) - timezone/24.0
return basic.JD2DateByZone(calcJD, date.Location(), false)
}
// RiseTimeN 升起时间(截断版) / truncated rise time.
func RiseTimeN(date time.Time, lon, lat, height float64, aero bool, n int) (time.Time, error) {
// RiseTimeN 升起时间(n 变体) / n-parameterised rise time.
func (module *Mercury) RiseTimeN(date time.Time, lon, lat, height float64, aero bool, n int) (time.Time, error) {
var aeroFloat float64
if aero {
aeroFloat = 1
@@ -107,17 +106,17 @@ func RiseTimeN(date time.Time, lon, lat, height float64, aero bool, n int) (time
localJD := basic.Date2JD(date)
_, loc := date.Zone()
timezone := float64(loc) / 3600.0
riseJD, err := basic.MercuryRiseTimeN(localJD, lon, lat, timezone, aeroFloat, height, n)
riseJD, err := basic.MercuryRiseTimeNWithInstance(localJD, lon, lat, timezone, aeroFloat, height, n, module.inst)
return riseSetResult(date, riseJD, err)
}
// DownTimeN 落下时间别名(截断版) / truncated down-time alias.
func DownTimeN(date time.Time, lon, lat, height float64, aero bool, n int) (time.Time, error) {
return SetTimeN(date, lon, lat, height, aero, n)
// DownTimeN 落下时间别名(n 变体) / n-parameterised down-time alias.
func (module *Mercury) DownTimeN(date time.Time, lon, lat, height float64, aero bool, n int) (time.Time, error) {
return module.SetTimeN(date, lon, lat, height, aero, n)
}
// SetTimeN 落下时间(截断版) / truncated set time.
func SetTimeN(date time.Time, lon, lat, height float64, aero bool, n int) (time.Time, error) {
// SetTimeN 落下时间(n 变体) / n-parameterised set time.
func (module *Mercury) SetTimeN(date time.Time, lon, lat, height float64, aero bool, n int) (time.Time, error) {
var aeroFloat float64
if aero {
aeroFloat = 1
@@ -126,6 +125,6 @@ func SetTimeN(date time.Time, lon, lat, height float64, aero bool, n int) (time.
localJD := basic.Date2JD(date)
_, loc := date.Zone()
timezone := float64(loc) / 3600.0
riseJD, err := basic.MercurySetTimeN(localJD, lon, lat, timezone, aeroFloat, height, n)
riseJD, err := basic.MercurySetTimeNWithInstance(localJD, lon, lat, timezone, aeroFloat, height, n, module.inst)
return riseSetResult(date, riseJD, err)
}