feat: 完善日月食与月掩几何链路并扩展历法接口
- 新增日月食中心带、偏食带、阴影足迹、等时线、食分线及升落边界计算,支持极区与混合食拓扑 - 新增日食单时刻阴影求解器、站心状态查询、批量采样和 ΔT 覆盖接口 - 重构恒星与行星月掩路径,补充有限盘面接触、站心修正、掩带宽度、极区投影及升落边界 - 扩展 SVG 与 GeoJSON 输出,支持详细面板、全球/极区/地球投影、边界闭合、时间标记和拓扑签名 - 扩展日月食候选搜索、局地搜索、沙罗序列预计算与范围外推,补充系列锚点和成员一致性校验 - 补齐古历纪年、儒略历独有闰日、多公历候选、历法改革跨日及精确日期运算接口 - 优化 ΔT、章动、恒星时、月球地平线、事件根搜索和本地星历缓存,降低重复计算开销并提升边界稳定
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
package svg
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var eclipseMapDataSourcePattern = regexp.MustCompile(`data-source="([^"]+)"`)
|
||||
|
||||
// 降级标记必须收敛到包注释里的词表:拼错的来源会让消费方静默漏掉降级图层。
|
||||
func TestEclipseMapDataSourcesUseDocumentedVocabulary(t *testing.T) {
|
||||
// 词表必须与包注释逐项一致:常量改名或拼错都会让消费方的匹配静默失效。
|
||||
documented := []string{
|
||||
"partial-band-union", "sampled-footprint-sweep", "partial-band-contours",
|
||||
"rise-set-phase-lines", "magnitude-contours", "greatest-time-isochrones",
|
||||
"besselian-critical-envelope", "paired-limit-chords", "sampled-open-sweep",
|
||||
"central-path-limits", "penumbral-outlines", "central-shadow-outlines",
|
||||
"p1-p4-visibility-regions", "p1-p4-horizon-boundaries",
|
||||
}
|
||||
if len(documented) != len(eclipseMapDataSources) {
|
||||
t.Fatalf("vocabulary has %d entries, want %d", len(eclipseMapDataSources), len(documented))
|
||||
}
|
||||
known := make(map[string]bool, len(documented))
|
||||
for index, source := range documented {
|
||||
if eclipseMapDataSources[index] != source {
|
||||
t.Fatalf("vocabulary entry %d = %q, want %q", index, eclipseMapDataSources[index], source)
|
||||
}
|
||||
known[source] = true
|
||||
}
|
||||
|
||||
solarOptions := SolarEclipseMapSVGOptions{
|
||||
Width: 960, Height: 640, Location: time.UTC, PartialStep: 10 * time.Minute,
|
||||
GreatestTimeStep: 30 * time.Minute, PenumbralOutlineStep: time.Hour, CentralShadowStep: 10 * time.Minute,
|
||||
}
|
||||
charts := map[string]string{}
|
||||
if rendered, ok := SolarEclipseMapSVG(time.Date(2024, time.April, 8, 0, 0, 0, 0, time.UTC), solarOptions); ok {
|
||||
charts["2024-04-08 total"] = rendered
|
||||
} else {
|
||||
t.Fatal("missing 2024-04-08 map")
|
||||
}
|
||||
if rendered, ok := SolarEclipseMapSVG(time.Date(2014, time.April, 29, 0, 0, 0, 0, time.UTC), solarOptions); ok {
|
||||
charts["2014-04-29 non-central"] = rendered
|
||||
} else {
|
||||
t.Fatal("missing 2014-04-29 map")
|
||||
}
|
||||
if rendered, ok := LunarEclipseMapSVG(time.Date(2026, time.March, 3, 0, 0, 0, 0, time.UTC),
|
||||
LunarEclipseMapSVGOptions{Width: 960, Height: 640, Location: time.UTC}); ok {
|
||||
charts["2026-03-03 lunar"] = rendered
|
||||
} else {
|
||||
t.Fatal("missing 2026-03-03 lunar map")
|
||||
}
|
||||
|
||||
seen := map[string]bool{}
|
||||
for name, chart := range charts {
|
||||
for _, match := range eclipseMapDataSourcePattern.FindAllStringSubmatch(chart, -1) {
|
||||
if !known[match[1]] {
|
||||
t.Fatalf("%s: undocumented data-source %q", name, match[1])
|
||||
}
|
||||
seen[match[1]] = true
|
||||
}
|
||||
}
|
||||
// 主要图层必须带标记,否则消费方无法判断这一层是否降级。
|
||||
for _, source := range []string{
|
||||
eclipseMapSourcePartialBandUnion,
|
||||
eclipseMapSourcePartialBandContours,
|
||||
eclipseMapSourceRiseSetPhaseLines,
|
||||
eclipseMapSourceMagnitudeContours,
|
||||
eclipseMapSourceGreatestTimeIsochrones,
|
||||
eclipseMapSourceBesselianEnvelope,
|
||||
eclipseMapSourceCentralPathLimits,
|
||||
eclipseMapSourcePenumbralOutlines,
|
||||
eclipseMapSourceCentralShadowOutlines,
|
||||
eclipseMapSourceLunarVisibilityRegions,
|
||||
eclipseMapSourceLunarHorizonBoundaries,
|
||||
} {
|
||||
if !seen[source] {
|
||||
t.Fatalf("main layer source %q carries no data-source marker", source)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user