feat: 完善日月食与月掩几何链路并扩展历法接口
- 新增日月食中心带、偏食带、阴影足迹、等时线、食分线及升落边界计算,支持极区与混合食拓扑 - 新增日食单时刻阴影求解器、站心状态查询、批量采样和 ΔT 覆盖接口 - 重构恒星与行星月掩路径,补充有限盘面接触、站心修正、掩带宽度、极区投影及升落边界 - 扩展 SVG 与 GeoJSON 输出,支持详细面板、全球/极区/地球投影、边界闭合、时间标记和拓扑签名 - 扩展日月食候选搜索、局地搜索、沙罗序列预计算与范围外推,补充系列锚点和成员一致性校验 - 补齐古历纪年、儒略历独有闰日、多公历候选、历法改革跨日及精确日期运算接口 - 优化 ΔT、章动、恒星时、月球地平线、事件根搜索和本地星历缓存,降低重复计算开销并提升边界稳定
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
package eclipse
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"b612.me/astro/basic"
|
||||
)
|
||||
|
||||
// SolarEclipseCandidateOptions 批量枚举配置,零值为全部食型的 NASA bulletin Split-K / enumeration options.
|
||||
type SolarEclipseCandidateOptions struct {
|
||||
// Model 月亮半径模型,零值为 NASA bulletin Split-K / lunar radius model.
|
||||
Model SolarEclipseRadiusModel
|
||||
// CentralOnly 只保留全食、环食与混合食,含中心线未落到地表的 T0/A0 事件。
|
||||
// CentralOnly keeps total, annular, and hybrid eclipses, including T0/A0 events
|
||||
// whose axis misses the Earth; the kind filter matches SearchLocalCentralSolarEclipse.
|
||||
CentralOnly bool
|
||||
// IncludeSaros 附带沙罗序列信息 / attach Saros metadata.
|
||||
IncludeSaros bool
|
||||
}
|
||||
|
||||
// SolarEclipseCandidate 一场日食的时刻表条目,不含几何 / geometry-free timetable entry.
|
||||
type SolarEclipseCandidate struct {
|
||||
// GreatestEclipse 食甚时刻 / greatest-eclipse instant.
|
||||
GreatestEclipse time.Time
|
||||
// Type 全局食型,Centrality 中心食类型 / global type and centrality.
|
||||
Type SolarEclipseType
|
||||
Centrality SolarEclipseCentrality
|
||||
// Magnitude 与 Gamma 是全局食分与伽马 / global magnitude and gamma.
|
||||
Magnitude float64
|
||||
Gamma float64
|
||||
// Saros 仅在 IncludeSaros 时有效 / valid only with IncludeSaros.
|
||||
Saros SarosInfo
|
||||
HasSaros bool
|
||||
}
|
||||
|
||||
// 食甚可能早于朔,枚举上界要多留这么多天。
|
||||
const solarEclipseCandidateGreatestLeadDays = 0.5
|
||||
|
||||
// solarEclipseCandidateIsCentral 按全局食型判定,与站心搜索的 Kind 口径一致。
|
||||
func solarEclipseCandidateIsCentral(value basic.SolarEclipseType) bool {
|
||||
switch value {
|
||||
case basic.SolarEclipseTotal, basic.SolarEclipseAnnular, basic.SolarEclipseHybrid:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// SolarEclipseCandidates 枚举区间内的日食时刻表,按时间升序 / eclipses within a range, in time order.
|
||||
func SolarEclipseCandidates(
|
||||
start, end time.Time, options SolarEclipseCandidateOptions,
|
||||
) []SolarEclipseCandidate {
|
||||
if !end.After(start) {
|
||||
return nil
|
||||
}
|
||||
calculator := localSolarEclipseCalculatorForModel(options.Model)
|
||||
startTT := solarEclipseTimeToTTJDE(start)
|
||||
endTT := solarEclipseTimeToTTJDE(end)
|
||||
candidates := make([]SolarEclipseCandidate, 0, 8)
|
||||
candidateTT := basic.CalcMoonSHByJDE(startTT, 0)
|
||||
for iteration := 0; iteration < localSolarEclipseSearchIterationCap; iteration++ {
|
||||
// 食甚可能略早于朔,上界要多留一点余量,否则窗口末尾那场会被漏掉。
|
||||
if candidateTT > endTT+solarEclipseCandidateGreatestLeadDays {
|
||||
break
|
||||
}
|
||||
if isPotentialLocalSolarEclipse(candidateTT) {
|
||||
globalResult := calculator.global(candidateTT)
|
||||
if globalResult.Type != basic.SolarEclipseNone &&
|
||||
(!options.CentralOnly || solarEclipseCandidateIsCentral(globalResult.Type)) {
|
||||
greatest := solarEclipseTTJDEToTime(globalResult.GreatestEclipse, start.Location())
|
||||
// 候选朔月取的是“最近”的朔,可能落在 start 之前或 end 之后(食甚早于朔),
|
||||
// 按食甚时刻双侧过滤;注意不能 continue:候选推进在循环末尾,跳过它会原地打转。
|
||||
if !greatest.Before(start) && !greatest.After(end) {
|
||||
candidate := SolarEclipseCandidate{
|
||||
GreatestEclipse: greatest,
|
||||
Type: mapBasicSolarEclipseType(globalResult.Type),
|
||||
Centrality: mapBasicSolarEclipseCentrality(globalResult.Centrality),
|
||||
Magnitude: globalResult.Magnitude,
|
||||
Gamma: globalResult.Gamma,
|
||||
}
|
||||
if options.IncludeSaros {
|
||||
candidate.Saros, candidate.HasSaros = solarSarosInfo(globalResult.GreatestEclipse)
|
||||
}
|
||||
candidates = append(candidates, candidate)
|
||||
}
|
||||
}
|
||||
}
|
||||
candidateTT = nextEclipseSearchCandidateTT(candidateTT, 0, 1, localSolarEclipseSynodicMonthDays)
|
||||
}
|
||||
return candidates
|
||||
}
|
||||
Reference in New Issue
Block a user