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

88 lines
3.0 KiB
Go

package svg
import (
"testing"
"time"
)
// 本文件量化三族地图标签(等时线、中心线时刻、事件标记)的互相避让:
// 产物里任一族的 <text> 占位都不许与另一族相交。
type occultationLabelFixture struct {
name string
width int
height int
// labelStep 为 0 时用默认 30 分钟。
labelStep time.Duration
star bool
}
func TestOccultationMapLabelsDoNotOverlap(t *testing.T) {
fixtures := []occultationLabelFixture{
{name: "stellar 1200x800", width: 1200, height: 800, labelStep: 10 * time.Minute, star: true},
{name: "stellar 720x520", width: 720, height: 520, labelStep: 15 * time.Minute, star: true},
{name: "stellar 640x480", width: 640, height: 480, star: true},
{name: "planetary compact 1200x800", width: 1200, height: 800, labelStep: 10 * time.Minute},
{name: "planetary compact 720x520", width: 720, height: 520, labelStep: 15 * time.Minute},
}
totalLabels := 0
for _, fixture := range fixtures {
fixture := fixture
t.Run(fixture.name, func(t *testing.T) {
options := StarOccultationSVGOptions{
Width: fixture.width, Height: fixture.height, Location: time.UTC, TimeLabelStep: fixture.labelStep,
}
var diagram string
var err error
if fixture.star {
diagram, err = StarOccultationPathSVG(occultationTestStarPath(t), options)
} else {
diagram, err = PlanetOccultationPathSVG(occultationTestSaturnPath(t), options)
}
if err != nil {
t.Fatalf("render: %v", err)
}
labels := occultationSVGLabelTexts(occultationSVGTexts(t, diagram))
if len(labels) < 3 {
t.Fatalf("fixture produced only %d labels; the overlap check would be vacuous", len(labels))
}
if outside := occultationSVGTextsOutsideCanvas(labels, float64(fixture.width), float64(fixture.height)); len(outside) > 0 {
t.Fatalf("map labels outside the canvas: %v", outside)
}
if pairs := occultationSVGTextOverlapPairs(labels); pairs != 0 {
t.Fatalf("%d label overlap pairs among %d labels", pairs, len(labels))
}
totalLabels += len(labels)
})
}
if totalLabels < 40 {
t.Fatalf("label fixtures only produced %d labels, want a dense label set", totalLabels)
}
t.Logf("checked %d labels across %d fixtures", totalLabels, len(fixtures))
}
func TestPlanetOccultationMapLabelsAvoidTotalBandMarkers(t *testing.T) {
diagram, err := PlanetOccultationPathSVG(occultationTestMarsPath(t), StarOccultationSVGOptions{
Width: 1200, Height: 800, Location: time.UTC, TimeLabelStep: 10 * time.Minute,
})
if err != nil {
t.Fatalf("render: %v", err)
}
labels := occultationSVGLabelTexts(occultationSVGTexts(t, diagram))
if len(labels) < 5 {
t.Fatalf("total-band fixture produced only %d labels", len(labels))
}
if pairs := occultationSVGTextOverlapPairs(labels); pairs != 0 {
t.Fatalf("%d label overlap pairs among %d labels", pairs, len(labels))
}
markers := 0
for _, label := range labels {
if label.parentClass == "event-marker event-greatest" {
markers++
}
}
if markers != 1 {
t.Fatalf("greatest-event label count = %d, want one", markers)
}
}