feat(decart): interp

This commit is contained in:
gili8420 2026-08-03 22:10:10 +09:00
parent 1bd9143186
commit 19557f3a62
14 changed files with 681 additions and 208 deletions

View file

@ -119,14 +119,14 @@ func TestPiecewiseRate(t *testing.T) {
{Until: math.Inf(1), Rate: 0},
})
if r := m(50, State{}); r.Altitude != 5 {
t.Errorf("rate at t=50 = %v, want 5", r.Altitude)
if r := m(50, State{}); r.Vertical != 5 {
t.Errorf("rate at t=50 = %v, want 5", r.Vertical)
}
if r := m(150, State{}); r.Altitude != 3 {
t.Errorf("rate at t=150 = %v, want 3", r.Altitude)
if r := m(150, State{}); r.Vertical != 3 {
t.Errorf("rate at t=150 = %v, want 3", r.Vertical)
}
if r := m(300, State{}); r.Altitude != 0 {
t.Errorf("rate at t=300 = %v, want 0", r.Altitude)
if r := m(300, State{}); r.Vertical != 0 {
t.Errorf("rate at t=300 = %v, want 0", r.Vertical)
}
}
@ -149,11 +149,11 @@ func TestPiecewiseReferenceResolution(t *testing.T) {
ctx := StageContext{ProfileStart: 1000, PropagatorStart: 5000}
m := built.Build(ctx)
// Until=100 from propagator_start=5000 → absolute 5100.
if r := m(5050, State{}); r.Altitude != 5 {
t.Errorf("rate at t=5050 = %v, want 5", r.Altitude)
if r := m(5050, State{}); r.Vertical != 5 {
t.Errorf("rate at t=5050 = %v, want 5", r.Vertical)
}
if r := m(5150, State{}); r.Altitude != 3 {
t.Errorf("rate at t=5150 = %v, want 3", r.Altitude)
if r := m(5150, State{}); r.Vertical != 3 {
t.Errorf("rate at t=5150 = %v, want 3", r.Vertical)
}
}
@ -166,22 +166,20 @@ func (w fixedWind) Wind(_ float64, _, _, _ float64) (weather.Sample, error) {
func (fixedWind) Epoch() time.Time { return time.Unix(0, 0) }
func (fixedWind) Source() string { return "test-fixed" }
func TestWindTransportUnitConversion(t *testing.T) {
wind := WindTransport(fixedWind{u: 10, v: 0}, nil)
d := wind(0, State{Lat: 0, Lng: 0, Altitude: 0})
wantLng := (180.0 / math.Pi) * 10.0 / 6371009.0
if math.Abs(d.Lng-wantLng) > 1e-12 {
t.Errorf("dlng = %v, want %v", d.Lng, wantLng)
}
if math.Abs(d.Lat) > 1e-12 {
t.Errorf("dlat = %v, want 0 for u=10 v=0", d.Lat)
}
func TestWindTransportPassesWindThroughUnchanged(t *testing.T) {
// The wind field already gives a horizontal velocity, so the propagator
// receives it verbatim. This replaces a test of the old deg/s conversion,
// whose 1/cos(lat) factor is exactly what made the poles unusable.
wind := WindTransport(fixedWind{u: 10, v: -4}, nil)
wind2 := WindTransport(fixedWind{u: 0, v: 5}, nil)
d = wind2(0, State{Lat: 60, Lng: 0, Altitude: 0})
wantLat := (180.0 / math.Pi) * 5.0 / 6371009.0
if math.Abs(d.Lat-wantLat) > 1e-12 {
t.Errorf("dlat at lat=60 = %v, want %v", d.Lat, wantLat)
for _, lat := range []float64{0, 45, 60, 89, 89.999} {
r := wind(0, State{Lat: lat, Lng: 0, Altitude: 0})
if r.East != 10 || r.North != -4 {
t.Errorf("lat %g: rate = %+v, want East=10 North=-4", lat, r)
}
if r.Vertical != 0 {
t.Errorf("lat %g: wind must not produce vertical motion, got %v", lat, r.Vertical)
}
}
}