feat: polish & windviz & deploy
This commit is contained in:
parent
81b8e763bd
commit
465ad00f7b
78 changed files with 20622 additions and 2154 deletions
|
|
@ -5,57 +5,74 @@ import (
|
|||
"testing"
|
||||
)
|
||||
|
||||
// scalarAdd / scalarLerp let us drive RK4 on a plain float64.
|
||||
func scalarAdd(y float64, k float64, dy float64) float64 { return y + k*dy }
|
||||
func scalarLerpF(a, b float64, l float64) float64 { return Lerp(a, b, l) }
|
||||
|
||||
func TestRK4ExponentialDecay(t *testing.T) {
|
||||
// dy/dt = -y → exact: y(t) = y0 * exp(-t).
|
||||
deriv := func(_ float64, y float64) float64 { return -y }
|
||||
// dAlt/dt = -Alt → exact: Alt(t) = Alt0 * exp(-t).
|
||||
f := func(_ float64, y GeoVec) GeoVec { return GeoVec{Altitude: -y.Altitude} }
|
||||
|
||||
y := 1.0
|
||||
tnow := 0.0
|
||||
dt := 0.01
|
||||
y := GeoVec{Altitude: 1}
|
||||
tnow, dt := 0.0, 0.01
|
||||
for range 100 {
|
||||
y = RK4Step(tnow, y, dt, deriv, scalarAdd)
|
||||
y = RK4Step(tnow, y, dt, f)
|
||||
tnow += dt
|
||||
}
|
||||
want := math.Exp(-1.0)
|
||||
if math.Abs(y-want) > 1e-8 {
|
||||
t.Errorf("RK4 exp decay at t=1: got %v, want %v (diff %v)", y, want, y-want)
|
||||
if math.Abs(y.Altitude-want) > 1e-8 {
|
||||
t.Errorf("RK4 exp decay at t=1: got %v, want %v", y.Altitude, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRK4ReverseTime(t *testing.T) {
|
||||
// dy/dt = y → exact: y(t) = y0 * exp(t).
|
||||
// Integrating from t=1 backwards with dt=-0.01 over 100 steps should give y0.
|
||||
deriv := func(_ float64, y float64) float64 { return y }
|
||||
// dAlt/dt = Alt → exact: Alt(t) = Alt0 * exp(t).
|
||||
f := func(_ float64, y GeoVec) GeoVec { return GeoVec{Altitude: y.Altitude} }
|
||||
|
||||
y := math.E
|
||||
tnow := 1.0
|
||||
dt := -0.01
|
||||
y := GeoVec{Altitude: math.E}
|
||||
tnow, dt := 1.0, -0.01
|
||||
for range 100 {
|
||||
y = RK4Step(tnow, y, dt, deriv, scalarAdd)
|
||||
y = RK4Step(tnow, y, dt, f)
|
||||
tnow += dt
|
||||
}
|
||||
if math.Abs(y-1.0) > 1e-8 {
|
||||
t.Errorf("RK4 reverse: got %v, want 1.0 (diff %v)", y, y-1.0)
|
||||
if math.Abs(y.Altitude-1.0) > 1e-8 {
|
||||
t.Errorf("RK4 reverse: got %v, want 1.0", y.Altitude)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRefineTrigger(t *testing.T) {
|
||||
// y crosses 0 at l=0.4 between y1=1 and y2=-1.5.
|
||||
y1, y2 := 1.0, -1.5
|
||||
t1, t2 := 0.0, 1.0
|
||||
trig := func(_ float64, y float64) bool { return y <= 0 }
|
||||
func TestRefineCrossing(t *testing.T) {
|
||||
y1 := GeoVec{Altitude: 1}
|
||||
y2 := GeoVec{Altitude: -1.5}
|
||||
crossed := func(_ float64, y GeoVec) bool { return y.Altitude <= 0 }
|
||||
|
||||
tr, yr := RefineTrigger(t1, y1, t2, y2, trig, scalarLerpF, 0.001)
|
||||
|
||||
// The exact crossing is at l = 1/(1+1.5) = 0.4 → t = 0.4, y = 0.
|
||||
tr, yr := RefineCrossing(0, y1, 1, y2, crossed, 0.001)
|
||||
if math.Abs(tr-0.4) > 0.01 {
|
||||
t.Errorf("Refined t = %v, want ~0.4", tr)
|
||||
t.Errorf("refined t = %v, want ~0.4", tr)
|
||||
}
|
||||
if math.Abs(yr) > 0.01 {
|
||||
t.Errorf("Refined y = %v, want ~0", yr)
|
||||
if math.Abs(yr.Altitude) > 0.01 {
|
||||
t.Errorf("refined alt = %v, want ~0", yr.Altitude)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGeoAddWrapsLongitude(t *testing.T) {
|
||||
y := GeoAdd(GeoVec{Lng: 350}, 1, GeoVec{Lng: 20})
|
||||
if math.Abs(y.Lng-10) > 1e-9 {
|
||||
t.Errorf("GeoAdd wrap: lng = %v, want 10", y.Lng)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGeoLerpWrap(t *testing.T) {
|
||||
mid := GeoLerp(GeoVec{Lng: 350}, GeoVec{Lng: 10}, 0.5)
|
||||
if math.Abs(mid.Lng) > 1e-9 && math.Abs(mid.Lng-360) > 1e-9 {
|
||||
t.Errorf("GeoLerp lng wrap: %v, want 0 or 360", mid.Lng)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPathSoA(t *testing.T) {
|
||||
p := NewPath(4)
|
||||
p.Append(0, GeoVec{Lat: 1, Lng: 2, Altitude: 3})
|
||||
p.Append(60, GeoVec{Lat: 4, Lng: 5, Altitude: 6})
|
||||
if p.Len() != 2 {
|
||||
t.Fatalf("len = %d, want 2", p.Len())
|
||||
}
|
||||
tt, last := p.Last()
|
||||
if tt != 60 || last.Lat != 4 {
|
||||
t.Errorf("last = %v, %+v", tt, last)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue