044f2f4381
- 新增半解析、旧模型、自定义与多源堆叠星历实例,提供 Context、Instance、SPK 读取及状态与视位置计算 - 统一太阳、月球和行星实例接口,扩展黄经穿越、留、相位、最近角距、偕日可见、任意高度升落、轨道节点及凌日等天象查询 - 完善日月食、月掩与凌日的月缘剖面、有限盘面接触、站心修正、局地可见性、全球路径和地图输出 - 新增 SVG、GeoJSON、KML 天象输出及凌日、月掩和月缘地形相关缓存与几何求解 - 新增恒星星表导入与查询,支持 CSV、Hipparcos、BSC5、Stellarium 等格式及名称、交叉标识、锥面检索和星等过滤 - 补充 IAU 2006、地球定向、折射消光、大气观测、轨道传播及半解析行星/月球数据支持 - 将默认未来民用时标切换为 TimeScaleLeapHour,更新 2027–2400 农历速查表、中文日期解析和时区边界处理 - 增加事件基线、跨模型回归、几何边界、月缘地形和输出契约测试,完善中英文手册、示例资源、NOTICE 与忽略规则
128 lines
3.7 KiB
Go
128 lines
3.7 KiB
Go
package ephem
|
|
|
|
import (
|
|
"errors"
|
|
"testing"
|
|
)
|
|
|
|
type stackTestEngine struct {
|
|
bodies []Body
|
|
pairs map[[2]Body][3]float64
|
|
start float64
|
|
end float64
|
|
}
|
|
|
|
func (engine stackTestEngine) State(target, center Body, jdTDB float64) (pos, vel [3]float64, err error) {
|
|
if value, ok := engine.pairs[[2]Body{target, center}]; ok && jdTDB >= engine.start && jdTDB <= engine.end {
|
|
pos = value
|
|
return pos, vel, nil
|
|
}
|
|
for _, body := range engine.bodies {
|
|
if body == target || body == center {
|
|
return pos, vel, ErrOutOfRange
|
|
}
|
|
}
|
|
return pos, vel, ErrUnsupportedBody
|
|
}
|
|
|
|
func (engine stackTestEngine) Coverage(target Body) (start, end float64, ok bool) {
|
|
for _, body := range engine.bodies {
|
|
if body == target {
|
|
return engine.start, engine.end, true
|
|
}
|
|
}
|
|
return 0, 0, false
|
|
}
|
|
|
|
func (engine stackTestEngine) Bodies() []Body { return append([]Body(nil), engine.bodies...) }
|
|
|
|
func TestStackComposesAcrossSources(t *testing.T) {
|
|
first := stackTestEngine{
|
|
bodies: []Body{Sun, SSB},
|
|
pairs: map[[2]Body][3]float64{
|
|
{Sun, SSB}: {10, 20, 30},
|
|
},
|
|
start: 0,
|
|
end: 3000000,
|
|
}
|
|
second := stackTestEngine{
|
|
bodies: []Body{Body(2000001), Sun},
|
|
pairs: map[[2]Body][3]float64{
|
|
{Body(2000001), Sun}: {1, 2, 3},
|
|
},
|
|
start: 0,
|
|
end: 3000000,
|
|
}
|
|
stack := NewStack(first, second)
|
|
pos, _, err := stack.State(Body(2000001), SSB, 2451545)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if pos != [3]float64{11, 22, 33} {
|
|
t.Fatalf("position = %v", pos)
|
|
}
|
|
}
|
|
|
|
func TestStackFirstSourceWinsDirectState(t *testing.T) {
|
|
first := stackTestEngine{bodies: []Body{Mars, Earth}, pairs: map[[2]Body][3]float64{{Mars, Earth}: {1, 2, 3}}, start: 0, end: 10}
|
|
second := stackTestEngine{bodies: []Body{Mars, Earth}, pairs: map[[2]Body][3]float64{{Mars, Earth}: {4, 5, 6}}, start: 0, end: 10}
|
|
pos, _, err := NewStack(first, second).State(Mars, Earth, 5)
|
|
if err != nil || pos != [3]float64{1, 2, 3} {
|
|
t.Fatalf("state = %v, %v", pos, err)
|
|
}
|
|
}
|
|
|
|
func TestStackErrorPriority(t *testing.T) {
|
|
engine := stackTestEngine{bodies: []Body{Mars}, start: 0, end: 1}
|
|
_, _, err := NewStack(engine).State(Mars, Earth, 2)
|
|
if !errors.Is(err, ErrOutOfRange) {
|
|
t.Fatalf("error = %v", err)
|
|
}
|
|
}
|
|
|
|
func TestStackGenericApparentAcceptsArbitraryBody(t *testing.T) {
|
|
engine := stackTestEngine{
|
|
bodies: []Body{Earth, Sun, Body(2000001), SSB},
|
|
pairs: map[[2]Body][3]float64{
|
|
{Earth, SSB}: {0, 0, 0},
|
|
{Sun, SSB}: {1000000, 0, 0},
|
|
{Body(2000001), SSB}: {1001000, 0, 0},
|
|
},
|
|
start: 0,
|
|
end: 3000000,
|
|
}
|
|
instance := NewInstance(NewStack(engine))
|
|
if _, distance, _, err := instance.Apparent(Body(2000001), 2451545); err != nil || distance != 1001000 {
|
|
t.Fatalf("apparent distance = %.3f, err = %v", distance, err)
|
|
}
|
|
}
|
|
|
|
func BenchmarkStackStateChain(b *testing.B) {
|
|
first := stackTestEngine{bodies: []Body{Sun, SSB}, pairs: map[[2]Body][3]float64{{Sun, SSB}: {10, 20, 30}}, start: 0, end: 3000000}
|
|
second := stackTestEngine{bodies: []Body{Body(2000001), Sun}, pairs: map[[2]Body][3]float64{{Body(2000001), Sun}: {1, 2, 3}}, start: 0, end: 3000000}
|
|
stack := NewStack(first, second)
|
|
b.ReportAllocs()
|
|
for i := 0; i < b.N; i++ {
|
|
if _, _, err := stack.State(Body(2000001), SSB, 2451545); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestStackChainBeyondInlineCapacity(t *testing.T) {
|
|
bodies := []Body{SSB}
|
|
pairs := map[[2]Body][3]float64{}
|
|
previous := SSB
|
|
for index := 0; index < 2*stackInlineBodies; index++ {
|
|
body := Body(3000000 + index)
|
|
bodies = append(bodies, body)
|
|
pairs[[2]Body{body, previous}] = [3]float64{1, 0, 0}
|
|
previous = body
|
|
}
|
|
engine := stackTestEngine{bodies: bodies, pairs: pairs, start: 0, end: 10}
|
|
pos, _, err := NewStack(engine).State(previous, SSB, 5)
|
|
if err != nil || pos != [3]float64{2 * stackInlineBodies, 0, 0} {
|
|
t.Fatalf("state = %v, %v", pos, err)
|
|
}
|
|
}
|