feat: 引入可切换星历模型并扩展天象观测链路

- 新增半解析、旧模型、自定义与多源堆叠星历实例,提供 Context、Instance、SPK 读取及状态与视位置计算
- 统一太阳、月球和行星实例接口,扩展黄经穿越、留、相位、最近角距、偕日可见、任意高度升落、轨道节点及凌日等天象查询
- 完善日月食、月掩与凌日的月缘剖面、有限盘面接触、站心修正、局地可见性、全球路径和地图输出
- 新增 SVG、GeoJSON、KML 天象输出及凌日、月掩和月缘地形相关缓存与几何求解
- 新增恒星星表导入与查询,支持 CSV、Hipparcos、BSC5、Stellarium 等格式及名称、交叉标识、锥面检索和星等过滤
- 补充 IAU 2006、地球定向、折射消光、大气观测、轨道传播及半解析行星/月球数据支持
- 将默认未来民用时标切换为 TimeScaleLeapHour,更新 2027–2400 农历速查表、中文日期解析和时区边界处理
- 增加事件基线、跨模型回归、几何边界、月缘地形和输出契约测试,完善中英文手册、示例资源、NOTICE 与忽略规则
This commit is contained in:
2026-10-15 23:54:15 +08:00
parent 16c62a97d5
commit 044f2f4381
674 changed files with 62983 additions and 8396 deletions
@@ -0,0 +1,46 @@
package lunar
import (
_ "embed"
"sync"
)
//go:embed lunar.bin
var defaultTable []byte
var (
defaultOnce sync.Once
defaultModel *Model
)
// Default 内置表,首次调用时解析 / the built-in table, parsed on first use.
func Default() *Model {
defaultOnce.Do(func() {
m, err := Parse(defaultTable)
if err != nil {
panic(err)
}
defaultModel = m
})
return defaultModel
}
//go:embed fast.bin
var fastTable []byte
var (
fastOnce sync.Once
fastModel *Model
)
// Fast 快速档表(n ≥ 0 用),首次调用时解析 / the fast-tier table used for n ≥ 0, parsed on first use.
func Fast() *Model {
fastOnce.Do(func() {
m, err := Parse(fastTable)
if err != nil {
panic(err)
}
fastModel = m
})
return fastModel
}
Binary file not shown.
Binary file not shown.
+513
View File
@@ -0,0 +1,513 @@
// Package lunar 月球半解析级数运行时(地心,J2000 平黄道)。
package lunar
import (
"encoding/binary"
"errors"
"math"
"sync"
)
const (
j2000 = 2451545.0
century = 36525.0
arcsec = math.Pi / 648000.0
fundCount = 13
maxEnvelope = 8
)
type coordinate struct {
args []uint16
nodes []int32
// 包络阶数为 0 的项单独成段:flat0 为 [cos,sin] 交错
nodes0 []int32
flat0 []float32
// 其余项(阶数 ≥1)
nodesH []int32
envH []uint8
coefH []float32
env []uint8
secular []float64
coef []float32
}
// Model 已解析的月球级数表 / parsed lunar series table.
type Model struct {
s2 [5][]float64
args [fundCount][5]float64
lonPoly [5]float64
p, q [5]float64
maxMult [fundCount]int
powOff [fundCount]int
coords [3]coordinate
maxEnv int
// 前缀树:节点 i 的复相位 = 节点 parent[i] × pow[factor[i]],parent 恒小于 i(-1 为根)
nodeParent []int32
nodeFactor []int32
argNode []int32
// pow 槽位 → (基本幅角, 乘数),用于速度计算中的相位变化率
slotFund []int8
slotMult []float64
powLen int
legLen int
// Parse 之后 Model 只读;每次求值的缓冲从池中取,可并发调用
pool sync.Pool
}
// scratch 单次求值的工作区。
type scratch struct {
pow []complex128
node []complex128
nodeRate []float64
leg []float64
dleg []float64
env [maxEnvelope + 1]float64
denv [maxEnvelope + 1]float64
}
func (m *Model) getScratch() *scratch {
if s, ok := m.pool.Get().(*scratch); ok {
return s
}
return &scratch{
pow: make([]complex128, m.powLen),
node: make([]complex128, len(m.nodeParent)),
nodeRate: make([]float64, len(m.nodeParent)),
leg: make([]float64, m.legLen),
dleg: make([]float64, m.legLen),
}
}
type reader struct {
b []byte
off int
err error
}
func (r *reader) take(n int) []byte {
if r.err != nil || r.off+n > len(r.b) {
r.err = errors.New("lunar: truncated table")
return make([]byte, n)
}
s := r.b[r.off : r.off+n]
r.off += n
return s
}
func (r *reader) u8() uint8 { return r.take(1)[0] }
func (r *reader) u16() uint16 { return binary.LittleEndian.Uint16(r.take(2)) }
func (r *reader) f64() float64 { return math.Float64frombits(binary.LittleEndian.Uint64(r.take(8))) }
func (r *reader) f32() float32 { return math.Float32frombits(binary.LittleEndian.Uint32(r.take(4))) }
// Parse 解析 LM7 v2 二进制表 / parse an LM7 v2 table.
func Parse(b []byte) (*Model, error) {
r := &reader{b: b}
if string(r.take(4)) != "LM7\x02" {
return nil, errors.New("lunar: bad magic")
}
m := &Model{}
nargs := int(r.u16())
s2n := int(r.u16())
secDeg := int(r.u8())
for j := 0; j < 5; j++ {
m.s2[j] = make([]float64, s2n)
for k := range m.s2[j] {
m.s2[j][k] = r.f64()
}
}
for i := 0; i < fundCount; i++ {
for k := 0; k < 5; k++ {
m.args[i][k] = r.f64()
}
}
for k := range m.lonPoly {
m.lonPoly[k] = r.f64()
}
for k := range m.p {
m.p[k] = r.f64()
}
for k := range m.q {
m.q[k] = r.f64()
}
r.f64() // 距离比例已折入拟合系数
mults := make([][fundCount]int8, nargs)
for a := range mults {
mask := r.u16()
for i := 0; i < 16; i++ {
if mask&(1<<uint(i)) == 0 {
continue
}
if i >= fundCount {
return nil, errors.New("lunar: multiplier index out of range")
}
k := int8(r.u8())
mults[a][i] = k
if v := int(math.Abs(float64(k))); v > m.maxMult[i] {
m.maxMult[i] = v
}
}
}
m.buildTrie(mults)
for c := 0; c < 3; c++ {
n := int(r.u16())
co := &m.coords[c]
co.args = make([]uint16, n)
for j := range co.args {
co.args[j] = r.u16()
if int(co.args[j]) >= nargs {
return nil, errors.New("lunar: argument index out of range")
}
}
co.env = r.take(n)
ncoef := 0
for _, e := range co.env {
if int(e) > maxEnvelope {
return nil, errors.New("lunar: envelope degree too high")
}
if int(e) > m.maxEnv {
m.maxEnv = int(e)
}
ncoef += 2 * (int(e) + 1)
}
co.secular = make([]float64, secDeg+1)
for k := range co.secular {
co.secular[k] = r.f64()
}
raw := make([]float32, ncoef)
for k := range raw {
raw[k] = r.f32()
}
co.coef = interleave(co.env, raw)
}
if r.err != nil {
return nil, r.err
}
if r.off != len(b) {
return nil, errors.New("lunar: trailing bytes")
}
for c := range m.coords {
co := &m.coords[c]
co.nodes = make([]int32, len(co.args))
pos := 0
for j, a := range co.args {
co.nodes[j] = m.argNode[a]
e := int(co.env[j])
if e == 0 {
co.nodes0 = append(co.nodes0, co.nodes[j])
co.flat0 = append(co.flat0, co.coef[pos], co.coef[pos+1])
} else {
co.nodesH = append(co.nodesH, co.nodes[j])
co.envH = append(co.envH, co.env[j])
co.coefH = append(co.coefH, co.coef[pos:pos+2*(e+1)]...)
}
pos += 2 * (e + 1)
}
}
m.legLen = max3(s2n, secDeg+1, m.maxEnv+1)
return m, nil
}
func (m *Model) buildTrie(mults [][fundCount]int8) {
total := 0
for i := 0; i < fundCount; i++ {
m.powOff[i] = total + m.maxMult[i]
total += 2*m.maxMult[i] + 1
}
m.powLen = total
m.slotFund = make([]int8, total)
m.slotMult = make([]float64, total)
for i := 0; i < fundCount; i++ {
for k := -m.maxMult[i]; k <= m.maxMult[i]; k++ {
m.slotFund[m.powOff[i]+k] = int8(i)
m.slotMult[m.powOff[i]+k] = float64(k)
}
}
type edge struct{ parent, factor int32 }
index := map[edge]int32{}
m.argNode = make([]int32, len(mults))
for a, mv := range mults {
cur := int32(-1)
for i := 0; i < fundCount; i++ {
if mv[i] == 0 {
continue
}
e := edge{cur, int32(m.powOff[i] + int(mv[i]))}
n, ok := index[e]
if !ok {
n = int32(len(m.nodeParent))
index[e] = n
m.nodeParent = append(m.nodeParent, e.parent)
m.nodeFactor = append(m.nodeFactor, e.factor)
}
cur = n
}
m.argNode[a] = cur
}
}
// cmul 绕开内建复数乘法的 Inf/NaN 分支。
func cmul(a, b complex128) complex128 {
ar, ai, br, bi := real(a), imag(a), real(b), imag(b)
return complex(ar*br-ai*bi, ar*bi+ai*br)
}
func max3(a, b, c int) int {
if b > a {
a = b
}
if c > a {
a = c
}
return a
}
func poly(c *[5]float64, t float64) float64 {
return c[0] + t*(c[1]+t*(c[2]+t*(c[3]+t*c[4])))
}
// phase 与 poly 同值,但线性项单独做补偿归约:c1·t 在 ±1 万年达 1e6 rad,直接相加会丢掉约 1e-10 rad。
func phase(c *[5]float64, t, tLow float64) float64 {
const twoPiLow = 2.4492935982947064e-16
product := c[1] * t
roundoff := math.FMA(c[1], t, -product) + c[1]*tLow
turns := math.Round(product / (2 * math.Pi))
lin := math.FMA(-turns, 2*math.Pi, product) + (roundoff - turns*twoPiLow)
return lin + (c[0] + t*t*(c[2]+t*(c[3]+t*c[4])))
}
// dpoly 返回 poly 的一阶导数。
func dpoly(c *[5]float64, t float64) float64 {
return c[1] + t*(2*c[2]+t*(3*c[3]+t*4*c[4]))
}
// legendreD 写入 P0..P(n-1)(x);withD 时同时写入导数 P'k(x) 到 d。
func legendreD(x float64, out, d []float64, withD bool) {
out[0] = 1
if len(out) > 1 {
out[1] = x
}
for k := 2; k < len(out); k++ {
out[k] = ((2*float64(k)-1)*x*out[k-1] - (float64(k)-1)*out[k-2]) / float64(k)
}
if !withD {
return
}
d[0] = 0
if len(d) > 1 {
d[1] = 1
}
// P'k = P'(k-2) + (2k-1)·P(k-1)
for k := 2; k < len(d); k++ {
d[k] = d[k-2] + (2*float64(k)-1)*out[k-1]
}
}
func dot(c []float64, l []float64) float64 {
s := 0.0
for k, v := range c {
s += v * l[k]
}
return s
}
// PositionJ2000 地心月球 J2000 平黄道几何位置(km)/ geocentric Moon, J2000 mean ecliptic, km.
// 可并发调用。
func (m *Model) PositionJ2000(jdTT float64) [3]float64 {
p, _ := m.eval(jdTT, false)
return p
}
// PositionVelocityJ2000 位置(km)与解析速度(km/日,对 TT)/ position (km) and analytic velocity (km/day).
// 可并发调用。
func (m *Model) PositionVelocityJ2000(jdTT float64) (pos, vel [3]float64) {
return m.eval(jdTT, true)
}
// eval 所有量先对 t(儒略世纪)求导,最后换算到每日。
func (m *Model) eval(jdTT float64, wantVel bool) (pos, vel [3]float64) {
s := m.getScratch()
defer m.pool.Put(s)
days := jdTT - j2000
origin := days - jdTT
daysLow := (jdTT - (days - origin)) - (j2000 + origin)
t := days / century
// tLow 保留历元相减与世纪除法的舍入,远离 J2000 时线性相位才不丢精度。
tLow := (math.FMA(-t, century, days) + daysLow) / century
x := (t + 20) / 100
const dxdt = 0.01
leg, dleg := s.leg, s.dleg
// 递推前缀稳定,一次算到最长,S2 修正与各坐标长期项共用。
legendreD(x, leg[:m.legLen], dleg[:m.legLen], wantVel)
var dc, ddc [5]float64
for j := range dc {
dc[j] = dot(m.s2[j], leg)
if wantVel {
ddc[j] = dot(m.s2[j], dleg) * dxdt
}
}
// ζ 随 W1 修正,D/F/l/l′ 各自修正
var corr, dcorr, rate [fundCount]float64
corr[0], corr[1], corr[2], corr[3], corr[12] = dc[1], dc[2], dc[3], dc[4], dc[0]
dcorr[0], dcorr[1], dcorr[2], dcorr[3], dcorr[12] = ddc[1], ddc[2], ddc[3], ddc[4], ddc[0]
for i := 0; i < fundCount; i++ {
k := m.maxMult[i]
if k == 0 {
continue
}
rate[i] = dpoly(&m.args[i], t) + dcorr[i]
sn, cs := math.Sincos(phase(&m.args[i], t, tLow) + corr[i])
e := complex(cs, sn)
p := s.pow[m.powOff[i]-k : m.powOff[i]+k+1]
p[k] = 1
for n := 1; n <= k; n++ {
p[k+n] = cmul(p[k+n-1], e)
p[k-n] = complex(real(p[k+n]), -imag(p[k+n]))
}
}
// 热循环按 wantVel 拆开,纯位置路径不写 nodeRate
node, factor := s.node, m.nodeFactor
if wantVel {
nr := s.nodeRate
for n, parent := range m.nodeParent {
fac := factor[n]
f := s.pow[fac]
r := m.slotMult[fac] * rate[m.slotFund[fac]]
if parent >= 0 {
f = cmul(node[parent], f)
r += nr[parent]
}
node[n] = f
nr[n] = r
}
} else {
for n, parent := range m.nodeParent {
f := s.pow[factor[n]]
if parent >= 0 {
f = cmul(node[parent], f)
}
node[n] = f
}
}
env, denv := s.env[:m.maxEnv+1], s.denv[:m.maxEnv+1]
legendreD(x, env, denv, wantVel)
var v, dv [3]float64
for c := 0; c < 3; c++ {
co := &m.coords[c]
sum := dot(co.secular, leg)
dsum := 0.0
if wantVel {
dsum = dot(co.secular, dleg) * dxdt
}
f0 := co.flat0
if wantVel {
nr := s.nodeRate
for j, n := range co.nodes0 {
z := node[n]
a, b := float64(f0[2*j]), float64(f0[2*j+1])
sum += a*real(z) + b*imag(z)
dsum += nr[n] * (b*real(z) - a*imag(z))
}
pos := 0
for j, e := range co.envH {
n := co.nodesH[j]
z := node[n]
var ac, as, dac, das float64
for d := 0; d <= int(e); d++ {
cc, cn := float64(co.coefH[pos]), float64(co.coefH[pos+1])
ac += env[d] * cc
as += env[d] * cn
dac += denv[d] * cc
das += denv[d] * cn
pos += 2
}
sum += ac*real(z) + as*imag(z)
dsum += dxdt*(dac*real(z)+das*imag(z)) + nr[n]*(as*real(z)-ac*imag(z))
}
} else {
for j, n := range co.nodes0 {
z := node[n]
sum += float64(f0[2*j])*real(z) + float64(f0[2*j+1])*imag(z)
}
pos := 0
for j, e := range co.envH {
z := node[co.nodesH[j]]
var ac, as float64
for d := 0; d <= int(e); d++ {
ac += env[d] * float64(co.coefH[pos])
as += env[d] * float64(co.coefH[pos+1])
pos += 2
}
sum += ac*real(z) + as*imag(z)
}
}
v[c], dv[c] = sum, dsum
}
lon := v[0]*arcsec + phase(&m.lonPoly, t, tLow) + dc[0]
lat := v[1] * arcsec
rad := v[2]
sl, cl := math.Sincos(lon)
sb, cb := math.Sincos(lat)
x0, y0, z0 := rad*cb*cl, rad*cb*sl, rad*sb
p := poly(&m.p, t) * t
q := poly(&m.q, t) * t
ra := 2 * math.Sqrt(1-p*p-q*q)
pos = [3]float64{
(1-2*p*p)*x0 + 2*p*q*y0 + p*ra*z0,
2*p*q*x0 + (1-2*q*q)*y0 - q*ra*z0,
-p*ra*x0 + q*ra*y0 + (1-2*p*p-2*q*q)*z0,
}
if !wantVel {
return pos, vel
}
dlon := dv[0]*arcsec + dpoly(&m.lonPoly, t) + ddc[0]
dlat := dv[1] * arcsec
drad := dv[2]
// 球坐标 → 直角坐标的时间导数
dx0 := drad*cb*cl - rad*sb*cl*dlat - rad*cb*sl*dlon
dy0 := drad*cb*sl - rad*sb*sl*dlat + rad*cb*cl*dlon
dz0 := drad*sb + rad*cb*dlat
// 历元黄道 → J2000 旋转矩阵本身随 P、Q 变化
dp := dpoly(&m.p, t)*t + poly(&m.p, t)
dq := dpoly(&m.q, t)*t + poly(&m.q, t)
dra := -4 * (p*dp + q*dq) / ra
dpq := 2 * (dp*q + p*dq)
vel = [3]float64{
(1-2*p*p)*dx0 + 2*p*q*dy0 + p*ra*dz0 +
-4*p*dp*x0 + dpq*y0 + (dp*ra+p*dra)*z0,
2*p*q*dx0 + (1-2*q*q)*dy0 - q*ra*dz0 +
dpq*x0 - 4*q*dq*y0 - (dq*ra+q*dra)*z0,
-p*ra*dx0 + q*ra*dy0 + (1-2*p*p-2*q*q)*dz0 +
-(dp*ra+p*dra)*x0 + (dq*ra+q*dra)*y0 - 4*(p*dp+q*dq)*z0,
}
for i := range vel {
vel[i] /= century
}
return pos, vel
}
// interleave 把按阶数分块(每阶先 cos 块后 sin 块)的系数重排为逐项 [d0cos,d0sin,d1cos,…]。
func interleave(env []uint8, raw []float32) []float32 {
out := make([]float32, len(raw))
start := make([]int, len(env))
for j := 1; j < len(env); j++ {
start[j] = start[j-1] + 2*(int(env[j-1])+1)
}
pos := 0
for d := 0; ; d++ {
var idx []int
for j, e := range env {
if int(e) >= d {
idx = append(idx, j)
}
}
if len(idx) == 0 {
break
}
for n, j := range idx {
out[start[j]+2*d] = raw[pos+n]
out[start[j]+2*d+1] = raw[pos+len(idx)+n]
}
pos += 2 * len(idx)
}
return out
}
@@ -0,0 +1,115 @@
// 被测契约:内置表与参考向量一致(< 0.1 m),解析速度与差分一致,可并发求值。
package lunar
import (
"bufio"
"math"
"os"
"strconv"
"strings"
"sync"
"testing"
)
func sq(x float64) float64 { return x * x }
func TestMatchesReferenceVectors(t *testing.T) { checkVectors(t, Default(), "testdata/vectors.csv") }
func TestFastMatchesReferenceVectors(t *testing.T) { checkVectors(t, Fast(), "testdata/fast.csv") }
func checkVectors(t *testing.T, m *Model, path string) {
f, err := os.Open(path)
if err != nil {
t.Fatal(err)
}
defer f.Close()
sc := bufio.NewScanner(f)
n, worst := 0, 0.0
for sc.Scan() {
parts := strings.Split(sc.Text(), ",")
var v [4]float64
for i := range v {
if v[i], err = strconv.ParseFloat(parts[i], 64); err != nil {
t.Fatal(err)
}
}
got := m.PositionJ2000(v[0])
if d := math.Sqrt(sq(got[0]-v[1]) + sq(got[1]-v[2]) + sq(got[2]-v[3])); d > worst {
worst = d
}
n++
}
if n < 40 {
t.Fatalf("only %d vectors", n)
}
if worst > 1e-4 {
t.Fatalf("max diff %.3e km over %d vectors", worst, n)
}
}
func TestVelocityMatchesFiniteDifference(t *testing.T) {
m := Default()
const h = 0.05
worst := 0.0
for _, jd := range []float64{990545.5, 1500000.25, 2299160.5, 2451545.0, 2460676.5, 2816787.5, 3912545.0} {
p, v := m.PositionVelocityJ2000(jd)
if q := m.PositionJ2000(jd); q != p {
t.Fatalf("jd=%.1f position mismatch", jd)
}
a, b := m.PositionJ2000(jd+h), m.PositionJ2000(jd-h)
a2, b2 := m.PositionJ2000(jd+2*h), m.PositionJ2000(jd-2*h)
for i := range v {
fd := (8*(a[i]-b[i]) - (a2[i] - b2[i])) / (12 * h)
if d := math.Abs(fd - v[i]); d > worst {
worst = d
}
}
}
if worst > 2e-3 {
t.Fatalf("max velocity diff %.3e km/day", worst)
}
}
func TestParseRejectsTruncated(t *testing.T) {
for _, n := range []int{0, 3, 5, 40, len(defaultTable) / 2, len(defaultTable) - 1} {
if _, err := Parse(defaultTable[:n]); err == nil {
t.Errorf("len %d: expected error", n)
}
}
}
func TestConcurrentEvaluation(t *testing.T) {
m := Default()
const n = 64
var want [n][3]float64
for i := range want {
want[i] = m.PositionJ2000(2451545.0 + float64(i)*13.7)
}
var wg sync.WaitGroup
var bad [8]bool
for g := 0; g < 8; g++ {
wg.Add(1)
go func(g int) {
defer wg.Done()
for k := 0; k < n; k++ {
i := (k + g*7) % n
if m.PositionJ2000(2451545.0+float64(i)*13.7) != want[i] {
bad[g] = true
}
}
}(g)
}
wg.Wait()
for g, b := range bad {
if b {
t.Fatalf("goroutine %d saw a mismatch", g)
}
}
}
func BenchmarkPositionJ2000(b *testing.B) {
m := Default()
for i := 0; i < b.N; i++ {
_ = m.PositionJ2000(2460000.5 + float64(i%10000)*0.37)
}
}
+51
View File
@@ -0,0 +1,51 @@
-1931455,-263046.57528520969,297684.18718319025,-24345.864066160168
-1785355,24378.534686367391,-400825.36392118747,-44672.568525917093
-1639255,221175.99144970218,325206.96587989992,-14472.844556519216
-1493155,-319978.52720147866,-179819.4818149425,-7729.6582925465245
-1347055,362622.46972198499,20286.814075592443,4137.3575503146285
-1200955,-346235.18691354321,185914.73322113504,30174.27456151383
-1054855,171052.68131930399,-366289.65810158779,26232.886379638556
-908755,98623.637690714822,376297.77810421737,40802.587272379009
-762655,-253665.11515733672,-272838.23852057324,19911.166048921259
-616555,335485.16883375292,146456.59956479297,14870.504114287725
-470455,-383645.40573639271,65997.21790989369,-826.92611041679697
-324355,276927.4702533714,-295829.19680496032,-30322.013752343068
-178255,-26435.785915690412,386079.73800098576,-28015.326875332928
-32155,-173562.98376470321,-327340.8539868113,-37468.408479997677
113945,284098.82846766489,239256.46597111417,-25343.748850755001
260045,-385157.83176014025,-49369.527013191553,-15281.761574469898
406145,345160.97807879257,-214636.8383361497,3414.5771813550259
552245,-134108.10483846199,361980.9990905014,29968.389469456466
698345,-83984.239959958926,-355799.14247223095,28817.078112816904
844445,223226.00566205085,299354.17357796693,36909.979945451472
990545,-362607.45994305814,-147502.75304507115,28081.953043893249
1136645,383606.60880971845,-132531.90493783797,8832.002235690501
1282745,-216360.67463345666,321769.59784516064,-8957.0037364521304
1428845,7433.8731166889338,-359577.9208704764,-27286.722728085369
1574945,157042.40898349817,338967.54339773324,-30844.406074648126
1721045,-328371.10510008538,-221529.93877308263,-36739.865212875557
1867145,400234.08615918033,-57984.149689135251,-23513.254374541601
2013245,-274021.09564645251,273929.27390877635,-2133.8352285152291
2159345,92791.766991493409,-345234.67832922813,12342.071461675338
2305445,88338.286030037401,363169.93015197461,26462.650120618968
2451545,-291607.24183591013,-274978.62186731066,36267.30787189916
2597645,401391.47803711233,3266.8554273079903,31443.354743021413
2743745,-312245.28483573761,223268.80530781401,14449.195688692611
2889845,167261.68852763134,-317547.01628260425,854.67113282198795
3035945,22710.051466743793,377536.27831278293,-18254.778814458063
3182045,-258568.79979545044,-310953.08002426871,-31511.794215090176
3328145,391597.73715416581,50492.738155701489,-35663.250569429547
3474245,-336640.78667349386,169381.01759883287,-24138.799220522917
3620345,229894.62683911348,-283245.2596621954,-10124.478719948
3766445,-30725.076385326527,386554.31412064168,4630.937622600225
3912545,-232347.00044598628,-331529.30967142241,31692.736681196671
4058645,373153.27734119527,88709.654120304229,33189.966274715975
4204745,-352665.5780016224,110675.94346091514,29168.298060724752
4350845,279862.12418001605,-250761.84026383076,22491.093918623097
4496945,-63300.801294757643,393827.49900787073,-4549.380602734378
4643045,-211639.87281130059,-339806.65624159103,-18216.154066961921
4789145,345869.06789046078,125142.00856319141,-35847.90651925862
4935245,-365917.02341126435,47072.64876266574,-31135.795917215175
5081345,313235.01489341311,-233557.38203767358,-25005.730334995031
5227445,-71563.036314018507,398823.35837659024,-9633.2749911986139
5373545,-186164.91514019907,-338423.50248531549,24637.566759055353
1 -1931455 -263046.57528520969 297684.18718319025 -24345.864066160168
2 -1785355 24378.534686367391 -400825.36392118747 -44672.568525917093
3 -1639255 221175.99144970218 325206.96587989992 -14472.844556519216
4 -1493155 -319978.52720147866 -179819.4818149425 -7729.6582925465245
5 -1347055 362622.46972198499 20286.814075592443 4137.3575503146285
6 -1200955 -346235.18691354321 185914.73322113504 30174.27456151383
7 -1054855 171052.68131930399 -366289.65810158779 26232.886379638556
8 -908755 98623.637690714822 376297.77810421737 40802.587272379009
9 -762655 -253665.11515733672 -272838.23852057324 19911.166048921259
10 -616555 335485.16883375292 146456.59956479297 14870.504114287725
11 -470455 -383645.40573639271 65997.21790989369 -826.92611041679697
12 -324355 276927.4702533714 -295829.19680496032 -30322.013752343068
13 -178255 -26435.785915690412 386079.73800098576 -28015.326875332928
14 -32155 -173562.98376470321 -327340.8539868113 -37468.408479997677
15 113945 284098.82846766489 239256.46597111417 -25343.748850755001
16 260045 -385157.83176014025 -49369.527013191553 -15281.761574469898
17 406145 345160.97807879257 -214636.8383361497 3414.5771813550259
18 552245 -134108.10483846199 361980.9990905014 29968.389469456466
19 698345 -83984.239959958926 -355799.14247223095 28817.078112816904
20 844445 223226.00566205085 299354.17357796693 36909.979945451472
21 990545 -362607.45994305814 -147502.75304507115 28081.953043893249
22 1136645 383606.60880971845 -132531.90493783797 8832.002235690501
23 1282745 -216360.67463345666 321769.59784516064 -8957.0037364521304
24 1428845 7433.8731166889338 -359577.9208704764 -27286.722728085369
25 1574945 157042.40898349817 338967.54339773324 -30844.406074648126
26 1721045 -328371.10510008538 -221529.93877308263 -36739.865212875557
27 1867145 400234.08615918033 -57984.149689135251 -23513.254374541601
28 2013245 -274021.09564645251 273929.27390877635 -2133.8352285152291
29 2159345 92791.766991493409 -345234.67832922813 12342.071461675338
30 2305445 88338.286030037401 363169.93015197461 26462.650120618968
31 2451545 -291607.24183591013 -274978.62186731066 36267.30787189916
32 2597645 401391.47803711233 3266.8554273079903 31443.354743021413
33 2743745 -312245.28483573761 223268.80530781401 14449.195688692611
34 2889845 167261.68852763134 -317547.01628260425 854.67113282198795
35 3035945 22710.051466743793 377536.27831278293 -18254.778814458063
36 3182045 -258568.79979545044 -310953.08002426871 -31511.794215090176
37 3328145 391597.73715416581 50492.738155701489 -35663.250569429547
38 3474245 -336640.78667349386 169381.01759883287 -24138.799220522917
39 3620345 229894.62683911348 -283245.2596621954 -10124.478719948
40 3766445 -30725.076385326527 386554.31412064168 4630.937622600225
41 3912545 -232347.00044598628 -331529.30967142241 31692.736681196671
42 4058645 373153.27734119527 88709.654120304229 33189.966274715975
43 4204745 -352665.5780016224 110675.94346091514 29168.298060724752
44 4350845 279862.12418001605 -250761.84026383076 22491.093918623097
45 4496945 -63300.801294757643 393827.49900787073 -4549.380602734378
46 4643045 -211639.87281130059 -339806.65624159103 -18216.154066961921
47 4789145 345869.06789046078 125142.00856319141 -35847.90651925862
48 4935245 -365917.02341126435 47072.64876266574 -31135.795917215175
49 5081345 313235.01489341311 -233557.38203767358 -25005.730334995031
50 5227445 -71563.036314018507 398823.35837659024 -9633.2749911986139
51 5373545 -186164.91514019907 -338423.50248531549 24637.566759055353
+51
View File
@@ -0,0 +1,51 @@
-1931455,-263012.14372776932,297721.55430688168,-24324.987254599062
-1785355,24414.613429926769,-400822.30277713871,-44670.197726442522
-1639255,221200.37674641001,325184.92725227826,-14474.943560636351
-1493155,-319973.35559277143,-179836.67922932078,-7722.0931910639329
-1347055,362620.6275818554,20261.340424064758,4158.7475902214901
-1200955,-346245.11238489667,185898.25815803016,30163.905893696552
-1054855,171029.90424524632,-366296.60906562442,26231.502494924491
-908755,98585.018472548079,376301.83738717507,40804.120474682692
-762655,-253673.35964539216,-272828.69776402361,19905.706493336733
-616555,335481.25258198346,146459.68939852307,14858.106694331284
-470455,-383647.05975822004,66013.008896738858,-829.53397079068804
-324355,276926.62049089983,-295829.60577838111,-30320.482347503283
-178255,-26445.54739251201,386080.83489992673,-28013.881581822534
-32155,-173564.14468521808,-327344.00872558804,-37468.46077107366
113945,284090.35252503335,239265.58618684916,-25343.650846110519
260045,-385159.51631046517,-49348.816915762458,-15277.391684530896
406145,345165.46504725312,-214639.96530993938,3409.4271382105871
552245,-134100.72888107621,361985.48449367564,29978.850367708317
698345,-83982.342926013938,-355811.46501246258,28808.215852912752
844445,223235.08660139333,299351.08166803332,36915.189665281585
990545,-362602.7882248871,-147511.51703076772,28082.07356267815
1136645,383604.91929247783,-132547.95810837013,8838.4387429826493
1282745,-216364.57090490102,321764.38059364131,-8961.5757619206961
1428845,7411.8790805348717,-359585.32555476134,-27293.192427568905
1574945,157039.98810843128,338969.64958912093,-30843.917066599242
1721045,-328370.6008870838,-221528.04782516821,-36744.16639076647
1867145,400234.16277750907,-57976.122899650822,-23521.520092170747
2013245,-274016.4330496171,273934.67297238286,-2129.3720209763578
2159345,92794.113822126208,-345233.42375816189,12336.461166121979
2305445,88335.023380869083,363166.75449031434,26461.650624866372
2451545,-291608.37627978966,-274979.69324404577,36271.128877822775
2597645,401391.20135964605,3263.1459841862388,31451.825037924391
2743745,-312251.31017224718,223260.77557797215,14444.457253400202
2889845,167249.48724887962,-317556.36523747904,861.57897404768664
3035945,22695.663788870559,377539.04920572782,-18246.340165569305
3182045,-258575.29689052334,-310947.48117673211,-31511.022415741383
3328145,391596.12233842851,50493.68541584225,-35666.970403817082
3474245,-336640.9610806547,169391.52518719292,-24128.503619066782
3620345,229900.52348247898,-283241.08259236073,-10118.936107852864
3766445,-30703.555025148959,386554.4143357625,4624.3092540068592
3912545,-232340.39127966101,-331532.73305540072,31692.97586258821
4058645,373158.78561370028,88690.555206671619,33189.3675445954
4204745,-352676.95412928553,110654.5265917302,29168.430885959289
4350845,279850.74386479775,-250759.61582796593,22465.457479309545
4496945,-63304.248176228684,393828.06630098209,-4545.7108401102751
4643045,-211635.86742416851,-339798.65198398969,-18217.631416908665
4789145,345881.5840039468,125117.11976231023,-35854.923632790691
4935245,-365925.61155116902,47053.327116662622,-31140.397995070532
5081345,313238.78055125696,-233551.4275320005,-25002.984985012321
5227445,-71571.816487501972,398827.95987496921,-9638.4140099458273
5373545,-186177.32558991387,-338413.93355647428,24655.523094058852
1 -1931455 -263012.14372776932 297721.55430688168 -24324.987254599062
2 -1785355 24414.613429926769 -400822.30277713871 -44670.197726442522
3 -1639255 221200.37674641001 325184.92725227826 -14474.943560636351
4 -1493155 -319973.35559277143 -179836.67922932078 -7722.0931910639329
5 -1347055 362620.6275818554 20261.340424064758 4158.7475902214901
6 -1200955 -346245.11238489667 185898.25815803016 30163.905893696552
7 -1054855 171029.90424524632 -366296.60906562442 26231.502494924491
8 -908755 98585.018472548079 376301.83738717507 40804.120474682692
9 -762655 -253673.35964539216 -272828.69776402361 19905.706493336733
10 -616555 335481.25258198346 146459.68939852307 14858.106694331284
11 -470455 -383647.05975822004 66013.008896738858 -829.53397079068804
12 -324355 276926.62049089983 -295829.60577838111 -30320.482347503283
13 -178255 -26445.54739251201 386080.83489992673 -28013.881581822534
14 -32155 -173564.14468521808 -327344.00872558804 -37468.46077107366
15 113945 284090.35252503335 239265.58618684916 -25343.650846110519
16 260045 -385159.51631046517 -49348.816915762458 -15277.391684530896
17 406145 345165.46504725312 -214639.96530993938 3409.4271382105871
18 552245 -134100.72888107621 361985.48449367564 29978.850367708317
19 698345 -83982.342926013938 -355811.46501246258 28808.215852912752
20 844445 223235.08660139333 299351.08166803332 36915.189665281585
21 990545 -362602.7882248871 -147511.51703076772 28082.07356267815
22 1136645 383604.91929247783 -132547.95810837013 8838.4387429826493
23 1282745 -216364.57090490102 321764.38059364131 -8961.5757619206961
24 1428845 7411.8790805348717 -359585.32555476134 -27293.192427568905
25 1574945 157039.98810843128 338969.64958912093 -30843.917066599242
26 1721045 -328370.6008870838 -221528.04782516821 -36744.16639076647
27 1867145 400234.16277750907 -57976.122899650822 -23521.520092170747
28 2013245 -274016.4330496171 273934.67297238286 -2129.3720209763578
29 2159345 92794.113822126208 -345233.42375816189 12336.461166121979
30 2305445 88335.023380869083 363166.75449031434 26461.650624866372
31 2451545 -291608.37627978966 -274979.69324404577 36271.128877822775
32 2597645 401391.20135964605 3263.1459841862388 31451.825037924391
33 2743745 -312251.31017224718 223260.77557797215 14444.457253400202
34 2889845 167249.48724887962 -317556.36523747904 861.57897404768664
35 3035945 22695.663788870559 377539.04920572782 -18246.340165569305
36 3182045 -258575.29689052334 -310947.48117673211 -31511.022415741383
37 3328145 391596.12233842851 50493.68541584225 -35666.970403817082
38 3474245 -336640.9610806547 169391.52518719292 -24128.503619066782
39 3620345 229900.52348247898 -283241.08259236073 -10118.936107852864
40 3766445 -30703.555025148959 386554.4143357625 4624.3092540068592
41 3912545 -232340.39127966101 -331532.73305540072 31692.97586258821
42 4058645 373158.78561370028 88690.555206671619 33189.3675445954
43 4204745 -352676.95412928553 110654.5265917302 29168.430885959289
44 4350845 279850.74386479775 -250759.61582796593 22465.457479309545
45 4496945 -63304.248176228684 393828.06630098209 -4545.7108401102751
46 4643045 -211635.86742416851 -339798.65198398969 -18217.631416908665
47 4789145 345881.5840039468 125117.11976231023 -35854.923632790691
48 4935245 -365925.61155116902 47053.327116662622 -31140.397995070532
49 5081345 313238.78055125696 -233551.4275320005 -25002.984985012321
50 5227445 -71571.816487501972 398827.95987496921 -9638.4140099458273
51 5373545 -186177.32558991387 -338413.93355647428 24655.523094058852