126 lines
5.1 KiB
Go
126 lines
5.1 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 LastGalileanPhenomenonContactEvent(date time.Time, satellite int, phenomenonType GalileanPhenomenonType) GalileanPhenomenonContactEvent {
|
|||
|
|
return galileanPhenomenonContactEventFromBasic(
|
|||
|
|
basic.LastJupiterGalileanPhenomenonContactEvent(
|
|||
|
|
basic.Date2JDE(date.UTC()),
|
|||
|
|
satellite,
|
|||
|
|
basic.JupiterGalileanPhenomenonType(phenomenonType),
|
|||
|
|
),
|
|||
|
|
date.Location(),
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// NextGalileanPhenomenonContactEvent 下一次 IMCCE 风格接触事件 / next IMCCE-style contact event.
|
|||
|
|
func NextGalileanPhenomenonContactEvent(date time.Time, satellite int, phenomenonType GalileanPhenomenonType) GalileanPhenomenonContactEvent {
|
|||
|
|
return galileanPhenomenonContactEventFromBasic(
|
|||
|
|
basic.NextJupiterGalileanPhenomenonContactEvent(
|
|||
|
|
basic.Date2JDE(date.UTC()),
|
|||
|
|
satellite,
|
|||
|
|
basic.JupiterGalileanPhenomenonType(phenomenonType),
|
|||
|
|
),
|
|||
|
|
date.Location(),
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ClosestGalileanPhenomenonContactEvent 最近一次 IMCCE 风格接触事件 / closest IMCCE-style contact event.
|
|||
|
|
func ClosestGalileanPhenomenonContactEvent(date time.Time, satellite int, phenomenonType GalileanPhenomenonType) GalileanPhenomenonContactEvent {
|
|||
|
|
return galileanPhenomenonContactEventFromBasic(
|
|||
|
|
basic.ClosestJupiterGalileanPhenomenonContactEvent(
|
|||
|
|
basic.Date2JDE(date.UTC()),
|
|||
|
|
satellite,
|
|||
|
|
basic.JupiterGalileanPhenomenonType(phenomenonType),
|
|||
|
|
),
|
|||
|
|
date.Location(),
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func galileanPhenomenonContactEventFromBasic(event basic.JupiterGalileanPhenomenonContactEvent, loc *time.Location) GalileanPhenomenonContactEvent {
|
|||
|
|
if !event.Valid {
|
|||
|
|
return GalileanPhenomenonContactEvent{}
|
|||
|
|
}
|
|||
|
|
greatest := basic.JDE2DateByZone(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.JDE2DateByZone(contact.Start, loc, false)
|
|||
|
|
modelCrossing := basic.JDE2DateByZone(contact.ModelCrossing, loc, false)
|
|||
|
|
end := basic.JDE2DateByZone(contact.End, loc, false)
|
|||
|
|
return GalileanPhenomenonContact{
|
|||
|
|
Valid: true,
|
|||
|
|
Phase: GalileanPhenomenonContactPhase(contact.Phase),
|
|||
|
|
Start: start,
|
|||
|
|
ModelCrossing: modelCrossing,
|
|||
|
|
End: end,
|
|||
|
|
Duration: end.Sub(start),
|
|||
|
|
}
|
|||
|
|
}
|