astro/jupiter/phenomena_events.go
starainrt 3ffdbe0034
feat: 扩展天文计算能力
- 新增日食、月食、本地可见性、中心线、半影区域、SVG 图示与沙罗周期信息
- 新增行星冲合、留、方照、物理星历、视直径、相位、亮肢角、轨道节点等计算
- 新增木星伽利略卫星位置、现象与接触事件计算
- 新增恒星星表、星座判定、自行修正与观测辅助能力
- 新增 coord、formula、orbit、sundial、lite/sun、lite/moon 等扩展包
- 完善农历年号、月相英文别名、视差角、大气质量、折射、日晷与双星计算
- 增加 NASA、JPL Horizons、IMCCE 等回归测试数据与基线测试
- 重构基础算法文件组织,补充大量公开 API 注释和语义回归测试
- 更新中文和英文 README,补充示例、精度说明、SVG 配图
2026-05-01 22:38:44 +08:00

116 lines
4.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package jupiter
import (
"time"
"b612.me/astro/basic"
)
// GalileanPhenomenonType 伽利略卫星现象类型 / Galilean-satellite phenomenon type.
type GalileanPhenomenonType string
const (
// GalileanPhenomenonTransit 凌日 / satellite transit across Jupiter.
GalileanPhenomenonTransit GalileanPhenomenonType = "transit"
// GalileanPhenomenonOccultation 掩蔽 / occultation behind Jupiter.
GalileanPhenomenonOccultation GalileanPhenomenonType = "occultation"
// GalileanPhenomenonEclipse 食 / eclipse in Jupiter's shadow.
GalileanPhenomenonEclipse GalileanPhenomenonType = "eclipse"
// GalileanPhenomenonShadowTransit 影凌 / shadow transit across Jupiter.
GalileanPhenomenonShadowTransit GalileanPhenomenonType = "shadow_transit"
)
const (
// GalileanSatelliteIo 木卫一 / Io.
GalileanSatelliteIo = 1
// GalileanSatelliteEuropa 木卫二 / Europa.
GalileanSatelliteEuropa = 2
// GalileanSatelliteGanymede 木卫三 / Ganymede.
GalileanSatelliteGanymede = 3
// GalileanSatelliteCallisto 木卫四 / Callisto.
GalileanSatelliteCallisto = 4
)
// GalileanPhenomenonEvent 伽利略卫星整场现象 / full Galilean-satellite event.
//
// Start、Greatest、End 都保持调用者输入的时区。
// GreatestState 是食甚/现象最深时刻对应的瞬时现象标志与影心偏移。
// 这里的 Start/End 基于零半径几何模型是否 active不是 IMCCE 年表中的 D/F 接触时刻;
// 如果需要有限圆盘/有限影斑的接触窗口,请改用 `GalileanPhenomenonContactEvent`。
// Start, Greatest, and End preserve the caller's timezone.
// GreatestState contains the instantaneous phenomenon flags and shadow offsets at greatest event depth.
// Start/End here are based on whether the zero-radius geometric model is active, not the IMCCE D/F contact times.
// Use `GalileanPhenomenonContactEvent` when you need finite-disk or finite-shadow contact windows.
type GalileanPhenomenonEvent struct {
Valid bool
Satellite int
Type GalileanPhenomenonType
Start time.Time
Greatest time.Time
End time.Time
Duration time.Duration
GreatestState GalileanSatellitePhenomenon
}
// LastGalileanPhenomenonEvent 上一次伽利略卫星现象 / previous Galilean-satellite event.
//
// date 表示查询绝对时刻satellite 取 `1=Io, 2=Europa, 3=Ganymede, 4=Callisto`
// phenomenonType 取 `transit/occultation/eclipse/shadow_transit` 中之一。
// date is the query instant; satellite is `1=Io, 2=Europa, 3=Ganymede, 4=Callisto`;
// phenomenonType is one of `transit/occultation/eclipse/shadow_transit`.
func LastGalileanPhenomenonEvent(date time.Time, satellite int, phenomenonType GalileanPhenomenonType) GalileanPhenomenonEvent {
return galileanPhenomenonEventFromBasic(
basic.LastJupiterGalileanPhenomenonEvent(
basic.Date2JDE(date.UTC()),
satellite,
basic.JupiterGalileanPhenomenonType(phenomenonType),
),
date.Location(),
)
}
// NextGalileanPhenomenonEvent 下一次伽利略卫星现象 / next Galilean-satellite event.
func NextGalileanPhenomenonEvent(date time.Time, satellite int, phenomenonType GalileanPhenomenonType) GalileanPhenomenonEvent {
return galileanPhenomenonEventFromBasic(
basic.NextJupiterGalileanPhenomenonEvent(
basic.Date2JDE(date.UTC()),
satellite,
basic.JupiterGalileanPhenomenonType(phenomenonType),
),
date.Location(),
)
}
// ClosestGalileanPhenomenonEvent 最近一次伽利略卫星现象 / closest Galilean-satellite event.
func ClosestGalileanPhenomenonEvent(date time.Time, satellite int, phenomenonType GalileanPhenomenonType) GalileanPhenomenonEvent {
return galileanPhenomenonEventFromBasic(
basic.ClosestJupiterGalileanPhenomenonEvent(
basic.Date2JDE(date.UTC()),
satellite,
basic.JupiterGalileanPhenomenonType(phenomenonType),
),
date.Location(),
)
}
func galileanPhenomenonEventFromBasic(event basic.JupiterGalileanPhenomenonEvent, loc *time.Location) GalileanPhenomenonEvent {
if !event.Valid {
return GalileanPhenomenonEvent{}
}
start := basic.JDE2DateByZone(event.Start, loc, false)
greatest := basic.JDE2DateByZone(event.Greatest, loc, false)
end := basic.JDE2DateByZone(event.End, loc, false)
return GalileanPhenomenonEvent{
Valid: true,
Satellite: event.Satellite,
Type: GalileanPhenomenonType(event.Type),
Start: start,
Greatest: greatest,
End: end,
Duration: end.Sub(start),
GreatestState: galileanPhenomenonFromBasic(event.GreatestPhenomenon),
}
}