2026-05-03 19:00:08 +08:00
|
|
|
package eclipse
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"math"
|
|
|
|
|
|
|
|
|
|
"b612.me/astro/basic"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
eclipseSeasonNodeDistanceLimitDeg = 35.0
|
|
|
|
|
eclipseSeasonMaxSearchStep = 4
|
|
|
|
|
)
|
|
|
|
|
|
2026-10-15 23:54:15 +08:00
|
|
|
func nextEclipseSearchCandidateTT(candidateTT float64, phaseType, direction int, synodicMonthDays float64, modules ...*Eclipse) float64 {
|
|
|
|
|
module := &defaultModule
|
|
|
|
|
if len(modules) > 0 {
|
|
|
|
|
module = modules[0]
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-03 19:00:08 +08:00
|
|
|
step := eclipseSearchStep(candidateTT, direction, synodicMonthDays)
|
2026-10-15 23:54:15 +08:00
|
|
|
return basic.CalcMoonSHByJDEWithInstance(candidateTT+float64(direction*step)*synodicMonthDays, phaseType, module.inst)
|
2026-05-03 19:00:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func eclipseSearchStep(candidateTT float64, direction int, synodicMonthDays float64) int {
|
|
|
|
|
step := 1
|
|
|
|
|
for nextStep := 2; nextStep <= eclipseSeasonMaxSearchStep; nextStep++ {
|
|
|
|
|
skippedTT := candidateTT + float64(direction*(nextStep-1))*synodicMonthDays
|
|
|
|
|
if eclipseNodeDistance(skippedTT) < eclipseSeasonNodeDistanceLimitDeg {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
step = nextStep
|
|
|
|
|
}
|
|
|
|
|
return step
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func eclipseNodeDistance(ttJDE float64) float64 {
|
|
|
|
|
argument := normalizeDegree360(basic.MoonLonX(ttJDE))
|
|
|
|
|
toAscending := math.Min(argument, 360-argument)
|
|
|
|
|
toDescending := math.Abs(argument - 180)
|
|
|
|
|
return math.Min(toAscending, toDescending)
|
|
|
|
|
}
|