2bf8478639
- 新增日月食中心带、偏食带、阴影足迹、等时线、食分线及升落边界计算,支持极区与混合食拓扑 - 新增日食单时刻阴影求解器、站心状态查询、批量采样和 ΔT 覆盖接口 - 重构恒星与行星月掩路径,补充有限盘面接触、站心修正、掩带宽度、极区投影及升落边界 - 扩展 SVG 与 GeoJSON 输出,支持详细面板、全球/极区/地球投影、边界闭合、时间标记和拓扑签名 - 扩展日月食候选搜索、局地搜索、沙罗序列预计算与范围外推,补充系列锚点和成员一致性校验 - 补齐古历纪年、儒略历独有闰日、多公历候选、历法改革跨日及精确日期运算接口 - 优化 ΔT、章动、恒星时、月球地平线、事件根搜索和本地星历缓存,降低重复计算开销并提升边界稳定
88 lines
2.8 KiB
Go
88 lines
2.8 KiB
Go
package svg
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
eclipsecore "b612.me/astro/eclipse"
|
|
)
|
|
|
|
// 核心判定当天无日食时,三个日食图入口都必须返回 false,与 LunarEclipseMapSVG 的日期门一致;
|
|
// 偏食足迹是“取最近一次”语义,缺这道门会把邻近日期的图当成当天的图交出去。
|
|
func TestSolarEclipseMapSVGRequiresEclipseOnDate(t *testing.T) {
|
|
type entry struct {
|
|
name string
|
|
render func(time.Time, SolarEclipseMapSVGOptions) (string, bool)
|
|
global func(time.Time) (eclipsecore.SolarEclipseInfo, bool)
|
|
}
|
|
entries := []entry{
|
|
{
|
|
name: "default",
|
|
render: SolarEclipseMapSVG,
|
|
global: eclipsecore.SolarEclipseOnDateNASABulletinSplitK,
|
|
},
|
|
{
|
|
name: "nasaSplitK",
|
|
render: SolarEclipseMapSVGNASABulletinSplitK,
|
|
global: eclipsecore.SolarEclipseOnDateNASABulletinSplitK,
|
|
},
|
|
{
|
|
name: "iauSingleK",
|
|
render: SolarEclipseMapSVGIAUSingleK,
|
|
global: eclipsecore.SolarEclipseOnDateIAUSingleK,
|
|
},
|
|
}
|
|
// 2024-04-08 是本组日期里唯一有日食的一天,其余都在最近一次日食前后半个朔望月内。
|
|
for _, test := range []struct {
|
|
day string
|
|
want bool
|
|
}{
|
|
{day: "2024-04-08", want: true},
|
|
{day: "2024-04-15"},
|
|
{day: "2024-04-20"},
|
|
{day: "2024-04-23"},
|
|
{day: "2024-04-24"},
|
|
} {
|
|
date, err := time.Parse("2006-01-02", test.day)
|
|
if err != nil {
|
|
t.Fatalf("bad fixture date %q: %v", test.day, err)
|
|
}
|
|
for _, entry := range entries {
|
|
_, coreOK := entry.global(date)
|
|
if coreOK != test.want {
|
|
t.Fatalf("%s %s: core eclipse gate = %v, want %v", entry.name, test.day, coreOK, test.want)
|
|
}
|
|
rendered, ok := entry.render(date, SolarEclipseMapSVGOptions{
|
|
Width: 900, Height: 620, Location: time.UTC, PartialStep: 10 * time.Minute,
|
|
})
|
|
if ok != test.want {
|
|
t.Fatalf("%s %s: map gate = %v, want %v (core says %v)", entry.name, test.day, ok, test.want, coreOK)
|
|
}
|
|
if test.want && rendered == "" {
|
|
t.Fatalf("%s %s: gate passed but the map is empty", entry.name, test.day)
|
|
}
|
|
if !test.want && rendered != "" {
|
|
t.Fatalf("%s %s: rejected date still returned %d bytes", entry.name, test.day, len(rendered))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 过了日期门的日期必须仍带完整等时线层:等时线自己还要查一次核心,门不能把它挡掉。
|
|
func TestSolarEclipseMapOnDateKeepsIsochrones(t *testing.T) {
|
|
rendered, ok := SolarEclipseMapSVG(
|
|
time.Date(2024, time.April, 8, 0, 0, 0, 0, time.UTC),
|
|
SolarEclipseMapSVGOptions{
|
|
Width: 900, Height: 620, Location: time.UTC,
|
|
PartialStep: 10 * time.Minute, GreatestTimeStep: 30 * time.Minute,
|
|
},
|
|
)
|
|
if !ok {
|
|
t.Fatal("2024-04-08 is an eclipse date but the map was rejected")
|
|
}
|
|
if got := strings.Count(rendered, `class="solar-greatest-time-isoline"`); got != 7 {
|
|
t.Fatalf("isochrone paths = %d, want the full 7-branch fan", got)
|
|
}
|
|
}
|