Files
astro/eclipse/solar_panel_test.go
T
b612 2bf8478639 feat: 完善日月食与月掩几何链路并扩展历法接口
- 新增日月食中心带、偏食带、阴影足迹、等时线、食分线及升落边界计算,支持极区与混合食拓扑
- 新增日食单时刻阴影求解器、站心状态查询、批量采样和 ΔT 覆盖接口
- 重构恒星与行星月掩路径,补充有限盘面接触、站心修正、掩带宽度、极区投影及升落边界
- 扩展 SVG 与 GeoJSON 输出,支持详细面板、全球/极区/地球投影、边界闭合、时间标记和拓扑签名
- 扩展日月食候选搜索、局地搜索、沙罗序列预计算与范围外推,补充系列锚点和成员一致性校验
- 补齐古历纪年、儒略历独有闰日、多公历候选、历法改革跨日及精确日期运算接口
- 优化 ΔT、章动、恒星时、月球地平线、事件根搜索和本地星历缓存,降低重复计算开销并提升边界稳定
2026-09-17 12:27:40 +08:00

70 lines
3.4 KiB
Go

package eclipse
import (
"math"
"testing"
"time"
)
func solarEclipsePanelFormatRA(degrees float64) (int, int, float64) {
total := math.Mod(degrees, 360) / 15
hours := int(total)
minutes := int((total - float64(hours)) * 60)
seconds := ((total-float64(hours))*60 - float64(minutes)) * 60
return hours, minutes, seconds
}
// 地心量面板要与 NASA 星历表同量级:视半径/视差/天平动/月序数逐项对拍 2009-07-22。
func TestSolarEclipseGeocentricPanelMatchesNASABulletin(t *testing.T) {
panel, ok := SolarEclipseGeocentricPanelAt(time.Date(2009, time.July, 22, 0, 0, 0, 0, time.UTC))
if !ok {
t.Fatal("missing eclipse")
}
sunHours, sunMinutes, sunSeconds := solarEclipsePanelFormatRA(panel.SunRightAscensionDeg)
t.Logf("sun R.A. %02dh%02dm%04.1fs Dec %+.4f S.D. %.1f\" H.P. %.1f\"",
sunHours, sunMinutes, sunSeconds, panel.SunDeclinationDeg, panel.SunSemidiameterArcsec, panel.SunParallaxArcsec)
moonHours, moonMinutes, moonSeconds := solarEclipsePanelFormatRA(panel.MoonRightAscensionDeg)
t.Logf("moon R.A. %02dh%02dm%04.1fs Dec %+.4f S.D. %.1f\" H.P. %.1f\"",
moonHours, moonMinutes, moonSeconds, panel.MoonDeclinationDeg, panel.MoonSemidiameterArcsec, panel.MoonParallaxArcsec)
t.Logf("libration l=%+.2f b=%+.2f c=%.2f Brown=%d ΔT=%.1fs k1=%.7f k2=%.7f",
panel.LibrationLongitudeDeg, panel.LibrationLatitudeDeg, panel.LibrationPositionAngleDeg,
panel.BrownLunationNumber, panel.DeltaTSeconds, panel.PenumbralK, panel.UmbralK)
// NASA 2009-07-22:太阳 00°15'44.1" / 00°00'08.7",月亮 00°16'42.3" / 01°01'19.8"。
if math.Abs(panel.SunSemidiameterArcsec-944.1) > 1.5 {
t.Fatalf("sun semidiameter = %.1f\", want 944.1", panel.SunSemidiameterArcsec)
}
if math.Abs(panel.SunParallaxArcsec-8.7) > 0.4 {
t.Fatalf("sun parallax = %.1f\", want 8.7", panel.SunParallaxArcsec)
}
if math.Abs(panel.MoonSemidiameterArcsec-1002.3) > 2 {
t.Fatalf("moon semidiameter = %.1f\", want 1002.3", panel.MoonSemidiameterArcsec)
}
if math.Abs(panel.MoonParallaxArcsec-3679.8) > 4 {
t.Fatalf("moon parallax = %.1f\", want 3679.8", panel.MoonParallaxArcsec)
}
if panel.BrownLunationNumber != 1071 {
t.Fatalf("brown lunation = %d, want 1071", panel.BrownLunationNumber)
}
if math.Abs(panel.LibrationLongitudeDeg-0.67) > 0.05 || math.Abs(panel.LibrationPositionAngleDeg-10.52) > 0.05 {
t.Fatalf("libration l=%.2f c=%.2f, want +0.67 / 10.52",
panel.LibrationLongitudeDeg, panel.LibrationPositionAngleDeg)
}
if panel.Conjunction.IsZero() || panel.Conjunction.After(panel.Conjunction.Add(time.Hour)) {
t.Fatal("conjunction instant missing")
}
t.Logf("conjunction (equal apparent ecliptic longitude) %s", panel.Conjunction.UTC().Format("15:04:05.0"))
t.Logf("conjunction (equal apparent right ascension) %s", panel.RightAscensionConjunction.UTC().Format("15:04:05.0"))
// NASA 全球图的 Geocentric Conjunction 取视赤经相等,2009-07-22 为 02:33:04.4 UT。
nasa := time.Date(2009, time.July, 22, 2, 33, 4, 0, time.UTC)
if delta := panel.RightAscensionConjunction.Sub(nasa).Seconds(); math.Abs(delta) > 2 {
t.Fatalf("right-ascension conjunction %s differs from NASA by %.1f s",
panel.RightAscensionConjunction.Format("15:04:05.0"), delta)
}
// 朔(视黄经相等)比它晚约 90 s,两者不是同一个量。
if delta := panel.Conjunction.Sub(panel.RightAscensionConjunction).Seconds(); delta < 60 || delta > 120 {
t.Fatalf("new moon is %.1f s after the right-ascension conjunction, want about 90 s", delta)
}
}