算法实现

1. 初始化数据结构

1
2
QVector<double> weights;
QVector<double> weightedValues;
  • weights:用于存储每个输入点的权重。
  • weightedValues:用于存储每个输入点属性值与其权重的乘积。

2. 计算每个输入点到查询点的距离和权重

1
2
3
for (int i = 0; i < inputPoints.size(); i++) {
double distance = std::sqrt(std::pow(queryPoint.x() - inputPoints[i].x(), 2) +
std::pow(queryPoint.y() - inputPoints[i].y(), 2));
  • 遍历 inputPoints(输入点)集合。
  • 对于每一个输入点 inputPoints[i],计算它到查询点 queryPoint 的欧几里得距离。

3. 特殊情况处理

1
2
3
if (distance == 0) {
return inputAttributes[i]; // 如果查询点与某点重合,则直接返回该点的属性值
}
  • 如果查询点与当前输入点重合(即距离为0),直接返回该输入点的属性值 inputAttributes[i],因为插值结果就是此点的值。

4. 计算权重

1
2
3
double weight = 1.0 / distance;  // 计算权重
weights.append(weight);
weightedValues.append(weight * inputAttributes[i]);
  • 根据距离计算权重,权重与距离的倒数成正比。距离越小,权重越大,反之亦然。
  • 将计算得到的权重及其对应的加权属性值(即 weight * inputAttributes[i])添加到 weights 和 weightedValues 向量中。

5. 排序以选择最近的邻居

1
2
3
4
5
QVector<int> indices(inputPoints.size());
std::iota(indices.begin(), indices.end(), 0); // 填充 indices 为 0, 1, 2, ...
std::sort(indices.begin(), indices.end(), [&](int a, int b) {
return weights[a] > weights[b]; // 根据权重进行排序
});
  • 创建一个向量 indices,用于存储输入点的索引。
  • 使用 std::iota 函数填充 indices,使其包含从 0 到 inputPoints.size()-1 的整数。
  • 按照权重对这些索引进行排序,权重较大的点会排在前面,以便后续选择。

6. 计算插值的分子和分母

1
2
3
4
5
6
7
8
double numerator = 0.0;
double denominator = 0.0;

for (int i = 0; i < requiredNeighbors; i++) {
int index = indices[i];
numerator += weightedValues[index];
denominator += weights[index];
}
  • 初始化 numerator 和 denominator 为 0,用于存储插值公式中的分子和分母。
  • 迭代选择 requiredNeighbors 个权重最高的点:
    • 从 indices 中获取当前点的索引 index
    • 将对应的加权值加到分子 numerator 中。
    • 将对应的权重加到分母 denominator 中。

7. 返回插值结果

1
return numerator / denominator;  // 返回插值结果
  • 使用之前计算的分子和分母计算最终的插值结果,并返回该值。

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
double interpolate(const QPointF& queryPoint) {
QVector<double> weights;
QVector<double> weightedValues;

// 计算每个点到 queryPoint 的距离并求权重
for (int i = 0; i < inputPoints.size(); i++) {
double distance = std::sqrt(std::pow(queryPoint.x() - inputPoints[i].x(), 2) +
std::pow(queryPoint.y() - inputPoints[i].y(), 2));
if (distance == 0) {
return inputAttributes[i]; // 如果查询点与某点重合,则直接返回该点的属性值
}
double weight = 1.0 / distance; // 计算权重
weights.append(weight);
weightedValues.append(weight * inputAttributes[i]);
}

// 选择最近的 requiredNeighbors 个点进行插值
QVector<int> indices(inputPoints.size());
std::iota(indices.begin(), indices.end(), 0); // 填充 indices 为 0, 1, 2, ...
std::sort(indices.begin(), indices.end(), [&](int a, int b) {
return weights[a] > weights[b]; // 根据权重进行排序
});

double numerator = 0.0;
double denominator = 0.0;

for (int i = 0; i < requiredNeighbors; i++) {
int index = indices[i];
numerator += weightedValues[index];
denominator += weights[index];
}

return numerator / denominator; // 返回插值结果
}