gistools/util/interpolation/
idw.rs

1use super::{Interpolatable, get_distance};
2use crate::util::GetInterpolateValue;
3use libm::pow;
4use s2json::{GetM, GetXY, GetZ};
5
6/// # Inverse Distance Weighting Interpolation
7///
8/// ## Description
9/// Given a reference of data, interpolate a point using inverse distance weighting
10///
11/// ## Usage
12pub fn idw_interpolation<
13    M: Clone,
14    P: GetXY + GetZ,
15    R: GetM<M> + GetXY + GetZ,
16    V: Interpolatable,
17>(
18    point: &P,
19    ref_data: &[R],
20    get_value: GetInterpolateValue<R, V>,
21) -> V {
22    if ref_data.is_empty() {
23        return V::default();
24    }
25
26    let mut numerator = V::default();
27    let mut denom = V::default();
28    for ref_point in ref_data {
29        let d2 = pow(get_distance(point, ref_point), 2.);
30        let mut value = get_value(ref_point);
31        if d2 == 0. {
32            return value;
33        }
34        value /= d2;
35        numerator += value;
36        denom += 1. / d2;
37    }
38    numerator /= denom;
39
40    numerator
41}