C/C++ · 2025年3月13日 0

计算一个区域中的Z点高度

关键要点
一般情况下,离散点不共面,中间补充点的 z 值可以通过最佳拟合平面计算,简单且合理。
使用最小二乘法找到 z = ax + by + c 的系数 a, b, c,基于点的 x, y 坐标计算 z 值。

计算 z 值的步骤
找到最佳拟合平面
收集多边形顶点的坐标 (x_i, y_i, z_i),用最小二乘法求解 z = ax + by + c。
公式为:最小化 ∑(z_i – ax_i – by_i – c)^2,解线性方程组得到 a, b, c。

计算 z 值
对于多边形内的点 (x, y),用 z = ax + by + c 计算 z 值。

以下是计算 z 值的具体方法,采用 C++ 实现:

1. 找到最佳拟合平面
假设有 n 个点 (x_i, y_i, z_i),目标是找到平面 z = ax + by + c,最小化误差 ∑(z_i – ax_i – by_i – c)^2。
这是一个线性最小二乘问题,解法如下:
建立方程组:
a∑x_i^2 + b∑x_iy_i + c∑x_i = ∑x_iz_i
a∑x_iy_i + b∑y_i^2 + c∑y_i = ∑y_iz_i
a∑x_i + b∑y_i + c*n = ∑z_i
用线性代数库如 Eigen 求解,代码示例:
cpp

#include <iostream>
#include <vector>
#include <Eigen/Dense>

// Function to solve for the best-fit plane coefficients a, b, c
std::tuple<double, double, double> bestFitPlane(const std::vector<std::tuple<double, double, double>>& points) {
    int n = points.size();
    Eigen::MatrixXd A(n, 3);
    Eigen::VectorXd B(n);

    for (int i = 0; i < n; ++i) {
        double x, y, z;
        std::tie(x, y, z) = points[i];
        A(i, 0) = x;
        A(i, 1) = y;
        A(i, 2) = 1;
        B(i) = z;
    }

    Eigen::VectorXd coefficients = A.colPivHouseholderQr().solve(B);
    double a = coefficients(0);
    double b = coefficients(1);
    double c = coefficients(2);

    return std::make_tuple(a, b, c);
}

int main() {
    std::vector<std::tuple<double, double, double>> points = {
        {0, 0, 0},
        {1, 0, 1},
        {1, 1, 2},
        {0, 1, 1}
    };

    double a, b, c;
    std::tie(a, b, c) = bestFitPlane(points);
    std::cout << "Plane equation: z = " << a << "x + " << b << "y + " << c << std::endl;
    return 0;
}

这样得到 a, b, c,平面方程为 z = ax + by + c。

2.确定点是否在多边形内(这步已经获得,考虑可以省略)

3.计算 z 值

对于多边形内的点 (x, y),用 z = ax + by + c 计算 z 值。
代码示例:
cpp
double calculateZValue(double x, double y, double a, double b, double c) {
return a * x + b * y + c;
}

4.中间补充点的 z 值

    这种方法简单,适合交通设计中地形。