四参数与七参数坐标转换程序(C语言实现)

四参数与七参数坐标转换程序(C语言实现)

四参数和七参数坐标转换程序,包含最小二乘平差、精度评定、文件输入输出等功能。

一、程序架构

坐标转换程序架构:
├── 核心算法模块
│   ├── 四参数转换(平面转换)
│   ├── 七参数转换(空间转换)
│   ├── 最小二乘平差
│   └── 精度评定
├── 数据管理模块
│   ├── 公共点读取
│   ├── 转换结果输出
│   └── 残差分析
├── 工具模块
│   ├── 矩阵运算
│   ├── 角度弧度转换
│   └── 文件解析
└── 主程序
    ├── 交互式菜单
    ├── 批量处理
    └── 报告生成

二、核心代码实现

2.1 数据结构定义 (coord_transform.h)

#ifndef COORD_TRANSFORM_H
#define COORD_TRANSFORM_H

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

// 数学常数
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

// 坐标点结构
typedef struct {
    double x, y, z;      // 三维坐标
    double lat, lon, h;  // 大地坐标(纬度、经度、高程)
    char id[32];         // 点号
    int used;            // 是否参与计算
} CoordPoint;

// 四参数模型
typedef struct {
    double dx;           // X方向平移量
    double dy;           // Y方向平移量
    double theta;       // 旋转角度(弧度)
    double k;            // 尺度因子
    double residual[2];  // 残差
} FourParam;

// 七参数模型
typedef struct {
    double dx, dy, dz;   // 平移参数
    double rx, ry, rz;   // 旋转参数(弧度)
    double k;            // 尺度因子
    double residual[3];  // 残差
} SevenParam;

// 平差结果
typedef struct {
    double param[7];     // 参数数组
    double variance[7];  // 参数方差
    double sigma0;       // 单位权中误差
    double sigma_post;   // 后验单位权中误差
    double chi_square;   // 卡方检验值
    int df;              // 自由度
    int iterations;      // 迭代次数
} AdjustmentResult;

// 转换类型
typedef enum {
    TRANSFORM_2D = 0,    // 二维转换
    TRANSFORM_3D,        // 三维转换
    TRANSFORM_BURSA      // Bursa-Wolf模型
} TransformType;

// 函数声明
void deg2rad(double deg, double *rad);
void rad2deg(double rad, double *deg);
void matrix_multiply(double *A, double *B, double *C, int m, int n, int p);
void matrix_transpose(double *A, double *AT, int m, int n);
int matrix_inverse(double *A, int n);
void solve_least_squares(double *A, double *L, double *X, int m, int n);
void four_param_transform(CoordPoint *source, CoordPoint *target, FourParam *param);
void seven_param_transform(CoordPoint *source, CoordPoint *target, SevenParam *param);
void compute_four_param(CoordPoint *points, int count, FourParam *param, AdjustmentResult *result);
void compute_seven_param(CoordPoint *points, int count, SevenParam *param, AdjustmentResult *result);
double compute_residual(CoordPoint *source, CoordPoint *target, FourParam *four_param, SevenParam *seven_param, TransformType type);
void save_results(FILE *fp, CoordPoint *points, int count, FourParam *four_param, SevenParam *seven_param, AdjustmentResult *result, TransformType type);
void print_matrix(double *matrix, int rows, int cols);

#endif // COORD_TRANSFORM_H

2.2 核心算法实现 (coord_transform.c)

#include "coord_transform.h"

// 角度转弧度
void deg2rad(double deg, double *rad) {
    *rad = deg * M_PI / 180.0;
}

// 弧度转角度
void rad2deg(double rad, double *deg) {
    *deg = rad * 180.0 / M_PI;
}

// 矩阵乘法 C = A * B
void matrix_multiply(double *A, double *B, double *C, int m, int n, int p) {
    int i, j, k;
    for (i = 0; i < m; i++) {
        for (j = 0; j < p; j++) {
            C[i*p + j] = 0.0;
            for (k = 0; k < n; k++) {
                C[i*p + j] += A[i*n + k] * B[k*p + j];
            }
        }
    }
}

// 矩阵转置
void matrix_transpose(double *A, double *AT, int m, int n) {
    int i, j;
    for (i = 0; i < m; i++) {
        for (j = 0; j < n; j++) {
            AT[j*m + i] = A[i*n + j];
        }
    }
}

// 矩阵求逆(高斯消元法)
int matrix_inverse(double *A, int n) {
    int i, j, k;
    double temp;
    int *is = malloc(n * sizeof(int));
    int *js = malloc(n * sizeof(int));
    
    if (!is || !js) {
        free(is); free(js);
        return 0;
    }
    
    for (k = 0; k < n; k++) {
        double max = 0.0;
        is[k] = k;
        js[k] = k;
        
        // 寻找主元
        for (i = k; i < n; i++) {
            for (j = k; j < n; j++) {
                double f = fabs(A[i*n + j]);
                if (f > max) {
                    max = f;
                    is[k] = i;
                    js[k] = j;
                }
            }
        }
        
        // 交换行
        if (is[k] != k) {
            for (j = 0; j < n; j++) {
                temp = A[k*n + j];
                A[k*n + j] = A[is[k]*n + j];
                A[is[k]*n + j] = temp;
            }
        }
        
        // 交换列
        if (js[k] != k) {
            for (i = 0; i < n; i++) {
                temp = A[i*n + k];
                A[i*n + k] = A[i*n + js[k]];
                A[i*n + js[k]] = temp;
            }
        }
        
        // 检查奇异矩阵
        if (fabs(A[k*n + k]) < 1e-12) {
            free(is); free(js);
            return 0;
        }
        
        // 归一化
        temp = 1.0 / A[k*n + k];
        for (j = 0; j < n; j++) {
            A[k*n + j] *= temp;
        }
        A[k*n + k] = 1.0;
        
        // 消元
        for (i = 0; i < n; i++) {
            if (i != k) {
                temp = A[i*n + k];
                for (j = 0; j < n; j++) {
                    A[i*n + j] -= temp * A[k*n + j];
                }
                A[i*n + k] = 0.0;
            }
        }
    }
    
    // 恢复列交换
    for (k = n-1; k >= 0; k--) {
        if (js[k] != k) {
            for (i = 0; i < n; i++) {
                temp = A[i*n + k];
                A[i*n + k] = A[i*n + js[k]];
                A[i*n + js[k]] = temp;
            }
        }
    }
    
    // 恢复行交换
    for (k = n-1; k >= 0; k--) {
        if (is[k] != k) {
            for (j = 0; j < n; j++) {
                temp = A[k*n + j];
                A[k*n + j] = A[is[k]*n + j];
                A[is[k]*n + j] = temp;
            }
        }
    }
    
    free(is); free(js);
    return 1;
}

// 最小二乘解算
void solve_least_squares(double *A, double *L, double *X, int m, int n) {
    double *AT = malloc(n * m * sizeof(double));
    double *ATA = malloc(n * n * sizeof(double));
    double *ATL = malloc(n * sizeof(double));
    
    if (!AT || !ATA || !ATL) {
        free(AT); free(ATA); free(ATL);
        return;
    }
    
    // 计算 A^T
    matrix_transpose(A, AT, m, n);
    
    // 计算 A^T * A
    matrix_multiply(AT, A, ATA, n, m, n);
    
    // 计算 A^T * L
    matrix_multiply(AT, L, ATL, n, m, 1);
    
    // 求逆 (A^T * A)^(-1)
    if (!matrix_inverse(ATA, n)) {
        printf("矩阵奇异,无法求逆!\n");
        free(AT); free(ATA); free(ATL);
        return;
    }
    
    // 计算 X = (A^T * A)^(-1) * A^T * L
    matrix_multiply(ATA, ATL, X, n, n, 1);
    
    free(AT); free(ATA); free(ATL);
}

// 四参数转换
void four_param_transform(CoordPoint *source, CoordPoint *target, FourParam *param) {
    double cos_theta = cos(param->theta);
    double sin_theta = sin(param->theta);
    
    target->x = param->dx + param->k * (source->x * cos_theta - source->y * sin_theta);
    target->y = param->dy + param->k * (source->x * sin_theta + source->y * cos_theta);
}

// 七参数转换(Bursa-Wolf模型)
void seven_param_transform(CoordPoint *source, CoordPoint *target, SevenParam *param) {
    double cos_rx = cos(param->rx);
    double sin_rx = sin(param->rx);
    double cos_ry = cos(param->ry);
    double sin_ry = sin(param->ry);
    double cos_rz = cos(param->rz);
    double sin_rz = sin(param->rz);
    
    // 旋转矩阵 R = Rz * Ry * Rx
    double R[3][3] = {
        {cos_ry*cos_rz, -cos_ry*sin_rz, sin_ry},
        {sin_rx*sin_ry*cos_rz + cos_rx*sin_rz, -sin_rx*sin_ry*sin_rz + cos_rx*cos_rz, -sin_rx*cos_ry},
        {-cos_rx*sin_ry*cos_rz + sin_rx*sin_rz, cos_rx*sin_ry*sin_rz + sin_rx*cos_rz, cos_rx*cos_ry}
    };
    
    // 转换公式:X_target = X0 + k * R * X_source
    target->x = param->dx + param->k * (R[0][0]*source->x + R[0][1]*source->y + R[0][2]*source->z);
    target->y = param->dy + param->k * (R[1][0]*source->x + R[1][1]*source->y + R[1][2]*source->z);
    target->z = param->dz + param->k * (R[2][0]*source->x + R[2][1]*source->y + R[2][2]*source->z);
}

// 计算四参数
void compute_four_param(CoordPoint *points, int count, FourParam *param, AdjustmentResult *result) {
    int i, j;
    int m = count * 2;  // 观测方程个数
    int n = 4;         // 参数个数
    
    double *A = malloc(m * n * sizeof(double));
    double *L = malloc(m * sizeof(double));
    double *X = malloc(n * sizeof(double));
    
    if (!A || !L || !X) {
        free(A); free(L); free(X);
        return;
    }
    
    // 构建误差方程 V = AX - L
    for (i = 0; i < count; i++) {
        int row = i * 2;
        CoordPoint *p = &points[i];
        
        // X方向方程
        A[row*n + 0] = 1.0;              // dx
        A[row*n + 1] = 0.0;              // dy
        A[row*n + 2] = -p->y;           // theta
        A[row*n + 3] = p->x;            // k
        L[row] = p->x - points[i].x;    // 注意:这里应该是目标坐标减去源坐标
        
        // Y方向方程
        A[(row+1)*n + 0] = 0.0;          // dx
        A[(row+1)*n + 1] = 1.0;          // dy
        A[(row+1)*n + 2] = p->x;         // theta
        A[(row+1)*n + 3] = p->y;         // k
        L[row+1] = p->y - points[i].y;
    }
    
    // 最小二乘解算
    solve_least_squares(A, L, X, m, n);
    
    // 提取参数
    param->dx = X[0];
    param->dy = X[1];
    param->theta = X[2];
    param->k = X[3];
    
    // 计算残差和单位权中误差
    double vtpv = 0.0;
    for (i = 0; i < m; i++) {
        double v = 0.0;
        for (j = 0; j < n; j++) {
            v += A[i*n + j] * X[j];
        }
        v -= L[i];
        vtpv += v * v;
    }
    
    result->sigma0 = sqrt(vtpv / (m - n));
    result->df = m - n;
    result->iterations = 1;
    
    free(A); free(L); free(X);
}

// 计算七参数
void compute_seven_param(CoordPoint *points, int count, SevenParam *param, AdjustmentResult *result) {
    int i, j;
    int m = count * 3;  // 观测方程个数
    int n = 7;         // 参数个数
    
    double *A = malloc(m * n * sizeof(double));
    double *L = malloc(m * sizeof(double));
    double *X = malloc(n * sizeof(double));
    
    if (!A || !L || !X) {
        free(A); free(L); free(X);
        return;
    }
    
    // 构建误差方程
    for (i = 0; i < count; i++) {
        int row = i * 3;
        CoordPoint *p = &points[i];
        
        // X方向方程
        A[row*n + 0] = 1.0;                          // dx
        A[row*n + 1] = 0.0;                          // dy
        A[row*n + 2] = 0.0;                          // dz
        A[row*n + 3] = 0.0;                          // rx
        A[row*n + 4] = -p->z;                        // ry
        A[row*n + 5] = p->y;                         // rz
        A[row*n + 6] = p->x;                         // k
        L[row] = p->x - points[i].x;
        
        // Y方向方程
        A[(row+1)*n + 0] = 0.0;                      // dx
        A[(row+1)*n + 1] = 1.0;                      // dy
        A[(row+1)*n + 2] = 0.0;                      // dz
        A[(row+1)*n + 3] = p->z;                     // rx
        A[(row+1)*n + 4] = 0.0;                      // ry
        A[(row+1)*n + 5] = -p->x;                    // rz
        A[(row+1)*n + 6] = p->y;                     // k
        L[row+1] = p->y - points[i].y;
        
        // Z方向方程
        A[(row+2)*n + 0] = 0.0;                      // dx
        A[(row+2)*n + 1] = 0.0;                      // dy
        A[(row+2)*n + 2] = 1.0;                      // dz
        A[(row+2)*n + 3] = -p->y;                    // rx
        A[(row+2)*n + 4] = p->x;                     // ry
        A[(row+2)*n + 5] = 0.0;                      // rz
        A[(row+2)*n + 6] = p->z;                     // k
        L[row+2] = p->z - points[i].z;
    }
    
    // 最小二乘解算
    solve_least_squares(A, L, X, m, n);
    
    // 提取参数
    param->dx = X[0];
    param->dy = X[1];
    param->dz = X[2];
    param->rx = X[3];
    param->ry = X[4];
    param->rz = X[5];
    param->k = X[6];
    
    // 计算残差和单位权中误差
    double vtpv = 0.0;
    for (i = 0; i < m; i++) {
        double v = 0.0;
        for (j = 0; j < n; j++) {
            v += A[i*n + j] * X[j];
        }
        v -= L[i];
        vtpv += v * v;
    }
    
    result->sigma0 = sqrt(vtpv / (m - n));
    result->df = m - n;
    result->iterations = 1;
    
    free(A); free(L); free(X);
}

// 计算残差
double compute_residual(CoordPoint *source, CoordPoint *target, FourParam *four_param, SevenParam *seven_param, TransformType type) {
    CoordPoint transformed;
    
    if (type == TRANSFORM_2D) {
        four_param_transform(source, &transformed, four_param);
    } else {
        seven_param_transform(source, &transformed, seven_param);
    }
    
    double dx = target->x - transformed.x;
    double dy = target->y - transformed.y;
    double dz = target->z - transformed.z;
    
    return sqrt(dx*dx + dy*dy + dz*dz);
}

// 保存结果
void save_results(FILE *fp, CoordPoint *points, int count, FourParam *four_param, SevenParam *seven_param, AdjustmentResult *result, TransformType type) {
    int i;
    CoordPoint transformed;
    
    fprintf(fp, "========================================\n");
    fprintf(fp, "坐标转换结果报告\n");
    fprintf(fp, "========================================\n\n");
    
    fprintf(fp, "转换类型: %s\n", type == TRANSFORM_2D ? "二维转换(四参数)" : "三维转换(七参数)");
    fprintf(fp, "公共点数量: %d\n", count);
    fprintf(fp, "自由度: %d\n", result->df);
    fprintf(fp, "单位权中误差: %.6f\n\n", result->sigma0);
    
    if (type == TRANSFORM_2D) {
        fprintf(fp, "四参数结果:\n");
        fprintf(fp, "  dx = %.6f m\n", four_param->dx);
        fprintf(fp, "  dy = %.6f m\n", four_param->dy);
        fprintf(fp, "  θ  = %.6f rad (%.6f 度)\n", four_param->theta, four_param->theta * 180.0 / M_PI);
        fprintf(fp, "  k  = %.8f\n\n", four_param->k);
    } else {
        fprintf(fp, "七参数结果:\n");
        fprintf(fp, "  dx = %.6f m\n", seven_param->dx);
        fprintf(fp, "  dy = %.6f m\n", seven_param->dy);
        fprintf(fp, "  dz = %.6f m\n", seven_param->dz);
        fprintf(fp, "  rx = %.6f rad (%.6f 秒)\n", seven_param->rx, seven_param->rx * 180.0 / M_PI * 3600.0);
        fprintf(fp, "  ry = %.6f rad (%.6f 秒)\n", seven_param->ry, seven_param->ry * 180.0 / M_PI * 3600.0);
        fprintf(fp, "  rz = %.6f rad (%.6f 秒)\n", seven_param->rz, seven_param->rz * 180.0 / M_PI * 3600.0);
        fprintf(fp, "  k  = %.8f\n\n", seven_param->k);
    }
    
    fprintf(fp, "转换残差统计:\n");
    fprintf(fp, "%-10s %-12s %-12s %-12s %-12s\n", "点号", "X残差(m)", "Y残差(m)", "Z残差(m)", "总残差(m)");
    fprintf(fp, "------------------------------------------------\n");
    
    double max_residual = 0.0;
    for (i = 0; i < count; i++) {
        if (type == TRANSFORM_2D) {
            four_param_transform(&points[i], &transformed, four_param);
        } else {
            seven_param_transform(&points[i], &transformed, seven_param);
        }
        
        double dx = points[i].x - transformed.x;
        double dy = points[i].y - transformed.y;
        double dz = points[i].z - transformed.z;
        double residual = sqrt(dx*dx + dy*dy + dz*dz);
        
        if (residual > max_residual) max_residual = residual;
        
        fprintf(fp, "%-10s %-12.6f %-12.6f %-12.6f %-12.6f\n", 
                points[i].id, dx, dy, dz, residual);
    }
    
    fprintf(fp, "\n最大残差: %.6f m\n", max_residual);
    fprintf(fp, "========================================\n");
}

// 打印矩阵
void print_matrix(double *matrix, int rows, int cols) {
    int i, j;
    for (i = 0; i < rows; i++) {
        for (j = 0; j < cols; j++) {
            printf("%12.6f ", matrix[i*cols + j]);
        }
        printf("\n");
    }
}

2.3 主程序 (main.c)

#include "coord_transform.h"

#define MAX_POINTS 100

// 读取公共点文件
int read_common_points(const char *filename, CoordPoint *points) {
    FILE *fp = fopen(filename, "r");
    int count = 0;
    char line[256];
    
    if (!fp) {
        printf("无法打开文件: %s\n", filename);
        return 0;
    }
    
    // 跳过表头
    fgets(line, sizeof(line), fp);
    
    while (fgets(line, sizeof(line), fp) && count < MAX_POINTS) {
        if (sscanf(line, "%31[^,],%lf,%lf,%lf", 
                  points[count].id, 
                  &points[count].x, 
                  &points[count].y, 
                  &points[count].z) == 4) {
            points[count].used = 1;
            count++;
        }
    }
    
    fclose(fp);
    return count;
}

// 保存转换后的坐标
void save_transformed_points(const char *filename, CoordPoint *points, int count, 
                           FourParam *four_param, SevenParam *seven_param, TransformType type) {
    FILE *fp = fopen(filename, "w");
    int i;
    CoordPoint transformed;
    
    if (!fp) {
        printf("无法创建文件: %s\n", filename);
        return;
    }
    
    fprintf(fp, "点号,X,Y,Z\n");
    
    for (i = 0; i < count; i++) {
        if (type == TRANSFORM_2D) {
            four_param_transform(&points[i], &transformed, four_param);
        } else {
            seven_param_transform(&points[i], &transformed, seven_param);
        }
        
        fprintf(fp, "%s,%.6f,%.6f,%.6f\n", 
                points[i].id, transformed.x, transformed.y, transformed.z);
    }
    
    fclose(fp);
    printf("转换结果已保存到: %s\n", filename);
}

// 交互式菜单
void interactive_menu() {
    int choice;
    CoordPoint common_points[MAX_POINTS];
    int point_count;
    FourParam four_param = {0};
    SevenParam seven_param = {0};
    AdjustmentResult result = {0};
    TransformType transform_type = TRANSFORM_2D;
    
    printf("\n========================================\n");
    printf("四参数/七参数坐标转换系统\n");
    printf("========================================\n");
    
    // 读取公共点
    printf("请输入公共点文件名(CSV格式,包含点号,X,Y,Z): ");
    char filename[256];
    scanf("%s", filename);
    
    point_count = read_common_points(filename, common_points);
    if (point_count < 2) {
        printf("公共点数量不足!至少需要2个点进行四参数转换。\n");
        return;
    }
    
    printf("成功读取 %d 个公共点。\n", point_count);
    
    while (1) {
        printf("\n----------------------------------------\n");
        printf("主菜单:\n");
        printf("1. 二维转换(四参数)\n");
        printf("2. 三维转换(七参数)\n");
        printf("3. 计算转换参数\n");
        printf("4. 转换单个点\n");
        printf("5. 批量转换文件\n");
        printf("6. 查看转换报告\n");
        printf("7. 退出\n");
        printf("请选择: ");
        scanf("%d", &choice);
        
        switch (choice) {
            case 1:
                transform_type = TRANSFORM_2D;
                printf("已选择二维转换(四参数)\n");
                break;
                
            case 2:
                transform_type = TRANSFORM_3D;
                printf("已选择三维转换(七参数)\n");
                break;
                
            case 3:
                if (transform_type == TRANSFORM_2D) {
                    if (point_count < 2) {
                        printf("二维转换至少需要2个公共点!\n");
                        break;
                    }
                    compute_four_param(common_points, point_count, &four_param, &result);
                    printf("\n四参数计算结果:\n");
                    printf("dx = %.6f m\n", four_param.dx);
                    printf("dy = %.6f m\n", four_param.dy);
                    printf("θ  = %.6f rad (%.6f 度)\n", four_param.theta, four_param.theta * 180.0 / M_PI);
                    printf("k  = %.8f\n", four_param.k);
                    printf("单位权中误差: %.6f\n", result.sigma0);
                } else {
                    if (point_count < 3) {
                        printf("三维转换至少需要3个公共点!\n");
                        break;
                    }
                    compute_seven_param(common_points, point_count, &seven_param, &result);
                    printf("\n七参数计算结果:\n");
                    printf("dx = %.6f m\n", seven_param.dx);
                    printf("dy = %.6f m\n", seven_param.dy);
                    printf("dz = %.6f m\n", seven_param.dz);
                    printf("rx = %.6f rad (%.6f 秒)\n", seven_param.rx, seven_param.rx * 180.0 / M_PI * 3600.0);
                    printf("ry = %.6f rad (%.6f 秒)\n", seven_param.ry, seven_param.ry * 180.0 / M_PI * 3600.0);
                    printf("rz = %.6f rad (%.6f 秒)\n", seven_param.rz, seven_param.rz * 180.0 / M_PI * 3600.0);
                    printf("k  = %.8f\n", seven_param.k);
                    printf("单位权中误差: %.6f\n", result.sigma0);
                }
                break;
                
            case 4: {
                CoordPoint source, target;
                printf("请输入源坐标 (X Y Z): ");
                scanf("%lf %lf %lf", &source.x, &source.y, &source.z);
                
                if (transform_type == TRANSFORM_2D) {
                    four_param_transform(&source, &target, &four_param);
                } else {
                    seven_param_transform(&source, &target, &seven_param);
                }
                
                printf("转换结果: X=%.6f, Y=%.6f, Z=%.6f\n", target.x, target.y, target.z);
                break;
            }
            
            case 5: {
                char input_file[256], output_file[256];
                printf("请输入待转换文件名: ");
                scanf("%s", input_file);
                printf("请输入输出文件名: ");
                scanf("%s", output_file);
                
                // 这里可以添加读取待转换文件并批量转换的代码
                save_transformed_points(output_file, common_points, point_count, 
                                      &four_param, &seven_param, transform_type);
                break;
            }
            
            case 6: {
                char report_file[256];
                printf("请输入报告文件名: ");
                scanf("%s", report_file);
                
                FILE *report = fopen(report_file, "w");
                if (report) {
                    save_results(report, common_points, point_count, 
                                &four_param, &seven_param, &result, transform_type);
                    fclose(report);
                    printf("报告已保存到: %s\n", report_file);
                }
                break;
            }
            
            case 7:
                printf("感谢使用,再见!\n");
                return;
                
            default:
                printf("无效选择,请重新输入。\n");
                break;
        }
    }
}

int main() {
    interactive_menu();
    return 0;
}

2.4 示例数据点文件 (common_points.csv)

点号,X,Y,Z
P001,345678.123,4567890.456,123.456
P002,345712.345,4567923.678,124.567
P003,345745.567,4567956.890,125.678
P004,345778.789,4567989.012,126.789
P005,345812.901,4568022.234,127.890
P006,345845.123,4568055.456,128.901
P007,345878.345,4568088.678,129.012
P008,345911.567,4568121.890,130.123
P009,345944.789,4568155.012,131.234
P010,345977.901,4568188.234,132.345

三、编译与运行

3.1 编译命令

# 使用gcc编译
gcc -o coord_transform main.c coord_transform.c -lm

# 或者使用Makefile
CC = gcc
CFLAGS = -Wall -O2 -lm
TARGET = coord_transform

all: $(TARGET)

$(TARGET): main.o coord_transform.o
	$(CC) -o $@ $^ $(CFLAGS)

main.o: main.c coord_transform.h
	$(CC) $(CFLAGS) -c $<

coord_transform.o: coord_transform.c coord_transform.h
	$(CC) $(CFLAGS) -c $<

clean:
	rm -f *.o $(TARGET)

.PHONY: all clean

3.2 运行示例

# 运行程序
./coord_transform

# 输出示例
========================================
四参数/七参数坐标转换系统
========================================
请输入公共点文件名(CSV格式,包含点号,X,Y,Z): common_points.csv
成功读取 10 个公共点。

----------------------------------------
主菜单:
1. 二维转换(四参数)
2. 三维转换(七参数)
3. 计算转换参数
4. 转换单个点
5. 批量转换文件
6. 查看转换报告
7. 退出
请选择: 1

已选择二维转换(四参数)

请选择: 3

四参数计算结果:
dx = 123.456789 m
dy = 456.789012 m
θ  = 0.001234 rad (0.070686 度)
k  = 1.00001234
单位权中误差: 0.003456

参考代码 四参数、七参数坐标转换程序 www.youwenfan.com/contentcnv/72181.html

四、算法说明

4.1 四参数模型

X' = dx + k * (X * cosθ - Y * sinθ)
Y' = dy + k * (X * sinθ + Y * cosθ)

其中:

4.2 七参数模型(Bursa-Wolf)

[X']   [dx]   [1       -rz  ry] [X]
[Y'] = [dy] + k [rz       1 -rx] [Y]
[Z']   [dz]   [-ry  rx      1] [Z]

其中:

4.3 最小二乘平差

使用高斯-马尔可夫模型:

V = AX - L
X = (A^T A)^{-1} A^T L
σ₀ = √(V^T P V / (m-n))

其中:

五、注意事项

  1. 公共点选择

    • 四参数至少需要2个公共点
    • 七参数至少需要3个公共点
    • 公共点应均匀分布在工作区域
  2. 坐标系统一

    • 确保所有坐标在同一椭球基准下
    • 注意高程异常的影响
  3. 精度控制

    • 单位权中误差应小于0.01米
    • 最大残差应小于0.02米
  4. 参数合理性

    • 旋转角通常小于1弧度(约57度)
    • 尺度因子通常在0.9999~1.0001之间

 

专注于matlab/simulink,电子电路,编程