Пример #1
0
        /// <summary>
        /// 获取线状要素
        /// </summary>
        /// <param name="pDataRecords">数据记录</param>
        /// <param name="dblProp">插值参数</param>
        /// <returns>在处理面状要素时,本程序将原面状要素的边界切开,按线状要素处理,处理完后再重新生成面状要素</returns>
        public CPolyline GetTargetcpl(double dblProp, CPolyline lastcpl)
        {
            if (dblProp == 0)
            {
                int aa = 5;
            }

            List <CCorrCpts> pCorrCptsLt = _DataRecords.ParameterResult.CCorrCptsLt;   //读取数据后,此处ResultPtLt中的对应点为一一对应
            double           dblTX       = _dblTX;

            int intPtNum = pCorrCptsLt.Count;
            int intXYNum = 2 * intPtNum;

            //计算长度初始值(全部计算)
            double[] adblLength0   = new double[intPtNum - 1];
            double[] adblFrLength0 = new double[intPtNum - 1];
            double[] adblToLength0 = new double[intPtNum - 1];
            for (int i = 0; i < pCorrCptsLt.Count - 1; i++)
            {
                double dblfrsublength = CGeoFunc.CalDis(pCorrCptsLt[i + 1].FrCpt, pCorrCptsLt[i].FrCpt);
                adblFrLength0[i] = dblfrsublength;
                double dbltosublength = CGeoFunc.CalDis(pCorrCptsLt[i + 1].ToCpt, pCorrCptsLt[i].ToCpt);
                adblToLength0[i] = dbltosublength;
                adblLength0[i]   = (1 - dblProp) * dblfrsublength + dblProp * dbltosublength;
            }

            //计算角度初始值(全部计算)
            double[] adblAngle0 = new double[intPtNum - 2];
            for (int i = 0; i < pCorrCptsLt.Count - 2; i++)
            {
                //较大比例尺线状要素上的夹角
                double dblfrAngle = CGeoFunc.CalAngle_Counterclockwise(pCorrCptsLt[i].FrCpt, pCorrCptsLt[i + 1].FrCpt, pCorrCptsLt[i + 2].FrCpt);
                //较小比例尺线状要素上的夹角
                double dbltoAngle = CGeoFunc.CalAngle_Counterclockwise(pCorrCptsLt[i].ToCpt, pCorrCptsLt[i + 1].ToCpt, pCorrCptsLt[i + 2].ToCpt);

                //角度初始值
                adblAngle0[i] = (1 - dblProp) * dblfrAngle + dblProp * dbltoAngle;
            }

            //计算坐标初始值,以及各线段方位角初始值
            //注意:默认固定第一条边
            pCorrCptsLt[0].FrCpt.isCtrl = true;
            pCorrCptsLt[1].FrCpt.isCtrl = true;
            //固定最后两条边
            pCorrCptsLt[intPtNum - 1].FrCpt.isCtrl = true;
            pCorrCptsLt[intPtNum - 2].FrCpt.isCtrl = true;

            VBMatrix X0 = new VBMatrix(intXYNum, 1);

            //以上一次结果的值作为新的估算值
            List <CPoint> lastcptlt = lastcpl.CptLt;

            for (int i = 0; i < intPtNum; i++)
            {
                if (pCorrCptsLt[i].FrCpt.isCtrl == false)
                {
                    X0[2 * i + 0, 0] = lastcptlt[i].X;
                    X0[2 * i + 1, 0] = lastcptlt[i].Y;
                }
                else
                {
                    X0[2 * i + 0, 0] = (1 - dblProp) * pCorrCptsLt[i].FrCpt.X + dblProp * pCorrCptsLt[i].ToCpt.X;
                    X0[2 * i + 1, 0] = (1 - dblProp) * pCorrCptsLt[i].FrCpt.Y + dblProp * pCorrCptsLt[i].ToCpt.Y;
                }
            }

            //统计插值点数
            int intKnownPt   = 0;                             //固定点的数目
            int intUnknownPt = 0;                             //非固定点的数目

            List <int> intKnownLocationLt = new List <int>(); //记录已知点的序号

            //注意:对于该循环,有一个默认条件,即FromCpl的第一个顶点只有一个对应点
            for (int i = 0; i < pCorrCptsLt.Count; i++)
            {
                if (pCorrCptsLt[i].FrCpt.isCtrl == true)
                {
                    intKnownLocationLt.Add(i);
                    intKnownPt += 1;
                }
                else
                {
                    intUnknownPt += 1;
                }
            }
            int intUnknownXY = intUnknownPt * 2;   //每个点都有X、Y坐标

            //找出长度固定的位置(如果一个线段的前后两个点都固定,则该长度固定)。另外,长度固定则该边的方位角也固定
            List <int> intKnownLengthLt = new List <int>();

            for (int i = 0; i < intKnownLocationLt.Count - 1; i++)
            {
                if ((intKnownLocationLt[i + 1] - intKnownLocationLt[i]) == 1)
                {
                    intKnownLengthLt.Add(intKnownLocationLt[i]);
                }
            }
            int intUnknownLength = intPtNum - 1 - intKnownLengthLt.Count;

            //找出角度固定的位置(如果一个固定顶点的前后两个点都固定,则该角度固定)
            List <int> intKnownAngleLt = new List <int>();

            for (int i = 0; i < intKnownLocationLt.Count - 2; i++)
            {
                if ((intKnownLocationLt[i + 1] - intKnownLocationLt[i]) == 1 && (intKnownLocationLt[i + 2] - intKnownLocationLt[i + 1]) == 1)
                {
                    intKnownAngleLt.Add(intKnownLocationLt[i]);
                }
            }
            int intUnknownAngle = intPtNum - 2 - intKnownAngleLt.Count;

            //长度及角度未知量(方便使用)
            int intUnknownLengthAngle = intUnknownLength + intUnknownAngle;
            //总未知量
            int intUnknownLengthAnglePt = intUnknownLength + intUnknownAngle + intUnknownPt;

            //定义权重矩阵
            int      intKnownCount   = 0;
            int      intUnKnownCount = 0;
            VBMatrix P = new VBMatrix(intUnknownLengthAnglePt, intUnknownLengthAnglePt);

            for (int i = 0; i < intUnknownLength; i++)
            {
                P[i, i] = 1;
            }
            for (int i = 0; i < intUnknownAngle; i++)
            {
                int intSumCount = intKnownCount + intUnKnownCount;

                //开始计算系数值,由于将以下三个情况排列组合将有八种情况,因此按如下方式计算
                if (pCorrCptsLt[intSumCount].FrCpt.isCtrl == true && pCorrCptsLt[intSumCount + 1].FrCpt.isCtrl == true && pCorrCptsLt[intSumCount + 2].FrCpt.isCtrl == true)
                {
                    i -= 1;
                }
                else
                {
                    double dblWeight = 0;
                    if (pCorrCptsLt[intSumCount + 1].FrCpt.isCtrl == false)
                    {
                        dblWeight = adblFrLength0[intSumCount] + adblFrLength0[intSumCount + 1] + adblToLength0[intSumCount] + adblToLength0[intSumCount + 1];
                    }
                    else if (pCorrCptsLt[intSumCount].FrCpt.isCtrl == false && pCorrCptsLt[intSumCount + 1].FrCpt.isCtrl == true && pCorrCptsLt[intSumCount + 2].FrCpt.isCtrl == false)
                    {
                        dblWeight = adblFrLength0[intSumCount] + adblFrLength0[intSumCount + 1] + adblToLength0[intSumCount] + adblToLength0[intSumCount + 1];
                    }
                    else if (pCorrCptsLt[intSumCount].FrCpt.isCtrl == true && pCorrCptsLt[intSumCount + 1].FrCpt.isCtrl == true && pCorrCptsLt[intSumCount + 2].FrCpt.isCtrl == false)
                    {
                        dblWeight = adblFrLength0[intSumCount + 1] + adblToLength0[intSumCount + 1];
                    }
                    else if (pCorrCptsLt[intSumCount].FrCpt.isCtrl == false && pCorrCptsLt[intSumCount + 1].FrCpt.isCtrl == true && pCorrCptsLt[intSumCount + 2].FrCpt.isCtrl == true)
                    {
                        dblWeight = adblFrLength0[intSumCount] + adblToLength0[intSumCount];
                    }

                    P[intUnknownLength + i, intUnknownLength + i] = dblWeight;
                }

                if (pCorrCptsLt[intSumCount].FrCpt.isCtrl == true)
                {
                    intKnownCount += 1;
                }
                else
                {
                    intUnKnownCount += 1;
                }
            }
            for (int i = 0; i < intUnknownPt; i++)
            {
                P[intUnknownLengthAngle + i, intUnknownLengthAngle + i] = 0.000000000000001;
            }

            //定义坐标近似值矩阵XA
            VBMatrix XA           = new VBMatrix(intUnknownXY, 1);
            VBMatrix XA0          = new VBMatrix(intUnknownXY, 1);
            int      intSumCount0 = 0;

            for (int i = 0; i < intUnknownPt; i++)
            {
                if (pCorrCptsLt[intSumCount0].FrCpt.isCtrl == false)
                {
                    XA0[i * 2 + 0, 0] = X0[intSumCount0 * 2 + 0, 0];
                    XA0[i * 2 + 1, 0] = X0[intSumCount0 * 2 + 1, 0];

                    XA[i * 2 + 0, 0] = XA0[i * 2 + 0, 0] - 0.0000000001;
                    XA[i * 2 + 1, 0] = XA0[i * 2 + 1, 0] - 0.0000000001;
                }
                else
                {
                    i -= 1;
                }
                intSumCount0 += 1;
            }

            //Xmix里存储了XA和X0的最新混合值(此矩阵在公式推导中并不存在,只是为了方便编写代码而建立)
            VBMatrix Xmix = new VBMatrix(intXYNum, 1);

            for (int i = 0; i < intXYNum; i++)
            {
                Xmix[i, 0] = X0[i, 0];
            }

            //近似值与观测值之差matl,平差中的-l
            VBMatrix matl = new VBMatrix(intUnknownLengthAnglePt, 1);

            //定义系数矩阵A(各方程对坐标的导数值),A的导数值将在循环中给出
            VBMatrix A                 = new VBMatrix(intUnknownLengthAnglePt, intUnknownXY);
            double   dblJudge1         = 0; //该值用于判断是否应该跳出循环
            double   dblJudge2         = 0; //该值用于判断是否应该跳出循环
            int      intJudgeIndex     = intUnknownLength / 4;
            int      intIterativeCount = 0;

            double[] adblSubDis  = new double[intPtNum - 1];
            double[] adblAngle   = new double[intPtNum - 2];
            double[] adblAzimuth = new double[intPtNum - 1];
            do
            {
                //计算系数矩阵A第0行到"intUnknownLength"行的各元素,即线段长度对各未知数求偏导的值
                for (int i = 0; i < intPtNum - 1; i++)
                {
                    adblSubDis[i] = Math.Pow((Xmix[2 * i, 0] - Xmix[2 * i + 2, 0]) * (Xmix[2 * i, 0] - Xmix[2 * i + 2, 0]) + (Xmix[2 * i + 1, 0] - Xmix[2 * i + 3, 0]) * (Xmix[2 * i + 1, 0] - Xmix[2 * i + 3, 0]), 0.5);
                }
                //计算新的方位角
                adblAzimuth[0] = CGeoFunc.CalAxisAngle(Xmix[0, 0], Xmix[1, 0], Xmix[2, 0], Xmix[3, 0]);
                for (int i = 1; i < intPtNum - 1; i++)
                {
                    adblAngle[i - 1] = CGeoFunc.CalAngle_Counterclockwise(Xmix[i * 2 - 2, 0], Xmix[i * 2 - 1, 0], Xmix[i * 2, 0], Xmix[i * 2 + 1, 0], Xmix[i * 2 + 2, 0], Xmix[i * 2 + 3, 0]);
                    adblAzimuth[i]   = adblAzimuth[i - 1] + adblAngle[i - 1] - Math.PI;
                }

                //计算系数矩阵中关于长度值的导数部分
                _pCAL.CalADevLength(pCorrCptsLt, 0, intUnknownLength, ref A, ref matl, adblSubDis, adblAzimuth, adblLength0);

                //计算系数矩阵中关于夹角值的导数部分
                _pCAL.CalADevAngle(pCorrCptsLt, intUnknownLength, intUnknownAngle, Xmix, ref A, ref matl, adblSubDis, adblAngle, adblAngle0);

                //计算系数矩阵中关于与上一个LSA结果坐标距离的导数部分
                for (int i = 0; i < intUnknownPt; i++)
                {
                    //平差后的点与估计值点之间的距离
                    double dblDis = Math.Pow((XA[2 * i, 0] - XA0[2 * i, 0]) * (XA[2 * i, 0] - XA0[2 * i, 0]) + (XA[2 * i + 1, 0] - XA0[2 * i + 1, 0]) * (XA[2 * i + 1, 0] - XA0[2 * i + 1, 0]), 0.5);

                    A[intUnknownLengthAngle + i, i * 2 + 0] = (XA[2 * i + 0, 0] - XA0[2 * i + 0, 0]) / dblDis;
                    A[intUnknownLengthAngle + i, i * 2 + 1] = (XA[2 * i + 1, 0] - XA0[2 * i + 1, 0]) / dblDis;

                    //if (dblDis==0)
                    //{
                    //    //导数值
                    //    A[intUnknownLengthAngle + i, i * 2 + 0] = 0;
                    //    A[intUnknownLengthAngle + i, i * 2 + 1] = 0;
                    //}
                    //else
                    //{
                    //    //导数值
                    //    A[intUnknownLengthAngle + i, i * 2 + 0] = (XA[2 * i + 0, 0] - XA0[2 * i + 0, 0]) / dblDis;
                    //    A[intUnknownLengthAngle + i, i * 2 + 1] = (XA[2 * i + 1, 0] - XA0[2 * i + 1, 0]) / dblDis;
                    //}

                    matl[intUnknownLengthAngle + i, 0] = -dblDis;    //图方便,顺便计算matl
                }

                //CHelpFuncExcel.ExportDataToExcel2(A, "maxA", _DataRecords.ParameterInitialize.strSavePath);
                //CHelpFuncExcel.ExportDataToExcelP(P, "maxP", _DataRecords.ParameterInitialize.strSavePath);
                //CHelpFuncExcel.ExportDataToExcel2(matl, "maxmatl", _DataRecords.ParameterInitialize.strSavePath);


                //平差(阻尼最小二乘法)
                VBMatrix Temp = A.Trans() * P * A;
                //VBMatrix E = new VBMatrix(intUnknownXY, intUnknownXY);  //单位矩阵
                //for (int i = 0; i < intUnknownXY; i++)
                //{
                //    E[i, i] = 1;
                //}
                //Temp = Temp + E;
                VBMatrix InvTemp = Temp.Inv(Temp);
                VBMatrix x       = InvTemp * A.Trans() * P * matl;

                //CHelpFuncExcel.ExportDataToExcel2(x, "maxX", _DataRecords.ParameterInitialize.strSavePath);
                //CHelpFuncExcel.ExportDataToExcel2(XA, "maxXA", _DataRecords.ParameterInitialize.strSavePath);

                XA += x;

                //对坐标值进行改正
                int intSumCount5 = 0;
                for (int i = 0; i < intUnknownPt; i++)
                {
                    if (pCorrCptsLt[intSumCount5].FrCpt.isCtrl == false)
                    {
                        Xmix[intSumCount5 * 2 + 0, 0] = XA[i * 2 + 0, 0];
                        Xmix[intSumCount5 * 2 + 1, 0] = XA[i * 2 + 1, 0];
                    }
                    else
                    {
                        i -= 1;
                    }
                    intSumCount5 += 1;
                }

                if (intIterativeCount == 50)
                {
                    int kk = 5;
                }

                intIterativeCount += 1;


                if (intIterativeCount >= 20)
                {
                    break;
                }

                //这里只是随便取两个中间值以观测是否收敛
                dblJudge1 = Math.Abs(x[intJudgeIndex, 0]);
                dblJudge2 = Math.Abs(x[3 * intJudgeIndex, 0]);
            } while ((dblJudge1 > dblTX) || (dblJudge2 > dblTX));


            //生成目标线段
            List <CPoint> CTargetPtLt = new List <CPoint>();

            for (int i = 0; i < intPtNum; i++)
            {
                CPoint cpt = new CPoint(i);
                cpt.X = Xmix[2 * i, 0];
                cpt.Y = Xmix[2 * i + 1, 0];

                if (pCorrCptsLt[i].FrCpt.isCtrl == true)
                {
                    cpt.isCtrl = true;
                }
                else
                {
                    cpt.isCtrl = false;
                }

                CTargetPtLt.Add(cpt);
            }
            CPolyline cpl = new CPolyline(0, CTargetPtLt);

            cpl.CreateSubPllt();

            //记录各平差成果
            //坐标改正值
            VBMatrix Xc = XA - XA0;
            //观测值改正值矩阵V
            VBMatrix V = A * Xc + matl;

            //VtPV值
            cpl.dblVtPV = (V.Trans() * P * V).MatData[0, 0];


            int intUnKnownCountL6 = 0;

            for (int i = 0; i < intPtNum - 1; i++)
            {
                if (pCorrCptsLt[i].FrCpt.isCtrl == false || pCorrCptsLt[i + 1].FrCpt.isCtrl == false)
                {
                    cpl.SubCPlLt[i].dblLengthV = cpl.SubCPlLt[i].pPolyline.Length - adblLength0[i];
                    //double dblLength = cpl.SubCPlLt[i].Length;
                    //double dblLength0 = adblLength0[i];


                    intUnKnownCountL6 += 1;
                }
                else
                {
                    cpl.SubCPlLt[i].dblLengthV = 0;
                }
            }

            int intUnKnownCountA6 = 0;

            for (int i = 0; i < intPtNum - 2; i++)
            {
                if (pCorrCptsLt[i].FrCpt.isCtrl == false || pCorrCptsLt[i + 1].FrCpt.isCtrl == false || pCorrCptsLt[i + 2].FrCpt.isCtrl == false)
                {
                    double dblAngle = CGeoFunc.CalAngle_Counterclockwise(cpl.CptLt[i], cpl.CptLt[i + 1], cpl.CptLt[i + 2]);
                    cpl.CptLt[i + 1].dblAngleV = dblAngle - adblAngle0[i];
                    //double dblAngle = CGeoFunc.CalAngle_Counterclockwise(cpl.CptLt[i], cpl.CptLt[i + 1], cpl.CptLt[i + 2]);
                    //cpl.CptLt[i + 1].dblAngleV = V[intUnknownLength + intUnKnownCountA6, 0];
                    intUnKnownCountA6 += 1;
                }
                else
                {
                    cpl.CptLt[i + 1].dblAngleV = 0;
                }
            }

            return(cpl);
        }
Пример #2
0
        /// <summary>
        /// 获取线状要素
        /// </summary>
        /// <param name="pDataRecords">数据记录</param>
        /// <param name="dblProp">插值参数</param>
        /// <returns>在处理面状要素时,本程序将原面状要素的边界切开,按线状要素处理,处理完后再重新生成面状要素</returns>
        public CPolyline GetTargetcpl(double dblProp)
        {
            List <CCorrCpts> pCorrCptsLt = _DataRecords.ParameterResult.CCorrCptsLt;   //Read Datasets后,此处ResultPtLt中的对应点为一一对应
            double           dblTX       = _dblTX;

            int intPtNum = pCorrCptsLt.Count;

            //计算长度初始值(全部计算)
            double[] adblLength0 = new double[intPtNum - 1];
            double[] adblLength  = new double[intPtNum - 1];  //可以变化的值
            for (int i = 0; i < pCorrCptsLt.Count - 1; i++)
            {
                double dblfrsublength = CGeoFunc.CalDis(pCorrCptsLt[i + 1].FrCpt, pCorrCptsLt[i].FrCpt);
                double dbltosublength = CGeoFunc.CalDis(pCorrCptsLt[i + 1].ToCpt, pCorrCptsLt[i].ToCpt);
                adblLength0[i] = (1 - dblProp) * dblfrsublength + dblProp * dbltosublength;
                adblLength[i]  = adblLength0[i];
            }

            //计算角度初始值(全部计算)
            double[] adblAngle0 = new double[intPtNum - 2];
            double[] adblAngle  = new double[intPtNum - 2]; //可以变化的值
            for (int i = 0; i < pCorrCptsLt.Count - 2; i++)
            {
                //较大比例尺线状要素上的夹角
                double dblfrAngle = CGeoFunc.CalAngle_Counterclockwise(pCorrCptsLt[i].FrCpt, pCorrCptsLt[i + 1].FrCpt, pCorrCptsLt[i + 2].FrCpt);
                //较小比例尺线状要素上的夹角
                double dbltoAngle = CGeoFunc.CalAngle_Counterclockwise(pCorrCptsLt[i].ToCpt, pCorrCptsLt[i + 1].ToCpt, pCorrCptsLt[i + 2].ToCpt);

                //角度初始值
                adblAngle0[i] = (1 - dblProp) * dblfrAngle + dblProp * dbltoAngle;
                adblAngle[i]  = adblAngle0[i];
            }

            //生成点数组(初始值),同时计算各线段方位角混合值
            //注意:默认固定第一条边
            List <CPoint> cptlt = new List <CPoint>();

            double[] adblAzimuth = new double[intPtNum - 1];
            //计算第一个点和第二个点
            double dblnewX0 = (1 - dblProp) * pCorrCptsLt[0].FrCpt.X + dblProp * pCorrCptsLt[0].ToCpt.X;
            double dblnewY0 = (1 - dblProp) * pCorrCptsLt[0].FrCpt.Y + dblProp * pCorrCptsLt[0].ToCpt.Y;
            CPoint newcpt0  = new CPoint(0, dblnewX0, dblnewY0);

            newcpt0.isCtrl = true;
            cptlt.Add(newcpt0);
            double dblnewX1 = (1 - dblProp) * pCorrCptsLt[1].FrCpt.X + dblProp * pCorrCptsLt[1].ToCpt.X;
            double dblnewY1 = (1 - dblProp) * pCorrCptsLt[1].FrCpt.Y + dblProp * pCorrCptsLt[1].ToCpt.Y;
            CPoint newcpt1  = new CPoint(1, dblnewX1, dblnewY1);

            newcpt1.isCtrl = true;
            cptlt.Add(newcpt1);
            adblAzimuth[0] = CGeoFunc.CalAxisAngle(newcpt0, newcpt1);
            ////后面的其它点(不固定最后两个点)
            ////pCorrCptsLt[intPtNum - 2].FrCpt.isCtrl = false;
            ////pCorrCptsLt[intPtNum - 1].FrCpt.isCtrl = false;
            //for (int i = 2; i < pCorrCptsLt.Count; i++)
            //{
            //    CPoint newcpt = new CPoint();
            //    if (pCorrCptsLt[i].FrCpt.isCtrl == false)
            //    {
            //        adblAzimuth[i - 1] = adblAzimuth[i - 2] + adblAngle0[i - 2] - Math.PI;
            //        double dblnewX = cptlt[i - 1].X + adblLength0[i - 1] * Math.Cos(adblAzimuth[i - 1]);
            //        double dblnewY = cptlt[i - 1].Y + adblLength0[i - 1] * Math.Sin(adblAzimuth[i - 1]);
            //        newcpt = new CPoint(i, dblnewX, dblnewY);
            //    }
            //    else
            //    {
            //        double dblnewX = (1 - dblProp) * pCorrCptsLt[i].FrCpt.X + dblProp * pCorrCptsLt[i].ToCpt.X;
            //        double dblnewY = (1 - dblProp) * pCorrCptsLt[i].FrCpt.Y + dblProp * pCorrCptsLt[i].ToCpt.Y;
            //        newcpt = new CPoint(i, dblnewX, dblnewY);
            //        newcpt.isCtrl = true;

            //        //计算角度:不能采用“CGeoFunc.CalAxisAngle”,因为此处的方位角不一定在0到2Pi之间,采用重新连接法
            //        double dblAngle = CGeoFunc.CalAngle_Counterclockwise(cptlt[cptlt.Count - 2], cptlt[cptlt.Count - 1], newcpt);  //计算实际夹角
            //        adblAzimuth[i - 1] = adblAzimuth[i - 2] + dblAngle - Math.PI;
            //    }
            //    cptlt.Add(newcpt);
            //}

            //后面的其它点(固定最后两个点)
            for (int i = 2; i < pCorrCptsLt.Count - 2; i++)
            {
                CPoint newcpt = new CPoint();
                if (pCorrCptsLt[i].FrCpt.isCtrl == false)
                {
                    adblAzimuth[i - 1] = adblAzimuth[i - 2] + adblAngle0[i - 2] - Math.PI;
                    double dblnewX = cptlt[i - 1].X + adblLength0[i - 1] * Math.Cos(adblAzimuth[i - 1]);
                    double dblnewY = cptlt[i - 1].Y + adblLength0[i - 1] * Math.Sin(adblAzimuth[i - 1]);
                    newcpt = new CPoint(i, dblnewX, dblnewY);
                }
                else
                {
                    double dblnewX = (1 - dblProp) * pCorrCptsLt[i].FrCpt.X + dblProp * pCorrCptsLt[i].ToCpt.X;
                    double dblnewY = (1 - dblProp) * pCorrCptsLt[i].FrCpt.Y + dblProp * pCorrCptsLt[i].ToCpt.Y;
                    newcpt        = new CPoint(i, dblnewX, dblnewY);
                    newcpt.isCtrl = true;

                    //计算角度:不能采用“CGeoFunc.CalAxisAngle”,因为此处的方位角不一定在0到2Pi之间,采用重新连接法
                    double dblAngle = CGeoFunc.CalAngle_Counterclockwise(cptlt[cptlt.Count - 2], cptlt[cptlt.Count - 1], newcpt);  //计算实际夹角
                    adblAzimuth[i - 1] = adblAzimuth[i - 2] + dblAngle - Math.PI;
                }
                cptlt.Add(newcpt);
            }
            //计算最后两个点
            double dblnewXlast1 = (1 - dblProp) * pCorrCptsLt[pCorrCptsLt.Count - 2].FrCpt.X + dblProp * pCorrCptsLt[pCorrCptsLt.Count - 2].ToCpt.X;
            double dblnewYlast1 = (1 - dblProp) * pCorrCptsLt[pCorrCptsLt.Count - 2].FrCpt.Y + dblProp * pCorrCptsLt[pCorrCptsLt.Count - 2].ToCpt.Y;
            CPoint newcptlast1  = new CPoint(pCorrCptsLt.Count - 2, dblnewXlast1, dblnewYlast1);

            newcptlast1.isCtrl = true;
            cptlt.Add(newcptlast1);
            double dblAnglelast1 = CGeoFunc.CalAngle_Counterclockwise(cptlt[cptlt.Count - 3], cptlt[cptlt.Count - 2], cptlt[cptlt.Count - 1]);  //计算实际夹角

            adblAzimuth[pCorrCptsLt.Count - 3] = adblAzimuth[pCorrCptsLt.Count - 4] + dblAnglelast1 - Math.PI;

            double dblnewXlast0 = (1 - dblProp) * pCorrCptsLt[pCorrCptsLt.Count - 1].FrCpt.X + dblProp * pCorrCptsLt[pCorrCptsLt.Count - 1].ToCpt.X;
            double dblnewYlast0 = (1 - dblProp) * pCorrCptsLt[pCorrCptsLt.Count - 1].FrCpt.Y + dblProp * pCorrCptsLt[pCorrCptsLt.Count - 1].ToCpt.Y;
            CPoint newcptlast0  = new CPoint(pCorrCptsLt.Count - 1, dblnewXlast0, dblnewYlast0);

            newcptlast0.isCtrl = true;
            cptlt.Add(newcptlast0);
            double dblAnglelast0 = CGeoFunc.CalAngle_Counterclockwise(cptlt[cptlt.Count - 3], cptlt[cptlt.Count - 2], cptlt[cptlt.Count - 1]);  //计算实际夹角

            adblAzimuth[pCorrCptsLt.Count - 2] = adblAzimuth[pCorrCptsLt.Count - 3] + dblAnglelast0 - Math.PI;


            //统计插值点数
            int intKnownPt   = 0;                             //固定点的数目
            int intUnknownPt = 0;                             //非固定点的数目

            List <int> intKnownLocationLt = new List <int>(); //记录已知点的序号

            //注意:对于该循环,有一个默认条件,即FromCpl的第一个顶点只有一个对应点
            for (int i = 0; i < cptlt.Count; i++)
            {
                if (cptlt[i].isCtrl == true)
                {
                    intKnownLocationLt.Add(i);
                    intKnownPt += 1;
                }
                else
                {
                    intUnknownPt += 1;
                }
            }
            int intUnknownXY = intUnknownPt * 2;   //每个点都有X、Y坐标

            //找出长度固定的位置(如果一个线段的前后两个点都固定,则该长度固定)。另外,长度固定则该边的方位角也固定
            List <int> intKnownLengthLt = new List <int>();

            for (int i = 0; i < intKnownLocationLt.Count - 1; i++)
            {
                if ((intKnownLocationLt[i + 1] - intKnownLocationLt[i]) == 1)
                {
                    intKnownLengthLt.Add(intKnownLocationLt[i]);
                }
            }
            int intUnknownLength = cptlt.Count - 1 - intKnownLengthLt.Count;

            //找出角度固定的位置(如果一个固定顶点的前后两个点都固定,则该角度固定)
            List <int> intKnownAngleLt = new List <int>();

            for (int i = 0; i < intKnownLocationLt.Count - 2; i++)
            {
                if ((intKnownLocationLt[i + 1] - intKnownLocationLt[i]) == 1 && (intKnownLocationLt[i + 2] - intKnownLocationLt[i + 1]) == 1)
                {
                    intKnownAngleLt.Add(intKnownLocationLt[i]);
                }
            }
            int intUnknownAngle = cptlt.Count - 2 - intKnownAngleLt.Count;

            //总未知量
            int intUnknownLengthAngle = intUnknownLength + intUnknownAngle;

            //定义权重矩阵
            VBMatrix P = new VBMatrix(intUnknownLengthAngle, intUnknownLengthAngle);

            for (int i = 0; i < intUnknownLength; i++)
            {
                P[i, i] = 1;
            }
            for (int i = 0; i < intUnknownAngle; i++)
            {
                P[intUnknownLength + i, intUnknownLength + i] = 1;
            }

            //定义权重矩阵倒数
            VBMatrix QLL = new VBMatrix(intUnknownLengthAngle, intUnknownLengthAngle);

            for (int i = 0; i < intUnknownLength; i++)
            {
                QLL[i, i] = 1;
            }
            for (int i = 0; i < intUnknownAngle; i++)
            {
                QLL[intUnknownLength + i, intUnknownLength + i] = 1;
            }
            //for (int i = 0; i < intXYCst; i++)
            //{
            //    P[intUnknownLengthAngle + i, intUnknownLengthAngle + i] = 1;
            //}
            //for (int i = 0; i < intAngleCst; i++)
            //{
            //    P[intUnknownLengthAngle + intXYCst + i, intUnknownLengthAngle + intXYCst + i] =100000;
            //}

            //计算初始值矩阵X0
            VBMatrix X0 = new VBMatrix(2 * intPtNum, 1);

            for (int i = 0; i < intPtNum; i++)
            {
                X0[2 * i, 0]     = cptlt[i].X;
                X0[2 * i + 1, 0] = cptlt[i].Y;
            }
            //Xmix里存储了XA和X0的最新混合值(此矩阵在公式推导中并不存在,只是为了方便编写代码而建立)
            VBMatrix Xmix = new VBMatrix(2 * intPtNum, 1);

            for (int i = 0; i < (2 * intPtNum); i++)
            {
                Xmix[i, 0] = X0[i, 0];
            }

            //定义系数矩阵B(各方程对长度、角度的导数值)
            VBMatrix B = new VBMatrix(intUnknownLengthAngle, intUnknownLengthAngle);

            for (int i = 0; i < intUnknownLengthAngle; i++)
            {
                B[i, i] = -1;
            }

            //定义系数矩阵A(各方程对坐标的导数值),A的导数值将在循环中给出
            VBMatrix A                 = new VBMatrix(intUnknownLengthAngle, intUnknownXY);
            double   dblJudge1         = 0; //该值用于判断是否应该跳出循环
            double   dblJudge2         = 0; //该值用于判断是否应该跳出循环
            int      intJudgeIndex     = intUnknownLength / 4;
            int      intIterativeCount = 0;

            double[] dblSubDis = new double[intPtNum - 1];
            do
            {
                VBMatrix w = new VBMatrix(intUnknownLengthAngle, 1);

                //计算系数矩阵A第0行到"intUnknownLength"行的各元素,即线段长度对各未知数求偏导的值
                //先计算各分母值(注意:分母实际上是求偏导后的一部分值,但却恰好等于两点之间距离,因此其计算公式与距离计算公式相同
                dblSubDis = new double[intPtNum - 1];
                for (int i = 0; i < intPtNum - 1; i++)
                {
                    dblSubDis[i] = Math.Pow((Xmix[2 * i, 0] - Xmix[2 * i + 2, 0]) * (Xmix[2 * i, 0] - Xmix[2 * i + 2, 0]) + (Xmix[2 * i + 1, 0] - Xmix[2 * i + 3, 0]) * (Xmix[2 * i + 1, 0] - Xmix[2 * i + 3, 0]), 0.5);
                }
                //计算新的方位角
                adblAzimuth[0] = CGeoFunc.CalAxisAngle(Xmix[0, 0], Xmix[1, 0], Xmix[2, 0], Xmix[3, 0]);
                for (int i = 1; i < intPtNum - 1; i++)
                {
                    double dblAngle = CGeoFunc.CalAngle_Counterclockwise(Xmix[i * 2 - 2, 0], Xmix[i * 2 - 1, 0], Xmix[i * 2, 0], Xmix[i * 2 + 1, 0], Xmix[i * 2 + 2, 0], Xmix[i * 2 + 3, 0]);
                    adblAzimuth[i] = adblAzimuth[i - 1] + dblAngle - Math.PI;
                }

                //开始计算系数矩阵第"intUnknownXY"行到"intUnknownXY+intUnknownLength-1"行的各元素
                int intKnownCount2   = 0;
                int intUnKnownCount2 = 0;
                for (int j = 0; j < intUnknownLength; j++)
                {
                    int intSumCount = intKnownCount2 + intUnKnownCount2;
                    if (cptlt[intSumCount].isCtrl == false && cptlt[intSumCount + 1].isCtrl == false)
                    {
                        A[j, 2 * intUnKnownCount2 + 0] = -Math.Cos(adblAzimuth[intSumCount]);
                        A[j, 2 * intUnKnownCount2 + 1] = -Math.Sin(adblAzimuth[intSumCount]);
                        A[j, 2 * intUnKnownCount2 + 2] = -A[j, 2 * intUnKnownCount2 + 0];
                        A[j, 2 * intUnKnownCount2 + 3] = -A[j, 2 * intUnKnownCount2 + 1];

                        w[j, 0] = dblSubDis[intSumCount] - adblLength[intSumCount];   //图方便,顺便计算matl

                        intUnKnownCount2 += 1;
                    }
                    else if (cptlt[intSumCount].isCtrl == false && cptlt[intSumCount + 1].isCtrl == true)
                    {
                        A[j, 2 * intUnKnownCount2 + 0] = -Math.Cos(adblAzimuth[intSumCount]);
                        A[j, 2 * intUnKnownCount2 + 1] = -Math.Sin(adblAzimuth[intSumCount]);

                        w[j, 0] = dblSubDis[intSumCount] - adblLength[intSumCount];   //图方便,顺便计算matl

                        intUnKnownCount2 += 1;
                    }
                    else if (cptlt[intSumCount].isCtrl == true && cptlt[intSumCount + 1].isCtrl == false)
                    {
                        //注意这种情况,由于"pCorrCptsLt[intSumCount].FrCpt.isCtrl == true"不占位子(即不占列),因此列序号依然为" 2 * intUnKnownCount2 + 0"和" 2 * intUnKnownCount2 + 1",而不是+2,+3
                        A[j, 2 * intUnKnownCount2 + 0] = Math.Cos(adblAzimuth[intSumCount]);
                        A[j, 2 * intUnKnownCount2 + 1] = Math.Sin(adblAzimuth[intSumCount]);

                        w[j, 0] = dblSubDis[intSumCount] - adblLength[intSumCount];   //图方便,顺便计算matl

                        intKnownCount2 += 1;
                    }
                    else
                    {
                        intKnownCount2 += 1;
                        j -= 1;
                    }
                }

                //计算系数矩阵A第"intUnknownXY+intUnknownLength"行到"intUnknownXY+intUnknownLength+intUnknownAngle"行的各元素,即角度对各未知数求偏导的值
                int intKnownCount3   = 0;
                int intUnKnownCount3 = 0;
                for (int j = 0; j < intUnknownAngle; j++)
                {
                    //真是太幸运了,虽然求两向量逆时针夹角时需分多种情况讨论,但各情况的导数形式却是一致的,节省了不少编程精力啊,哈哈
                    int intSumCount = intKnownCount3 + intUnKnownCount3;

                    //常用数据准备
                    double dblA2 = dblSubDis[intSumCount] * dblSubDis[intSumCount];
                    double dblB2 = dblSubDis[intSumCount + 1] * dblSubDis[intSumCount + 1];

                    //开始计算系数值,由于将以下三个情况排列组合将有八种情况,因此按如下方式计算
                    if (cptlt[intUnKnownCount3 + intKnownCount3].isCtrl == true && cptlt[intUnKnownCount3 + intKnownCount3 + 1].isCtrl == true && cptlt[intUnKnownCount3 + intKnownCount3 + 2].isCtrl == true)
                    {
                        intKnownCount3 += 1;
                        j -= 1;
                    }
                    else
                    {
                        double dblNewAngle = CGeoFunc.CalAngle_Counterclockwise(Xmix[2 * intSumCount + 0, 0], Xmix[2 * intSumCount + 1, 0],
                                                                                Xmix[2 * intSumCount + 2, 0], Xmix[2 * intSumCount + 3, 0],
                                                                                Xmix[2 * intSumCount + 4, 0], Xmix[2 * intSumCount + 5, 0]);
                        w[intUnknownLength + j, 0] = dblNewAngle - adblAngle[intSumCount];   //图方便,顺便计算matl

                        int intPreTrueNum           = 0;
                        int intUnKnownCount3orginal = intUnKnownCount3;
                        int intKnownCount3orginal   = intKnownCount3;
                        if (cptlt[intUnKnownCount3orginal + intKnownCount3orginal + 0].isCtrl == false)
                        {
                            //X1,Y1的导数值(注意:该部分是减数,因此值为导数的负数)
                            A[intUnknownLength + j, 2 * intUnKnownCount3orginal + 0] = -(Xmix[2 * intSumCount + 3, 0] - Xmix[2 * intSumCount + 1, 0]) / dblA2;
                            A[intUnknownLength + j, 2 * intUnKnownCount3orginal + 1] = (Xmix[2 * intSumCount + 2, 0] - Xmix[2 * intSumCount + 0, 0]) / dblA2;

                            intUnKnownCount3 += 1;
                        }
                        else
                        {
                            intPreTrueNum  += 1;
                            intKnownCount3 += 1;
                        }

                        if (cptlt[intUnKnownCount3orginal + intKnownCount3orginal + 1].isCtrl == false)
                        {
                            //X2,Y2的导数值
                            //A[intUnknownLength + j, 2 * (intUnKnownCount3orginal - intPreTrueNum) + 2] = -(Xmix[2 * intSumCount + 5, 0] - Xmix[2 * intSumCount + 3, 0]) / dblB2 - (Xmix[2 * intSumCount + 3, 0] - Xmix[2 * intSumCount + 1, 0]) / dblA2;
                            //A[intUnknownLength + j, 2 * (intUnKnownCount3orginal - intPreTrueNum) + 3] = (Xmix[2 * intSumCount + 4, 0] - Xmix[2 * intSumCount + 2, 0]) / dblB2 + (Xmix[2 * intSumCount + 2, 0] - Xmix[2 * intSumCount + 0, 0]) / dblA2;

                            A[intUnknownLength + j, 2 * (intUnKnownCount3orginal - intPreTrueNum) + 2] = (Xmix[2 * intSumCount + 5, 0] - Xmix[2 * intSumCount + 3, 0]) / dblB2 + (Xmix[2 * intSumCount + 3, 0] - Xmix[2 * intSumCount + 1, 0]) / dblA2;
                            A[intUnknownLength + j, 2 * (intUnKnownCount3orginal - intPreTrueNum) + 3] = -(Xmix[2 * intSumCount + 4, 0] - Xmix[2 * intSumCount + 2, 0]) / dblB2 - (Xmix[2 * intSumCount + 2, 0] - Xmix[2 * intSumCount + 0, 0]) / dblA2;
                        }
                        else
                        {
                            intPreTrueNum += 1;
                        }
                        if (cptlt[intUnKnownCount3orginal + intKnownCount3orginal + 2].isCtrl == false)
                        {
                            //X3,Y3的导数值
                            A[intUnknownLength + j, 2 * (intUnKnownCount3orginal - intPreTrueNum) + 4] = -(Xmix[2 * intSumCount + 5, 0] - Xmix[2 * intSumCount + 3, 0]) / dblB2;
                            A[intUnknownLength + j, 2 * (intUnKnownCount3orginal - intPreTrueNum) + 5] = (Xmix[2 * intSumCount + 4, 0] - Xmix[2 * intSumCount + 2, 0]) / dblB2;
                        }
                    }
                }

                //一个中间值
                VBMatrix InvBQLLBt = new VBMatrix(intUnknownLengthAngle, intUnknownLengthAngle);
                for (int i = 0; i < intUnknownLengthAngle; i++)  //注意:此处之所以可以这样计算是因为B矩阵是元素为-1的对角矩阵,且QLL是对角矩阵
                {
                    InvBQLLBt[i, i] = 1 / (QLL[i, i] * QLL[i, i]);
                }

                //计算Q22
                VBMatrix TempQ22 = A.Trans() * InvBQLLBt * A;
                VBMatrix NegQ22  = TempQ22.Inv(TempQ22);
                VBMatrix Q22     = new VBMatrix(intUnknownXY, intUnknownXY);
                for (int i = 0; i < intUnknownXY; i++)
                {
                    for (int j = 0; j < intUnknownXY; j++)
                    {
                        Q22[i, j] = -NegQ22[i, j];
                    }
                }

                //计算Q12
                VBMatrix NegQ12 = InvBQLLBt * A * Q22;
                VBMatrix Q12    = new VBMatrix(intUnknownLengthAngle, intUnknownXY);
                for (int i = 0; i < intUnknownLengthAngle; i++)
                {
                    for (int j = 0; j < intUnknownXY; j++)
                    {
                        Q12[i, j] = -NegQ12[i, j];
                    }
                }

                //计算Q21
                VBMatrix Q21 = Q12.Trans();

                //计算Q11********************************************************************
                VBMatrix I = new VBMatrix(intUnknownLengthAngle, intUnknownLengthAngle);
                for (int i = 0; i < intUnknownLengthAngle; i++)
                {
                    I[i, i] = 1;
                }
                VBMatrix Q11 = InvBQLLBt * (I - A * Q21);

                //计算负v
                VBMatrix Negv = QLL * B.Trans() * Q11 * w;

                //计算负x
                VBMatrix Negx = Q21 * w;

                //对观测值进行改正
                int intSumCountL4 = 0;
                for (int i = 0; i < intUnknownLength; i++) //长度近似值部分
                {
                    if (cptlt[intSumCountL4].isCtrl == false || cptlt[intSumCountL4 + 1].isCtrl == false)
                    {
                        adblLength[intSumCountL4] = adblLength[intSumCountL4] - Negv[i, 0];
                    }
                    else
                    {
                        i -= 1;
                    }
                    intSumCountL4 += 1;
                }
                int intSumCountA4 = 0;
                for (int i = intUnknownLength; i < intUnknownLengthAngle; i++) //角度近似值部分
                {
                    if (cptlt[intSumCountA4].isCtrl == false || cptlt[intSumCountA4 + 1].isCtrl == false || cptlt[intSumCountA4 + 2].isCtrl == false)
                    {
                        adblAngle[intSumCountA4] = adblAngle[intSumCountA4] - Negv[i, 0];
                    }
                    else
                    {
                        i -= 1;
                    }
                    intSumCountA4 += 1;
                }

                //对坐标值进行改正
                int intSumCount5 = 0;
                for (int i = 0; i < intUnknownPt; i++)
                {
                    if (cptlt[intSumCount5].isCtrl == false)
                    {
                        Xmix[intSumCount5 * 2, 0]     = Xmix[intSumCount5 * 2, 0] - Negx[i * 2, 0];
                        Xmix[intSumCount5 * 2 + 1, 0] = Xmix[intSumCount5 * 2 + 1, 0] - Negx[i * 2 + 1, 0];
                    }
                    else
                    {
                        i -= 1;
                    }
                    intSumCount5 += 1;
                }

                if (intIterativeCount == 50)
                {
                    int kk = 5;
                }

                intIterativeCount += 1;


                if (intIterativeCount >= 1000)
                {
                    break;
                }


                //这里只是随便取两个中间值以观测是否收敛

                dblJudge1 = Math.Abs(Negx[intJudgeIndex, 0]);
                dblJudge2 = Math.Abs(Negx[3 * intJudgeIndex, 0]);
            } while ((dblJudge1 > dblTX) || (dblJudge2 > dblTX));


            //生成目标线段
            List <CPoint> CTargetPtLt = new List <CPoint>();

            for (int i = 0; i < intPtNum; i++)
            {
                CPoint cpt = new CPoint(i);
                cpt.X = Xmix[2 * i, 0];
                cpt.Y = Xmix[2 * i + 1, 0];
                CTargetPtLt.Add(cpt);
            }
            CPolyline cpl = new CPolyline(0, CTargetPtLt);

            return(cpl);
        }
Пример #3
0
        /// <summary>
        /// 获取线状要素
        /// </summary>
        /// <param name="intInterNum">Inter: Interpolation</param>
        /// <returns>在处理面状要素时,本程序将原面状要素的边界切开,按线状要素处理,处理完后再重新生成面状要素</returns>
        public List<CPolyline> GetTargetcpllt()
        {
            int intIterationNum = Convert.ToInt32(_DataRecords.ParameterInitialize.txtIterationNum.Text);
            int intInterNum = Convert.ToInt32(_DataRecords.ParameterInitialize.txtInterpolationNum.Text);
            List<CCorrCpts> pCorrCptsLt = _DataRecords.ParameterResult.CCorrCptsLt;   //Read Datasets后,此处ResultPtLt中的对应点为一一对应
            double dblTX = _dblTX;
            double dblInterval = 1 / Convert.ToDouble(intInterNum + 1);


            int intPtNum = pCorrCptsLt.Count;
            int intXYNum = intPtNum * 2;
            int intMultiXYNum = intInterNum * intXYNum;


            //计算长度初始值(全部计算)
            double[,] adblLength0 = new double[intInterNum, intPtNum - 1];
            double[,] adblLength = new double[intInterNum, intPtNum - 1];   //顺便定义中间值数组
            for (int j = 0; j < pCorrCptsLt.Count - 1; j++)
            {
                double dblfrsublength = CGeoFunc.CalDis(pCorrCptsLt[j + 1].FrCpt, pCorrCptsLt[j].FrCpt);
                double dbltosublength = CGeoFunc.CalDis(pCorrCptsLt[j + 1].ToCpt, pCorrCptsLt[j].ToCpt);
                for (int i = 0; i < intInterNum; i++)
                {
                    double dblProp = (i+1) * dblInterval;
                    adblLength0[i, j] = (1 - dblProp) * dblfrsublength + dblProp * dbltosublength;
                }
                //pCorrCptsLt[j].FrCpt.isCtrl = false;  //仅以最开始两对和最终两队对应点为固定点,故此先设置为false
            }

            //计算角度初始值(全部计算)
            double[,] adblAngle0 = new double[intInterNum, intPtNum - 2];
            double[,] adblAngle = new double[intInterNum, intPtNum - 2];
            for (int j = 0; j < pCorrCptsLt.Count - 2; j++)
            {
                //较大比例尺线状要素上的夹角
                double dblfrAngle = CGeoFunc.CalAngle_Counterclockwise(pCorrCptsLt[j].FrCpt, pCorrCptsLt[j + 1].FrCpt, pCorrCptsLt[j + 2].FrCpt);
                //较小比例尺线状要素上的夹角
                double dbltoAngle = CGeoFunc.CalAngle_Counterclockwise(pCorrCptsLt[j].ToCpt, pCorrCptsLt[j + 1].ToCpt, pCorrCptsLt[j + 2].ToCpt);

                //角度初始值
                for (int i = 0; i < intInterNum; i++)
                {
                    double dblProp = (i + 1) * dblInterval;
                    adblAngle0[i, j] = (1 - dblProp) * dblfrAngle + dblProp * dbltoAngle;
                }
            }

            //多线段间对应顶点距离初始值(全部计算),全部设置为0
            //目标值也设置为0
            double[,] adblIntervalDis0 = new double[intInterNum + 1, intPtNum];
            double[,] adblIntervalDis = new double[intInterNum + 1, intPtNum];   //顺便定义中间值数组
            for (int j = 0; j < pCorrCptsLt.Count; j++)
            {
                //长度初始值
                for (int i = 0; i <= intInterNum; i++)
                {
                    adblIntervalDis0[i, j] = 0;
                    adblIntervalDis[i, j] = 0;
                }
            }


            //计算坐标初始值,以及各线段方位角初始值
            //注意:默认固定第一条边
            pCorrCptsLt[0].FrCpt.isCtrl = true;
            pCorrCptsLt[1].FrCpt.isCtrl = true;
            VBMatrix X0 = new VBMatrix(intMultiXYNum, 1);
            double[,] adblAzimuth = new double[intInterNum, intPtNum - 1];
            for (int i = 0; i < intInterNum; i++)
            {
                double dblProp = (i + 1) * dblInterval;
                double dblnewX0 = (1 - dblProp) * pCorrCptsLt[0].FrCpt.X + dblProp * pCorrCptsLt[0].ToCpt.X;
                double dblnewY0 = (1 - dblProp) * pCorrCptsLt[0].FrCpt.Y + dblProp * pCorrCptsLt[0].ToCpt.Y;
                double dblnewX1 = (1 - dblProp) * pCorrCptsLt[1].FrCpt.X + dblProp * pCorrCptsLt[1].ToCpt.X;
                double dblnewY1 = (1 - dblProp) * pCorrCptsLt[1].FrCpt.Y + dblProp * pCorrCptsLt[1].ToCpt.Y;
                adblAzimuth[i, 0] = CGeoFunc.CalAxisAngle(dblnewX0, dblnewY0, dblnewX1, dblnewY1);

                int intBasicIndex = i * intXYNum;
                X0[intBasicIndex + 0, 0] = dblnewX0;
                X0[intBasicIndex + 1, 0] = dblnewY0;
                X0[intBasicIndex + 2, 0] = dblnewX1;
                X0[intBasicIndex + 3, 0] = dblnewY1;
            }

            //其它点
            //是否固定最后两个点
            pCorrCptsLt[pCorrCptsLt.Count - 2].FrCpt.isCtrl = true;
            pCorrCptsLt[pCorrCptsLt.Count - 1].FrCpt.isCtrl = true;

            for (int j = 2; j < intPtNum; j++)
            {
                for (int i = 0; i < intInterNum; i++)
                {
                    int intBasicIndexIJ = i * intXYNum + 2 * j;
                    double dblProp = (i + 1) * dblInterval;
                    X0[intBasicIndexIJ + 0, 0] = (1 - dblProp) * pCorrCptsLt[j].FrCpt.X + dblProp * pCorrCptsLt[j].ToCpt.X;
                    X0[intBasicIndexIJ + 1, 0] = (1 - dblProp) * pCorrCptsLt[j].FrCpt.Y + dblProp * pCorrCptsLt[j].ToCpt.Y;
                    double dblAngle = CGeoFunc.CalAngle_Counterclockwise(X0[intBasicIndexIJ - 4, 0], X0[intBasicIndexIJ - 3, 0], X0[intBasicIndexIJ - 2, 0], X0[intBasicIndexIJ - 1, 0], X0[intBasicIndexIJ - 0, 0], X0[intBasicIndexIJ + 1, 0]);  //计算实际夹角 
                    adblAzimuth[i, j - 1] = adblAzimuth[i, j - 2] + dblAngle - Math.PI;
                }
            }


            //for (int j = 2; j < intPtNum; j++)
            //{

            //    if (pCorrCptsLt[j].FrCpt.isCtrl == false)
            //    {
            //        for (int i = 0; i < intInterNum; i++)
            //        {
            //            int intBasicIndexI = i * intXYNum;
            //            adblAzimuth[i, j - 1] = adblAzimuth[i, j - 2] + adblAngle0[i, j - 2] - Math.PI;
            //            X0[intBasicIndexI + 2 * j + 0, 0] = X0[intBasicIndexI + 2 * (j - 1) + 0, 0] + adblLength0[i, j - 1] * Math.Cos(adblAzimuth[i, j - 1]);
            //            X0[intBasicIndexI + 2 * j + 1, 0] = X0[intBasicIndexI + 2 * (j - 1) + 1, 0] + adblLength0[i, j - 1] * Math.Sin(adblAzimuth[i, j - 1]);
            //        }
            //    }
            //    else
            //    {
            //        for (int i = 0; i < intInterNum; i++)
            //        {
            //            int intBasicIndexIJ = i * intXYNum + 2 * j;
            //            double dblProp = (i + 1) * dblInterval;
            //            X0[intBasicIndexIJ + 0, 0] = (1 - dblProp) * pCorrCptsLt[j].FrCpt.X + dblProp * pCorrCptsLt[j].ToCpt.X;
            //            X0[intBasicIndexIJ + 1, 0] = (1 - dblProp) * pCorrCptsLt[j].FrCpt.Y + dblProp * pCorrCptsLt[j].ToCpt.Y;
            //            double dblAngle = CGeoFunc.CalAngle_Counterclockwise(X0[intBasicIndexIJ - 4, 0], X0[intBasicIndexIJ - 3, 0], X0[intBasicIndexIJ - 2, 0], X0[intBasicIndexIJ - 1, 0], X0[intBasicIndexIJ - 0, 0], X0[intBasicIndexIJ + 1, 0]);  //计算实际夹角 
            //            adblAzimuth[i, j - 1] = adblAzimuth[i, j - 2] + dblAngle - Math.PI;
            //        }
            //    }
            //}


            //统计插值点数
            int intKnownPt = 0;           //固定点的数目
            int intUnknownPt = 0;         //非固定点的数目

            List<int> intKnownLocationLt = new List<int>();  //记录已知点的序号
            //注意:对于该循环,有一个默认条件,即FromCpl的第一个顶点只有一个对应点
            for (int i = 0; i < intPtNum; i++)
            {
                if (pCorrCptsLt[i].FrCpt.isCtrl == true)
                {
                    intKnownLocationLt.Add(i);
                    intKnownPt += 1;
                }
                else
                {
                    intUnknownPt += 1;
                }
            }
            int intUnknownXY = intUnknownPt * 2;   //每个点都有X、Y坐标
            int intMultiUnknownXY = intInterNum * intUnknownXY;

            //找出长度固定的位置(如果一个线段的前后两个点都固定,则该长度固定)。另外,长度固定则该边的方位角也固定
            List<int> intKnownLengthLt = new List<int>();
            for (int i = 0; i < intKnownLocationLt.Count - 1; i++)
            {
                if ((intKnownLocationLt[i + 1] - intKnownLocationLt[i]) == 1)
                {
                    intKnownLengthLt.Add(intKnownLocationLt[i]);
                }
            }
            int intUnknownLength = intPtNum - 1 - intKnownLengthLt.Count;

            //找出角度固定的位置(如果一个固定顶点的前后两个点都固定,则该角度固定)
            List<int> intKnownAngleLt = new List<int>();
            for (int i = 0; i < intKnownLocationLt.Count - 2; i++)
            {
                if ((intKnownLocationLt[i + 1] - intKnownLocationLt[i]) == 1 && (intKnownLocationLt[i + 2] - intKnownLocationLt[i + 1]) == 1)
                {
                    intKnownAngleLt.Add(intKnownLocationLt[i]);
                }
            }
            int intUnknownAngle = intPtNum - 2 - intKnownAngleLt.Count;

            //长度角度未知量
            int intUnknownLengthAngle = intUnknownLength + intUnknownAngle;

            //各未知量个数
            int intMultiUnknownLength = intInterNum * intUnknownLength;
            int intMultiUnknownAngle = intInterNum * intUnknownAngle;
            int intMultiUnknownLengthAngle = intMultiUnknownLength + intMultiUnknownAngle;
            int intMultiUnknownInterval = (intInterNum + 1) * intUnknownPt;
            int intSumConstraints = intMultiUnknownLength + intMultiUnknownAngle + intMultiUnknownInterval;

            //定义权重矩阵
            VBMatrix P = new VBMatrix(intSumConstraints, intSumConstraints);
            for (int i = 0; i < intMultiUnknownLength; i++)  //长度权重
            {
                P[i, i] = 1;
            }
            for (int i = 0; i < intMultiUnknownAngle; i++)   //角度权重
            {
                P[intMultiUnknownLength + i, intMultiUnknownLength + i] = 40;
            }
            for (int i = 0; i < intMultiUnknownInterval; i++)   //角度权重
            {
                P[intMultiUnknownLengthAngle + i, intMultiUnknownLengthAngle + i] = 10000000000000;
            }




            //for (int i = 0; i < intInterNum; i++)
            //{
            //    int intBasicIndex2 = i * intUnknownLengthAngle;
            //    for (int j = 0; j < intUnknownLength; j++)
            //    {
            //        P[intBasicIndex2 + j, intBasicIndex2 + j] = 1;
            //    }
            //    for (int j = 0; j < intUnknownAngle; j++)
            //    {
            //        P[intBasicIndex2 + intUnknownLength + j, intBasicIndex2 + intUnknownLength + j] = 1;
            //    }
            //}

            //Xmix里存储了XA和X0的最新混合值(此矩阵在公式推导中并不存在,只是为了方便编写代码而建立)
            VBMatrix Xmix = new VBMatrix(intMultiXYNum, 1);
            for (int i = 0; i < intMultiXYNum; i++)
            {
                Xmix[i, 0] = X0[i, 0];
            }

            //定义坐标近似值矩阵XA
            VBMatrix XA = new VBMatrix(intMultiUnknownXY, 1);
            VBMatrix XA0 = new VBMatrix(intMultiUnknownXY, 1);
            int intSumCount0 = 0;
            for (int j = 0; j < intUnknownPt; j++)
            {
                if (pCorrCptsLt[intSumCount0].FrCpt.isCtrl == false)
                {
                    for (int i = 0; i < intInterNum; i++)
                    {
                        XA[i * intUnknownXY + j * 2 + 0, 0] = X0[i * intXYNum + intSumCount0 * 2 + 0, 0];
                        XA[i * intUnknownXY + j * 2 + 1, 0] = X0[i * intXYNum + intSumCount0 * 2 + 1, 0];

                        XA0[i * intUnknownXY + j * 2 + 0, 0] = XA[i * intUnknownXY + j * 2 + 0, 0];
                        XA0[i * intUnknownXY + j * 2 + 1, 0] = XA[i * intUnknownXY + j * 2 + 1, 0];
                    }
                }
                else
                {
                    j -= 1;
                }
                intSumCount0 += 1;
            }

            //定义系数矩阵A(各方程对坐标的导数值),A的导数值将在循环中给出
            VBMatrix A = new VBMatrix(intSumConstraints, intMultiUnknownXY);
            double dblJudge1 = 0;   //该值用于判断是否应该跳出循环
            double dblJudge2 = 0;   //该值用于判断是否应该跳出循环
            double dblJudge3 = 0;   //该值用于判断是否应该跳出循环
            int intJudgeIndex = intMultiUnknownXY / 4;
            int intIterativeCount = 0;

            for (int k = 0; k < 2; k++)
            {
                //break;
                do
                {

                    
                    if (intIterativeCount >= intIterationNum)
                    {
                        break;
                    }
                    intIterativeCount += 1;


                    VBMatrix matl = new VBMatrix(intSumConstraints, 1);


                    //计算系数矩阵A第0行到"intUnknownLength"行的各元素,即线段长度对各未知数求偏导的值
                    //先计算各分母值(注意:分母实际上是求偏导后的一部分值,但却恰好等于两点之间距离,因此其计算公式与距离计算公式相同
                    for (int i = 0; i < intInterNum; i++)
                    {
                        int intBasicIndexS1 = i * intXYNum;
                        for (int j = 0; j < intPtNum - 1; j++)
                        {
                            int intBasicIndexIJS1 = intBasicIndexS1 + 2 * j;
                            adblLength[i, j] = Math.Sqrt((Xmix[intBasicIndexIJS1 + 0, 0] - Xmix[intBasicIndexIJS1 + 2, 0]) * (Xmix[intBasicIndexIJS1 + 0, 0] - Xmix[intBasicIndexIJS1 + 2, 0]) +
                                                         (Xmix[intBasicIndexIJS1 + 1, 0] - Xmix[intBasicIndexIJS1 + 3, 0]) * (Xmix[intBasicIndexIJS1 + 1, 0] - Xmix[intBasicIndexIJS1 + 3, 0]));
                        }
                    }

                    //计算新的方位角
                    for (int i = 0; i < intInterNum; i++)
                    {
                        int intBasicIndexA1 = i * intXYNum;
                        //第一条线段的方位角
                        adblAzimuth[i, 0] = CGeoFunc.CalAxisAngle(Xmix[intBasicIndexA1 + 0, 0], Xmix[intBasicIndexA1 + 1, 0], Xmix[intBasicIndexA1 + 2, 0], Xmix[intBasicIndexA1 + 3, 0]);
                        //后面线段的方位角
                        for (int j = 1; j < intPtNum - 1; j++)
                        {
                            int intBasicIndexIJA1 = intBasicIndexA1 + 2 * j;
                            double dblAngle = CGeoFunc.CalAngle_Counterclockwise(Xmix[intBasicIndexIJA1 - 2, 0], Xmix[intBasicIndexIJA1 - 1, 0],
                                                                        Xmix[intBasicIndexIJA1 + 0, 0], Xmix[intBasicIndexIJA1 + 1, 0],
                                                                        Xmix[intBasicIndexIJA1 + 2, 0], Xmix[intBasicIndexIJA1 + 3, 0]);
                            adblAzimuth[i, j] = adblAzimuth[i, j - 1] + dblAngle - Math.PI;
                        }
                    }

                    //计算新的多线段间对应顶点距离
                    for (int j = 0; j < intPtNum; j++)
                    {
                        int int2J = 2 * j;
                        //源线段与第一生成线段间对应点距离
                        adblIntervalDis[0, j] = Math.Sqrt((pCorrCptsLt[j].FrCpt.X - Xmix[int2J + 0, 0]) * (pCorrCptsLt[j].FrCpt.X - Xmix[int2J + 0, 0]) +
                                                          (pCorrCptsLt[j].FrCpt.Y - Xmix[int2J + 1, 0]) * (pCorrCptsLt[j].FrCpt.Y - Xmix[int2J + 1, 0]));
                        //目标线段与最后生成线段间对应点距离
                        adblIntervalDis[intInterNum, j] = Math.Sqrt((pCorrCptsLt[j].ToCpt.X - Xmix[(intInterNum - 1) * intXYNum + int2J + 0, 0]) * (pCorrCptsLt[j].ToCpt.X - Xmix[(intInterNum - 1) * intXYNum + int2J + 0, 0]) +
                                                                    (pCorrCptsLt[j].ToCpt.Y - Xmix[(intInterNum - 1) * intXYNum + int2J + 1, 0]) * (pCorrCptsLt[j].ToCpt.Y - Xmix[(intInterNum - 1) * intXYNum + int2J + 1, 0]));
                        //各生成线段间对应点距离
                        for (int i = 1; i < intInterNum; i++)
                        {
                            adblIntervalDis[i, j] = Math.Sqrt((Xmix[(i - 1) * intXYNum + int2J + 0, 0] - Xmix[i * intXYNum + int2J + 0, 0]) * (Xmix[(i - 1) * intXYNum + int2J + 0, 0] - Xmix[i * intXYNum + int2J + 0, 0]) +
                                                              (Xmix[(i - 1) * intXYNum + int2J + 1, 0] - Xmix[i * intXYNum + int2J + 1, 0]) * (Xmix[(i - 1) * intXYNum + int2J + 1, 0] - Xmix[i * intXYNum + int2J + 1, 0]));
                        }
                    }

                    //计算系数矩阵中关于长度值的导数部分(注意:隐含的距离计算公式为后一个点的坐标减前一个点的坐标)
                    int intKnownCount2 = 0;
                    int intUnKnownCount2 = 0;
                    for (int j = 0; j < intUnknownLength; j++)
                    {
                        int intSumCount = intKnownCount2 + intUnKnownCount2;
                        int intBasicIndexL2 = 2 * intUnKnownCount2;
                        if (pCorrCptsLt[intSumCount].FrCpt.isCtrl == false && pCorrCptsLt[intSumCount + 1].FrCpt.isCtrl == false)
                        {
                            for (int i = 0; i < intInterNum; i++)
                            {
                                A[i * intUnknownLength + j, i * intUnknownXY + intBasicIndexL2 + 0] = -Math.Cos(adblAzimuth[i, intSumCount]);
                                A[i * intUnknownLength + j, i * intUnknownXY + intBasicIndexL2 + 1] = -Math.Sin(adblAzimuth[i, intSumCount]);
                                A[i * intUnknownLength + j, i * intUnknownXY + intBasicIndexL2 + 2] = -A[i * intUnknownLength + j, i * intUnknownXY + intBasicIndexL2 + 0];
                                A[i * intUnknownLength + j, i * intUnknownXY + intBasicIndexL2 + 3] = -A[i * intUnknownLength + j, i * intUnknownXY + intBasicIndexL2 + 1];

                                matl[i * intUnknownLength + j, 0] =adblLength0[i, intSumCount]- adblLength[i, intSumCount];   //图方便,顺便计算matl                            
                            }
                            intUnKnownCount2 += 1;
                        }
                        else if (pCorrCptsLt[intSumCount].FrCpt.isCtrl == false && pCorrCptsLt[intSumCount + 1].FrCpt.isCtrl == true)
                        {
                            for (int i = 0; i < intInterNum; i++)
                            {
                                A[i * intUnknownLength + j, i * intUnknownXY + intBasicIndexL2 + 0] = -Math.Cos(adblAzimuth[i, intSumCount]);
                                A[i * intUnknownLength + j, i * intUnknownXY + intBasicIndexL2 + 1] = -Math.Sin(adblAzimuth[i, intSumCount]);

                                matl[i * intUnknownLength + j, 0] = adblLength0[i, intSumCount]- adblLength[i, intSumCount];   //图方便,顺便计算matl                            
                            }
                            intUnKnownCount2 += 1;
                        }
                        else if (pCorrCptsLt[intSumCount].FrCpt.isCtrl == true && pCorrCptsLt[intSumCount + 1].FrCpt.isCtrl == false)
                        {
                            for (int i = 0; i < intInterNum; i++)
                            {
                                //注意这种情况,由于"pCorrCptsLt[intSumCount].FrCpt.isCtrl == true"不占位子(即不占列),因此列序号依然为" 2 * intUnKnownCount + 0"和" 2 * intUnKnownCount + 1",而不是+2,+3
                                A[i * intUnknownLength + j, i * intUnknownXY + intBasicIndexL2 + 0] = Math.Cos(adblAzimuth[i, intSumCount]);
                                A[i * intUnknownLength + j, i * intUnknownXY + intBasicIndexL2 + 1] = Math.Sin(adblAzimuth[i, intSumCount]);

                                matl[i * intUnknownLength + j, 0] =adblLength0[i, intSumCount]- adblLength[i, intSumCount];   //图方便,顺便计算matl                            
                            }
                            intKnownCount2 += 1;
                        }
                        else
                        {
                            intKnownCount2 += 1;
                            j -= 1;
                        }
                    }

                    //计算系数矩阵中关于夹角值的导数部分
                    int intKnownCount3 = 0;
                    int intUnKnownCount3 = 0;
                    for (int j = 0; j < intUnknownAngle; j++)
                    {
                        //真是太幸运了,虽然求两向量逆时针夹角时需分多种情况讨论,但各情况的导数形式却是一致的,节省了不少编程精力啊,哈哈
                        int intSumCount = intKnownCount3 + intUnKnownCount3;


                        //常用数据准备
                        double[] adblA2 = new double[intInterNum];
                        double[] adblB2 = new double[intInterNum];
                        for (int i = 0; i < intInterNum; i++)
                        {
                            adblA2[i] = adblLength[i, intSumCount + 0] * adblLength[i, intSumCount + 0];
                            adblB2[i] = adblLength[i, intSumCount + 1] * adblLength[i, intSumCount + 1];
                        }

                        //开始计算系数值,由于将以下三个情况排列组合将有八种情况,因此按如下方式计算
                        if (pCorrCptsLt[intUnKnownCount3 + intKnownCount3].FrCpt.isCtrl == true && pCorrCptsLt[intUnKnownCount3 + intKnownCount3 + 1].FrCpt.isCtrl == true && pCorrCptsLt[intUnKnownCount3 + intKnownCount3 + 2].FrCpt.isCtrl == true)
                        {
                            intKnownCount3 += 1;
                            j -= 1;
                        }
                        else
                        {
                            for (int i = 0; i < intInterNum; i++)
                            {
                                int intBasicIndexFi3 = i * intXYNum + 2 * intSumCount;
                                double dblNewAngle = CGeoFunc.CalAngle_Counterclockwise(Xmix[intBasicIndexFi3 + 0, 0], Xmix[intBasicIndexFi3 + 1, 0],
                                                                               Xmix[intBasicIndexFi3 + 2, 0], Xmix[intBasicIndexFi3 + 3, 0],
                                                                               Xmix[intBasicIndexFi3 + 4, 0], Xmix[intBasicIndexFi3 + 5, 0]);

                                adblAngle[i, j] = dblNewAngle;
                                matl[intMultiUnknownLength + i * intUnknownAngle + j, 0] =adblAngle0[i, intSumCount]- dblNewAngle;      //图方便,顺便计算matl
                            }

                            int intPreTrueNum = 0;
                            int intUnKnownCount3orginal = intUnKnownCount3;
                            int intKnownCount3orginal = intKnownCount3;
                            if (pCorrCptsLt[intUnKnownCount3orginal + intKnownCount3orginal + 0].FrCpt.isCtrl == false)
                            {
                                //X1,Y1的导数值(注意:该部分是减数,因此值为导数的负数)
                                for (int i = 0; i < intInterNum; i++)
                                {
                                    A[intMultiUnknownLength + i * intUnknownAngle + j, i * intUnknownXY + 2 * intUnKnownCount3orginal + 0] = -(Xmix[i * intXYNum + 2 * intSumCount + 3, 0] - Xmix[i * intXYNum + 2 * intSumCount + 1, 0]) / adblA2[i];
                                    A[intMultiUnknownLength + i * intUnknownAngle + j, i * intUnknownXY + 2 * intUnKnownCount3orginal + 1] = (Xmix[i * intXYNum + 2 * intSumCount + 2, 0] - Xmix[i * intXYNum + 2 * intSumCount + 0, 0]) / adblA2[i];
                                }

                                intUnKnownCount3 += 1;
                            }
                            else
                            {
                                intPreTrueNum += 1;
                                intKnownCount3 += 1;
                            }

                            if (pCorrCptsLt[intUnKnownCount3orginal + intKnownCount3orginal + 1].FrCpt.isCtrl == false)
                            {
                                //X2,Y2的导数值
                                for (int i = 0; i < intInterNum; i++)
                                {
                                    A[intMultiUnknownLength + i * intUnknownAngle + j, i * intUnknownXY + 2 * (intUnKnownCount3orginal - intPreTrueNum) + 2] = (Xmix[i * intXYNum + 2 * intSumCount + 5, 0] - Xmix[i * intXYNum + 2 * intSumCount + 3, 0]) / adblB2[i]
                                                                                                                                                             + (Xmix[i * intXYNum + 2 * intSumCount + 3, 0] - Xmix[i * intXYNum + 2 * intSumCount + 1, 0]) / adblA2[i];
                                    A[intMultiUnknownLength + i * intUnknownAngle + j, i * intUnknownXY + 2 * (intUnKnownCount3orginal - intPreTrueNum) + 3] = -(Xmix[i * intXYNum + 2 * intSumCount + 4, 0] - Xmix[i * intXYNum + 2 * intSumCount + 2, 0]) / adblB2[i]
                                                                                                                                                              - (Xmix[i * intXYNum + 2 * intSumCount + 2, 0] - Xmix[i * intXYNum + 2 * intSumCount + 0, 0]) / adblA2[i];
                                }
                            }
                            else
                            {
                                intPreTrueNum += 1;
                            }
                            if (pCorrCptsLt[intUnKnownCount3orginal + intKnownCount3orginal + 2].FrCpt.isCtrl == false)
                            {
                                //X3,Y3的导数值
                                for (int i = 0; i < intInterNum; i++)
                                {
                                    A[intMultiUnknownLength + i * intUnknownAngle + j, i * intUnknownXY + 2 * (intUnKnownCount3orginal - intPreTrueNum) + 4] = -(Xmix[i * intXYNum + 2 * intSumCount + 5, 0] - Xmix[i * intXYNum + 2 * intSumCount + 3, 0]) / adblB2[i];
                                    A[intMultiUnknownLength + i * intUnknownAngle + j, i * intUnknownXY + 2 * (intUnKnownCount3orginal - intPreTrueNum) + 5] = (Xmix[i * intXYNum + 2 * intSumCount + 4, 0] - Xmix[i * intXYNum + 2 * intSumCount + 2, 0]) / adblB2[i];
                                }
                            }
                        }
                    }

                    //计算系数矩阵中关于多线段间对应顶点距离的导数部分(注意:隐含的距离计算公式为后一个点的坐标减前一个点的坐标)
                    int intKnownCount4 = 0;
                    int intUnKnownCount4 = 0;
                    for (int j = 0; j < intUnknownPt; j++)
                    {
                        int intSumCount4 = intKnownCount4 + intUnKnownCount4;
                        int intBasicIndexL4 = 2 * intUnKnownCount4;
                        if (pCorrCptsLt[intSumCount4].FrCpt.isCtrl == false)
                        {
                            int l = 0;
                            //源线段与第一生成线段间对应点距离导数
                            A[intMultiUnknownLengthAngle + l * intUnknownPt + j, (l - 0) * intUnknownXY + intBasicIndexL4 + 0] = (Xmix[l * intXYNum + 2 * intSumCount4 + 0, 0] - pCorrCptsLt[intSumCount4].FrCpt.X) / adblIntervalDis[l, intSumCount4];
                            A[intMultiUnknownLengthAngle + l * intUnknownPt + j, (l - 0) * intUnknownXY + intBasicIndexL4 + 1] = (Xmix[l * intXYNum + 2 * intSumCount4 + 1, 0] - pCorrCptsLt[intSumCount4].FrCpt.Y) / adblIntervalDis[l, intSumCount4];

                            matl[intMultiUnknownLengthAngle + l * intUnknownPt + j, 0] =adblIntervalDis0[l, intSumCount4]- adblIntervalDis[l, intSumCount4];      //图方便,顺便计算matl

                            //最后生成线段与目标线段间对应点距离导数
                            l = intInterNum;
                            A[intMultiUnknownLengthAngle + l  * intUnknownPt + j, (l  - 1) * intUnknownXY + intBasicIndexL4 + 0] = -(pCorrCptsLt[intSumCount4].ToCpt.X - Xmix[(l  - 1) * intXYNum + 2 * intSumCount4 + 0, 0]) / adblIntervalDis[l , intSumCount4];
                            A[intMultiUnknownLengthAngle + l  * intUnknownPt + j, (l  - 1) * intUnknownXY + intBasicIndexL4 + 1] = -(pCorrCptsLt[intSumCount4].ToCpt.Y - Xmix[(l  - 1) * intXYNum + 2 * intSumCount4 + 1, 0]) / adblIntervalDis[l , intSumCount4];

                            matl[intMultiUnknownLengthAngle + l  * intUnknownPt + j, 0] =adblIntervalDis0[l , intSumCount4]- adblIntervalDis[l , intSumCount4];      //图方便,顺便计算matl

                            //各生成线段间对应点距离导数
                            for (int i = 1; i < intInterNum; i++)
                            {
                                A[intMultiUnknownLengthAngle + i * intUnknownPt + j, (i - 1) * intUnknownXY + intBasicIndexL4 + 0] = -(Xmix[i * intXYNum + 2 * intSumCount4 + 0, 0] - Xmix[(i - 1) * intXYNum + 2 * intSumCount4 + 0, 0]) / adblIntervalDis[i, intSumCount4];
                                A[intMultiUnknownLengthAngle + i * intUnknownPt + j, (i - 1) * intUnknownXY + intBasicIndexL4 + 1] = -(Xmix[i * intXYNum + 2 * intSumCount4 + 1, 0] - Xmix[(i - 1) * intXYNum + 2 * intSumCount4 + 1, 0]) / adblIntervalDis[i, intSumCount4];
                                A[intMultiUnknownLengthAngle + i * intUnknownPt + j, (i - 0) * intUnknownXY + intBasicIndexL4 + 0] = -A[intMultiUnknownLengthAngle + i * intUnknownPt + j, (i - 1) * intUnknownXY + +intBasicIndexL4 + 0];
                                A[intMultiUnknownLengthAngle + i * intUnknownPt + j, (i - 0) * intUnknownXY + intBasicIndexL4 + 1] = -A[intMultiUnknownLengthAngle + i * intUnknownPt + j, (i - 1) * intUnknownXY + +intBasicIndexL4 + 1];

                                matl[intMultiUnknownLengthAngle + i * intUnknownPt + j, 0] =adblIntervalDis0[i, intSumCount4]- adblIntervalDis[i, intSumCount4];      //图方便,顺便计算matl
                                //double dblIntervalDis = adblIntervalDis[i, intSumCount4];
                                //double dblIntervalDis0 = adblIntervalDis0[i, intSumCount4];
                                //double dblmatl = dblIntervalDis - dblIntervalDis0;
                                //double ttt = 6;
                            }

                            intUnKnownCount4 += 1;
                        }
                        else
                        {
                            intKnownCount4 += 1;
                            j -= 1;
                        }
                    }



                    int tt = 5;

                    //CHelpFuncExcel.ExportDataToExcel2(A, "matA", _DataRecords.ParameterInitialize.strSavePath);
                    //CHelpFuncExcel.ExportDataToExcelP(P, "matP", _DataRecords.ParameterInitialize.strSavePath);
                    //CHelpFuncExcel.ExportDataToExcel2(matl, "matmatl", _DataRecords.ParameterInitialize.strSavePath);



                    //平差
                    VBMatrix Temp = A.Trans() * P * A;
                    VBMatrix InvTemp = Temp.Inv(Temp);
                    VBMatrix x = InvTemp * A.Trans() * P * matl;

                    XA += x;


                    //CHelpFuncExcel.ExportDataToExcel2(XA, "matXA", _DataRecords.ParameterInitialize.strSavePath);

                    //记录各平差成果
                    //坐标改正值
                    //VBMatrix Xc = XA - XA0;
                    //观测值改正值矩阵V
                    VBMatrix V = A * x - matl;
                    //VtPV值
                    double dblVtPV = (V.Trans() * P * V).MatData[0, 0];

                    _DataRecords.ParameterInitialize.txtVtPV.Text = "   VtPV = " + dblVtPV.ToString();


                    //VBMatrix L = new VBMatrix(intSumConstraints, 1);
                    //for (int i = 0; i < intInterNum; i++)
                    //{
                    //    for (int j = 0; j < intUnknownLength; j++)
                    //    {
                    //        L[i * intUnknownLength + j, 0] = adblLength[i, j];
                    //    }

                    //    for (int j = 0; j < intUnknownAngle; j++)
                    //    {
                    //        L[intInterNum * intUnknownLength + i * intUnknownAngle + j, 0] = adblAngle[i, j];
                    //    }
                    //}
                    //for (int i = 0; i <= intInterNum; i++)
                    //{
                    //    for (int j = 0; j < intUnknownPt; j++)
                    //    {
                    //        L[intInterNum * intUnknownLengthAngle + i * intUnknownPt + j, 0] = adblIntervalDis[i, j];
                    //    }
                    //}


                    //VBMatrix LPlusV = L + V;
                    //VBMatrix AX = A * XA;

                    //CHelpFuncExcel.ExportDataToExcel2(LPlusV, "matLPlusV", _DataRecords.ParameterInitialize.strSavePath);
                    //CHelpFuncExcel.ExportDataToExcel2(AX, "matAX", _DataRecords.ParameterInitialize.strSavePath);



                    //更新Xmix
                    int intSumCount5 = 0;
                    for (int j = 0; j < intUnknownPt; j++)
                    {
                        if (pCorrCptsLt[intSumCount5].FrCpt.isCtrl == false)
                        {
                            for (int i = 0; i < intInterNum; i++)
                            {
                                Xmix[i * intXYNum + intSumCount5 * 2 + 0, 0] = XA[i * intUnknownXY + j * 2 + 0, 0];
                                Xmix[i * intXYNum + intSumCount5 * 2 + 1, 0] = XA[i * intUnknownXY + j * 2 + 1, 0];
                            }
                        }
                        else
                        {
                            j -= 1;
                        }
                        intSumCount5 += 1;
                    }



                    //这里只是随便取两个中间值以观测是否收敛
                    dblJudge1 = Math.Abs(x[1 * intJudgeIndex, 0]);
                    dblJudge2 = Math.Abs(x[2 * intJudgeIndex, 0]);
                    dblJudge3 = Math.Abs(x[3 * intJudgeIndex, 0]);

                //} while ((dblJudge1 > dblTX) || (dblJudge2 > dblTX) || (dblJudge3 > dblTX));
                }while ((dblJudge1 >= 0) || (dblJudge2 >= 0) || (dblJudge3 >= 0)) ;
                break;








                for (int i = 0; i < intMultiUnknownLength; i++)  //长度权重
                {
                    P[i, i] = 1;
                }
                for (int i = 0; i < intMultiUnknownAngle; i++)   //角度权重
                {
                    P[intMultiUnknownLength + i, intMultiUnknownLength + i] = 39.48;
                }
                for (int i = 0; i < intMultiUnknownInterval; i++)   //角度权重
                {
                    P[intMultiUnknownLengthAngle + i, intMultiUnknownLengthAngle + i] = 1;
                }
            }
           

            //生成目标线段
            List<CPolyline> cpllt = new List<CPolyline>();
            for (int i = 0; i < intInterNum; i++)
            {
                List<CPoint> cptlt = new List<CPoint>();
                for (int j = 0; j < intPtNum; j++)
                {
                    CPoint cpt = new CPoint(j, Xmix[i * intXYNum + j * 2, 0], Xmix[i * intXYNum + j * 2 + 1, 0]);
                    cptlt.Add(cpt);
                }
                CPolyline cpl = new CPolyline(i, cptlt);
                cpllt.Add(cpl);
            }

            return cpllt;
        }