2bf8478639
- 新增日月食中心带、偏食带、阴影足迹、等时线、食分线及升落边界计算,支持极区与混合食拓扑 - 新增日食单时刻阴影求解器、站心状态查询、批量采样和 ΔT 覆盖接口 - 重构恒星与行星月掩路径,补充有限盘面接触、站心修正、掩带宽度、极区投影及升落边界 - 扩展 SVG 与 GeoJSON 输出,支持详细面板、全球/极区/地球投影、边界闭合、时间标记和拓扑签名 - 扩展日月食候选搜索、局地搜索、沙罗序列预计算与范围外推,补充系列锚点和成员一致性校验 - 补齐古历纪年、儒略历独有闰日、多公历候选、历法改革跨日及精确日期运算接口 - 优化 ΔT、章动、恒星时、月球地平线、事件根搜索和本地星历缓存,降低重复计算开销并提升边界稳定
91 lines
3.1 KiB
Go
91 lines
3.1 KiB
Go
package svg
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"b612.me/astro/moon"
|
|
)
|
|
|
|
// 本文件钉住紧凑掩带合并缓存的契约:同输入复用只读结果、不同几何不会串味、产物逐字节确定。
|
|
|
|
func occultationTestCompactSweep(t *testing.T) occultationFootprintSweep {
|
|
t.Helper()
|
|
path := occultationTestSaturnPath(t)
|
|
if len(path.PartialBandFootprints) == 0 {
|
|
t.Fatal("fixture carries no compact band footprints")
|
|
}
|
|
return occultationFootprintSweep{
|
|
footprints: path.PartialBandFootprints,
|
|
contours: path.PartialBandContours,
|
|
visibilityContours: path.PartialVisibilityContours,
|
|
northern: path.NorthernLimit,
|
|
southern: path.SouthernLimit,
|
|
curves: path.RiseSetCurves,
|
|
compactBand: true,
|
|
kind: partialOccultationFootprintSweep,
|
|
}
|
|
}
|
|
|
|
func TestOccultationBandCacheReusesIdenticalGeometry(t *testing.T) {
|
|
sweep := occultationTestCompactSweep(t)
|
|
first, firstAuthoritative, err := sweep.mergedBandPolygons()
|
|
if err != nil {
|
|
t.Fatalf("first mergedBandPolygons() error = %v", err)
|
|
}
|
|
if len(first) == 0 {
|
|
t.Fatal("compact band merge produced no polygon")
|
|
}
|
|
second, secondAuthoritative, err := sweep.mergedBandPolygons()
|
|
if err != nil {
|
|
t.Fatalf("second mergedBandPolygons() error = %v", err)
|
|
}
|
|
if len(second) != len(first) || &second[0][0] != &first[0][0] {
|
|
t.Fatal("identical band geometry was merged again instead of reusing the cached polygons")
|
|
}
|
|
if secondAuthoritative != firstAuthoritative {
|
|
t.Fatalf("cached authoritative flag = %v, want %v", secondAuthoritative, firstAuthoritative)
|
|
}
|
|
}
|
|
|
|
func TestOccultationBandCacheSeparatesDifferentGeometry(t *testing.T) {
|
|
sweep := occultationTestCompactSweep(t)
|
|
first, _, err := sweep.mergedBandPolygons()
|
|
if err != nil {
|
|
t.Fatalf("first mergedBandPolygons() error = %v", err)
|
|
}
|
|
mutated := sweep
|
|
mutated.footprints = append([]moon.PlanetOccultationFootprint(nil), sweep.footprints...)
|
|
last := len(mutated.footprints) - 1
|
|
mutated.footprints[last].Polygons = append([][]moon.OccultationPathPoint(nil), mutated.footprints[last].Polygons...)
|
|
polygon := append([]moon.OccultationPathPoint(nil), mutated.footprints[last].Polygons[0]...)
|
|
polygon[0].Longitude += 1.5
|
|
mutated.footprints[last].Polygons[0] = polygon
|
|
second, _, err := mutated.mergedBandPolygons()
|
|
if err != nil {
|
|
t.Fatalf("mutated mergedBandPolygons() error = %v", err)
|
|
}
|
|
if len(second) > 0 && len(first) > 0 && &second[0][0] == &first[0][0] {
|
|
t.Fatal("a shifted footprint reused the cached band polygons")
|
|
}
|
|
}
|
|
|
|
func TestCompactBandRenderIsDeterministic(t *testing.T) {
|
|
path := occultationTestSaturnPath(t)
|
|
options := StarOccultationSVGOptions{Width: 1200, Height: 800, Location: time.UTC}
|
|
first, err := PlanetOccultationPathSVG(path, options)
|
|
if err != nil {
|
|
t.Fatalf("first render: %v", err)
|
|
}
|
|
second, err := PlanetOccultationPathSVG(path, options)
|
|
if err != nil {
|
|
t.Fatalf("second render: %v", err)
|
|
}
|
|
if first != second {
|
|
t.Fatal("compact-band SVG changed between renders after the merge was cached")
|
|
}
|
|
if len(first) == 0 {
|
|
t.Fatal("compact-band render is empty")
|
|
}
|
|
}
|