导线网平差/C++

引言:

起因是我的同学想在网上搜一份C++的导线平差代码,发现没有直接高效、可以用简单C++直接实现的代码,然后找到了一份古早代码,代码本身应该还是挺强大的,但是我没有细看,帮着调试了一波,将其升级到了现代版本,然后倒推了一下数据的组织格式,跑通后就扔给我同学了。在此开源给测绘牛马作为一个小小的参考。


allinone.cpp:

都在同一份cpp里面(原始代码就这个样子,有裹脚布的嫌疑,但对小白友好),main函数在最后,可自己拆分。


#include   
#include   
#define MAX 100   
#define PI 3.14159265358979312   
#define rou (180.0*60*60/PI)   
#include   
#include   
using namespace std;



int inverse(double C[][MAX], double B[][MAX], int n);
//define the function of inverseing;   
//return 0 means mat can't be inversed or;   
//return 1 means mat inversed correctly, and B is inversed mat;   

void AXB(double A[][MAX], double B[][MAX], double C[][MAX], int m, int n, int k);
void AXB(double a, double A[][MAX], double aA[][MAX], int m, int n);
void AXB(double A[][MAX], double B[][1], double C[][1], int m, int n);
//define the time fuction of mats or mat and a number   

void AT(double A[][MAX], double AH[][MAX], int m, int n);
void AT(double A[][1], double AH[][MAX], int m);
void AT(double A[][MAX], double AH[][1], int m);
//define the fuction to turn over a mat    

void ATPA(double A[][MAX], double P[][MAX], double ATPA[][MAX], int m, int n);
void ATPL(double A[][MAX], double P[][MAX], double L[][1], double ATPL[][1], int m, int n);
double VPV(double V[][1], double P[][MAX], int m);
//define initial fuctions of doadj()   

void matdis(double A[][MAX], int n, int m);
void matdis(double A[][1], int n);
//define two fuctions to output a mat to screen     

struct adj;
void ksetadj(adj& a);     //input data from keyboard    
int fsetadj(adj& aa, char name[20]);  //input data from a file    
int  doadj(adj& a);       //adjusting a adj    
int rubust(adj& a);       //抗差估计   
void adjdis(adj& aa);     //output a adj results to screen

int foutadj(adj& aa, char name[20]); //outputdate to a file   
//define adj and it related fuctions   

//************************************************************************************************   
void AXB(double A[][MAX], double B[][MAX], double C[][MAX], int m, int n, int k)
{
    for (int i = 0; i < m; i++)
        for (int j = 0; j < k; j++)
        {
            C[i][j] = 0;
            for (int l = 0; l < n; l++)
                C[i][j] += A[i][l] * B[l][j];
        }
}
//************************************************************************************************   

void AXB(double A[][MAX], double B[][1], double C[][1], int m, int n)
{
    for (int i = 0; i < m; i++)
        for (int j = 0; j < 1; j++)
        {
            C[i][j] = 0;
            for (int l = 0; l < n; l++)
                C[i][j] += A[i][l] * B[l][j];
        }

}
//************************************************************************************************   

void AXB(double a, double A[][MAX], double aA[][MAX], int m, int n) //void     
{
    for (int i = 0; i < m; i++)
        for (int j = 0; j < n; j++)
            aA[i][j] = a * A[i][j];

}
//************************************************************************************************   

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

void AT(double A[][1], double AH[][MAX], int m)    //  列向量转置为行向量   
{
    for (int i = 0; i < m; i++)
        AH[0][i] = A[i][0];
}
//************************************************************************************************   

void AT(double A[][MAX], double AH[][1], int m)    //  行向量转置为列向量   
{
    for (int i = 0; i < m; i++)
        AH[i][0] = A[0][i];
}
//************************************************************************************************   


void ATPA(double A[][MAX], double P[][MAX], double ATPA[][MAX], int m, int n)
{
    double AH[MAX][MAX], ATP[MAX][MAX];
    AT(A, AH, m, n);
    AXB(AH, P, ATP, n, m, m);
    AXB(ATP, A, ATPA, n, m, n);
}
//************************************************************************************************   


double VPV(double V[][1], double P[][MAX], int m)
{
    double VH[1][MAX], VTP[1][MAX];
    for (int i = 0; i < m; i++)
        VH[0][i] = V[i][0];
    for (int i = 0; i < m; i++)
    {
        VTP[0][i] = 0;
        for (int j = 0; j < m; j++)
            VTP[0][i] += VH[0][j] * P[j][i];
    }

    double dd(0);
    for (int i = 0; i < m; i++)
        dd += VTP[0][i] * V[i][0];
    return dd;
}
//************************************************************************************************   
void ATPL(double A[][MAX], double P[][MAX], double L[][1], double ATPL[][1], int m, int n)
{
    double AH[MAX][MAX], ATP[MAX][MAX];
    AT(A, AH, m, n);
    AXB(AH, P, ATP, n, m, m);
    for (int i = 0; i < n; i++)
    {
        ATPL[i][0] = 0;
        for (int j = 0; j < m; j++)
            ATPL[i][0] += ATP[i][j] * L[j][0];
    }
}
//************************************************************************************************    
void matdis(double A[][MAX], int n, int m) // 显示矩阵   
{//1.set B[][] I;   
    for (int i = 0; i < n; i++)
    {
        cout << "     ";
        for (int j = 0; j < m; j++)
            cout << A[i][j] << "  ";
        cout << endl;
    }
}
//************************************************************************************************   
void matdis(double A[][1], int n)       //  显示列向量   
{//1.set B[][] I;   
    for (int i = 0; i < n; i++)
        cout << "     " << A[i][0] << endl;

}
//************************************************************************************************   
int inverse(double C[][MAX], double B[][MAX], int n)
{//1.set B[][] I;   
    double A[MAX][MAX], e;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
        {
            A[i][j] = C[i][j];
            if(  i== j) B[i][j] = 1;
            else B[i][j] = 0;

        }

    //2. inverse and judge the Matrix inversable   
    for (int i = 0; i < n; i++)
    {
        //对主元为零的处理   
        if (A[i][i] == 0)
            for (int j = i + 1; j < n; j++)
            {
                if (A[j][i] != 0)
                    for (int k = 0; k < n; k++)
                    {
                        A[i][k] += A[j][k];
                        B[i][k] += B[j][k];
                    }
                break;
            }
        if (fabs(A[i][i]) < 0.000000000000001)
        {
            for (int i = 0; i < n; i++)
                for (int j = 0; j < n; j++)
                    B[i][j] = 0;
            return 0;
        }//MAT can't be inversed   
// line processing   
        e = A[i][i];
        for (int j = 0; j < n; j++)
        {
            A[i][j] = A[i][j] / e;
            B[i][j] = B[i][j] / e;
        }
        // row processing   
        for (int j = 0; j < n; j++)
        {
            e = A[j][i];
            for (int k = 0; k < n; k++)
                if (i != j)
                {
                    A[j][k] += -1 * e * A[i][k];
                    B[j][k] += -1 * e * B[i][k];
                }
        }
    }
    return 1;
}
//************************************************************************************************   
double setf(double a, int t)
{
    double b = fabs(a);
    for (int i = 0; i < t; i++)
        b *= 10;
    if (b - floor(b) > 0.5) b = floor(b) + 1;
    else b = floor(b);
    for (int i = 0; i < t; i++)
        b /= 10;
    if (a < 0) b = -b;
    return b;
}
//************************************************************************************************   
struct adj {
    // adjustment model :   
    //      V=AX-L P    
    //      A[m][n], P[m][m], L[m][1]   
    char name[40];       // V=AX-L P    
    int m;               // the number of observations   
    int n;               // the number of unknown data   
    double A[MAX][MAX];  // paremater mat of unknown data    
    double P[MAX][MAX];  // observation weight mat   
    double l[MAX][1];    // fix data mat   
    double X[MAX][1];    // unknown data mat   
    double QXX[MAX][MAX];// coherance date mat    
    double m0;           // unit weight error     
    double V[MAX][1];
    int flag;            // flag=1 means adjustment successfully   
};
//************************************************************************************************   
void ksetadj(adj& a) //keyboard and screen input   
{
    cout << "  input the object  name:   ";
    cin >> a.name; cout << endl;

    cout << "  input observation number:   ";
    cin >> a.m; cout << endl;

    cout << "  input unknown data number:   ";
    cin >> a.n; cout << endl;

    cout << "  input data of mat A[" << a.m << "][" << a.n << "]" << endl;

    for (int i = 0; i < a.m; i++)
        for (int j = 0; j < a.n; j++)
            cin >> a.A[i][j];

    cout << "  input data of mat P[" << a.m << "][" << a.m << "]" << endl;

    for( int i=  0; i < a.m; i++)
        for (int j = 0; j < a.m; j++)
            cin >> a.P[i][j];

    cout << "  input data of mat L[" << a.m << "][1]" << endl;

    for( int i=  0; i < a.m; i++)
        cin >> a.l[i][0];
}
//************************************************************************************************   
int fsetadj(adj& aa, const char* name) //keyboard and screen input   
{

    ifstream in(name);
    if (!in) return 0;
    // 输入平差项目名       
    in >> aa.name;

    // input observation number:     
    in >> aa.m;

    // input unknown data number:    
    in >> aa.n;

    // input data of mat A[m][n]:   

    for (int i = 0; i < aa.m; i++)
        for (int j = 0; j < aa.n; j++)
            in >> aa.A[i][j];

    // input data of mat P[m][m]:   

    for( int i=  0; i < aa.m; i++)
        for (int j = 0; j < aa.m; j++)
            in >> aa.P[i][j];

    // input data of mat L[m][1]:   

    for( int i=  0; i < aa.m; i++)
        in >> aa.l[i][0];
    in.close();
    return 1;
}

//*******************************************************************************************   

int  doadj(adj& a)            // 普通最小二乘平差   
{
    double APA[MAX][MAX];
    ATPA(a.A, a.P, APA, a.m, a.n);
    int flag = inverse(APA, a.QXX, a.n);
    if (flag != 1)
    {
        a.flag = 0;
        return 0;
    }
    double AX[MAX][1];
    ATPL(a.A, a.P, a.l, AX, a.m, a.n);
    AXB(a.QXX, AX, a.X, a.n, a.n);
    AXB(a.A, a.X, AX, a.m, a.n);
    for (int i = 0; i < a.m; i++)
        a.V[i][0] = AX[i][0] - a.l[i][0];
    double cc = VPV(a.V, a.P, a.m);
    a.m0 = sqrt(cc / (a.m - a.n));
    a.flag = 1;
    return 1;

}

//*******************************************************************************************   
int doadj(adj& a, int known, int r)        // 极大权法最小二乘平差,known--控制点已知数据个数;   
{                                        // r-固定数据个数+测站数(平面网)   
    double APA[MAX][MAX];
    ATPA(a.A, a.P, APA, a.m, a.n);
    double add(0);
    for (int i = 0; i < a.n; i++)
        if (add <= APA[i][i]) add = APA[i][i];
    add *= 1000;
    for( int i=  0; i < known; i++)                 // 对已知点方法程系数阵的处理:   
        APA[i][i] += add;                  // 控制点点号对应矩阵主元加平均权的10000倍   
    int flag = inverse(APA, a.QXX, a.n);
    if (flag != 1)                          // 不可求逆的判断及处理    
    {
        a.flag = 0;  return 0;
    }
    double AX[MAX][1];                   // 极大权平差过程   
    ATPL(a.A, a.P, a.l, AX, a.m, a.n);
    AXB(a.QXX, AX, a.X, a.n, a.n);
    AXB(a.A, a.X, AX, a.m, a.n);
    for( int i=  0; i < a.m; i++)
        a.V[i][0] = AX[i][0] - a.l[i][0];
    double cc = VPV(a.V, a.P, a.m);           // VTPV计算   
    a.m0 = sqrt(cc / (a.m - a.n + known - r));     // 单位权中误差计算,必要观测数为(a.n-knownp)   
    a.flag = 1;                            // 平差完毕   
    return 1;
}
//*******************************************************************************************   

void adjdis(adj& aa)
{
    cout << "   平差项目名 :" << aa.name << endl << endl;

    cout << " 误差方程阵:" << endl;
    matdis(aa.A, aa.m, aa.n);

    cout << endl << endl << " 观测值权矩阵:" << endl;
    matdis(aa.P, aa.m, aa.m);

    cout << endl << endl << " 常数项:" << endl;
    matdis(aa.l, aa.m);
    cout << endl << endl;

    cout << endl << endl << "  未知数解:" << endl;
    matdis(aa.X, aa.n);

    cout << endl << endl << " 未知数协因数阵:" << endl;
    matdis(aa.QXX, aa.n, aa.n);

    cout << endl << endl << " 改正数:" << endl;
    matdis(aa.V, aa.m);

    cout << endl << endl << " 单位权中误差:+-" << aa.m0 << endl;

}
//************************************************************************************************   
int foutadj(adj& aa, char* name)
{
    ofstream on(name);
    if (!on) return 0;
    // 输出平差项目名       
    on << aa.name << endl << endl;

    // output observation number:     
    on << aa.m << endl;

    // output unknown data number:    
    on << aa.n << endl << endl;

    //out unknown data results    
    for (int i = 0; i < aa.n; i++)
        on << aa.X[i][0] << endl;
    on << endl;
    // 未知数协因数阵:"<
    for (int i = 0; i < aa.n; i++)
    {
        for (int j = 0; j < aa.n; j++)
            on << aa.QXX[i][j] << "  ";
        on << endl;
    }

    on << endl;
    //output 改正数:;   
    for (int i = 0; i < aa.m; i++)
        on << aa.V[i][0] << endl;
    on << endl;

    on << aa.m0 << endl;
    on.close();
    return 1;

}
//************************************************************************************************   
int rubust(adj& a)  // 定义抗差估计   
{
    // 1.最小二成平差   
    if (!doadj(a)) return 0;
    double* xold, * xnew, small(0), P[MAX], n0(0);
    xold = new double[a.n];
    int num(0);
    xnew = new double[a.n];
    for (int i = 0; i < a.m; i++)
        P[i] = a.P[i][i];
    do {
        small = 0;
        for (int i = 0; i < a.n; i++) *(xold + i) = a.X[i][0];
        // 2.等权处理   
        for( int i=  0; i < a.m; i++)
        {
            if (fabs(a.V[i][0]) > 2.5 * a.m0) { a.P[i][i] = 0; n0++; }
            else if (fabs(a.V[i][0]) < 1.8 * a.m0 * sqrt(1 / a.P[i][i]));
            else a.P[i][i] = a.P[i][i] / 1.8 / a.m0;
        }
        cout << "a.m0=" << a.m0 << endl;
        matdis(a.P, a.m, a.m);
        doadj(a);
        for (int i = 0; i < a.n; i++)
        {
            *(xnew + i) = a.X[i][0] - *(xold + i);
            if (small < fabs(*(xnew + i))) small = fabs(*(xnew + i));
        }
        num++;
    } while (small > 0.0000000001);
    if (n0) a.m0 *= sqrt((a.m - a.n) / (a.m - a.n - n0));
    delete[] xold;
    delete[] xnew;
    return 1;
}
//************************************************************************************************   
void matout(double A[][1], int n, ofstream &out)         // 向文件输出矩阵   
{
    for (int i = 0; i < n; i++)
        out << "     " << A[i][0] << endl;
}
//************************************************************************************************   
void matout(double A[][MAX], int n, int m, ofstream &out) // 向文件输出矩阵   
{//1.set B[][] I;   
    for (int i = 0; i < n; i++)
    {
        out << "     ";
        for (int j = 0; j < m; j++)
            out << A[i][j] << "  ";
        out << endl;
    }
}
//**********************************************************************************   
//****************       高程网平差程序     ****************************************   
struct Hpnt {                            //  高程点结构   
    char name[20];
    double H;
    double H0;
    double mH;
    int fixed; // known=1;else =0;   
    int i;     // point number   
};

struct line {                            //  水准线路结构                
    Hpnt* startp;
    Hpnt* endp;
    double length;
    double h;
    int style;  // 水准测量=1;三角高程=2   
};

struct Hnet {                            //  高程网结构   
    char netname[40];                   //  网名   
    int allpnum;                      //  总点数   
    int fixpnum;                      //  控制点个数   
    int obnum;                        //  观测值个数   
    double m0;                        //  验前单位权中误差   
    Hpnt Pt[MAX];                     //  高程点数组   
    line L[MAX];                      //  水准线路数组   
    adj aa;                           //  平差结构   
};
//************************************************************************************************   
int finHnet(Hnet& a, char* fname)        //  文件输入高程网函数    
{
    ifstream in(fname);   // 建立文件流,并与输入文件名建立关联   
    if (!in) { cout << fname << " error: file does not exist!   " << endl; return 0; }
   
    //  文件现实性判断  
    char name[20];
    in >> a.netname;
    cout << a.netname << endl;
    in >> a.obnum;
    cout << a.obnum<< endl;
    in >> a.allpnum;
    cout << a.allpnum << endl;
    in >> a.fixpnum;
    cout << a.fixpnum << endl;
    in >> a.m0;
    cout << a.m0 << endl;
    int n(a.fixpnum);                   // n为已输入名字的点的个数   
// 输入控制点信息     
    for (int i = 0; i < a.fixpnum; i++)
    {
        in >> a.Pt[i].name >> a.Pt[i].H;
        a.Pt[i].fixed = 1;                // 控制点标记   
        a.Pt[i].H0 = a.Pt[i].H;
        a.Pt[i].mH = 0;
        a.Pt[i].i = i;                    // 控制点编号,从0到a.fixpnum-1   
    }
    for( int i=  a.fixpnum; i < a.allpnum; i++)    // 输入未知点相关信息(名字在后面输入)       
    {
        a.Pt[i].fixed = 0;                // 未知点标记   
        a.Pt[i].H = 0; a.Pt[i].H0 = -PI;
        a.Pt[i].mH = 0;
        *(a.Pt[i].name) = 0;
        a.Pt[i].i = i;                    // 为未知点编号,从a.fixpnum到a.allpnum-1   
    }
    // 输入观测值        
    for( int i=  0; i < a.obnum; i++)
    {
        int t = 0;                           // 点名比较标志   
        in >> name;                         // 输入起点名   
        for (int k = 0; k < n; k++)
            if (_strnicmp(name, a.Pt[k].name, 20) == 0)
            {
                a.L[i].startp = &(a.Pt[k]); // 找到同名点,起点指针指向该点   
                t++;                      // 找到标志   
            }
        if (t == 0) {
            strcpy_s(a.Pt[n].name, name);
            a.L[i].startp = &(a.Pt[n]);   // 找不到同名点,该名输给新点   
            n++;
        }
        in >> name; t = 0;                    // 输入终点名,操作过程同上       
        for (int k = 0; k < n; k++)
            if (_strnicmp(name, a.Pt[k].name, 20) == 0)
            {
                a.L[i].endp = &(a.Pt[k]);
                t++;
            }
        if (t == 0) {
            strcpy_s(a.Pt[n].name, name);
            a.L[i].endp = &(a.Pt[n]);
            n++;
        }
        in >> a.L[i].h;                     // 输入线路高差   
        in >> a.L[i].length;                // 输入线路长度   
    }
    if (n != a.allpnum) {
       
        cout << fname << " error: file provide not correct point number !  " << endl;
        return 0;
    }
    //  文件正确性判断   
    in.close();                             // 关闭输入流及关联文件   

    // 向屏幕输出原始平差文件   
    cout << "     平差文件 " << fname << " 数据输入结果:" << endl;
    cout << "     " << a.netname << "  " << a.obnum << "  " << a.allpnum << "   "
        << a.fixpnum << "   " << a.m0 << endl << endl;
    for( int i=  0; i < a.fixpnum; i++)                // 控制点数据   
        cout << "     " << a.Pt[i].name << "   " << a.Pt[i].H << endl;
    cout << endl;
    for( int i=  0; i < a.obnum; i++)                  // 水准线路数据   
        cout << "     " << a.L[i].startp->name << "  " << a.L[i].endp->name << "  " << a.L[i].h
        << "  " << a.L[i].length << endl;

    //***********************  平差数据准备  ***************************   
    //   近似高程计算    
    do {
        n = 0;                     // 近似高程标志,=1表示仍有点近似高程未知   
        for( int i=  0; i < a.obnum; i++)
            if (a.L[i].startp->H0 == -PI || a.L[i].endp->H0 == -PI) { n = 1; break; }
        for( int i=  0; i < a.obnum; i++)          // 由水准线路计算近似高程   
        {
            if (a.L[i].startp->H0 != -PI && a.L[i].endp->H0 == -PI)
                a.L[i].endp->H0 = a.L[i].startp->H0 + a.L[i].h;
            if (a.L[i].startp->H0 == -PI && a.L[i].endp->H0 != -PI)
                a.L[i].startp->H0 = a.L[i].endp->H0 - a.L[i].h;
        }
    } while (n == 1);
    // 极大权法平差数据     
    a.aa.m = a.obnum;                       // 观测值个数   
    a.aa.n = a.allpnum;                     // 未知点个数(极大权处理,含控制点)   
  // 观测值权阵计算    
    for( int i=  0; i < a.aa.m; i++)
        for (int j = 0; j < a.aa.m; j++)
            if (i != j) a.aa.P[i][j] = 0;
            else a.aa.P[i][j] = 1 / a.L[i].length;
    cout << endl << endl << "     平差数据准备,请稍等......    " << endl << endl;
    cout << "      观测值权阵计算结果 :" << endl; matdis(a.aa.P, a.obnum, a.obnum);
    cout << endl;
    // 误差方程系数阵计算   
    for( int i=  0; i < a.aa.m; i++)                // 根据水准线路号及起、终点号确定   
        for (int j = 0; j < a.aa.n; j++)
            a.aa.A[i][j] = 0;
    for( int i=  0; i < a.aa.m; i++)
    {
        a.aa.A[i][a.L[i].endp->i] = 1;
        a.aa.A[i][a.L[i].startp->i] = -1;
    }
    cout << "     " << " 误差方程系数阵计算结果:  " << endl;
    matdis(a.aa.A, a.aa.m, a.aa.n);
    cout << endl;
    // 误差方程常数项计算   
    double AX0;
    for( int i=  0; i < a.aa.m; i++)                   // V=AX-L    
    {                                       // L=h-AX0   
        AX0 = 0;
        for (int j = 0; j < a.aa.n; j++)
            AX0 += a.aa.A[i][j] * a.Pt[j].H0;
        a.aa.l[i][0] = a.L[i].h - AX0;
    }
    cout << endl;
    cout << "     " << " 误差方程常数项计算结果 :" << endl;
    matdis(a.aa.l, a.aa.m);
    cout << endl;
    // 平差数据保存在date.txt文件中   
    ofstream out("date.txt");
    out << a.netname << endl;
    out << a.obnum << endl;
    out << a.allpnum << endl;
    matout(a.aa.A, a.aa.m, a.aa.n, out);
    out << endl;
    matout(a.aa.P, a.aa.m, a.aa.m, out);
    out << endl;
    matout(a.aa.l, a.aa.m, out);
    out.close();
    return 1;
}

//************************************************************************************************   
int Hnetadj(Hnet& a, char* outfile)       // 高程网平差函数   
{
    fsetadj(a.aa, "date.txt");
    cout << endl << "     正在平差计算,请稍等......    " << endl << endl;
    doadj(a.aa, a.fixpnum, 0);               // 极大权法最小二乘平差:   
    for (int i = 0; i < a.allpnum; i++)           // 未知点高程及精度计算   
    {
        a.Pt[i].H = a.Pt[i].H0 + a.aa.X[i][0];
        a.Pt[i].mH = a.aa.m0 * sqrt(a.aa.QXX[i][i]);
    }
    // 结果屏幕输出:   
    cout << endl << "     " << " 验后单位权中误差:+-" << a.aa.m0 << endl << endl << " 未知数改正数dX:  " << endl;
    matdis(a.aa.X, a.aa.n);
    cout << endl << "     " << " 观测值改正数V:" << endl;
    matdis(a.aa.V, a.aa.m);
    cout << endl << "     " << " 未知点高程及精度 :" << endl;
    for( int i=  a.fixpnum; i < a.allpnum; i++)
        cout << "     " << a.Pt[i].name << "高程=" << a.Pt[i].H << "  +-" << a.Pt[i].mH << endl;
    cout << endl;
    //  平差结果文件保存   
    ofstream out(outfile);
    if (!out) cout << "can not open save file!" << endl;
    out << "         高程网" << a.netname << "平差计算   " << endl << endl;
    out << "1. 原始数据:   " << endl << endl;
    out << "    " << a.netname << "   " << a.obnum << "   " << a.allpnum << "  " << a.fixpnum << "  " << a.m0 << endl;
    for( int i=  0; i < a.fixpnum; i++)
        out << "    " << a.Pt[i].name << "   " << a.Pt[i].H << endl;
    out << endl;
    for( int i=  0; i < a.obnum; i++)
        out << "    " << a.L[i].startp->name << "   " << a.L[i].endp->name << "   " << a.L[i].h
        << "   " << a.L[i].length << endl;
    out << endl;
    out << "2. 平差数据:" << endl << endl;
    out << "   2.1  误差方程系数阵: " << endl;
    matout(a.aa.A, a.aa.m, a.aa.n, out);
    out << endl << endl;
    out << "   2.2  误差方程权阵: " << endl;
    matout(a.aa.P, a.aa.m, a.aa.m, out);
    out << endl << endl;
    out << "   2.3  未知点近似高程: " << endl;
    for( int i=  a.fixpnum; i < a.allpnum; i++)
    {
        out << "     ";
        out << a.Pt[i].name << "   " << a.Pt[i].H0 << "  ";
        out << endl;
    }
    out << endl << endl;
    out << "   2.4  误差方程常数项: " << endl;
    matout(a.aa.l, a.aa.m, out);
    out << endl;
    out << "3. 平差结果 " << endl << endl;
    out << "   3.1  观测值改正数V: " << endl;
    matout(a.aa.V, a.aa.m, out);
    out << endl << endl;
    out << "   3.2  单位权中误差m0:+-" << a.aa.m0 << endl;
    out << endl << endl;
    out << "   3.3  未知数改正数dH:" << endl;
    for( int i=  a.fixpnum; i < a.allpnum; i++)
    {
        out << "     ";
        out << a.aa.X[i][0] << "  ";
        out << endl;
    }
    out << endl << endl;
    out << "   3.4  未知点高程及精度: " << endl;
    for( int i=  a.fixpnum; i < a.allpnum; i++)
    {
        out << "     ";
        out << a.Pt[i].name << "   " << a.Pt[i].H << "   +-" << a.Pt[i].mH;
        out << endl;
    }
    out << endl << endl;
    out << "   3.5  未知参数协方差阵: " << endl;
    for( int i=  a.fixpnum; i < a.allpnum; i++)
    {
        out << "     ";
        for (int j = a.fixpnum; j < a.allpnum; j++)
            out << a.aa.m0 * a.aa.m0 * a.aa.QXX[i][j] << "  ";
        out << endl;
    }
    out.close();
    return 1;
}


int Hdoadj(Hnet& a, char* infilename, char* outfilename)
{
    if (finHnet(a, infilename)) {

        Hnetadj(a, outfilename);
        return 1;
    }
    else return 0;
}

// ***********************************************************************************************   
// *********************************** 平面网平差******** ****************************************   

double d_h(double angle)                      //角度化弧度   
{
    double a, b;
    angle = modf(angle, &a);
    angle = modf(angle * 100.0, &b);
    return (a + b / 60.0 + angle / 36.0) * (PI + 3.0E-16) / 180.0;
}
// ***********************************************************************************************   
double h_d(double angle)                      //弧度化角度   
{
    double a, b, c;
    angle = modf(angle * 180.0 / (PI - 3.0E-16), &a);
    angle = modf(angle * 60.0, &b);
    angle = modf(angle * 60.0, &c);
    return a + b * 0.01 + c * 0.0001 + angle * 0.0001;
}


// ************************************平面网平差计算*********************************************   
// ************************************平面网点结构定义*******************************************   
struct XYP {
    char name[20];                  // 点名   
    double X;                     // x坐标值   
    double Y;                     // y坐标值   
    double X0;                    // x坐标近似值   
    double Y0;                    // y坐标近似值   
    double mX;                    // x坐标中误差   
    double mY;                    // y坐标中误差   
    double mp;                    // 点位中误差   
    double E;                     // 误差椭圆长半轴    
    double F;                     // 误差椭圆短半轴   
    double T;                     // 误差椭圆长半轴方向     
    int fixed;                    // 是否控制点(控制点为1;未知点为0)   
    int i;                        // 点号(0-->allpnum-1)   
};

//*****************************对点的"=="的重载***************************************************   
int operator ==(XYP& a, XYP& b)
{

    if (_strnicmp(b.name, a.name, 20))
        return 1;
    else return 0;
}

//***********************************平面网观测值结构*********************************************   
struct obser {
    XYP* startp;                  // 观测值起点指针   
    XYP* endp;                    // 观测值终点指针   
    double dist;                  // 距离观测值   
    double dist0;                 // 近似距离   
    double angle;                 // 方向观测值   
    double A;                     // 观测值方位角   
    double A0;                    // 近似方位角    
    double m0;                    // 观测值平差值精度    
    int i;                        // 测站的观测值序号   
    int sti;                      // 测站序号   
    int style;                    // 角度测量=1;距离测量=2;固定方位角=3;固定边长=4    
};

//******************************平面网测站结构****************************************************   
struct stat1 {
    XYP* stp;
    int obnum;                    // 测站观测值总数    
    int disnum;                   // 测站距离观测值个数   
    int aglnum;                   // 测站方向观测值个数        
    int i;                        // 测站序号     
};
//********************************平面网结构******************************************************   
struct XYnet {
    char netname[40];             //  网名   
    int allpnum;                  //  总点数   
    int fixpnum;                  //  控制点个数   
    int statnum;                  //  测站数   
    int obnum;                    //  观测值总数   
    int fixdisn;                  //  固定边长个数   
    int fixafn;                   //  固定方位角个数   
    int anglenum;                 //  方向观测值总数   
    int distnum;                  //  距离观测值总数   
    double mangle;                //  验前方向观测值误差   
    double msa;                   //  距离误差加常数   
    double msb;                   //  距离误差乘常数   
    stat1 st[MAX];                 //  定义平面网测站结构    
    XYP Pt[MAX];                  //  平面网点结构   
    obser L[MAX];                 //  平面网观测值结构   
    adj aa;                       //  平面网平差结构   
};

//************************* 坐标反算距离**********************************************************   
double dist(XYP& a, XYP& b)
{
    if (a.X != -PI && b.X != -PI)
        return sqrt((b.X - a.X) * (b.X - a.X) + (b.Y - a.Y) * (b.Y - a.Y));
    if (a.X0 != -PI && b.X0 != -PI)
        return sqrt((b.X0 - a.X0) * (b.X0 - a.X0) + (b.Y0 - a.Y0) * (b.Y0 - a.Y0));
    return -PI;
}


//************************* 坐标反算方位角********************************************************   
double afa(XYP& a, XYP& b)
{
    if (a.X != -PI && b.X != -PI)
    {
        double d = dist(a, b);
        double t = acos((b.X - a.X) / d);
        if (b.Y - a.Y < 0.0) t = 2.0 * PI - t;
        return t;
    }
    if (a.X0 != -PI && b.X0 != -PI)
    {
        double d = dist(a, b);
        double t = acos((b.X0 - a.X0) / d);
        if (b.Y0 - a.Y0 < 0.0) t = 2.0 * PI - t;
        return t;
    }
    return -PI;
}

//**********************************两方向交会近似坐标计算****************************************   
int XY0ang(obser& a1, obser& a2)           // 两方向交会近似坐标计算   
{
    if (a1.A0 == -PI || a2.A0 == -PI || a1.A0 == a2.A0)  return 0;
    if (d_h(a1.A0) == d_h(a2.A0) + PI || d_h(a1.A0) == d_h(a2.A0) - PI) return 0;
    if (a1.dist != -PI || a1.dist0 != -PI || a2.dist != -PI || a2.dist0 != -PI) return 0;

    double k, B[MAX][MAX], A[MAX][MAX], L[MAX][1], X[MAX][1];
    if (a1.startp == a2.startp && a1.startp->X0 == -PI && a1.endp->X0 != -PI && a2.endp->X0 != -PI)
    {

        k = tan(d_h(a1.A0));
        A[0][0] = k; A[0][1] = -1;
        L[0][0] = k * a1.endp->X0 - a1.endp->Y0;
        k = tan(d_h(a2.A0));
        A[1][0] = k; A[1][1] = -1;
        L[1][0] = k * a2.endp->X0 - a2.endp->Y0;
        inverse(A, B, 2);
        AXB(B, L, X, 2, 2);
        a1.startp->X0 = X[0][0];
        a1.startp->Y0 = X[1][0];
        //      cout<<"XY0ang****1   "<
        return 1;
    }
    /*
        if(a1.endp==a2.endp && a1.startp->X0!=-PI && a2.startp->X0!=-PI && a1.endp->X0==-PI)
       {
            k=tan(d_h(a1.A0));
            A[0][0]=-k;A[0][1]=1;
            L[0][0]=-(k*a1.startp->X0-a1.startp->Y0);
            k=tan(d_h(a2.A0));
            A[1][0]=-k;A[1][1]=1;
            L[1][0]=-(k*a2.startp->X0-a2.startp->Y0);
            inverse(A,B,2);
    //      cout<<"XY0ang****3   "<X0=X[0][0];
            a1.endp->Y0=X[1][0];
                return 1;
        }

         if(a1.startp==a2.endp && a1.startp->X0==-PI && a1.endp->X0!=-PI && a2.startp->X0!=-PI)
        {
            k=tan(d_h(a1.A0));
            A[0][0]=k;A[0][1]=-1;
            L[0][0]=k*a1.endp->X0-a1.endp->Y0;
            k=tan(d_h(a2.A0));
            A[1][0]=-k;A[1][1]=1;
            L[1][0]=-(k*a2.startp->X0-a2.startp->Y0);
            inverse(A,B,2);
            AXB(B,L,X,2,2);
            a1.startp->X0=X[0][0];
            a1.startp->Y0=X[1][0];
    //          cout<<"XY0ang****3   "<X0==-PI && a1.startp->X0!=-PI && a2.endp->X0!=-PI)
        {
            k=tan(d_h(a1.A0));
            A[0][0]=-k;A[0][1]=1;
            L[0][0]=-(k*a1.startp->X0-a1.startp->Y0);
            k=tan(d_h(a2.A0));
            A[1][0]=k;A[1][1]=-1;
            L[1][0]=k*a2.endp->X0-a2.endp->Y0;
            inverse(A,B,2);
            AXB(B,L,X,2,2);
            a1.endp->X0=X[0][0];
            a1.endp->Y0=X[1][0];
        //          cout<<"XY0ang****4   "<
    return 0;
}
//**********************************三边交会法计算近似坐标****************************************   
int XY0dist(obser& a, obser& b, obser& c) // 三边交会法计算近似坐标   
{
    if (a.dist0 == -PI || b.dist0 == -PI || c.dist0 == -PI)  return 0;
    if (a.startp != b.startp || a.startp != c.startp || b.startp != c.startp) return 0;
    if (a.endp == b.endp || a.endp == c.endp || b.endp == c.endp) return 0;
    if (a.endp->X0 == -PI || b.endp->X0 == -PI || c.endp->X0 == -PI || a.startp->X0 != -PI) return 0;
    double a1 = afa(*(a.endp), *(b.endp)) - afa(*(a.endp), *(c.endp));
    if (fabs(a1) < 0.2 * PI || fabs(fabs(a1) - PI) < 0.2) return 0;
    double B[MAX][MAX], A[MAX][MAX], L[MAX][1], X[MAX][1];

    A[0][0] = a.endp->X0 - b.endp->X0;  A[0][1] = a.endp->Y0 - b.endp->Y0;
    L[0][0] = (-a.dist0 * a.dist0 + b.dist0 * b.dist0 + a.endp->X0 * a.endp->X0
        - b.endp->X0 * b.endp->X0 + a.endp->Y0 * a.endp->Y0 - b.endp->Y0 * b.endp->Y0) / 2.0;

    A[1][0] = a.endp->X0 - c.endp->X0;  A[1][1] = a.endp->Y0 - c.endp->Y0;
    L[1][0] = (-a.dist0 * a.dist0 + c.dist0 * c.dist0 + a.endp->X0 * a.endp->X0
        - c.endp->X0 * c.endp->X0 + a.endp->Y0 * a.endp->Y0 - c.endp->Y0 * c.endp->Y0) / 2.0;
    inverse(A, B, 2);
    AXB(B, L, X, 2, 2);
    a.startp->X0 = X[0][0];
    a.startp->Y0 = X[1][0];
    //      cout<<"XY0dist****1   "<
    return 1;
}
//***********************************坐标正算法近似坐标计算***************************************   

// 坐标正算   
int zheng(obser& a)
{
    if (a.startp->X0 == -PI && a.endp->X0 == -PI || a.startp->X0 != -PI && a.endp->X0 != -PI
        || a.dist0 == -PI || a.A0 == -PI)
        return 0;
    if (a.startp->X0 != -PI && a.endp->X0 == -PI)
    {
        a.endp->X0 = a.startp->X0 + cos(d_h(a.A0)) * a.dist0;                     // 要求方位角为弧度制   
        a.endp->Y0 = a.startp->Y0 + sin(d_h(a.A0)) * a.dist0;
        return 1;
    }

    if (a.startp->X0 == -PI && a.endp->X0 != -PI)
    {
        a.startp->X0 = a.endp->X0 - cos(d_h(a.A0)) * a.dist0;                     // 要求方位角为弧度制   
        a.startp->Y0 = a.endp->Y0 - sin(d_h(a.A0)) * a.dist0;
        return 1;
    }
    return 0;
}
//*********************************角度后方交会法计算近似坐标*************************************   

//角度后方交会法计算近似坐标   
int houj(obser& a, obser& b, obser& c)
{
    if (a.startp != b.startp || a.startp != c.startp || b.startp != c.startp) return 0;
    if (a.endp->X0 == -PI || b.endp->X0 == -PI || c.endp->X0 == -PI) return 0;
    if (a.angle == -PI || b.angle == -PI || c.angle == -PI) return 0;
    if (a.A0 != -PI || b.A0 != -PI || c.A0 != -PI || a.startp->X0 != -PI) return 0;
    // add code here...   
    obser L1, L2, L0;
    int i = 0;
    if (i < a.i) { i = a.i; L2 = a; } if (i < b.i) { i = b.i; L2 = b; } if (i < c.i) { i = c.i; L2 = c; }
    i = 1000000;
    if (i > a.i) { i = a.i; L0 = a; } if (i > b.i) { i = b.i; L0 = b; } if (i > c.i) { i = c.i; L0 = c; }
    if ((a.i == L0.i || a.i == L2.i) && (b.i == L0.i || b.i == L2.i))  L1 = c;
    if ((a.i == L0.i || a.i == L2.i) && (c.i == L0.i || c.i == L2.i))  L1 = b;
    if ((b.i == L0.i || b.i == L2.i) && (c.i == L0.i || c.i == L2.i))  L1 = a;
    double A, B, C, af, bt, B1, B2;
    B = afa(*(L1.endp), *(L0.endp)) - afa(*(L1.endp), *(L2.endp));   //弧度   
    A = afa(*(L0.endp), *(L2.endp)) - afa(*(L0.endp), *(L1.endp));   //弧度   
    C = afa(*(L2.endp), *(L1.endp)) - afa(*(L2.endp), *(L0.endp));   //弧度   
    B = fabs(B); if (B > PI) B = 2 * PI - B;
    A = fabs(A); if (A > PI) A = 2 * PI - A;
    C = fabs(C); if (C > PI) C = 2 * PI - C;

    af = d_h(L1.angle) - d_h(L0.angle);     //弧度   

    if (af > PI) af = 2 * PI - af;
    bt = d_h(L2.angle) - d_h(L1.angle);     //弧度   
    if (bt > PI) bt = 2 * PI - bt;

    B1 = atan((1 / tan(A) - 1 / tan(bt)) / (1 - 1 / tan(A) / tan(af) - 1 / tan(B) * (1 / tan(af) + 1 / tan(bt))));
    if (B1 < 0)B1 += PI;
    B2 = atan((1 / tan(C) - 1 / tan(af)) / (1 - 1 / tan(C) / tan(bt) - 1 / tan(B) * (1 / tan(af) + 1 / tan(bt))));
    if (B2 < 0)B2 += PI;
    //  cout<
    L1.A0 = h_d(afa(*(L1.endp), *(L0.endp)) - B1 + PI);
    if (L1.A0 > 360) L1.A0 = h_d(d_h(L1.A0) - 2 * PI);
    double dd = d_h(L1.angle) - d_h(L1.A0);
    L0.A0 = h_d(d_h(L0.angle) - dd);
    L2.A0 = h_d(d_h(L2.angle) - dd);

    XY0ang(L0, L1);
    //    cout<X0<<"    "<Y0<

    return 1;
}

//**************************键盘输入未知点近似坐标************************************************   
void kinXY0(XYnet& a)     // 键盘输入未知点近似坐标   
{
    for (int i = a.fixpnum; i < a.allpnum; i++)
    {
        cout << a.Pt[i].name << " x0= "; cin >> a.Pt[i].X0; cout << endl;
        cout << a.Pt[i].name << " y0= "; cin >> a.Pt[i].Y0; cout << endl;
    }

}
//****************************文件输入未知点近似坐标**********************************************   
int finXY0(XYnet& a, char* XY0filename)      // 文件输入未知点近似坐标   
{
    // add code here   
    return 1;

}
//****************************************逐测站近似方位角推算************************************   
void statangc(XYnet& a)
{
    int n1 = 0;
    int n = a.obnum + a.fixafn + a.fixdisn;
    for (int i = 0; i < a.statnum; i++) // 逐测站   
    {
        for (int j = n1; j < n1 + a.st[i].aglnum; j++) //  测站首观测值的序号    
        {
            if (a.L[j].A0 != -PI)
            {
                double df = d_h(a.L[j].angle) - d_h(a.L[j].A0);
                for (int k = j - a.L[j].i; k < j - a.L[j].i + a.st[a.L[j].sti].aglnum; k++)
                    if (a.L[k].A0 == -PI)
                    {
                        if (d_h(a.L[k].angle) - df >= 0) a.L[k].A0 = h_d(d_h(a.L[k].angle) - df);
                        if (d_h(a.L[k].angle) - df >= 2 * PI) a.L[k].A0 = h_d(d_h(a.L[k].angle) - df - 2 * PI);
                        if (d_h(a.L[k].angle) - df < 0) a.L[k].A0 = h_d(d_h(a.L[k].angle) - df + 2.0 * PI);

                        for (int k1 = 0; k1 < n; k1++)            //  已知近似方位角的传递   
                        {
                            if (a.L[k1].A0 == -PI && a.L[k1].startp == a.L[k].endp
                                && a.L[k1].endp == a.L[k].startp)
                                if (d_h(a.L[k].A0) - PI >= 0) a.L[k1].A0 = h_d(d_h(a.L[k].A0) - PI);
                                else a.L[k1].A0 = h_d(d_h(a.L[k].A0) + PI);
                            if (a.L[k1].A0 == -PI && a.L[k1].startp == a.L[k].startp
                                && a.L[k1].endp == a.L[k].endp)
                                a.L[k1].A0 = a.L[k].A0;
                        }
                        break;
                    }
            }
        }
        n1 += a.st[i].disnum + a.st[i].aglnum;      //  下一个测站   
    }
}
//****************************************???三角形结构*******************************************   
struct Triangle
{
    XYP p1;
    XYP p2;
    XYP p3;
    double p1ang;
    double p2ang;
    double p3ang;
    double d12;
    double d13;
    double d23;
    double adajian180;
};
//************************无定向导线计算未知点的近似坐标******************************************   
int Udxdsetx0y0(XYnet& a)      // 用于三角网控制点不相邻且无方向观测情况     
{
    // add code here   
    int obi, flag;
    for (int i = 0; i < a.obnum; i++)
        if (a.L[i].startp->fixed == 1 && a.L[i].endp->fixed || a.L[i].A0 != -PI) return 0;
    // 1号以上控制点近似坐标归零       
    for( int i=  1; i < a.fixpnum; i++)
        a.Pt[i].X0 = a.Pt[i].Y0 = -PI;
    // 起始边确定       
    for( int i=  0; i < a.obnum; i++)
        if (a.L[i].startp->i == 0 && a.L[i].endp->fixed == 0
            || a.L[i].startp->fixed == 0 && a.L[i].endp->i == 0) {
            obi = i; break;
        }
    // 假设方位角与边长     
    if (a.L[obi].A0 == -PI)a.L[obi].A0 = 0;
    if (a.L[obi].dist0 == -PI)a.L[obi].dist0 = 1;
    XYP end;
    zheng(a.L[obi]);
    // 假设方位角计算         
    do {
        flag = 0;
        statangc(a);
        for (int i = 0; i < a.obnum; i++)
            if (a.L[i].A0 == -PI) { flag = 1; break; }
    } while (flag == 1);
    // 假设近似坐标计算    
    flag = 0;
    do {
        for (int i = 0; i < a.obnum - 1; i++)
            for (int j = i + 1; j < a.obnum; j++)
                XY0ang(a.L[i], a.L[j]);
        flag++;
    } while (flag < a.obnum);
    end.X0 = a.Pt[1].X0; end.Y0 = a.Pt[1].Y0;
    end.X = end.Y = -PI;

    // 计算改正后起始坐标方位角与长度           
    a.L[obi].dist0 *= dist(a.Pt[0], a.Pt[1]) / dist(a.Pt[0], end);
    double ddf = afa(a.Pt[0], a.Pt[1]) - afa(a.Pt[0], end);
    if (ddf < 0) ddf += 2 * PI;
    a.L[obi].A0 += h_d(ddf);
    // 各点近似坐标归零           
    for( int i=  1; i < a.allpnum; i++)
        if (i < a.fixpnum) { a.Pt[i].X0 = a.Pt[i].X; a.Pt[i].Y0 = a.Pt[i].Y; }
        else a.Pt[i].X0 = a.Pt[i].Y0 = -PI;

    // 近似方位角归零           
    for( int i=  0; i < a.obnum + a.fixafn + a.fixdisn; i++)
        if (i != obi)a.L[i].A0 = -PI;
    zheng(a.L[obi]);                       //   坐标正算   
// 计算改正后近似方位角          
    do {
        flag = 0;
        statangc(a);
        for (int i = 0; i < a.obnum; i++)
            if (a.L[i].A0 == -PI) { flag = 1; break; }
    } while (flag == 1);
    // 计算改正后各点的近似坐标           
    do {
        flag = 0;
        for (int i = 0; i < a.obnum - 1; i++)
            for (int j = i + 1; j < a.obnum; j++)
                XY0ang(a.L[i], a.L[j]);
        for( int i=  0; i < a.allpnum; i++)
            if (a.Pt[i].X0 == -PI)
            {
                flag = 1; break;
            }
    } while (flag == 1);
    //  for(i=0;i
    //      cout<
    //      <

    return 1;
}
//************************计算控制网未知点的近似坐标**********************************************   
int setx0y0(XYnet& a)
{
    int n = a.obnum + a.fixdisn + a.fixafn;
    // 1.计算近似坐标、近似边长确定的方位角与边长   
    int t(0);
    do {
        for (int i = 0; i < n; i++)
        {
            if (a.L[i].startp->X0 != -PI && a.L[i].endp->X0 != -PI && a.L[i].A0 == -PI)
            {
                //1.1 近似坐标确定的边的方位角        
                a.L[i].A0 = h_d(afa(*(a.L[i].startp), *(a.L[i].endp)));
                for (int k = 0; k < n; k++)
                {
                    if (a.L[i].startp == a.L[k].endp && a.L[i].endp == a.L[k].startp && a.L[k].A0 == -PI)
                    {
                        if (d_h(a.L[i].A0) - PI >= 0)
                            a.L[k].A0 = h_d(d_h(a.L[i].A0) - PI);
                        else a.L[k].A0 = h_d(d_h(a.L[i].A0) + PI);
                    }
                    if (a.L[i].startp == a.L[k].startp && a.L[i].endp == a.L[k].endp && a.L[k].A0 == -PI)
                        a.L[k].A0 = a.L[i].A0;
                }
            }
            //1.2 边长观测值计算的近似边长        
            if (a.L[i].style == 2 || a.L[i].style == 4)
                for (int k = 0; k < n; k++)
                    if (a.L[i].startp == a.L[k].endp && a.L[i].endp == a.L[k].startp && a.L[k].dist0 == -PI
                        || a.L[i].startp == a.L[k].startp && a.L[i].endp == a.L[k].endp && a.L[k].dist0 == -PI)
                        a.L[k].dist0 = a.L[i].dist0;
            //1.3 由已知近似方位角推算未知近似方位角   
            if (a.L[i].A0 != -PI)
                for (int k = 0; k < n; k++)
                {
                    if (a.L[i].startp == a.L[k].endp && a.L[i].endp == a.L[k].startp && a.L[k].A0 == -PI)
                    {
                        if (d_h(a.L[i].A0) - PI >= 0)
                            a.L[k].A0 = h_d(d_h(a.L[i].A0) - PI);
                        else a.L[k].A0 = h_d(d_h(a.L[i].A0) + PI);
                    }
                    if (a.L[i].startp == a.L[k].startp && a.L[i].endp == a.L[k].endp && a.L[k].A0 == -PI)
                        a.L[k].A0 = a.L[i].A0;
                }
        }

        // 2. 以测站计算观测值近似方位角   
        statangc(a);
        // 3.近似坐标计算   

        //   3.1 两方位角交会法   
        for( int i=  0; i < n - 1; i++)
            for (int j = i + 1; j < n; j++)
                XY0ang(a.L[i], a.L[j]);

        //   3.2 坐标正算法   
        for( int i=  0; i < a.obnum + a.fixafn + a.fixdisn; i++)
            zheng(a.L[i]);

        //   3.3 角度后方交会法   
        for( int i=  0; i < a.obnum - 2; i++)
            for (int j = i + 1; j < a.obnum - 1; j++)
                for (int k = j + 1; k < a.obnum; k++)
                    houj(a.L[i], a.L[j], a.L[k]);

        //   3.4边长后方交会法      
        for( int i=  0; i < a.obnum + a.fixafn + a.fixdisn - 2; i++)
            for (int j = i + 1; j < a.obnum + a.fixafn + a.fixdisn - 1; j++)
                for (int k = j + 1; k < a.obnum + a.fixafn + a.fixdisn; k++)
                    XY0dist(a.L[i], a.L[j], a.L[k]);

        //   3.5 无定向导线   
        Udxdsetx0y0(a);

        // 4. 迭代条件的判断           
        t = 0;
        for( int i=  0; i < a.allpnum; i++)
        {
            //      cout<
            if (a.Pt[i].X0 == -PI || a.Pt[i].Y0 == -PI)
                t = 1;
        }
    } while (t == 1);

    cout << "---------------------------------------------------------------------------" << endl;
    cout << "            未知点近似坐标           " << endl;
    cout << "---------------------------------------------------------------------------" << endl;
    for (int ii = a.fixpnum; ii < a.allpnum; ii++)
        cout << "    " << a.Pt[ii].name << "  " << setf(a.Pt[ii].X0, 3) << "  " << setf(a.Pt[ii].Y0, 3) << endl;
    cout << "---------------------------------------------------------------------------" << endl;

    return 1;
}

//********************************设置平面网平差的A,P,L*******************************************   
int setXYadj(XYnet& a)
{
    // 1 确定平差网基本信息   
    a.aa.m = a.obnum + a.fixafn + a.fixdisn;
    a.aa.n = 2 * a.allpnum + a.statnum;
    // 2 确定观测值的权镇P    
    for (int i = 0; i < a.aa.m; i++)
    {
        for (int j = 0; j < a.aa.m; j++)
            a.aa.P[i][j] = 0;
        if (a.L[i].style == 1)        // 设置角度观测值的权               
        {
            a.aa.P[i][i] = 1;
        }
        if (a.L[i].style == 2)        // 设置距离观测值的权   
        {
            double mlml = a.msa + a.msb / 1000000 * a.L[i].dist;
            mlml *= mlml;
            a.aa.P[i][i] = a.mangle / rou * a.mangle / rou / mlml;
        }
        if (a.L[i].style == 3 || a.L[i].style == 4)// 设置固定距离与方位角观测值的权   
            a.aa.P[i][i] = 1000000;
    }
    //  matdis(a.aa.P,a.aa.m,a.aa.m);         
   // 3 确定误差方程系数阵A    
    for( int i=  0; i < a.aa.m; i++)
    {
        double s = dist(*(a.L[i].startp), *(a.L[i].endp));
        //     cout<
        double ss = s * s;

        double dy = a.L[i].endp->Y0 - a.L[i].startp->Y0;
        double dx = a.L[i].endp->X0 - a.L[i].startp->X0;
        double aki = dy / ss; double bki = -1 * dx / ss;

        for (int j = 0; j < a.aa.n; j++)
        {
            a.aa.A[i][j] = 0;
            if (a.L[i].style == 1)                             // 方向观测值误差方程系数    
            {
                a.aa.A[i][2 * a.allpnum + a.L[i].sti] = -1;          // 测站定向角未知数系数   

                a.aa.A[i][2 * (a.L[i].startp->i)] = aki;
                a.aa.A[i][2 * (a.L[i].startp->i) + 1] = bki;
                a.aa.A[i][2 * (a.L[i].endp->i)] = -aki;
                a.aa.A[i][2 * (a.L[i].endp->i) + 1] = -bki;
            }
            if (a.L[i].style == 2 || a.L[i].style == 4)        // 边长观测值、固定边长误差方程系数   
            {
                a.aa.A[i][2 * (a.L[i].startp->i)] = bki * s;
                a.aa.A[i][2 * (a.L[i].startp->i) + 1] = -aki * s;
                a.aa.A[i][2 * (a.L[i].endp->i)] = -bki * s;
                a.aa.A[i][2 * (a.L[i].endp->i) + 1] = aki * s;
            }
            if (a.L[i].style == 3)                             // 固定方位角误差方程系数    
            {
                a.aa.A[i][2 * a.L[i].startp->i] = aki;
                a.aa.A[i][2 * a.L[i].startp->i + 1] = bki;
                a.aa.A[i][2 * a.L[i].endp->i] = -aki;
                a.aa.A[i][2 * a.L[i].endp->i + 1] = -bki;
            }
        }

    }
    //  matdis(a.aa.A,a.aa.m,a.aa.n);    
    // 4 确定误差方程常数项L   
    for( int i=  0; i < a.aa.m; i++)
    {
        a.L[i].A0 = h_d(afa(*(a.L[i].startp), *(a.L[i].endp)));
        a.L[i].dist0 = dist(*(a.L[i].startp), *(a.L[i].endp));

        if (a.L[i].style == 3)
        {
            a.aa.l[i][0] = d_h(a.L[i].A - a.L[i].A0);
        }
        if (a.L[i].style == 2 || a.L[i].style == 4)
        {
            a.aa.l[i][0] = a.L[i].dist - a.L[i].dist0;
        }

    }
    //方向观测值误差方程常数项   
    int n = 0;
    for (int j = 0; j < a.statnum; j++)
    {
        for (int i = n; i < n + a.st[j].aglnum; i++)
        {
            double scd = d_h(a.L[i].A0) - d_h(a.L[n].A0);
            if (scd < 0) scd += 2 * PI;
            a.aa.l[i][0] = d_h(a.L[i].angle) - scd;
        }
        n += a.st[j].aglnum + a.st[j].disnum;
    }
    //matdis(a.aa.l,a.aa.m);   

    return 1;
}
//********************************控制网平差计算**************************************************   
int doXYadj(XYnet& a)
{
    // 6 平差计算   
    int r0 = a.fixafn + a.fixdisn;
    if (!doadj(a.aa, 2 * a.fixpnum, r0))return 0;            // 其中第二项为控制点数与测站数之和   
    cout << "---------------------------------------------------------------------------" << endl;
    cout << "   未知数改正数           " << endl;
    cout << "---------------------------------------------------------------------------" << endl;
    matdis(a.aa.X, a.aa.n);

    cout << "---------------------------------------------------------------------------" << endl;
    cout << "   验后单位权中误差:" << a.aa.m0 * 206264.8 << " 秒 " << endl;
    cout << "---------------------------------------------------------------------------" << endl;
    cout << "   平差后未知点坐标: " << endl << endl;
    cout << "---------------------------------------------------------------------------" << endl;

    for (int i = a.fixpnum; i < a.allpnum; i++)
    {
        a.Pt[i].X = a.Pt[i].X0 + a.aa.X[2 * i][0];
        a.Pt[i].Y = a.Pt[i].Y0 + a.aa.X[2 * i + 1][0];
        a.Pt[i].X0 += a.aa.X[2 * i][0];
        a.Pt[i].Y0 += a.aa.X[2 * i + 1][0];
        cout.precision(11); cout.width(10);
        cout << "      " << a.Pt[i].name << "  " << setf(a.Pt[i].X, 4) << "  " << setf(a.Pt[i].Y, 4) << endl;
    }
    cout << "---------------------------------------------------------------------------" << endl;
    cout << "    未知点坐标的协方差阵:" << endl << endl;
    cout << "---------------------------------------------------------------------------" << endl;
    for( int i=  2 * a.fixpnum; i < 2 * a.allpnum; i++)
    {
        cout << "    ";
        for (int j = 2 * a.fixpnum; j < 2 * a.allpnum; j++)
        {
            cout << a.aa.m0 * a.aa.m0 * a.aa.QXX[i][j] << "  ";

        }cout << endl;
    }
    cout << "---------------------------------------------------------------------------" << endl;
    cout << "    观测值改正数:" << endl << endl;
    cout << "---------------------------------------------------------------------------" << endl;
    matdis(a.aa.V, a.aa.m);
    cout << "---------------------------------------------------------------------------" << endl;

    //7 点位中误差与误差椭圆元素计算   

    for( int i=  a.fixpnum; i < a.allpnum; i++)
    {
        // 坐标中误差计算   
        a.Pt[i].mX = a.aa.m0 * sqrt(a.aa.QXX[2 * i][2 * i]);
        a.Pt[i].mY = a.aa.m0 * sqrt(a.aa.QXX[2 * i + 1][2 * i + 1]);

        // 误差椭圆参数计算    
        double  K = sqrt((a.aa.QXX[2 * i][2 * i] - a.aa.QXX[2 * i + 1][2 * i + 1])
            * (a.aa.QXX[2 * i][2 * i] - a.aa.QXX[2 * i + 1][2 * i + 1])
            + 4 * a.aa.QXX[2 * i][2 * i + 1] * a.aa.QXX[2 * i][2 * i + 1]);
        a.Pt[i].mp = sqrt(a.Pt[i].mX * a.Pt[i].mX + a.Pt[i].mY * a.Pt[i].mY);
        a.Pt[i].E = sqrt(1 / 2.0 * a.aa.m0 * a.aa.m0 * (a.aa.QXX[2 * i][2 * i] + a.aa.QXX[2 * i + 1][2 * i + 1] + K));
        a.Pt[i].F = sqrt(1 / 2.0 * a.aa.m0 * a.aa.m0 * (a.aa.QXX[2 * i][2 * i] + a.aa.QXX[2 * i + 1][2 * i + 1] - K));

        double F2 = atan2(2 * a.aa.QXX[2 * i][2 * i + 1], a.aa.QXX[2 * i][2 * i] - a.aa.QXX[2 * i + 1][2 * i + 1]);
        if (F2 <= 0) F2 += 2 * PI; F2 /= 2.0;
        if (a.aa.QXX[2 * i][2 * i + 1] > 0 && F2 > PI / 2.0 && F2 < PI
            || a.aa.QXX[2 * i][2 * i + 1]>0 && F2 > PI * 3 / 2.0 && F2 < 2 * PI)
            F2 += PI / 2.0;
        if (a.aa.QXX[2 * i][2 * i + 1] < 0 && F2 < PI / 2.0 && F2>0
            || a.aa.QXX[2 * i][2 * i + 1]<0 && F2>PI && F2 < PI * 3 / 2.0)
            F2 += PI / 2.0;
        if (F2 >= 2 * PI) F2 -= 2 * PI;
        a.Pt[i].T = h_d(F2);

    }

    return 1;
}

//*******************************平面网的文件输入*************************************************   
int finXYnet(XYnet& a,const  char* fname)        //  文件输入平面网函数    
{
    ifstream in(fname);     // 建立文件流,并与输入文件名建立关联   
    if (!in) { cout << fname << " error: file does not exist!   " << endl; return 0; }
    //  文件现实性判断   

// 1 输入网的基本信息   
    char name[20];
    in >> a.netname;
    in >> a.allpnum;
    in >> a.fixpnum;
    in >> a.statnum;
    //  in>>a.obnum;   
    a.obnum = 0;
    in >> a.fixdisn;
    in >> a.fixafn;
    in >> a.mangle;
    in >> a.msa;
    in >> a.msb;
    int n(a.fixpnum);                   // n为已输入名字的点的个数   

// 2输入控制点信息    
    for (int i = 0; i < a.fixpnum; i++)
    {
        in >> a.Pt[i].name >> a.Pt[i].X >> a.Pt[i].Y;
        a.Pt[i].fixed = 1;                // 控制点标记   
        a.Pt[i].X0 = a.Pt[i].X;
        a.Pt[i].Y0 = a.Pt[i].Y;
        a.Pt[i].mX = a.Pt[i].mY = 0;
        a.Pt[i].i = i;                    // 控制点编号,从0到a.fixpnum-1   
    }

    // 3 输入未知点相关信息(名字在后面输入)     
    for( int i=  a.fixpnum; i < a.allpnum; i++)
    {
        a.Pt[i].fixed = 0;                // 未知点标记   
        a.Pt[i].X = a.Pt[i].Y = -PI;
        a.Pt[i].X0 = a.Pt[i].Y0 = -PI;
        a.Pt[i].mX = a.Pt[i].mY = 0;
        *(a.Pt[i].name) = 0;
        a.Pt[i].i = i;                    // 为未知点编号,从a.fixpnum到a.allpnum-1   
    }
    a.anglenum = 0;
    a.distnum = 0;
    // 4 输入测站及观测值   

    int obsnum(0);

    for( int i=  0; i < a.statnum; i++)
    {
        // 4-1 输入测站信息        
        int t = 0;                           // 点名比较标志   
        in >> name;                         // 输入测站名   
        for (int k = 0; k < n; k++)
            if (_strnicmp(name, a.Pt[k].name, 20) == 0)
            {
                a.st[i].stp = &(a.Pt[k]);   // 找到同名点,起点指针指向该点   
                t++;                      // 找到标志   
            }
        if (t == 0) {
            strcpy_s(a.Pt[n].name, name);
            a.st[i].stp = &(a.Pt[n]);     // 找不到同名点,该名输给新点   
            n++;
        }
        in >> a.st[i].obnum;

        a.st[i].aglnum = 0;                // 测站角度观测个数   
        a.st[i].disnum = 0;                // 测站距离观测个数    
        a.st[i].i = i;
        // 4-2 输入本站观测值   
        for (int j = obsnum; j < obsnum + a.st[i].obnum; j++)
        {
            in >> name; t = 0;                    // 输入照准点名,操作过程同上       
            a.L[j].startp = a.st[i].stp;
            for (int k = 0; k < n; k++)
                if (_strnicmp(name, a.Pt[k].name, 20) == 0)
                {
                    a.L[j].endp = &(a.Pt[k]);
                    t++;
                }
            if (t == 0)
            {
                strcpy_s(a.Pt[n].name, name);
                a.L[j].endp = &(a.Pt[n]);
                n++;
            }
            in >> a.L[j].style;
            a.L[j].A = a.L[j].A0 = -PI;
            if (a.L[j].style == 1)
            {
                a.anglenum++;
                a.st[i].aglnum++;
                in >> a.L[j].angle;                                    // 输入方向观测值   
                a.L[j].dist0 = -PI;
                a.L[j].dist = -PI;
            }
            if (a.L[j].style == 2)
            {
                a.distnum++;
                a.st[i].disnum++;
                in >> a.L[j].dist;                                     // 输入距离观测值   
                a.L[j].dist0 = a.L[j].dist;
                a.L[j].angle = -PI;
            }

            a.L[j].i = j - obsnum;
            a.L[j].sti = i;
        }

        obsnum += a.st[i].aglnum + a.st[i].disnum;
        a.obnum += a.st[i].aglnum + a.st[i].disnum;
    }

    //  文件正确性判断   

// 5 固定边长输入   
    for( int i=  obsnum; i < obsnum + a.fixdisn; i++)
    {
        in >> name; int t = 0;
        for (int k = 0; k < n; k++)
            if (_strnicmp(name, a.Pt[k].name, 20) == 0)
            {
                a.L[i].startp = &(a.Pt[k]);
                t++;
            }
        if (t == 0)
        {
            strcpy_s(a.Pt[n].name, name);
            a.L[i].startp = &(a.Pt[n]);
            n++;
        }
        in >> name; t = 0;
        for (int k = 0; k < n; k++)
            if (_strnicmp(name, a.Pt[k].name, 20) == 0)
            {
                a.L[i].endp = &(a.Pt[k]);
                t++;
            }
        if (t == 0)
        {
            strcpy_s(a.Pt[n].name, name);
            a.L[i].endp = &(a.Pt[n]);
            n++;
        }
        in >> a.L[i].dist;
        a.L[i].dist0 = a.L[i].dist;                                  //输入距离值   
        a.L[i].A = a.L[i].A0 = -PI;
        a.L[i].style = 4;
        a.L[i].angle = -PI;
        a.L[i].i = i - obsnum;
    }
    obsnum += a.fixdisn;
    // 5 固定方位角输入   
    for( int i=  obsnum; i < obsnum + a.fixafn; i++)
    {
        in >> name; int t = 0;
        for (int k = 0; k < n; k++)
            if (_strnicmp(name, a.Pt[k].name, 20) == 0)
            {
                a.L[i].startp = &(a.Pt[k]);
                t++;
            }
        if (t == 0)
        {
            strcpy_s(a.Pt[n].name, name);
            a.L[i].startp = &(a.Pt[n]);
            n++;
        }
        in >> name; t = 0;
        for (int k = 0; k < n; k++)
            if (_strnicmp(name, a.Pt[k].name, 20) == 0)
            {
                a.L[i].endp = &(a.Pt[k]);
                t++;
            }
        if (t == 0)
        {
            strcpy_s(a.Pt[n].name, name);
            a.L[i].endp = &(a.Pt[n]);
            n++;
        }
        in >> a.L[i].A; a.L[i].A0 = a.L[i].A;
        a.L[i].style = 3;
        a.L[i].dist = -PI;
        a.L[i].dist0 = -PI;
        a.L[i].i = i - obsnum;
        a.L[i].angle = -PI;
    }
    obsnum += a.fixafn;
    if (n != a.allpnum) {
        cout << fname << " error: file provide not correct point number !  " << endl;
        return 0;
    }
    in.close();

    return 1;                             // 关闭输入流及关联文件   
}

//***************************平面网数据屏幕输出***************************************************   
void XYnetdis(XYnet& aa)
{
    cout << "\n基本信息:\n";
    cout << "k控制网名称:\t"<<aa.netname << "\n总点数:\t" << aa.allpnum << "\n控制点点数:\t" << aa.fixpnum << "\n测站数:\t" << aa.statnum << "\n观测值总数:\t"
        << aa.obnum << "\n固定边长个数:\t" << aa.fixdisn << "\n固定角度个数:\t" << aa.fixafn << endl;
    cout << "\n验前方向观测值误差:\t" << aa.mangle << "\n距离误差加常数:\t" << aa.msa << "\n距离误差乘常数:\t" << aa.msb << endl << endl;
    cout << "控制点信息:\n";
    for (int i = 0; i < aa.fixpnum; i++)
        cout << aa.Pt[i].name << "    " << aa.Pt[i].X << "    " << aa.Pt[i].Y << endl;
    cout << endl;
    cout << "测站信息:\n";
    int n(0);
    for (int j = 0; j < aa.statnum; j++)

    {
        cout << "第" << j+1 << "个测站:\n";
        cout << aa.st[j].stp->name << "  " << aa.st[j].aglnum << "   " << aa.st[j].disnum << endl;
        for( int i=  n; i < n + aa.st[j].aglnum + aa.st[j].disnum; i++)
        {
            cout << "    " << aa.L[i].i << "    " << aa.L[i].endp->name << "  " << aa.L[i].style;
            if (aa.L[i].style == 1) cout << "  " << aa.L[i].angle << endl;
            if (aa.L[i].style == 2) cout << "  " << aa.L[i].dist << endl;
        }cout << endl;
        n += aa.st[j].aglnum + aa.st[j].disnum;
    }

    for( int i=  aa.obnum; i < aa.obnum + aa.fixdisn + aa.fixafn; i++)
    {
        cout << aa.L[i].startp->name << "  " << aa.L[i].endp->name << "  " << aa.L[i].style << "  ";
        if (aa.L[i].style == 4)cout << aa.L[i].dist << endl;
        if (aa.L[i].style == 3)cout << aa.L[i].A << endl;
    }cout << endl;

}
//*****************************平面网的边结构****************************************************   
struct range {
    XYP st;                          // 起点   
    XYP ed;                          // 终点   
    double A;                        // 计算方位角   
    double MA;                       // 方位角中误差   
    double S;                        // 计算边长   
    double MS;                       // 边长中误差   
    double sMS;                      // 边长相对精度   
    double E;                        // 相对误差极大值   
    double F;                        // 相对误差极小值   
    double T;                        // 相对误差极大值方位角   
};

//*******************************平面控制网平差结果文件输出函数***********************************   
//平面控制网平差结果文件输出函数   
int XYfileout(XYnet& aa,const char* outfile)
{
    ofstream ou(outfile);
    ou.width(5);
    ou.right;
    ou.precision(11);
    // 1网的基本信息输出   
    ou << endl << "                 平面控制网" << aa.netname << "平差计算结果         " << endl << endl;
    ou << "-----------------------------------------------------------------------" << endl;
    ou << "                          控制网输入数据      " << endl;
    ou << "-----------------------------------------------------------------------" << endl;
    ou << " 网  名: " << aa.netname << "  总点数: " << aa.allpnum << "  控制点数: "
        << aa.fixpnum << "  测站数: " << aa.statnum << "  观测值总数: " << aa.obnum << endl
        << " 固定边长数: " << aa.fixdisn << "  固定方位角数: " << aa.fixafn;
    ou << endl << " 角度测量中误差: " << aa.mangle << "s  距离误差加常数: " << aa.msa
        << "m   距离误差乘常数: " << aa.msb << "ppm" << endl << endl;
    ou << "-----------------------------------------------------------------------" << endl;
    ou << "          控制点名         X                   Y                  " << endl;
    ou << "-----------------------------------------------------------------------" << endl;
    for (int i = 0; i < aa.fixpnum; i++)
    {
        ou << "          "; ou.width(5); ou << aa.Pt[i].name; ou << "    "; ou.width(13);
        ou << aa.Pt[i].X; ou << "       "; ou.width(13); ou << aa.Pt[i].Y << endl;
    }ou << endl;

    ou << "-----------------------------------------------------------------------" << endl;
    ou << "  测站名  方向观测数  边长观测数    照准点  观测类型        观测值            " << endl;
    ou << "-----------------------------------------------------------------------" << endl;

    int n(0);
    for (int j = 0; j < aa.statnum; j++)
    {
        ou.width(6); ou << aa.st[j].stp->name; ou.width(12); ou << aa.st[j].aglnum;
        ou.width(12); ou << aa.st[j].disnum << endl;
        for( int i=  n; i < n + aa.st[j].aglnum + aa.st[j].disnum; i++)
        {
            ou << "                        " << "    "; ou.width(12); ou << aa.L[i].endp->name << "       ";
            if (aa.L[i].style == 1)ou << "方向" << "        " << aa.L[i].angle << endl;
            if (aa.L[i].style == 2)ou << "边长" << "        " << aa.L[i].dist << endl;
        }ou << "                        " << endl;
        n += aa.st[j].aglnum + aa.st[j].disnum;
    }
    if (aa.fixafn + aa.fixdisn > 0) {
        ou << "-----------------------------------------------------------------------" << endl;
        ou << "                           固定方位角与边长数据      " << endl;
        ou << "-----------------------------------------------------------------------" << endl;
        ou << "              起点名    终点名     数据类型      数     据   " << endl;
        ou << "-----------------------------------------------------------------------" << endl;

        for( int i=  aa.obnum; i < aa.obnum + aa.fixdisn + aa.fixafn; i++)
        {
            ou << "              "; ou.width(6); ou << aa.L[i].startp->name << "    ";
            ou.width(6); ou << aa.L[i].endp->name; ou.width(12);
            if (aa.L[i].style == 4) { ou << "边  长"; ou.width(16); ou << aa.L[i].dist << endl; }
            if (aa.L[i].style == 3) { ou << "方位角"; ou.width(16); ou << aa.L[i].A0 << endl; }
        }
        ou << "-----------------------------------------------------------------------" << endl;
    }
    ou << endl;

    // 2输出网的近似坐标计算结果   
    ou << "-----------------------------------------------------------------------" << endl;
    ou << "                      控制网近似坐标计算结果      " << endl;
    ou << "-----------------------------------------------------------------------" << endl;

    ou << "                 Name            X(m)              Y(m)" << endl;
    ou << "-----------------------------------------------------------------------" << endl;
    for (int i = 0; i < aa.allpnum; i++)
    {
        ou << "            "; ou.width(6); ou << aa.Pt[i].name << "        "; ou.width(12);
        ou.precision(10); ou << setf(aa.Pt[i].X0, 3) << "        "; ou.width(12);
        ou.precision(10); ou << setf(aa.Pt[i].Y0, 3) << endl;
    }
    ou << "-----------------------------------------------------------------------" << endl;

    double A[MAX][MAX], AQAT[MAX][MAX];
    // 3输出观测值的平差结果   
    ou << "--------------------------------------------------------------------------------" << endl;
    if (aa.anglenum > 0) {
        ou << "                              方向观测值平差结果" << endl;
        ou << "--------------------------------------------------------------------------------" << endl;
        ou << "     FROM      TO  TYPE      VALUE(dms)   M(sec)  V(sec)    RESULT(dms)     Ri" << endl;
        ou << "--------------------------------------------------------------------------------" << endl;

        for( int i=  0; i < aa.obnum; i++)
            for (int j = 0; j < 2 * aa.allpnum + aa.statnum; j++)
                AT(aa.aa.A, A, aa.obnum, 2 * aa.allpnum + aa.statnum);
        ATPA(A, aa.aa.QXX, AQAT, 2 * aa.allpnum + aa.statnum, aa.obnum);
        //   cout<<"now,output QLL:"<
        //   matdis(AQAT,aa.obnum,aa.obnum);   
        for (int i = 0; i < aa.obnum; i++)
            if (aa.L[i].style == 1)
            {
                ou.width(9); ou << aa.L[i].startp->name;
                ou.width(8); ou << aa.L[i].endp->name;
                ou.width(6); ou << " 方向";
                ou.width(16);
                ou << aa.L[i].angle;
                ou.width(8);
                ou << setf(aa.aa.m0 * sqrt(AQAT[i][i]) * rou, 2);

                ou.width(9);
                ou << setf(aa.aa.V[i][0] * rou, 2);

                ou << " ";
                ou.width(12);
                ou << setf(h_d(d_h(aa.L[i].angle) + aa.aa.V[i][0]), 5);
                // ou<
                ou << endl;
            }

        ou << "--------------------------------------------------------------------------------" << endl;
    }
    if (aa.distnum > 0) {
        ou << "--------------------------------------------------------------------------------" << endl;
        ou << "                             边长观测值平差结果" << endl;
        ou << "--------------------------------------------------------------------------------" << endl;
        ou << "     FROM      TO  TYPE        VALUE(m)    M(cm)   V(cm)   RESULT(m)    " << endl;
        ou << "--------------------------------------------------------------------------------" << endl;
        for( int i=  0; i < aa.obnum; i++)
            if (aa.L[i].style == 2)
            {
                ou.width(9); ou << aa.L[i].startp->name;
                ou.width(8); ou << aa.L[i].endp->name;
                ou.width(6); ou << "边长";
                ou.width(16);
                ou << aa.L[i].dist;
                ou.width(8);
                ou << setf(aa.aa.m0 * sqrt(AQAT[i][i]) * 100, 2);

                ou.width(9);
                ou << setf(aa.aa.V[i][0] * 100, 2);

                ou << " ";
                ou.width(11);
                ou << setf(aa.L[i].dist + aa.aa.V[i][0], 4);
                ou << endl;
            }
        ou << "--------------------------------------------------------------------------------" << endl;
    }

    // 4输出坐标计算结果与精度   
    ou << "-----------------------------------------------------------------------------------------" << endl;
    ou << "                                  平差坐标及其精度" << endl;
    ou << "-----------------------------------------------------------------------------------------" << endl;
    ou << "   Name            X(m)             Y(m)   MX(cm)  MY(cm) MP(cm) E(cm)  F(cm)     T(d.ms)  " << endl;
    ou << "-----------------------------------------------------------------------------------------" << endl;
    for( int i=  0; i < aa.fixpnum; i++)
    {
        ou.right;
        ou.width(8); ou << aa.Pt[i].name; ou.precision(11); ou.width(17);
        ou << setf(aa.Pt[i].X, 4); ou.precision(11); ou.width(16); ou << setf(aa.Pt[i].Y, 4) << endl;
    }


    double Mx(0), My(0), Mp(0);
    for( int i=  aa.fixpnum; i < aa.allpnum; i++)
    {
        ou.right;
        ou.width(8); ou << aa.Pt[i].name; ou.precision(11);
        ou.width(17); ou << setf(aa.Pt[i].X, 4); ou.precision(11);
        ou.width(16); ou << setf(aa.Pt[i].Y, 4);
        ou.precision(4); ou.width(8); ou << aa.Pt[i].mX * 100;
        ou.precision(4); ou.width(7); ou << aa.Pt[i].mY * 100;
        ou.precision(4); ou.width(7); ou << aa.Pt[i].mp * 100;
        ou.precision(4); ou.width(7); ou << aa.Pt[i].E * 100;
        ou.precision(4); ou.width(7); ou << aa.Pt[i].F * 100;
        ou << " ";
        ou.precision(9); ou.width(11); ou << setf(aa.Pt[i].T, 5);
        ou << endl;

        Mx += aa.Pt[i].mX * 100 / (aa.allpnum - aa.fixpnum);
        My += aa.Pt[i].mY * 100 / (aa.allpnum - aa.fixpnum);
        Mp += aa.Pt[i].mp * 100 / (aa.allpnum - aa.fixpnum);
    }
    ou.precision(4);
    ou << "-----------------------------------------------------------------------------------------" << endl;
    ou << "                Mx均值:  "; ou.width(5); ou << Mx;
    ou << "      My均值:  "; ou.width(5); ou << My;
    ou << "      Mp均值:  "; ou.width(5); ou << Mp << endl;
    ou << "-----------------------------------------------------------------------------------------" << endl << endl;
    // 5最弱点及精度   

    ou << "                                    最弱点及其精度" << endl;
    ou << "-----------------------------------------------------------------------------------------" << endl;
    ou << "   Name            X(m)             Y(m)   MX(cm)  MY(cm) MP(cm) E(cm)  F(cm)     T(dms) " << endl;

    double a(0);
    for( int i=  aa.fixpnum; i < aa.allpnum; i++)
        if (a <= aa.Pt[i].mp) { a = aa.Pt[i].mp; n = i; }
    ou.right;
    ou.width(8); ou << aa.Pt[n].name; ou.precision(11); ou.width(17);
    ou << setf(aa.Pt[n].X, 4); ou.precision(11); ou.width(16); ou << setf(aa.Pt[n].Y, 4);
    ou.precision(4); ou.width(8); ou << aa.Pt[n].mX * 100;
    ou.precision(4); ou.width(7); ou << aa.Pt[n].mY * 100;
    ou.precision(4); ou.width(7); ou << aa.Pt[n].mp * 100;
    ou.precision(4); ou.width(7); ou << aa.Pt[n].E * 100;
    ou.precision(4); ou.width(7); ou << aa.Pt[n].F * 100;
    ou << " ";
    ou.precision(9); ou.width(10); ou << setf(aa.Pt[n].T, 5);
    ou << endl;
    ou << "-----------------------------------------------------------------------------------------" << endl;

    // 6 网点间边长、方位角及其相对精度   

    ou << "                                 网点间边长、方位角及其相对精度" << endl;
    ou << "--------------------------------------------------------------------------------------------------" << endl;
    ou << "  FROM       TO       A(dms)   MA(sec)     S(m)      MS(cm)    S/MS     E(cm)   F(cm)     T(dms) " << endl;
    ou << "--------------------------------------------------------------------------------------------------" << endl;
    range L[MAX];
    int Li(0);
    for( int i=  aa.fixpnum; i < aa.allpnum; i++)
        for (int j = 0; j < aa.allpnum; j++)
        {
            if( i== j || aa.Pt[j].fixed == 0 && j < i) continue;
            for (int k = 0; k < aa.obnum + aa.fixdisn + aa.fixafn; k++)
                if (*(aa.L[k].startp) == aa.Pt[i] && *(aa.L[k].endp) == aa.Pt[j] ||
                    *(aa.L[k].startp) == aa.Pt[j] && *(aa.L[k].endp) == aa.Pt[i])
                {
                    L[Li].st = aa.Pt[i]; L[Li].ed = aa.Pt[j];
                    Li++;
                    break;
                }
        }

    for( int i=  0; i < Li; i++)
    {
        for (int k = 0; k < 4; k++)
            for (int j = 0; j < 2 * aa.allpnum + aa.statnum; j++)
            {
                A[k][j] = 0;
            }

        double s = dist(L[i].ed, L[i].st);
        double ss = s * s;
        double dy = L[i].ed.Y - L[i].st.Y;
        double dx = L[i].ed.X - L[i].st.X;
        double aki = dy / ss; double bki = -1 * dx / ss;

        A[0][2 * (L[i].st.i)] = bki * s;  A[0][2 * (L[i].st.i) + 1] = -aki * s;
        A[0][2 * (L[i].ed.i) + 1] = aki * s; A[0][2 * (L[i].ed.i)] = -bki * s;

        A[1][2 * (L[i].st.i)] = aki;    A[1][2 * (L[i].st.i) + 1] = bki;
        A[1][2 * (L[i].ed.i)] = -aki;   A[1][2 * (L[i].ed.i) + 1] = -bki;

        A[2][2 * (L[i].st.i)] = -1;    A[2][2 * (L[i].ed.i)] = 1;

        A[3][2 * (L[i].st.i) + 1] = -1;    A[3][2 * (L[i].ed.i) + 1] = 1;
        double AH[MAX][MAX];
        AT(A, AH, 4, 2 * aa.allpnum + aa.statnum);
        ATPA(AH, aa.aa.QXX, AQAT, 2 * aa.allpnum + aa.statnum, 4);
        //   matdis(AQAT,4,4);   
        L[i].S = dist(L[i].st, L[i].ed);
        L[i].A = h_d(afa(L[i].st, L[i].ed));
        L[i].MS = aa.aa.m0 * sqrt(AQAT[0][0]);
        L[i].MA = aa.aa.m0 * sqrt(AQAT[1][1]) * rou;
        double  K = sqrt((AQAT[2][2] - AQAT[3][3]) * (AQAT[2][2] - AQAT[3][3]) + 4 * AQAT[2][3] * AQAT[2][3]);
        //a.Pt[i].mp=sqrt(a.Pt[i].mX*a.Pt[i].mX+a.Pt[i].mY*a.Pt[i].mY);   
        L[i].E = sqrt(1 / 2.0 * aa.aa.m0 * aa.aa.m0 * (AQAT[2][2] + AQAT[3][3] + K));
        L[i].F = sqrt(1 / 2.0 * aa.aa.m0 * aa.aa.m0 * (AQAT[2][2] + AQAT[3][3] - K));

        double F2 = atan2(2 * AQAT[2][3], AQAT[2][2] - AQAT[3][3]);
        if (F2 <= 0) F2 += 2 * PI; F2 /= 2.0;
        if (AQAT[2][3] > 0 && F2 > PI / 2.0 && F2 < PI || AQAT[2][3]>0 && F2 > PI * 3 / 2.0 && F2 < 2 * PI)
            F2 += PI / 2.0;
        if (AQAT[2][3] < 0 && F2 < PI / 2.0 && F2>0 || AQAT[2][3]<0 && F2>PI && F2 < PI * 3 / 2.0)
            F2 += PI / 2.0;
        if (F2 >= 2 * PI) F2 -= 2 * PI;
        L[i].T = h_d(F2);

        ou.width(6); ou << L[i].st.name; ou.width(9); ou << L[i].ed.name;
        ou.width(13); ou << setf(h_d(afa(L[i].st, L[i].ed)), 5); ou.width(9);
        ou << setf(L[i].MA, 2); ou.width(13); ou << setf(dist(L[i].st, L[i].ed), 4);
        ou.width(8); ou << setf(L[i].MS * 100, 2);
        ou.width(11);
        if (L[i].S / L[i].MS > 10E+9) ou << "无穷大";
        else ou << setf(L[i].S / L[i].MS, 0);
        ou.width(8); ou << setf(L[i].E * 100, 2); ou.width(8); ou << setf(L[i].F * 100, 2);
        ou.width(12); ou << setf(L[i].T, 4);
        ou << endl;
    }

    ou << "--------------------------------------------------------------------------------------------------" << endl;
    // 7输出最弱边信息   
    ou << "                                           最弱边及其精度" << endl;
    ou << "--------------------------------------------------------------------------------------------------" << endl;
    ou << "  FROM       TO       A(dms)   MA(sec)     S(m)      MS(cm)    S/MS     E(cm)   F(cm)     T(dms) " << endl;
    a = 0;
    for( int i=  0; i < Li; i++)
        if (a < L[i].MS / L[i].S) { a = L[i].MS / L[i].S; n = i; }
    ou.width(6); ou << L[n].st.name; ou.width(9); ou << L[n].ed.name;
    ou.width(13); ou << setf(h_d(afa(L[n].st, L[n].ed)), 5); ou.width(9);
    ou << setf(L[n].MA, 3); ou.width(13); ou << setf(dist(L[n].st, L[n].ed), 4);
    ou.width(8); ou << setf(L[n].MS * 100, 2);
    ou.width(11); ou << setf(L[n].S / L[n].MS, 0); ou.width(8);
    ou << setf(L[n].E * 100, 3); ou.width(8); ou << setf(L[n].F * 100, 3);
    ou.width(12); ou << setf(L[n].T, 5);
    ou << endl;
    ou << "--------------------------------------------------------------------------------------------------" << endl << endl;
    // 7输出单位权中误差与多于观测信息   
    ou << "                              单位权中误差与多于观测信息" << endl;
    ou << "----------------------------------------------------------------------------------------------" << endl;
    ou << "                                先验单位权中误差:  " << aa.mangle << endl;
    ou << "                                后验单位权中误差:  " << setf(aa.aa.m0 * rou, 2) << endl;
    ou << "                                多余观测值总数:  " << aa.obnum - 2 * (aa.allpnum - aa.fixpnum) << endl;
    ou << "                                平均多余观测值数: " << setf((double)aa.obnum / 2 / (aa.allpnum - aa.fixpnum) - 1, 2) << endl;
    ou << "-----------------------------------------------------------------------------------------------------" << endl;
    // 控制网总体信息   
    ou << "-----------------------------------------------------------------------------------------------------" << endl;
    ou << endl;
    ou << "                                      " << aa.netname << "控制网总体信息" << endl;
    ou << endl;
    ou << "          已知点数:   " << aa.fixpnum << "                                     未知点数: "
        << aa.allpnum - aa.fixpnum << endl;
    ou << "          方向角数:   " << aa.fixafn << "                                     固定边数:   "
        << aa.fixdisn << endl;
    ou << "          方向观测值数:  " << aa.anglenum << "                                 边长观测值数:  "
        << aa.distnum << endl;
    ou << "-----------------------------------------------------------------------------------------------------" << endl;

    ou.close();
    return 1;
}
//***********************************************************************************************   
//*******************平面三角网平差主程序模块****************************************************   

int XYadj(XYnet& aa,const  char* infile,const char* outfile)
{
    if (finXYnet(aa, infile)) {                              // 文件输入控制网数据   
        XYnetdis(aa);                                         // 网的基本信息屏幕输出   
        setx0y0(aa);                                          // 未知点近似坐标的计算   

        int i(0);
        double  xold[MAX];
        double  dx[MAX], a;

        do {                                                   // 近似坐标要求的平差迭代计算      
            a = 0;
            setXYadj(aa);
            if (!doXYadj(aa)) return 0;
            for (int i = 0; i < aa.allpnum * 2; i++)
            {
                dx[i] = aa.aa.X[i][0] - xold[i];
                xold[i] = aa.aa.X[i][0];
                if (a < fabs(dx[i])) a = fabs(dx[i]);
            }
        } while (a > 0.00001);  // 迭代的两次坐标差标准   
        for( int i=  0; i < aa.obnum; i++)
        {
            if (aa.L[i].style == 1) cout << "Vang==" << aa.aa.V[i][0] * rou << endl;
            else cout << "Vdis==" << aa.aa.V[i][0] << endl;

        }
        XYfileout(aa, outfile);
    }
    else return 0;
    return 1;
}
//******************************      main()     ************************************************   
void main()
{
    cout.precision(16);
    cout.width(12);
    XYnet aa;
    //finXYnet(aa,"pingmian1.txt");    
    // XYnetdis(aa);   
    //setx0y0(aa);    
    //setXYadj(aa);   
    //doXYadj(aa);    
    XYadj(aa, "data_bd-4.txt", "result_bd.txt");
    
}

数据组织格式:

//基本信息
平面控制网名字
总点数
控制点个数
测站数
固定边长个数
固定方位角个数 
验前方向观测值误差  
距离误差加常数 
距离误差乘常数

//控制点信息
控制点点名1 X坐标 Y坐标
控制点点名2 X坐标 Y坐标
......

//测站信息
测站名1  观测值总数
   照准点名1
   观测值属性(角度测量=1;距离测量=2;固定方位角=3;固定边长=4 )
   观测值(角度或距离)
   照准点名2
   观测值属性(角度测量=1;距离测量=2;固定方位角=3;固定边长=4 )
   观测值(角度或距离)

测站名2
观测值总数 
照准点名3
观测值属性(角度测量=1;距离测量=2;固定方位角=3;固定边长=4 )
观测值(角度或距离)
照准点名4
观测值属性(角度测量=1;距离测量=2;固定方位角=3;固定边长=4 )
观测值(角度或距离)
......

//固定边长信息
边名1 距离
边名2 距离
......

//固定方位角信息
角名1 角度
角名2 角度
......

data.txt:

导线网数据示例。


SHUJV

6
4
5
0
0
2.5
0
15

A 3143.237 5260.334 
B 4609.361 5025.696 
C 4157.197 8853.254 
D 3822.911 9795.726


A 3 
  B 1 0.0
  P1 1 44.05448 
  P1 2 2185.070
B 3 
  P1 1 0.0
  A 1 93.10431
  P1 2 1522.853
P1 4 
  A 1 0.0 
  B 1 42.43272 
  P2 1 244.32184 
  P2 2 1500.017
P2 3
   P1 1 0.0 
   C  1 201.57340
   C 2 1009.021
C 2
   P2 1 0.0 
   D  1 168.01452


result.txt:

以上导线网的文件输出结果,这个输出还是做的相当美观的哈。


                 平面控制网SHUJV平差计算结果         

-----------------------------------------------------------------------
                          控制网输入数据      
-----------------------------------------------------------------------
 网  名: SHUJV  总点数: 6  控制点数: 4  测站数: 5  观测值总数: 15
 固定边长数: 0  固定方位角数: 0
 角度测量中误差: 2.5s  距离误差加常数: 0m   距离误差乘常数: 15ppm

-----------------------------------------------------------------------
          控制点名         X                   Y                  
-----------------------------------------------------------------------
              A         3143.237            5260.334
              B         4609.361            5025.696
              C         4157.197            8853.254
              D         3822.911            9795.726

-----------------------------------------------------------------------
  测站名  方向观测数  边长观测数    照准点  观测类型        观测值            
-----------------------------------------------------------------------
     A           2           1
                                       B       方向        0
                                      P1       方向        44.05448
                                      P1       边长        2185.07
                        
     B           2           1
                                      P1       方向        0
                                       A       方向        93.10431
                                      P1       边长        1522.853
                        
    P1           3           1
                                       A       方向        0
                                       B       方向        42.43272
                                      P2       方向        244.32184
                                      P2       边长        1500.017
                        
    P2           2           1
                                      P1       方向        0
                                       C       方向        201.5734
                                       C       边长        1009.021
                        
     C           2           0
                                      P2       方向        0
                                       D       方向        168.01452
                        

-----------------------------------------------------------------------
                      控制网近似坐标计算结果      
-----------------------------------------------------------------------
                 Name            X(m)              Y(m)
-----------------------------------------------------------------------
                 A            3143.237            5260.334
                 B            4609.361            5025.696
                 C            4157.197            8853.254
                 D            3822.911            9795.726
                P1            4933.052            6513.721
                P2            4684.411            7992.944
-----------------------------------------------------------------------
--------------------------------------------------------------------------------
                              方向观测值平差结果
--------------------------------------------------------------------------------
     FROM      TO  TYPE      VALUE(dms)   M(sec)  V(sec)    RESULT(dms)     Ri
--------------------------------------------------------------------------------
        A       B  方向               0    2.41     0.31        3e-05
        A      P1  方向        44.05448    2.41    -0.31     44.05445
        B      P1  方向               0    2.49    -2.28     -0.00023
        B       A  方向        93.10431    2.49     2.28     93.10454
       P1       A  方向               0    2.02    -0.35       -3e-05
       P1       B  方向        42.43272    2.43     0.61     42.43278
       P1      P2  方向       244.32184     2.7    -0.26    244.32181
       P2      P1  方向               0    2.88     0.47        5e-05
       P2       C  方向        201.5734    2.88    -0.47    201.57335
        C      P2  方向               0    2.62     1.56      0.00016
        C       D  方向       168.01452    2.62    -1.56    168.01436
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
                             边长观测值平差结果
--------------------------------------------------------------------------------
     FROM      TO  TYPE        VALUE(m)    M(cm)   V(cm)   RESULT(m)    
--------------------------------------------------------------------------------
        A      P1  边长         2185.07    1.76    -2.61   2185.0439
        B      P1  边长        1522.853    1.96    -2.87   1522.8243
       P1      P2  边长        1500.017    2.05    -4.25   1499.9745
       P2       C  边长        1009.021    1.73    -1.74   1009.0036
--------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------
                                  平差坐标及其精度
-----------------------------------------------------------------------------------------
   Name            X(m)             Y(m)   MX(cm)  MY(cm) MP(cm) E(cm)  F(cm)     T(d.ms)  
-----------------------------------------------------------------------------------------
       A         3143.237        5260.334
       B         4609.361        5025.696
       C         4157.197        8853.254
       D         3822.911        9795.726
      P1        4933.0521       6513.7209   1.578  1.954  2.512   1.96  1.571    82.48199
      P2        4684.4114       7992.9441   1.396  1.659  2.168  1.734  1.302   116.03522
-----------------------------------------------------------------------------------------
                Mx均值:  1.487      My均值:  1.807      Mp均值:   2.34
-----------------------------------------------------------------------------------------

                                    最弱点及其精度
-----------------------------------------------------------------------------------------
   Name            X(m)             Y(m)   MX(cm)  MY(cm) MP(cm) E(cm)  F(cm)     T(dms) 
      P1        4933.0521       6513.7209   1.578  1.954  2.512   1.96  1.571   82.48199
-----------------------------------------------------------------------------------------
                                 网点间边长、方位角及其相对精度
--------------------------------------------------------------------------------------------------
  FROM       TO       A(dms)   MA(sec)     S(m)      MS(cm)    S/MS     E(cm)   F(cm)     T(dms) 
--------------------------------------------------------------------------------------------------
    P1        A    215.00112     1.69    2185.0439    1.76     124360    1.96    1.57      82.482
    P1        B    257.43394     2.13    1522.8243    1.96      77819    1.96    1.57      82.482
    P1        C    108.20491     1.38    2464.8258    1.89     130177    1.96    1.57      82.482
    P1        D    108.41173     0.98    3464.6747    1.89     183147    1.96    1.57      82.482
    P1       P2     99.32297     1.92    1499.9745    2.05      73076    2.05     1.4     96.5535
    P2        A    240.34382     1.06    3137.2562    1.45     215664    1.73     1.3    116.0352
    P2        B    268.33041     0.98     2968.197    1.65     179764    1.73     1.3    116.0352
    P2        C    121.30027     2.67    1009.0036    1.73      58311    1.73     1.3    116.0352
    P2        D    115.32307     1.34    1998.0504    1.73     115244    1.73     1.3    116.0352
--------------------------------------------------------------------------------------------------
                                           最弱边及其精度
--------------------------------------------------------------------------------------------------
  FROM       TO       A(dms)   MA(sec)     S(m)      MS(cm)    S/MS     E(cm)   F(cm)     T(dms) 
    P2        C    121.30027    2.671    1009.0036    1.73      58311   1.734   1.302   116.03522
--------------------------------------------------------------------------------------------------

                              单位权中误差与多于观测信息
----------------------------------------------------------------------------------------------
                                先验单位权中误差:  2.5
                                后验单位权中误差:  3.19
                                多余观测值总数:  11
                                平均多余观测值数: 2.75
-----------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------

                                      SHUJV控制网总体信息

          已知点数:   4                                     未知点数: 2
          方向角数:   0                                     固定边数:   0
          方向观测值数:  11                                 边长观测值数:  4
-----------------------------------------------------------------------------------------------------


你可能感兴趣的:(C++,c++,算法)