044f2f4381
- 新增半解析、旧模型、自定义与多源堆叠星历实例,提供 Context、Instance、SPK 读取及状态与视位置计算 - 统一太阳、月球和行星实例接口,扩展黄经穿越、留、相位、最近角距、偕日可见、任意高度升落、轨道节点及凌日等天象查询 - 完善日月食、月掩与凌日的月缘剖面、有限盘面接触、站心修正、局地可见性、全球路径和地图输出 - 新增 SVG、GeoJSON、KML 天象输出及凌日、月掩和月缘地形相关缓存与几何求解 - 新增恒星星表导入与查询,支持 CSV、Hipparcos、BSC5、Stellarium 等格式及名称、交叉标识、锥面检索和星等过滤 - 补充 IAU 2006、地球定向、折射消光、大气观测、轨道传播及半解析行星/月球数据支持 - 将默认未来民用时标切换为 TimeScaleLeapHour,更新 2027–2400 农历速查表、中文日期解析和时区边界处理 - 增加事件基线、跨模型回归、几何边界、月缘地形和输出契约测试,完善中英文手册、示例资源、NOTICE 与忽略规则
126 lines
5.2 KiB
Go
126 lines
5.2 KiB
Go
package jupiter
|
|
|
|
import (
|
|
"time"
|
|
|
|
"b612.me/astro/basic"
|
|
)
|
|
|
|
// GalileanPhenomenonContactPhase 接触阶段 / contact phase.
|
|
type GalileanPhenomenonContactPhase string
|
|
|
|
const (
|
|
// GalileanPhenomenonContactDisappearance 初亏/初入接触阶段 / disappearance ingress contact.
|
|
GalileanPhenomenonContactDisappearance GalileanPhenomenonContactPhase = "disappearance"
|
|
// GalileanPhenomenonContactReappearance 复圆/复出接触阶段 / reappearance egress contact.
|
|
GalileanPhenomenonContactReappearance GalileanPhenomenonContactPhase = "reappearance"
|
|
)
|
|
|
|
// GalileanPhenomenonContact 伽利略卫星接触窗口 / Galilean-satellite contact window.
|
|
//
|
|
// Start/End 是有限圆盘或有限影斑开始/结束接触的时刻;ModelCrossing 是这套连续接触模型下,
|
|
// 零半径参考点穿越边界的时刻。
|
|
// Start/End mark the beginning/end of the finite-disk or finite-shadow contact interval.
|
|
// ModelCrossing is the zero-radius boundary crossing in this continuous contact model.
|
|
type GalileanPhenomenonContact struct {
|
|
Valid bool
|
|
Phase GalileanPhenomenonContactPhase
|
|
|
|
Start time.Time
|
|
ModelCrossing time.Time
|
|
End time.Time
|
|
|
|
Duration time.Duration
|
|
}
|
|
|
|
// GalileanPhenomenonContactEvent IMCCE 风格的 D/F 接触事件 / IMCCE-style D/F contact event.
|
|
//
|
|
// 这个 API 返回有限圆盘/有限影斑的接触窗口,适合和 IMCCE 的 `TR.D/TR.F/OC.D/OC.F/EC.D/EC.F/SH.D/SH.F` 对齐;
|
|
// 现有 `GalileanPhenomenonEvent` 返回的是零半径几何模型保持 active 的整段区间,两者语义不同。
|
|
// 其中 `shadow_transit` 先用半影/本影边界求部分相持续时间,再把这段持续时间中心放在旧影轴过盘时刻上。
|
|
// This API returns finite-disk / finite-shadow contact windows and is intended to align with IMCCE
|
|
// `TR.D/TR.F/OC.D/OC.F/EC.D/EC.F/SH.D/SH.F` rows. The existing `GalileanPhenomenonEvent` returns the
|
|
// whole active interval of the zero-radius geometric model, so the semantics are different.
|
|
// For `shadow_transit`, the partial-phase duration comes from penumbra/umbra boundaries,
|
|
// while the reported D/F time is centered on the shadow-axis limb crossing from the existing full-event model.
|
|
type GalileanPhenomenonContactEvent struct {
|
|
Valid bool
|
|
Satellite int
|
|
Type GalileanPhenomenonType
|
|
|
|
Disappearance GalileanPhenomenonContact
|
|
Greatest time.Time
|
|
Reappearance GalileanPhenomenonContact
|
|
|
|
GreatestState GalileanSatellitePhenomenon
|
|
}
|
|
|
|
// LastGalileanPhenomenonContactEvent 上一次 IMCCE 风格接触事件 / previous IMCCE-style contact event.
|
|
func (module *Jupiter) LastGalileanPhenomenonContactEvent(date time.Time, satellite int, phenomenonType GalileanPhenomenonType) GalileanPhenomenonContactEvent {
|
|
return galileanPhenomenonContactEventFromBasic(
|
|
basic.LastJupiterGalileanPhenomenonContactEventWithInstance(
|
|
basic.Date2JD(date.UTC()),
|
|
satellite,
|
|
basic.JupiterGalileanPhenomenonType(phenomenonType), module.inst,
|
|
),
|
|
date.Location(),
|
|
)
|
|
}
|
|
|
|
// NextGalileanPhenomenonContactEvent 下一次 IMCCE 风格接触事件 / next IMCCE-style contact event.
|
|
func (module *Jupiter) NextGalileanPhenomenonContactEvent(date time.Time, satellite int, phenomenonType GalileanPhenomenonType) GalileanPhenomenonContactEvent {
|
|
return galileanPhenomenonContactEventFromBasic(
|
|
basic.NextJupiterGalileanPhenomenonContactEventWithInstance(
|
|
basic.Date2JD(date.UTC()),
|
|
satellite,
|
|
basic.JupiterGalileanPhenomenonType(phenomenonType), module.inst,
|
|
),
|
|
date.Location(),
|
|
)
|
|
}
|
|
|
|
// ClosestGalileanPhenomenonContactEvent 最近一次 IMCCE 风格接触事件 / closest IMCCE-style contact event.
|
|
func (module *Jupiter) ClosestGalileanPhenomenonContactEvent(date time.Time, satellite int, phenomenonType GalileanPhenomenonType) GalileanPhenomenonContactEvent {
|
|
return galileanPhenomenonContactEventFromBasic(
|
|
basic.ClosestJupiterGalileanPhenomenonContactEventWithInstance(
|
|
basic.Date2JD(date.UTC()),
|
|
satellite,
|
|
basic.JupiterGalileanPhenomenonType(phenomenonType), module.inst,
|
|
),
|
|
date.Location(),
|
|
)
|
|
}
|
|
|
|
func galileanPhenomenonContactEventFromBasic(event basic.JupiterGalileanPhenomenonContactEvent, loc *time.Location) GalileanPhenomenonContactEvent {
|
|
if !event.Valid {
|
|
return GalileanPhenomenonContactEvent{}
|
|
}
|
|
greatest := basic.JD2DateByZone(event.Greatest, loc, false)
|
|
return GalileanPhenomenonContactEvent{
|
|
Valid: true,
|
|
Satellite: event.Satellite,
|
|
Type: GalileanPhenomenonType(event.Type),
|
|
Disappearance: galileanPhenomenonContactFromBasic(event.Disappearance, loc),
|
|
Greatest: greatest,
|
|
Reappearance: galileanPhenomenonContactFromBasic(event.Reappearance, loc),
|
|
GreatestState: galileanPhenomenonFromBasic(event.GreatestPhenomenon),
|
|
}
|
|
}
|
|
|
|
func galileanPhenomenonContactFromBasic(contact basic.JupiterGalileanPhenomenonContact, loc *time.Location) GalileanPhenomenonContact {
|
|
if !contact.Valid {
|
|
return GalileanPhenomenonContact{}
|
|
}
|
|
start := basic.JD2DateByZone(contact.Start, loc, false)
|
|
modelCrossing := basic.JD2DateByZone(contact.ModelCrossing, loc, false)
|
|
end := basic.JD2DateByZone(contact.End, loc, false)
|
|
return GalileanPhenomenonContact{
|
|
Valid: true,
|
|
Phase: GalileanPhenomenonContactPhase(contact.Phase),
|
|
Start: start,
|
|
ModelCrossing: modelCrossing,
|
|
End: end,
|
|
Duration: end.Sub(start),
|
|
}
|
|
}
|