package grib import "math" func lerp(a, b, t float64) float64 { return a + t*(b-a) } // Interpolate 16‑point (time, p, lat, lon) func (d *dataset) uv(lat, lon, alt float64, tHours float64) (float64, float64) { if lon < 0 { lon += 360 } iy := (lat + 90) * 2 y0 := int(math.Floor(iy)) y1 := y0 + 1 wy := iy - float64(y0) ix := lon * 2 x0 := int(math.Floor(ix)) % d.cube.lon x1 := (x0 + 1) % d.cube.lon wx := ix - float64(x0) // For hourly data (step = 1 hour) it0 := int(math.Floor(tHours)) wt := tHours - float64(it0) p := pressureFromAlt(alt) ip0 := 0 for ip0+1 < len(pressureLevels) && pressureLevels[ip0+1] > p { ip0++ } ip1 := ip0 + 1 wp := (pressureLevels[ip0] - p) / (pressureLevels[ip0] - pressureLevels[ip1]) fetch := func(ti, pi int) (float64, float64) { u00 := d.cube.val(1, ti, pi, y0, x0) u10 := d.cube.val(1, ti, pi, y0, x1) u01 := d.cube.val(1, ti, pi, y1, x0) u11 := d.cube.val(1, ti, pi, y1, x1) v00 := d.cube.val(2, ti, pi, y0, x0) v10 := d.cube.val(2, ti, pi, y0, x1) v01 := d.cube.val(2, ti, pi, y1, x0) v11 := d.cube.val(2, ti, pi, y1, x1) uxy := (1-wy)*((1-wx)*float64(u00)+wx*float64(u10)) + wy*((1-wx)*float64(u01)+wx*float64(u11)) vxy := (1-wy)*((1-wx)*float64(v00)+wx*float64(v10)) + wy*((1-wx)*float64(v01)+wx*float64(v11)) return uxy, vxy } u0p0, v0p0 := fetch(it0, ip0) u0p1, v0p1 := fetch(it0, ip1) u1p0, v1p0 := fetch(it0+1, ip0) u1p1, v1p1 := fetch(it0+1, ip1) uLow := lerp(u0p0, u0p1, wp) vLow := lerp(v0p0, v0p1, wp) uHig := lerp(u1p0, u1p1, wp) vHig := lerp(v1p0, v1p1, wp) u := lerp(uLow, uHig, wt) v := lerp(vLow, vHig, wt) return u, v }