- 新增日食、月食、本地可见性、中心线、半影区域、SVG 图示与沙罗周期信息 - 新增行星冲合、留、方照、物理星历、视直径、相位、亮肢角、轨道节点等计算 - 新增木星伽利略卫星位置、现象与接触事件计算 - 新增恒星星表、星座判定、自行修正与观测辅助能力 - 新增 coord、formula、orbit、sundial、lite/sun、lite/moon 等扩展包 - 完善农历年号、月相英文别名、视差角、大气质量、折射、日晷与双星计算 - 增加 NASA、JPL Horizons、IMCCE 等回归测试数据与基线测试 - 重构基础算法文件组织,补充大量公开 API 注释和语义回归测试 - 更新中文和英文 README,补充示例、精度说明、SVG 配图
152 lines
4.0 KiB
Go
152 lines
4.0 KiB
Go
package basic
|
|
|
|
import (
|
|
"math"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestLunarEclipseDiagramIncludesContacts(t *testing.T) {
|
|
diagram := LunarEclipseDiagram(JDECalc(2026, 3, 3), LunarEclipseDiagramOptions{StepDays: 10.0 / 1440.0})
|
|
if diagram.Eclipse.Type != LunarEclipseTotal {
|
|
t.Fatalf("unexpected eclipse type: got %s want %s", diagram.Eclipse.Type, LunarEclipseTotal)
|
|
}
|
|
if diagram.MoonRadius != 1 {
|
|
t.Fatalf("moon radius mismatch: got %.9f want 1", diagram.MoonRadius)
|
|
}
|
|
if !(diagram.PenumbraRadius > diagram.UmbraRadius && diagram.UmbraRadius > diagram.MoonRadius) {
|
|
t.Fatalf(
|
|
"unexpected radii: penumbra=%.9f umbra=%.9f moon=%.9f",
|
|
diagram.PenumbraRadius,
|
|
diagram.UmbraRadius,
|
|
diagram.MoonRadius,
|
|
)
|
|
}
|
|
|
|
labels := map[string]bool{}
|
|
for _, point := range diagram.Points {
|
|
if point.Label != "" {
|
|
labels[point.Label] = true
|
|
}
|
|
}
|
|
for _, label := range []string{"P1", "U1", "U2", "Greatest", "U3", "U4", "P4"} {
|
|
if !labels[label] {
|
|
t.Fatalf("missing label %s in diagram points", label)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestLocalSolarEclipseDiagramIncludesContacts(t *testing.T) {
|
|
diagram := LocalSolarEclipseDiagram(
|
|
TD2UT(Date2JDE(time.Date(2024, 4, 8, 12, 0, 0, 0, time.UTC)), true),
|
|
-96.7970,
|
|
32.7767,
|
|
0,
|
|
LocalSolarEclipseDiagramOptions{StepDays: 5.0 / 1440.0},
|
|
)
|
|
if diagram.Eclipse.Type == SolarEclipseNone {
|
|
t.Fatalf("expected local solar eclipse")
|
|
}
|
|
if len(diagram.Frames) == 0 {
|
|
t.Fatalf("expected diagram frames")
|
|
}
|
|
|
|
labels := map[string]bool{}
|
|
for _, frame := range diagram.Frames {
|
|
if frame.SunRadius != 1 {
|
|
t.Fatalf("sun radius mismatch: got %.9f want 1", frame.SunRadius)
|
|
}
|
|
if !(frame.MoonRadius > 0) {
|
|
t.Fatalf("invalid moon radius: %.9f", frame.MoonRadius)
|
|
}
|
|
if math.IsNaN(frame.MoonX) || math.IsNaN(frame.MoonY) {
|
|
t.Fatalf("invalid moon position: x=%f y=%f", frame.MoonX, frame.MoonY)
|
|
}
|
|
if frame.Label != "" {
|
|
labels[frame.Label] = true
|
|
}
|
|
}
|
|
for _, label := range []string{"C1", "Greatest", "C4"} {
|
|
if !labels[label] {
|
|
t.Fatalf("missing label %s in diagram frames", label)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestLocalSolarEclipseDiagramTimesKeepCoincidentLabels(t *testing.T) {
|
|
eclipse := LocalSolarEclipseResult{
|
|
HasPartial: true,
|
|
HasCentral: true,
|
|
PartialStart: 1,
|
|
GreatestEclipse: 2,
|
|
CentralStart: 2,
|
|
CentralEnd: 2,
|
|
PartialEnd: 3,
|
|
}
|
|
times, _ := localSolarEclipseDiagramTimes(eclipse, 0.5)
|
|
var coincident localSolarEclipseDiagramTime
|
|
found := false
|
|
for _, item := range times {
|
|
if item.jde == 2 {
|
|
coincident = item
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
t.Fatalf("missing coincident event time")
|
|
}
|
|
want := []string{"C2", "Greatest", "C3"}
|
|
if len(coincident.labels) != len(want) {
|
|
t.Fatalf("coincident labels = %v, want %v", coincident.labels, want)
|
|
}
|
|
for i, label := range want {
|
|
if coincident.labels[i] != label {
|
|
t.Fatalf("coincident labels = %v, want %v", coincident.labels, want)
|
|
}
|
|
}
|
|
if got := localSolarEclipseDiagramPrimaryLabel(coincident.labels); got != "Greatest" {
|
|
t.Fatalf("primary label = %q, want %q", got, "Greatest")
|
|
}
|
|
}
|
|
|
|
func TestLunarEclipseDiagramTimesKeepCoincidentLabels(t *testing.T) {
|
|
eclipse := LunarEclipseResult{
|
|
HasPenumbral: true,
|
|
HasPartial: true,
|
|
HasTotal: true,
|
|
PenumbralStart: 1,
|
|
PartialStart: 1.5,
|
|
TotalStart: 2,
|
|
Maximum: 2,
|
|
TotalEnd: 2,
|
|
PartialEnd: 2.5,
|
|
PenumbralEnd: 3,
|
|
}
|
|
times, _ := lunarEclipseDiagramTimes(eclipse, 0.5)
|
|
var coincident lunarEclipseDiagramTime
|
|
found := false
|
|
for _, item := range times {
|
|
if item.jde == 2 {
|
|
coincident = item
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
t.Fatalf("missing coincident event time")
|
|
}
|
|
want := []string{"U2", "Greatest", "U3"}
|
|
if len(coincident.labels) != len(want) {
|
|
t.Fatalf("coincident labels = %v, want %v", coincident.labels, want)
|
|
}
|
|
for i, label := range want {
|
|
if coincident.labels[i] != label {
|
|
t.Fatalf("coincident labels = %v, want %v", coincident.labels, want)
|
|
}
|
|
}
|
|
if got := lunarEclipseDiagramPrimaryLabel(coincident.labels); got != "Greatest" {
|
|
t.Fatalf("primary label = %q, want %q", got, "Greatest")
|
|
}
|
|
}
|