Skip to content

Commit 506972a

Browse files
Merge pull request #90 from open-meteo/3-point-interpolation
fix: allow 3 point interpolation
2 parents e77c41e + 66df1ad commit 506972a

File tree

1 file changed

+59
-11
lines changed

1 file changed

+59
-11
lines changed

src/grids/interpolations.ts

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,70 @@ export const interpolateLinear = (
1111
yFraction: number,
1212
nx: number
1313
): number => {
14+
// Right border
15+
// Note: For global grids, data could be allowed to wrap
16+
if ((index + 1) % nx === 0) {
17+
return NaN;
18+
}
19+
20+
// Bottom border
21+
if (index + nx > values.length) {
22+
return NaN;
23+
}
24+
1425
const p0 = Number(values[index]);
15-
let p1 = Number(values[index + 1]);
26+
const p1 = Number(values[index + 1]);
1627
const p2 = Number(values[index + nx]);
17-
let p3 = Number(values[index + 1 + nx]);
28+
const p3 = Number(values[index + 1 + nx]);
1829

19-
if ((index + 1) % nx == 0) {
20-
p1 = p0;
21-
p3 = p0;
30+
const w0 = (1 - xFraction) * (1 - yFraction);
31+
const w1 = xFraction * (1 - yFraction);
32+
const w2 = (1 - xFraction) * yFraction;
33+
const w3 = xFraction * yFraction;
34+
35+
const n0 = Number.isNaN(p0);
36+
const n1 = Number.isNaN(p1);
37+
const n2 = Number.isNaN(p2);
38+
const n3 = Number.isNaN(p3);
39+
40+
// If none are NaN → normal bilinear interpolation
41+
if (!n0 && !n1 && !n2 && !n3) {
42+
return p0 * w0 + p1 * w1 + p2 * w2 + p3 * w3;
2243
}
2344

24-
return (
25-
p0 * (1 - xFraction) * (1 - yFraction) +
26-
p1 * xFraction * (1 - yFraction) +
27-
p2 * (1 - xFraction) * yFraction +
28-
p3 * xFraction * yFraction
29-
);
45+
// --- EXACTLY ONE POINT MISSING CASES ---
46+
// ------------------
47+
// p0 is missing → valid triangle = (p1, p2, p3)
48+
// ------------------
49+
if (n0 && !n1 && !n2 && !n3) {
50+
if (xFraction + yFraction < 1) return NaN; // Not in triangle
51+
const ws = w1 + w2 + w3;
52+
return (p1 * w1 + p2 * w2 + p3 * w3) / ws;
53+
}
54+
55+
// p1 is missing → valid triangle = (p0, p2, p3)
56+
if (!n0 && n1 && !n2 && !n3) {
57+
if (1 - xFraction + yFraction < 1) return NaN; // Not in triangle
58+
const ws = w0 + w2 + w3;
59+
return (p0 * w0 + p2 * w2 + p3 * w3) / ws;
60+
}
61+
62+
// p2 is missing → valid triangle = (p0, p1, p3)
63+
if (!n0 && !n1 && n2 && !n3) {
64+
if (xFraction + 1 - yFraction < 1) return NaN; // Not in triangle
65+
const ws = w0 + w1 + w3;
66+
return (p0 * w0 + p1 * w1 + p3 * w3) / ws;
67+
}
68+
69+
// p3 is missing → valid triangle = (p0, p1, p2)
70+
if (!n0 && !n1 && !n2 && n3) {
71+
if (1 - xFraction + 1 - yFraction < 1) return NaN; // Not in triangle
72+
const ws = w0 + w1 + w2;
73+
return (p0 * w0 + p1 * w1 + p2 * w2) / ws;
74+
}
75+
76+
// More than 1 point missing → no valid triangle
77+
return NaN;
3078
};
3179

3280
// 1D Cardinal Spline for 4 values

0 commit comments

Comments
 (0)