摄影测量--相对定向-绝对定向(C++实现)

摄影测量与遥感 专栏收录该内容
22 篇文章 1 订阅

一. 目的

  1. 理解并掌握空间相对定向-原理。
  2. 体会相对定向-绝对定向与前后方交会的异同,理解各参数含义。
  3. 熟悉计算流程,并通过编程运用到实践上。
  4. 提高编程计算能力,并将算式转换为程序,体会编程计算的特点。

二. 实验要求

  1. 提交实习报告:程序框图、程序源代码、计算结果、体会。
  2. 计算结果:相对定向五参数及精度评定、计算模型点坐标、绝对定向七参数及精度评定。

三. 实验思路

先求解相对定向,解得五参数,然后计算模型点,最后求解七参数,求解地面摄影测量坐标。

四.实验数据

  1. 点位信息。
    点位信息


    f=150.000mm,x0=0,y0=0

五. 实验结果

  1. 待求点地面摄影测量坐标


    结果
  2. 相对定向五参数

五 参 数 :f w k u v
0.0155932 0.0155955 0.0157996 -0.0159242 0.0312629
相 对 定 向 精 度 : 2.55745e-07
相 对 定 向 迭 代 次 数 : 4

  1. 模型点坐标

X Y Z
153.706 767.599 4.98951
826.447 757.146 45.0979
130.021 -772.319 -14.688
804.556 -782.906 -22.5479
489.955 762.558 24.9652
142.214 -2.24693 -14.3932
478.625 -7.48203 5.57837
815.018 -12.7547 25.6743
467.161 -777.641 -13.908

  1. 绝对定向七参数

    绝 对 定 向 七 参 数 :x y z l f w k
    5000.07 5043.55 499.508 1.03883 0.000437969 0.0287284 0.095136
    绝 对 定 向 精 度 : 0.0999457
    相 对 定 向 迭 代 次 数 : 5

  1. 地面摄影测量坐标

X Y Z
5083.26 5852.04 527.963
5779.98 5906.4 571.513
5210.76 4258.46 461.775
5909.37 4314.29 455.517
5431.48 5879.4 549.662
5147.37 5055.69 484.963
5495.77 5082.86 506.652
5844.15 5110 528.47
5559.93 4286.2 463.536

六. 程序框图

  1. 相对定向


    相对定向结果
  2. 模型点计算


    模型点计算
  3. 绝对定向


    绝对定向

七. 实验原理公式

  1. 共线方程


    共线方程
  2. 旋转矩阵


    旋转矩阵
  3. 最小二乘准则


    最小二乘准则
  4. 解析法相对定向原理:

根据同名光线对对相交这一立体像对内在的几何关系,通过量测的像点坐标,用解析计算的方法解求相对定向元素,建立与地面相似的立体模型,确定模型点的三维坐标。
相对定向的共面条件:B·(S1a1·S2a2)=0,即F=
连续像对的相对定向:连续像对法相对定向是以左像片为基准,求出右像片相对于左像片的五个定向元素 .为了统一单位,把bY,bZ两个基线元素改为角度形式表示,如下,μ和ν为极限的偏角和倾角。

  1. 前方交会


    前方交会
  2. 模型点计算


  3. 绝对定向。

相对定向后建立的立体模型是相对于摄影测量坐标系统的,它在地面坐标系统中的方位是未知的,其比例尺也是任意的。如果想要知道模型中某点相应的地面点的地面坐标,就必须对所建立的模型进行绝对定向,即要确定模型在地面坐标系中的正确方位,及比例尺因子。很容易将模型坐标转化为地面坐标,这样就能确定出加密点的地面坐标。这叫立体模型的绝对定向。
绝对定向的定义:解算立体模型绝对方位元素的工作。立体模型绝对方位元素有7个,它们是: 。
绝对定向的目的:恢复立体模型在地面坐标系中的大小和方位的工作。

八.实验代码(附录)

九.实验结果(截图)

十. 实验心得体会

一句话总结这次实验:收获甚丰,内心很苦。为何这样说?

首先说一下收获甚丰。这次实验真正的让我体会到相对定向-绝对定向与前后方交会之间的区别、联系。他们是空间双象解析的两种重要方法,但是求解思路却不相同。前后交会是先求解单张相片的地面摄影测量坐标,然后再前方交会实现还原相片位置,求解坐标;然而相对-绝对是先求解左右相片的相对位置,然后再逐步求解其在空间中的位置。两者相通的可能就是最基本的原理—共线方程,两者都采用前方交会计算坐标。因此,从根本上讲,前后方交会是同一问题的不同求解顺序。

其次想谈一谈内心的痛苦。说白了就是编程中所遇到的问题。

  1. 绝对定向中bx。
    在求解过程中,bx = x1 – x2; 我开始写的是bx = x2 – x1;就是这样简单的问题,因为没有想清楚,所以就出错了。
    相对定向中,bx其实是一个无关紧要的量,因此,我算出来相对定向的值是正确的;然而到了绝对定向,出现问题了,七参数中z异常打!然而找不到问题所在,最后在调试时,发现不对,才改正过来,于是乎,绝对定向才收敛,这个过程持续了至少5个小时。
  2. 数据录入错误。
    这可能是最低级的错误,但是这次我又犯了,把一个数据的正负号搞错了,于是乎,根本不会闭合,看着迭代次数1,100,100…绝望!
  3. 矩阵与数组之间的频繁转换。
    由于原始数据是数组,操作起来也很便捷,但有时候为了求逆,不得不将数据转为矩阵;有时候矩阵与数组结构不相同,出现了某一个位置未赋值的情况,从而出现各种奇怪的值!
  4. 参数过多,传值频繁。
    此程序内的定向类可以认为根本不符合面向对象的编程思想,因为这个类的存在几乎就是为了在函数之间传递变量。因此,在数值传递过程中就会出现变量混乱,变量名污染的情况。
    总之,这三天的编程还是蛮刺激的,不仅要一遍遍看书,还有详细了解编程知识,同时要不断地Debug,Debug,Debug……

附录

  1. 入口文件ResAblOrientation
#include "stdafx.h"
#include <iostream>
#include "Orientation.h"
using namespace std;
int main()
{
    //左片数据
    double l[9][2] = {
        { 0.016012 ,0.079963 },
        { 0.08856 ,0.081134 },
        { 0.013362 ,-0.07937 },
        { 0.08224 ,-0.080027 },
        { 0.051758,0.080555 },
        { 0.014618,-0.000231 },
        { 0.04988,-0.000782 },
        { 0.08614,-0.001346 },
        { 0.048035,-0.079962 }
    };
    //右片数据
    double r[9][2] = {
        { -0.07393,0.078706 },
        { -0.005252,0.078184 },
        { -0.079122,-0.078879 },
        { -0.009887,-0.080089 },
        { -0.039953,0.078463 },
        { -0.076006,0.000036 },
        { -0.042201,-0.001022 },
        { -0.007706,-0.002112 },
        { -0.044438,-0.079736 }
    };
    //控制点地面摄影测量坐标
    double g[4][3] = {
        { 5083.205,5852.099,527.925 },
        { 5780.02,5906.365,571.549 },
        { 5210.879,4258.446,461.81 },
        { 5909.264,4314.283,455.484 }
    };
    double f = 0.15; //焦距

    //实例化定向对象
    COrientation o(l,r,g,f);

    cout << endl << endl;
    cout << "--------定向计算结果--------" << endl;
    cout << endl << endl;
    //相对定向
    o.RelaOrientation();

    cout << "--------------------------------" << endl;

    //计算模型点
    o.ModelPoints();

    cout << "--------------------------------" << endl;

    //绝对定向
    o.AbsOrientation();

    cout << "--------------------------------" << endl;

    //计算坐标值
    o.GetPoints();

    cin.get();
    return 0;
}
  1. 定向类COrientation
#pragma once
#include "Matrix.h"
#include <iostream>
/*
定向类
*/
class COrientation
{
private:
    //相对定向五参数
    double f;
    double w;
    double k;
    double u;
    double v;
    double countx; //相对定向循环次数

    double df; //焦距
    double bx;
    double by;
    double bz;

    //七参数
    double x;
    double y;
    double z;
    double jf;
    double jw;
    double jk;
    double jl;
    double countj; //绝对定向循环次数

    double N1;
    double N2;

    double l[9][2]; //左片数据
    double r[9][2]; //右片数据
    double g[4][3]; //控制点地面摄影测量数据
    double p[9][3]; //模型点数据

public:
    //初始化
    COrientation(double l[9][2], double r[9][2], double g[4][3],double f);
    void RelaOrientation(); //相对定向
    void ModelPoints(); //计算模型点
    void AbsOrientation(); //绝对定向
    void GetPoints(); //得出地面摄影测量坐标
    CMatrix GetR(double f, double w, double k); //计算旋转矩阵
    ~COrientation();
};
#include "stdafx.h"
#include "Orientation.h"
#include "math.h"
#include <iostream>
using namespace std;
COrientation::COrientation(double lpoints[9][2], double rpoints[9][2], double g[4][3], double df)
{
    //焦距
    this->df = df;
    //初始值
    bx = lpoints[0][0] - rpoints[0][0]; //bx初始值
    //初始值
    f = w = k = u = v = 0;
    countx = countj = 0;
    //赋值
    for (int i = 0; i < 9; i++)
    {
        for (int j = 0; j < 2; j++)
        {
            l[i][j] = lpoints[i][j];
            r[i][j] = rpoints[i][j];
        }
    }
    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            this->g[i][j] = g[i][j];
        }
    }
}

void COrientation::RelaOrientation()
{
    //误差方程参数
    CMatrix A(6, 5), L(6, 1), X(5, 1), V(6, 1);

    //右片相对相空间坐标,相对摄影测量坐标
    CMatrix mr(3, 1), mrimg(3, 1);

    //迭代运算
    while (1)
    {
        //计算旋转矩阵
        CMatrix R2 = GetR(f, w, k);

        //by,bz计算
        by = bx*u;
        bz = bx*v;

        //计算每个点参数,组成法方程矩阵
        for (int i = 0; i < 6; i++)
        {
            //左片相对摄影测量坐标
            double x1 = l[i][0];
            double y1 = l[i][1];
            double z1 = -df;

            //右片相对摄影测量坐标
            mr(0, 0) = r[i][0];
            mr(1, 0) = r[i][1];
            mr(2, 0) = -df;
            //计算相对摄影测量坐标
            mrimg = R2*mr;

            //计算N1,N2
            N1 = (bx*mrimg(2, 0)- bz*mrimg(0, 0)) / (x1*mrimg(2, 0) - mrimg(0, 0)*z1);
            N2 = (bx*z1 - bz*x1) / (x1*mrimg(2, 0) - mrimg(0, 0)*z1);
            //计算每个点的Q值
            double Q = N1*y1 - N2*mrimg(1, 0) - by;
            //计算每个点误差系数
            double v[5] = {0};
            v[0] = -mrimg(0, 0)*mrimg(1, 0)*N2 / mrimg(2, 0);
            v[1] = -(mrimg(2, 0) + mrimg(1, 0)*mrimg(1, 0) / mrimg(2, 0))*N2;
            v[2] = mrimg(0, 0)*N2;
            v[3] = bx;
            v[4] = -mrimg(1, 0)*bx / mrimg(2, 0);

            //加入总误差系数阵
            for (int ii = 0; ii < 5; ii++)
                A(i, ii) = v[ii];
            L(i, 0) = Q;
        }
        //求解X
        X = (~A*A).Inv()*(~A)*L;

        //累加五参数
        f += X(0, 0);
        w += X(1, 0);
        k += X(2, 0);
        u += X(3, 0);
        v += X(4, 0);

        //循环次数+
        countx++;

        //判断是否收敛
        if (abs(X(0, 0)) < 0.00003 && abs(X(1, 0)) < 0.00003 && abs(X(2, 0)) < 0.00003 && abs(X(3, 0)) < 0.00003 && abs(X(4, 0)) < 0.00003)
        {
            //输出五参数
            cout << "五参数:f w k u v" << endl;
            cout << f << " " << w << " " << k << " " << u << "  " << v << endl;
            //评定精度
            V = A*X - L;
            double c1 = sqrt((~V*V)(0, 0) / 6);
            cout << "相对定向精度:" << c1 << endl;
            cout << "相对定向迭代次数:" << countx << endl;
            break;
        }
    }


}

void COrientation::ModelPoints()
{
    //比例尺
    double m1 = sqrt((l[0][0] - l[1][0])*(l[0][0] - l[1][0]) + (l[0][1] - l[1][1])*(l[0][1] - l[1][1]));
    double m2 = sqrt((g[0][0] - g[1][0])*(g[0][0] - g[1][0]) + (g[0][1] - g[1][1])*(g[0][1] - g[1][1]));
    double m = m2 / m1;
    //m = 10000;

    //计算每个点模型坐标
    //右片相对相空间坐标,相对摄影测量坐标
    CMatrix mr(3, 1), mrimg(3, 1);
    //计算旋转矩阵
    CMatrix R2 = GetR(f, w, k);
    for (int i = 0; i < 9; i++)
    {

        //左片相对摄影测量坐标
        double x1 = l[i][0];
        double y1 = l[i][1];
        double z1 = -df;

        //右片相对摄影测量坐标
        mr(0, 0) = r[i][0];
        mr(1, 0) = r[i][1];
        mr(2, 0) = -df;
        //计算相对摄影测量坐标
        mrimg = R2*mr;

        //计算N1,N2
        N1 = (bx*mrimg(2, 0) - bz*mrimg(0, 0)) / (x1*mrimg(2, 0) - mrimg(0, 0)*z1);
        N2 = (bx*z1 - bz*x1) / (x1*mrimg(2, 0) - mrimg(0, 0)*z1);

        double xp = m*N1*x1;
        double yp = 0.5*m*(N1*y1 + N2*mrimg(1, 0) + by);
        double zp = m*df + m* N1*(-df);
        p[i][0] = xp;
        p[i][1] = yp;
        p[i][2] = zp;
    }
    cout << "模型点坐标:" << endl;
    for (int i = 0; i < 9; i++)
    {
        for (int j = 0; j < 3; j++)
            cout << p[i][j] << " ";
        cout << endl;
    }
}

void COrientation::AbsOrientation()
{
    //初始化七参数
    x = y = z = jf = jw = jk = 0;
    jl = 1;
    //法方程系数
    CMatrix A(12, 7), L(12, 1), V(12, 1), X(7,1);
    //迭代计算
    while (true)
    {
        //计算每一个点的系数
        for (int i = 0; i < 4; i++)
        {
            //旋转矩阵
            CMatrix R = GetR(jf, jw, jk);
            //每个点误差方程系数
            CMatrix mtp(3, 1), mp(3, 1), p0(3, 1);
            //赋值给矩阵,便于计算
            for (int j = 0; j < 3; j++)
            {
                mtp(j, 0) = g[i][j];
                mp(j, 0) = p[i][j];
            }
            p0(0, 0) = x;
            p0(1, 0) = y;
            p0(2, 0) = z;
            //计算每个点的L
            CMatrix jL = mtp - jl*R*mp - p0;
            //每个点3X3的系数阵A
            CMatrix jA(3, 7);
            jA(0, 0) = 1;
            jA(1, 1) = 1;
            jA(2, 2) = 1;
            jA(0, 3) = p[i][0];
            jA(0, 4) = -p[i][2];
            jA(0, 6) = -p[i][1];
            jA(1, 3) = p[i][1];
            jA(1, 5) = -p[i][2];
            jA(1, 6) = p[i][0];
            jA(2, 3) = p[i][2];
            jA(2, 4) = p[i][0];
            jA(2, 5) = p[i][1];

            //添加到大系数阵A,L
            for (int j = 0; j < 7; j++)
            {
                A(3 * i, j) = jA(0, j);
                A(3 * i + 1, j) = jA(1, j);
                A(3 * i + 2, j) = jA(2, j);
            }
            L(3 * i, 0) = jL(0, 0);
            L(3 * i + 1, 0) = jL(1, 0);
            L(3 * i + 2, 0) = jL(2, 0);
        }

        //求解法方程
        X = (~A*A).Inv()*~A*L;

        //累加七参数
        x += X(0, 0);
        y += X(1, 0);
        z += X(2, 0);
        jl += X(3, 0);
        jf += X(4, 0);
        jw += X(5, 0);
        jk += X(6, 0);

        //循环次数累加
        countj++;
        //判断是否收敛
        if (abs(X(0, 0)) < 0.001 && abs(X(1, 0)) < 0.001 && abs(X(2, 0)) < 0.001 && abs(X(3, 0)) < 0.001 && abs(X(4, 0)) < 0.001&& abs(X(5, 0)) < 0.001 && abs(X(6, 0)) < 0.001)
        {
            cout << "绝对定向七参数:x y z l f w k" << endl;;
            cout << x << " " << y << " " << z << " " << jl << " " << jf << " " << jw << " " << jk << endl;;
            //精度评定
            V = A*X - L;
            double c2 = sqrt((~V*V)(0, 0) / 4);
            cout << "绝对定向精度:" << c2 << endl;
            cout << "相对定向迭代次数:" << countj << endl;
            break;
        }
    }

}

void COrientation::GetPoints()
{
    CMatrix XTP(9,3); //地面摄影测量坐标
    //计算坐标
    for (int i = 0; i < 9; i++)
    {
        //依次为相对摄影测量坐标、七参数、地面摄影测量坐标
        CMatrix XP(3, 1), DX(3, 1), mXTP(3, 1);
        //为矩阵赋值
        XP(0, 0) = p[i][0]; 
        XP(1, 0) = p[i][1]; 
        XP(2, 0) = p[i][2];

        DX(0, 0) = x; 
        DX(1, 0) = y, 
        DX(2, 0) = z;
        //计算摄影测量坐标
        mXTP = jl*GetR(jf, jw, jk)*XP + DX;
        for (int j = 0; j < 3; j++)
        {
            XTP(i, j) = mXTP(j, 0);
        }
    }
    cout << "地面摄影测量坐标为:" << endl;
    cout << XTP;
}

CMatrix COrientation::GetR(double f, double w, double k)
{
    CMatrix R2(3, 3);
    R2(0, 0) = cos(f)*cos(k) - sin(f)*sin(w)*sin(k);
    R2(0, 1) = -cos(f)*sin(k) - sin(f)*sin(w)*cos(k);
    R2(0, 2) = -sin(f)*cos(w);
    R2(1, 0) = cos(w)*sin(k);
    R2(1, 1) = cos(w)*cos(k);
    R2(1, 2) = -sin(w);
    R2(2, 0) = sin(f)*cos(k) + cos(f)*sin(w)*sin(k);
    R2(2, 1) = -sin(f)*sin(k) + cos(f)*sin(w)*cos(k);
    R2(2, 2) = cos(f)*cos(w);

    return R2;
}

COrientation::~COrientation()
{
}
  1. 矩阵类CMatrix
#pragma once
#include <iostream>
using namespace std;
class CMatrix
{
public:
    CMatrix(int row = 3, int col = 3);
    // copy constructor

    CMatrix(const CMatrix& m);


    ~CMatrix(void);
private:
    double **dMatData;//保存矩阵元素数据的二维数组
    int iRow;//矩阵的行
    int iCol;//矩阵的列

public:
    int Row() const { return iRow; }//返回行
    int Col() const { return iCol; }//返回列
    void SetSize(int row, int col);//调整数组的大小,原有数据不变(未测试)
    void SetRow(int row, double arrrow[]); //设置一行元素

    double& operator () (int row, int col);//获取矩阵元素
    double  operator () (int row, int col) const;//重载获取矩阵元素函数,只有const对象能访问

    CMatrix& operator = (const CMatrix& m);

    //注意:友元函数并不是类自己的成员函数
    friend CMatrix operator + (const CMatrix& m1, const CMatrix& m2);
    friend CMatrix operator - (const CMatrix& m1, const CMatrix& m2);
    friend CMatrix operator * (const CMatrix& m1, const CMatrix& m2);
    friend CMatrix operator * (const double& num, const CMatrix& m1);
    friend CMatrix operator * (const CMatrix& m1, const double& num);
    friend ostream & operator<<(ostream &out, CMatrix &m); //重载<<

    friend CMatrix operator ~ (const CMatrix& m);//矩阵转置
    CMatrix Inv();//矩阵求逆
    void Unit();//生成单位矩阵
};


#include "stdafx.h"
#include "Matrix.h"
#include "math.h"

CMatrix::CMatrix(int row, int col)
{
    iRow = row;
    iCol = col;
    dMatData = new double*[row];

    for (int i = 0; i < row; i++)
    {
        dMatData[i] = new double[col];
        for (int j = 0; j<col; j++)
        {
            dMatData[i][j] = 0;
        }
    }
}

// copy constructor,
//拷贝构造函数的作用:
//(1)以类对象作为函数参数传值调用时;
//(2)函数返回值为类对象;
//(3)用一个已定义的对象去初始化一个新对象时;

CMatrix::CMatrix(const CMatrix& m)
{
    iRow = m.Row();
    iCol = m.Col();
    dMatData = new double*[iRow];

    for (int i = 0; i < iRow; i++)
    {
        dMatData[i] = new double[iCol];
        //  for(int j=0;j<iCol;j++)
        {
            memcpy(dMatData[i], m.dMatData[i], sizeof(double)*iCol);
        }
    }

}

CMatrix::~CMatrix(void)
{
    for (int i = 0; i < iRow; i++)
    {
        delete[] dMatData[i];
    }
    delete[] dMatData;
}

//返回数组元素(引用返回)
double& CMatrix::operator () (int row, int col)
{
    if (row >= iRow || col >= iCol)
    {
        throw("CMatrix::operator(): Index out of range!");
    }

    return dMatData[row][col];
}

返回数组元素(重载)
double CMatrix::operator () (int row, int col) const
{
    if (row >= iRow || col >= iCol)
    {
        throw("CMatrix::operator(): Index out of range!");
    }

    return dMatData[row][col];
}


//重载预算符+
CMatrix operator + (const CMatrix& m1, const CMatrix& m2)
{

    if ((m1.Col() != m2.Col()) || (m1.Row() != m2.Row()))
    {
        throw("CMatrix::operator+: The two matrix have different size!");
    }

    CMatrix matTmp(m1.Row(), m1.Col());
    for (int i = 0; i<m1.Row(); i++)
    {
        for (int j = 0; j<m1.Col(); j++)
        {
            matTmp(i, j) = m1(i, j) + m2(i, j);
        }
    }
    return matTmp;
}




//重载赋值运算符=,当左右两边矩阵的大小不相等时,
//以右边的大小为基准,调整左边矩阵的大小


CMatrix &CMatrix::operator = (const CMatrix& m)
{
    //revised in 2011-4-1, by Daiwujiao
    //   if(iRow!=m.Row()||iCol!=m.Col())
    //{
    //       throw( "CMatrix::operator=: The two matrix have different size!");
    //}

    if (iRow != m.Row() || iCol != m.Col())
    {
        SetSize(m.Row(), m.Col());
    }
    for (int i = 0; i < iRow; i++)
    {

        for (int j = 0; j<iCol; j++)
        {
            dMatData[i][j] = m(i, j);
        }
    }
    return *this;
}


//调整矩阵大小,原有值不变
void CMatrix::SetSize(int row, int col)
{
    if (row == iRow && col == iCol)
    {
        return;
    }

    double **rsData = new double*[row];
    for (int i = 0; i < row; i++)
    {
        rsData[i] = new double[col];
        for (int j = 0; j<col; j++)
        {
            rsData[i][j] = 0;
        }
    }

    int minRow = (iRow>row) ? row : iRow;
    int minCol = (iCol>col) ? col : iCol;
    int  colSize = minCol * sizeof(double);


    for (int i = 0; i < minRow; i++)
    {
        memcpy(rsData[i], dMatData[i], colSize);
    }

    for (int i = 0; i < minRow; i++)
    {
        delete[] dMatData[i];
    }
    delete[] dMatData;
    dMatData = rsData;
    iRow = row;
    iCol = col;
    return;
}
void CMatrix::SetRow(int row, double arrrow[])
{
    if (row > iRow)
        throw("CMatrix::SetRow: the row is out of index");
    if (sizeof(arrrow) / sizeof(double) > iCol)
        throw("CMatrix::SetRow: the col is out of index");
    for (int i = 0; i < iCol; i++)
    {
        dMatData[row][i] = arrrow[i];
    }
}



//重载预算符-
CMatrix operator - (const CMatrix& m1, const CMatrix& m2)
{

    if ((m1.Col() != m2.Col()) || (m1.Row() != m2.Row()))
    {
        throw("CMatrix::operator-: The two matrix have different size!");
    }

    CMatrix matTmp(m1.Row(), m1.Col());
    for (int i = 0; i<m1.Row(); i++)
    {
        for (int j = 0; j<m1.Col(); j++)
        {
            matTmp(i, j) = m1(i, j) - m2(i, j);
        }
    }
    return matTmp;
}

//重载预算符*,两个矩阵相乘,m1的列要等于m2的行
CMatrix operator * (const CMatrix& m1, const CMatrix& m2)
{

    if ((m1.Col() != m2.Row()))
    {
        throw("CMatrix::operator*: The col of matrix m1 doesn't equ to row of m2 !");
    }

    CMatrix matTmp(m1.Row(), m2.Col());
    for (int i = 0; i<m1.Row(); i++)
    {
        for (int j = 0; j<m2.Col(); j++)
        {
            for (int k = 0; k<m2.Row(); k++)
            {
                matTmp(i, j) += m1(i, k)*m2(k, j);
            }
        }
    }
    return matTmp;
}

//重载预算符*,矩阵右乘一个数
CMatrix operator * (const CMatrix& m1, const double& num)
{
    CMatrix matTmp(m1.Row(), m1.Col());
    for (int i = 0; i<m1.Row(); i++)
    {
        for (int j = 0; j<m1.Col(); j++)
        {
            matTmp(i, j) = m1(i, j)*num;

        }
    }
    return matTmp;
}

//重载预算符*,矩阵左乘一个数
CMatrix operator * (const double& num, const CMatrix& m1)
{
    CMatrix matTmp(m1.Row(), m1.Col());
    for (int i = 0; i<m1.Row(); i++)
    {
        for (int j = 0; j<m1.Col(); j++)
        {
            matTmp(i, j) = m1(i, j)*num;
        }
    }
    return matTmp;
}

//矩阵转置
CMatrix operator ~ (const CMatrix& m)
{
    CMatrix matTmp(m.Col(), m.Row());

    for (int i = 0; i < m.Row(); i++)
        for (int j = 0; j < m.Col(); j++)
        {
            matTmp(j, i) = m(i, j);
        }
    return matTmp;
}


//矩阵求逆
//采用选全主元法
CMatrix CMatrix::Inv()
{
    if (iRow != iCol)
    {
        throw("待求逆的矩阵行列不相等!");
    }

    int i, j, k, vv;

    CMatrix InvMat(iRow, iRow);

    //复制矩阵
    InvMat = *this;

    int* MainRow = new int[iRow];
    int* MainCol = new int[iRow];//用于记录主元素的行和列

    double dMainCell;//主元元素的值
    double dTemp;//临时变量

    for (k = 0; k<iRow; k++)
    {
        dMainCell = 0;
        //选全主元
        for (i = k; i<iRow; i++)
        {
            for (j = k; j<iRow; j++)
            {
                dTemp = fabs(InvMat(i, j));
                if (dTemp > dMainCell)
                {
                    dMainCell = dTemp;
                    MainRow[k] = i;
                    MainCol[k] = j;
                }
            }
        }

        if (fabs(dMainCell) < 0.0000000000001)//矩阵秩亏,不能求逆
        {
            throw("矩阵秩亏");
        }

        if (MainRow[k] != k)//交换行
        {
            for (j = 0; j<iRow; j++)
            {
                vv = MainRow[k];
                dTemp = InvMat(k, j);
                InvMat(k, j) = InvMat(vv, j);
                InvMat(vv, j) = dTemp;
            }
        }

        if (MainCol[k] != k)//交换列
        {
            for (i = 0; i<iRow; i++)
            {
                vv = MainCol[k];
                dTemp = InvMat(i, k);
                InvMat(i, k) = InvMat(i, vv);
                InvMat(i, vv) = dTemp;
            }
        }
        InvMat(k, k) = 1.0 / InvMat(k, k);//计算乘数

        for (j = 0; j< iRow; j++) //计算主行
        {
            if (j != k)
            {
                InvMat(k, j) = InvMat(k, j) * InvMat(k, k);
            }
        }
        for (i = 0; i<iRow; i++)//消元
        {
            if (i != k)
            {
                for (j = 0; j<iRow; j++)
                {
                    if (j != k)
                    {
                        InvMat(i, j) -= InvMat(i, k) * InvMat(k, j);
                    }
                }
            }
        }
        for (i = 0; i< iRow; i++)//计算主列
        {
            if (i != k)
            {
                InvMat(i, k) = -InvMat(i, k) * InvMat(k, k);
            }
        }
    }

    for (k = iRow - 1; k >= 0; k--)
    {
        if (MainCol[k] != k)// 交换行
        {
            for (j = 0; j<iRow; j++)
            {
                vv = MainCol[k];
                dTemp = InvMat(k, j);
                InvMat(k, j) = InvMat(vv, j);
                InvMat(vv, j) = dTemp;
            }
        }

        if (MainRow[k] != k)//交换列
        {
            for (i = 0; i<iRow; i++)
            {
                vv = MainRow[k];
                dTemp = InvMat(i, k);
                InvMat(i, k) = InvMat(i, vv);
                InvMat(i, vv) = dTemp;
            }
        }
    }
    delete[] MainRow;
    delete[] MainCol;
    return InvMat;
}
//单位化矩阵
void CMatrix::Unit()
{
    for (int i = 0; i<iRow; i++)
    {
        for (int j = 0; j<iCol; j++)
        {
            dMatData[i][j] = (i == j) ? 1 : 0;
        }
    }
}

//操作符<<重载,用于输出矩阵
ostream & operator<<(ostream &out, CMatrix &m)
{
    //out << "CMatrix:row=" << m.Row() << " col=" << m.Col() << endl;
    for (int i = 0; i < m.Row(); i++)
    {
        for (int j = 0; j < m.Col(); j++)
        {
            out << m(i, j) << "  ";
        }
        out << endl;
    }

    return out;
}


转载自:https://www.jianshu.com/p/abc75e1f8b97


  • 5
    点赞
  • 1
    评论
  • 45
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值