public static TilesReport rankRectangleTiles(string fileName, MCvBox2D[,] Tiles, RectangleGrids myGrid, RankArea rankArea)
    {
        #region 評分

        TilesReport myReport = new TilesReport(fileName);
        int         rowEnd;
        int         rowStart;
        switch (rankArea)
        {
        case RankArea.Top:
            rowStart = 0;
            rowEnd   = RectangleGrids.ROW_COUNT_HALF;
            break;

        case RankArea.Down:
            rowStart = RectangleGrids.ROW_COUNT_HALF;
            rowEnd   = RectangleGrids.ROW_COUNT;
            break;

        default:
            throw SmileLib.EnumTool.OutOfEnum <RankArea>();
        }

        #region 評分_絕對位置

#if false
        myReport.newLine("絕對位置:");
        double absoluteError = 0.0;
        for (int row = 0; row < rowEnd; row++)
        {
            string rowReport = "";
            for (int column = 0; column < RectangleGrids.columnCount; column++)
            {
                if ((row + column) % 2 != 1)
                {
                    Tile   tempTile  = new Tile(Tiles[column, row]);
                    double tempError = 0.0;
                    tempError += myGrid.mmFormPixel(myMath.GetDistance(tempTile.conerLT, myGrid.TileModelLT(column, row)));
                    tempError += myGrid.mmFormPixel(myMath.GetDistance(tempTile.conerLD, myGrid.TileModelLD(column, row)));
                    tempError += myGrid.mmFormPixel(myMath.GetDistance(tempTile.conerRT, myGrid.TileModelRT(column, row)));
                    tempError += myGrid.mmFormPixel(myMath.GetDistance(tempTile.conerRD, myGrid.TileModelRD(column, row)));

                    rowReport     += "\t" + tempError;
                    absoluteError += tempError;
                }
                else
                {
                    rowReport += "\t";
                }
            }
            myReport.newLine(rowReport);
        }
        myReport.newLine("絕對位置總誤差:\t" + absoluteError);
#endif

        #endregion 評分_絕對位置

        #region 評分_溝縫

        myReport.newLine("");
        myReport.newLine("溝縫間隔:");

        List <double> gap = new List <double>();

        #region 列與列間溝縫

        myReport.newLine("列與列間溝縫:");
        List <double> allRowError   = new List <double>();
        double        helfTileWidth = myGrid.PixelFormMm(RectangleGrids.tileWidth) / 2;

        #region 考慮第0條至第6條(共7條)水平溝縫,將溝縫視為上鄰接列的附屬,所以最後一列沒有溝縫

        for (int rowNum = rowStart; rowNum < rowEnd - 1; rowNum++)
        {
            string        rowReport = "第" + rowNum.ToString("D2") + "條:";
            List <double> rowError  = new List <double>();

            #region 依序考慮每一行磁磚要計算的溝縫

            for (int columnNum = 0; columnNum < RectangleGrids.columnCount; columnNum++)
            {
                #region  照行列,只計算"存在"磁磚位置

                if ((columnNum + rowNum) % 2 == 0)
                {
                    #region 只看奇數列中有存在的磁磚

                    #region 如果相對於本磁磚的左下磁磚存在的話

                    if (columnNum - 1 >= 0)
                    {
                        #region 溝縫差加上:左下磁磚中心點與上邊交點 與 本磁磚左下點 的y方向差

                        double disA = myGrid.mmFormPixel(myMath.GetDis <double>(
                                                             Tiles[columnNum - 1, rowNum + 1].center.Y - helfTileWidth
                                                             - new Tile(Tiles[columnNum, rowNum]).conerLD.Y));
                        rowError.Add(disA);
                        allRowError.Add(disA);
                        gap.Add(disA);

                        #endregion 溝縫差加上:左下磁磚中心點與上邊交點 與 本磁磚左下點 的y方向差

                        #region 溝縫差加上:左下磁磚右上點 與 本磁磚中心點與下邊交點 的y方向差

                        double disB = myGrid.mmFormPixel(myMath.GetDis <double>(
                                                             new Tile(Tiles[columnNum - 1, rowNum + 1]).conerRT.Y - helfTileWidth
                                                             - Tiles[columnNum, rowNum].center.Y));
                        rowError.Add(disB);
                        allRowError.Add(disB);
                        gap.Add(disB);

                        #endregion 溝縫差加上:左下磁磚右上點 與 本磁磚中心點與下邊交點 的y方向差
                    }

                    #endregion 如果相對於本磁磚的左下磁磚存在的話

                    #region 如果相對於本磁磚的右下磁磚存在的話

                    if (columnNum + 1 < RectangleGrids.columnCount)
                    {
                        #region 溝縫差加上:右下磁磚左上點 與 本磁磚中心點與下邊交點 的y方向差

                        double disC = myGrid.mmFormPixel(myMath.GetDis <double>(
                                                             new Tile(Tiles[columnNum + 1, rowNum + 1]).conerLT.Y - helfTileWidth
                                                             - Tiles[columnNum, rowNum].center.Y));
                        rowError.Add(disC);
                        allRowError.Add(disC);
                        gap.Add(disC);

                        #endregion 溝縫差加上:右下磁磚左上點 與 本磁磚中心點與下邊交點 的y方向差

                        #region 溝縫差加上:右下磁磚中心點與上邊交點 與 本磁磚右下點 的y方向差

                        double disD = myGrid.mmFormPixel(myMath.GetDis <double>(
                                                             Tiles[columnNum + 1, rowNum + 1].center.Y - helfTileWidth
                                                             - new Tile(Tiles[columnNum, rowNum]).conerRD.Y));
                        rowError.Add(disD);
                        allRowError.Add(disD);
                        gap.Add(disD);

                        #endregion 溝縫差加上:右下磁磚中心點與上邊交點 與 本磁磚右下點 的y方向差
                    }

                    #endregion 如果相對於本磁磚的右下磁磚存在的話

                    #endregion 只看奇數列中有存在的磁磚
                }

                #endregion  照行列,只計算"存在"磁磚位置
            }

            #endregion 依序考慮每一行磁磚要計算的溝縫

            foreach (double err in rowError)
            {
                rowReport += "\t" + err;
            }
            rowReport += "\t平均:\t" + rowError.Average() + "\t標準差:\t" + rowError.ToArray().StandardDeviation();
            myReport.newLine(rowReport);
        }

        #endregion 考慮第0條至第6條(共7條)水平溝縫,將溝縫視為上鄰接列的附屬,所以最後一列沒有溝縫

        myReport.GapHSD = allRowError.ToArray().StandardDeviation();

        #endregion 列與列間溝縫

        #region 行與行間溝縫

        myReport.newLine("行與行間溝縫:");
        List <double> allColumnError = new List <double>();
        for (int columnNum = 0; columnNum < RectangleGrids.gapCountInColumn; columnNum++)
        {
            string        columnReport = "第" + columnNum.ToString("D2") + "條:";
            List <double> columnError  = new List <double>();

            for (int rowNum = rowStart; rowNum < rowEnd; rowNum++)
            {
                if ((columnNum + rowNum) % 2 == 0)
                {
                    Tile   tempTileLeft  = new Tile(Tiles[columnNum, rowNum]);
                    Tile   tempTileRight = new Tile(Tiles[columnNum + 2, rowNum]);
                    double disA          = myGrid.mmFormPixel(myMath.GetDis <float>(tempTileRight.conerLT.X - tempTileLeft.conerRT.X));
                    double disB          = myGrid.mmFormPixel(myMath.GetDis <float>(tempTileRight.conerLD.X - tempTileLeft.conerRD.X));
                    columnError.Add(disA);
                    columnError.Add(disB);
                    columnReport += "\t" + disA + "\t" + disB;

                    allColumnError.Add(disA);
                    allColumnError.Add(disB);
                    gap.Add(disA);
                    gap.Add(disB);
                }
            }
            columnReport += "\t平均:\t" + columnError.Average() + "\t標準差\t" + columnError.StandardDeviation();
            myReport.newLine(columnReport);
        }
        myReport.GapVSD = allColumnError.StandardDeviation();

        #endregion 行與行間溝縫

        #region  分方向評分

        double gapSD            = gap.ToArray().StandardDeviation();
        double gapAvg           = gap.Average();
        double gapMax           = gap.Max();
        double gapMin           = gap.Min();
        double gapRange         = gapMax - gapMin;
        double gapRangeAvgRatio = gapRange / gapAvg;
        myReport.newLine("勾縫標準差:/t" + gapSD);
        myReport.GapSD = gapSD;
        myReport.newLine("勾縫極差:/t" + gapRange);
        myReport.GapRange = gapRange;
        myReport.newLine("平均勾縫寬:/t" + gapAvg);
        myReport.GapAvg = gapAvg;
        myReport.newLine("極差平均比/t" + gapAvg);
        myReport.GapRangeAvgRatio = gapRangeAvgRatio;

        #endregion  分方向評分

        #endregion 評分_溝縫

        #region 評分_磁磚角趨勢線
#if false
        myReport.newLine("");
        myReport.newLine("磁磚角趨勢線");

        #region 水平趨勢線

        myReport.newLine("水平趨勢線");
        for (int rowNum = rowStart; rowNum < rowEnd; rowNum++)
        {
            double[] tempTopXs = new double[RectangleGrids.ColumnCountInRow(rowNum) * 2];
            double[] tempTopYs = new double[RectangleGrids.ColumnCountInRow(rowNum) * 2];
            string   HorizontalTrendLineTopX = "";
            string   HorizontalTrendLineTopY = "";

            double[] tempDownXs = new double[RectangleGrids.ColumnCountInRow(rowNum) * 2];
            double[] tempDownYs = new double[RectangleGrids.ColumnCountInRow(rowNum) * 2];
            string   HorizontalTrendLineDownX = "";
            string   HorizontalTrendLineDownY = "";

            for (int columnNum = 0; columnNum < RectangleGrids.ColumnCountInRow(rowNum); columnNum++)
            {
                Tile tempTile = new Tile(Tiles[columnNum * 2 + (rowNum % 2), rowNum]);

                tempTopXs[columnNum * 2]     = tempTile.conerLT.X;
                tempTopXs[columnNum * 2 + 1] = tempTile.conerRT.X;
                HorizontalTrendLineTopX     += "\t" + tempTile.conerLT.X + "\t" + tempTile.conerRT.X;
                tempTopYs[columnNum * 2]     = tempTile.conerLT.Y * -1;
                tempTopYs[columnNum * 2 + 1] = tempTile.conerRT.Y * -1;
                HorizontalTrendLineTopY     += "\t" + tempTile.conerLT.Y + "\t" + tempTile.conerRT.Y;

                tempDownXs[columnNum * 2]     = tempTile.conerLD.X;
                tempDownXs[columnNum * 2 + 1] = tempTile.conerRD.X;
                HorizontalTrendLineDownX     += "\t" + tempTile.conerLD.X + "\t" + tempTile.conerRD.X;
                tempDownYs[columnNum * 2]     = tempTile.conerLD.Y * -1;
                tempDownYs[columnNum * 2 + 1] = tempTile.conerRD.Y * -1;
                HorizontalTrendLineDownY     += "\t" + tempTile.conerLD.Y + "\t" + tempTile.conerRD.Y;
            }
            myStatistics.TrendLine TrendLineTop = new myStatistics.TrendLine(tempTopXs, tempTopYs);
            myReport.newLine("第" + rowNum.ToString("D2") + "列上:");
            myReport.newLine("角度(度數):\t" + TrendLineTop.Angle());
            myReport.newLine("Xdata:\t" + HorizontalTrendLineTopX);
            myReport.newLine("Ydata:\t" + HorizontalTrendLineTopY);

            myStatistics.TrendLine TrendLineDown = new myStatistics.TrendLine(tempDownXs, tempDownYs);
            myReport.newLine("第" + rowNum.ToString("D2") + "列下:");
            myReport.newLine("角度(度數):\t" + TrendLineDown.Angle());
            myReport.newLine("Xdata:\t" + HorizontalTrendLineDownX);
            myReport.newLine("Ydata:\t" + HorizontalTrendLineDownY);
        }

        #endregion 水平趨勢線

        #region 垂直趨勢線

        myReport.newLine("垂直趨勢線");
        for (int columnNum = 0; columnNum < RectangleGrids.columnCount; columnNum++)
        {
            double[] tempLeftXs             = new double[rowEnd];
            double[] tempLeftYs             = new double[rowEnd];
            string   VerticalTrendLineLeftX = "";
            string   VerticalTrendLineLeftY = "";

            double[] tempRightXs             = new double[rowEnd];
            double[] tempRightYs             = new double[rowEnd];
            string   VerticalTrendLineRightX = "";
            string   VerticalTrendLineRightY = "";

            for (int rowNum = rowStart; rowNum < rowEnd / 2; rowNum++)
            {
                Tile tempTile = new Tile(Tiles[columnNum, rowNum * 2 + (columnNum % 2)]);

                tempLeftXs[rowNum * 2]     = tempTile.conerLT.X;
                tempLeftXs[rowNum * 2 + 1] = tempTile.conerLD.X;
                VerticalTrendLineLeftX    += "\t" + tempTile.conerLT.X + "\t" + tempTile.conerLD.X;
                tempLeftYs[rowNum * 2]     = tempTile.conerLT.Y * -1;
                tempLeftYs[rowNum * 2 + 1] = tempTile.conerLD.Y * -1;
                VerticalTrendLineLeftY    += "\t" + tempTile.conerLT.Y + "\t" + tempTile.conerLD.Y;

                tempRightXs[rowNum * 2]     = tempTile.conerRT.X;
                tempRightXs[rowNum * 2 + 1] = tempTile.conerRD.X;
                VerticalTrendLineRightX    += "\t" + tempTile.conerRT.X + "\t" + tempTile.conerRD.X;
                tempRightYs[rowNum * 2]     = tempTile.conerRT.Y * -1;
                tempRightYs[rowNum * 2 + 1] = tempTile.conerRD.Y * -1;
                VerticalTrendLineRightY    += "\t" + tempTile.conerRT.Y + "\t" + tempTile.conerRD.Y;
            }
            myStatistics.TrendLine TrendLineTop = new myStatistics.TrendLine(tempLeftYs, tempLeftXs);
            myReport.newLine("第" + columnNum.ToString("D2") + "行左:");
            myReport.newLine("角度(度數):\t" + myTool.CorrectingAngle_YXtoXY(TrendLineTop.Angle()));
            myReport.newLine("Xdata:\t" + VerticalTrendLineLeftX);
            myReport.newLine("Ydata:\t" + VerticalTrendLineLeftY);

            myStatistics.TrendLine TrendLineRight = new myStatistics.TrendLine(tempRightYs, tempRightXs);
            myReport.newLine("第" + columnNum.ToString("D2") + "行右:");
            myReport.newLine("角度(度數):\t" + myTool.CorrectingAngle_YXtoXY(TrendLineRight.Angle()));
            myReport.newLine("Xdata:\t" + VerticalTrendLineRightX);
            myReport.newLine("Ydata:\t" + VerticalTrendLineRightY);
        }

        #endregion 垂直趨勢線
#endif
        #endregion 評分_磁磚角趨勢線

        #region 評分_磁磚中心趨勢線

        myReport.newLine("");
        myReport.newLine("磁磚中心趨勢線");

        #region 水平趨勢線

        myReport.newLine("水平趨勢線");
        List <double> HorizontalTrendLineAngle = new List <double>();
        for (int rowNum = rowStart; rowNum < rowEnd; rowNum++)
        {
            double[] Xdata = new double[RectangleGrids.ColumnCountInRow(rowNum)];
            double[] Ydata = new double[RectangleGrids.ColumnCountInRow(rowNum)];
            string   HorizontalTrendLineX = "";
            string   HorizontalTrendLineY = "";

            for (int columnNum = 0; columnNum < RectangleGrids.ColumnCountInRow(rowNum); columnNum++)
            {
                Xdata[columnNum]      = Tiles[columnNum * 2 + (rowNum % 2), rowNum].center.X;
                HorizontalTrendLineX += "\t" + Xdata[columnNum];
                Ydata[columnNum]      = Tiles[columnNum * 2 + (rowNum % 2), rowNum].center.Y * -1;
                HorizontalTrendLineY += "\t" + Ydata[columnNum];
            }
            myStatistics.TrendLine TrendLine = new myStatistics.TrendLine(Xdata, Ydata);
            double angle = TrendLine.Angle();
            myReport.newLine("第" + rowNum.ToString("D2") + "列:");
            myReport.newLine("角度(度數):\t" + TrendLine.Angle());
            HorizontalTrendLineAngle.Add(angle);

            myReport.newLine("Xdata:\t" + HorizontalTrendLineX);
            myReport.newLine("Ydata:\t" + HorizontalTrendLineY);
        }
        double rowAngleSD = HorizontalTrendLineAngle.ToArray().StandardDeviation();
        myReport.RowAngleSD = rowAngleSD;
        myReport.newLine("水平趨勢線夾角標準差" + rowAngleSD);

        #endregion 水平趨勢線

        #region 垂直趨勢線

        myReport.newLine("垂直趨勢線");
        List <double> VerticalTrendLineAngle = new List <double>();
        for (int columnNum = 0; columnNum < RectangleGrids.columnCount; columnNum++)
        {
            List <double> Xdata = new List <double>();
            List <double> Ydata = new List <double>();

            string VerticalTrendLineX = "";
            string VerticalTrendLineY = "";
            for (int rowNum = rowStart; rowNum < rowEnd; rowNum++)
            {
                if ((columnNum + rowNum) % 2 == 1)
                {
                    continue;
                }
                double x = Tiles[columnNum, rowNum].center.X;
                double y = Tiles[columnNum, rowNum].center.Y * -1;
                Xdata.Add(x);
                VerticalTrendLineX += "\t" + x;
                Ydata.Add(y);
                VerticalTrendLineY += "\t" + y;
            }
            myStatistics.TrendLine TrendLine = new myStatistics.TrendLine(Ydata.ToArray(), Xdata.ToArray());
            double angle = myTool.CorrectingAngle_YXtoXY(TrendLine.Angle());
            VerticalTrendLineAngle.Add(angle);

            myReport.newLine("第" + columnNum.ToString("D2") + "行:");
            myReport.newLine("角度(度數):\t" + angle);
            myReport.newLine("Xdata:\t" + VerticalTrendLineX);
            myReport.newLine("Ydata:\t" + VerticalTrendLineY);
        }
        double columnAngleSD = VerticalTrendLineAngle.ToArray().StandardDeviation();
        myReport.ColumnAngleSD = columnAngleSD;
        myReport.newLine("垂直趨勢線夾角標準差" + columnAngleSD);

        #endregion 垂直趨勢線

        #endregion 評分_磁磚中心趨勢線

        #region 評分_座標標準差
#if false
        myReport.newLine("");
        myReport.newLine("座標標準差");

        #region 列中磁磚的Y方向

        myReport.newLine("列中磁磚的Y方向");
        List <double> RowY       = new List <double>();
        List <double> RowSpacing = new List <double>();

        for (int rowNum = rowStart; rowNum < rowEnd; rowNum++)
        {
            double[] TileYC      = new double[RectangleGrids.ColumnCountInRow(rowNum)];
            double[] TileYE      = new double[RectangleGrids.ColumnCountInRow(rowNum)];
            string   TileYReport = "第" + rowNum.ToString("D2") + "列:";
            for (int columnNum = 0; columnNum < RectangleGrids.ColumnCountInRow(rowNum); columnNum++)
            {
                TileYC[columnNum] = myGrid.mmFormPixel(Tiles[columnNum * 2 + (rowNum % 2), rowNum].center.Y);
                TileYReport      += "\t" + TileYC[columnNum];
            }

            double TileYC_avg = TileYC.Average();
            if (rowNum % 2 == 1)
            {
                TileYReport += "\t";
            }
            TileYReport +=
                "\t平均:\t" + TileYC_avg
                + "\t標準差\t" + myStatistics.StandardDeviation(TileYC) + "\t差:";

            for (int columnNum = 0; columnNum < RectangleGrids.ColumnCountInRow(rowNum); columnNum++)
            {
                TileYE[columnNum] = TileYC[columnNum] - TileYC_avg;
                TileYReport      += "\t" + TileYE[columnNum];
            }
            myReport.newLine(TileYReport);
            RowY.Add(TileYC.Average());
        }

        myReport.newLine("列與列間隔:");
        string RowSpacingReport = "\t";
        for (int rowNum = 0; rowNum < RowY.Count - 1; rowNum++)
        {
            double spacing = RowY[rowNum + 1] - RowY[rowNum];
            RowSpacing.Add(spacing);
            RowSpacingReport += "\t" + spacing;
        }
        myReport.newLine(RowSpacingReport
                         + "\t平均\t" + RowSpacing.Average()
                         + "\t標準差\t" + RowSpacing.StandardDeviation());

        #endregion 列中磁磚的Y方向

        #region 行中磁磚的X方向

        myReport.newLine("行中磁磚的X方向");
        List <double> ColumnX       = new List <double>();
        List <double> ColumnSpacing = new List <double>();

        for (int columnNum = 0; columnNum < RectangleGrids.columnCount; columnNum++)
        {
            List <double> TileXC      = new List <double>();
            List <double> TileXE      = new List <double>();
            string        TileXReport = "第" + columnNum.ToString("D2") + "行:";
            for (int rowNum = rowStart; rowNum < rowEnd; rowNum++)
            {
                if ((columnNum + rowNum) % 2 == 1)
                {
                    continue;
                }
                double centerX = myGrid.mmFormPixel(Tiles[columnNum, rowNum].center.X);
                TileXC.Add(centerX);
                TileXReport += "\t" + centerX;
            }
            double TileXC_avg = TileXC.Average();
            if (columnNum % 2 == 1)
            {
                TileXReport += "\t";
            }
            TileXReport +=
                "\t平均:\t" + TileXC_avg
                + "\t標準差\t" + TileXC.StandardDeviation() + "\t差:";
            for (int rowNum = 0; rowNum < TileXC.Count; rowNum++)
            {
                double err = TileXC[rowNum] - TileXC_avg;
                TileXE.Add(err);
                TileXReport += "\t" + err;
            }
            myReport.newLine(TileXReport);

            ColumnX[columnNum] = TileXC.Average();
        }

        myReport.newLine("行與行間隔:");
        string ColumnSpacingReport = "\t";
        for (int columnNum = 0; columnNum < RectangleGrids.columnCount - 1; columnNum++)
        {
            ColumnSpacing[columnNum] = ColumnX[columnNum + 1] - ColumnX[columnNum];
            ColumnSpacingReport     += "\t" + ColumnSpacing[columnNum];
        }
        myReport.newLine(ColumnSpacingReport
                         + "\t平均\t" + ColumnSpacing.Average()
                         + "\t標準差\t" + myStatistics.StandardDeviation(ColumnSpacing));

        #endregion 行中磁磚的X方向
#endif
        #endregion 評分_座標標準差

        #region 評分_磁磚中心與趨勢線距離和

        myReport.newLine("筆直度:");

        #region 平均Y方向離差

        myReport.newLine("Y方向離差:");
        double sumOfTileCenterToTrendLineH = 0;
        for (int rowNum = rowStart; rowNum < rowEnd; rowNum++)
        {
            string   rowReport = "第" + rowNum + "列";
            double[] Xdata     = new double[RectangleGrids.ColumnCountInRow(rowNum)];
            double[] Ydata     = new double[RectangleGrids.ColumnCountInRow(rowNum)];
            for (int columnNum = 0; columnNum < RectangleGrids.ColumnCountInRow(rowNum); columnNum++)
            {
                Xdata[columnNum] = Tiles[columnNum * 2 + (rowNum % 2), rowNum].center.X;
                Ydata[columnNum] = Tiles[columnNum * 2 + (rowNum % 2), rowNum].center.Y * -1;
            }
            myStatistics.TrendLine theTrendLine = new myStatistics.TrendLine(Xdata, Ydata);
            for (int columnNum = 0; columnNum < RectangleGrids.ColumnCountInRow(rowNum); columnNum++)
            {
                double Residual = Math.Abs(theTrendLine.PointToLineDis(Xdata[columnNum], Ydata[columnNum]));
                Residual = myGrid.mmFormPixel(Residual);
                sumOfTileCenterToTrendLineH += Residual;
                rowReport += "\t" + Residual;
            }
            myReport.newLine(rowReport);
        }
        int    numberOfTile   = RectangleGrids.tileCount / 2;
        double rowResidualAvg = sumOfTileCenterToTrendLineH / numberOfTile;
        string TotalRowReport = "平均y方向離差:" + rowResidualAvg.ToString("0.000");
        myReport.newLine(TotalRowReport);
        myReport.RowResidualAvg = rowResidualAvg;

        #endregion 平均Y方向離差

        #region 平均X方向離差

        myReport.newLine("平均X方向離差");
        double sumOfTileCenterToTrendLineV = 0;
        for (int columnNum = 0; columnNum < RectangleGrids.columnCount; columnNum++)
        {
            string ColumnReport = "第" + columnNum + "行";

            List <double> Xdata = new List <double>();
            List <double> Ydata = new List <double>();
            for (int rowNum = rowStart; rowNum < rowEnd; rowNum++)
            {
                if ((columnNum + rowNum) % 2 == 1)
                {
                    continue;
                }
                double x = Tiles[columnNum, rowNum].center.X;
                double y = Tiles[columnNum, rowNum].center.Y * -1;
                Xdata.Add(x);
                Ydata.Add(y);
            }
            myStatistics.TrendLine theTrendLine = new myStatistics.TrendLine(Ydata.ToArray(), Xdata.ToArray());
            for (int index = 0; index < Xdata.Count; index++)
            {
                double Residual = Math.Abs(theTrendLine.PointToLineDis(Ydata[index], Xdata[index]));
                Residual = myGrid.mmFormPixel(Residual);
                sumOfTileCenterToTrendLineV += Residual;
                ColumnReport += "\t" + Residual;
            }
            myReport.newLine(ColumnReport);
        }
        double columnResidualAvg = sumOfTileCenterToTrendLineV / numberOfTile;
        string TotalColumnReport = "平均X方向離差:" + columnResidualAvg.ToString("0.000");
        myReport.newLine(TotalColumnReport);
        myReport.ColumnResidualAvg = columnResidualAvg;

        #endregion 平均X方向離差

        #endregion 評分_磁磚中心與趨勢線距離和

        #region 評分_磁磚旋轉角

        myReport.newLine("");
        myReport.newLine("磁磚旋轉角");
        string TileAngleFirstRow = "";
        for (int columnNUm = 0; columnNUm < RectangleGrids.columnCount; columnNUm++)
        {
            TileAngleFirstRow += "\t第" + columnNUm.ToString("D2") + "行";
        }
        TileAngleFirstRow += "\t平均\t標準差";
        myReport.newLine(TileAngleFirstRow);

        #region 印出每列

        for (int rowNum = rowStart; rowNum < rowEnd; rowNum++)
        {
            string angleReport = "第" + rowNum.ToString("D2") + "列";
            if (rowNum % 2 == 1)
            {
                angleReport += "\t";
            }
            double[] angleDataInRow = new double[RectangleGrids.ColumnCountInRow(rowNum)];
            for (int columnNum = 0; columnNum < RectangleGrids.ColumnCountInRow(rowNum); columnNum++)
            {
                angleDataInRow[columnNum] = Tiles[columnNum * 2 + (rowNum % 2), rowNum].angle;
                if (columnNum != 0)
                {
                    angleReport += "\t";
                }
                angleReport += "\t" + angleDataInRow[columnNum];
            }
            if (rowNum % 2 == 1)
            {
                angleReport += "\t";
            }
            myReport.newLine(angleReport
                             + "\t" + angleDataInRow.Average()
                             + "\t" + myStatistics.StandardDeviation(angleDataInRow));
        }

        #endregion 印出每列

        #region 統計每行

        string angleAvgInColumn = "平均";
        string angleSDInColumn  = "標準差";
        for (int columnNum = 0; columnNum < RectangleGrids.columnCount; columnNum++)
        {
            List <double> angleData = new List <double>();
            for (int rowNum = rowStart; rowNum < rowEnd; rowNum++)
            {
                if ((columnNum + rowNum) % 2 == 1)
                {
                    continue;
                }

                angleData.Add(Tiles[columnNum, rowNum].angle);
            }
            angleAvgInColumn += "\t" + angleData.Average();
            angleSDInColumn  += "\t" + angleData.StandardDeviation();
        }
        myReport.newLine(angleAvgInColumn);
        myReport.newLine(angleSDInColumn);

        #endregion 統計每行

        #region 統計整個

        List <double> wholeAngleData = new List <double>();
        for (int columnNum = 0; columnNum < RectangleGrids.columnCount; columnNum++)
        {
            for (int rowNum = rowStart; rowNum < rowEnd; rowNum++)
            {
                if ((rowNum + columnNum) % 2 == 0)
                {
                    wholeAngleData.Add(Tiles[columnNum, rowNum].angle);
                }
            }
        }

        #endregion 統計整個

        myReport.newLine("總平均\t" + wholeAngleData.Average());

        myReport.AngleSD = myStatistics.StandardDeviation(wholeAngleData);
        myReport.newLine("總標準差\t" + myReport.AngleSD);

        #endregion 評分_磁磚旋轉角

        #region 林國良法(磁磚角離差)

        #region 垂直離差

        List <double> residualSetY = new List <double>();
        for (int rowNum = rowStart; rowNum < rowEnd; rowNum++)
        {
            List <PointF> pointSetInLineUpper = new List <PointF>();
            List <PointF> pointSetInLineLower = new List <PointF>();
            for (int columnNum = 0; columnNum < RectangleGrids.columnCount; columnNum++)
            {
                if ((rowNum + columnNum) % 2 != 0)
                {
                    continue;
                }
                Tile currentTile = new Tile(Tiles[columnNum, rowNum]);
                pointSetInLineUpper.Add(currentTile.conerLT);
                pointSetInLineUpper.Add(currentTile.conerRT);
                pointSetInLineLower.Add(currentTile.conerLD);
                pointSetInLineLower.Add(currentTile.conerRD);
            }
            myStatistics.TrendLine currentTrendLineUpper = new myStatistics.TrendLine(pointSetInLineUpper);
            myStatistics.TrendLine currentTrendLineLower = new myStatistics.TrendLine(pointSetInLineLower);
            foreach (var point in pointSetInLineUpper)
            {
                double residual = Math.Abs(currentTrendLineUpper.PointToLineDis(point.X, point.Y));
                residualSetY.Add(residual);
            }
            foreach (var point in pointSetInLineLower)
            {
                double residual = Math.Abs(currentTrendLineLower.PointToLineDis(point.X, point.Y));
                residualSetY.Add(residual);
            }
        }
        double residualAvgY           = residualSetY.Average();
        double residualYPerImageWidth = myGrid.mmFormPixel(residualAvgY);
        myReport.newLine("平均垂直離差(mm):" + residualYPerImageWidth);
        myReport.CornerResidualY = residualYPerImageWidth;

        double imageWidthInMm     = myGrid.mmFormPixel(myGrid.WidthInPixel);
        double residualYPer3mInMm = residualYPerImageWidth / imageWidthInMm * 3000;
        myReport.newLine("3m垂直離差(mm):" + residualYPer3mInMm);
        myReport.ResidualAvgY3m = residualYPer3mInMm;

        #endregion 垂直離差

        #region 水平離差

        myReport.newLine("磁磚角離差X方向:");
        List <double> residualSetX = new List <double>();
        for (int columnNum = 0; columnNum < RectangleGrids.columnCount; columnNum++)
        {
            List <PointF> pointSetInLineLeft  = new List <PointF>();
            List <PointF> pointSetInLineRight = new List <PointF>();
            for (int rowNum = rowStart; rowNum < rowEnd; rowNum++)
            {
                if ((rowNum + columnNum) % 2 != 0)
                {
                    continue;
                }
                Tile currentTile = new Tile(Tiles[columnNum, rowNum]);
                pointSetInLineLeft.Add(currentTile.conerLT);
                pointSetInLineLeft.Add(currentTile.conerLD);
                pointSetInLineRight.Add(currentTile.conerRT);
                pointSetInLineRight.Add(currentTile.conerRD);
            }
            myStatistics.TrendLine currentTrendLineLeft  = new myStatistics.TrendLine(pointSetInLineLeft, true);
            myStatistics.TrendLine currentTrendLineRight = new myStatistics.TrendLine(pointSetInLineRight, true);
            foreach (var point in pointSetInLineLeft)
            {
                double residual = Math.Abs(currentTrendLineLeft.PointToLineDis(point.Y, point.X));
                residualSetX.Add(residual);
            }
            foreach (var point in pointSetInLineRight)
            {
                double residual = Math.Abs(currentTrendLineRight.PointToLineDis(point.Y, point.X));
                residualSetX.Add(residual);
            }
        }
        double residualAvgX            = residualSetX.Average();
        double residualXPerImageHeight = myGrid.mmFormPixel(residualAvgX);
        myReport.newLine("平均水平離差(mm):" + residualXPerImageHeight);
        myReport.CornerResidualX = residualXPerImageHeight;

        double imageHeightInMm    = myGrid.mmFormPixel(myGrid.HeightInPixel);
        double residualXPer3mInMm = residualXPerImageHeight / imageHeightInMm * 3000;
        myReport.newLine("3m水平離差(mm):" + residualXPer3mInMm);
        myReport.ResidualAvgX3m = residualXPer3mInMm;

        #endregion 水平離差

        #endregion 林國良法(磁磚角離差)

        //string output = myReport.result(TilesType.Rectangle);
        //myReport.doToReport("評分報告");
        myReport.SaveReport(rankArea);
        //return myReport.ScoringByVariance(TilesType.Rectangle);
        return(myReport);

        //return myReport.SaveReport(rankTopOnly);

        #endregion 評分
    }
Esempio n. 2
0
    public static TilesReport RankSquareTile(string fileName, MCvBox2D[,] Tiles, SquareGrids myGrid, RankArea rankArea, ref ErrMark outPutErrMark)
    {
        #region 評分

        TilesReport myReport = new TilesReport(fileName);
        int         rowStart;
        int         rowEnd;
        switch (rankArea)
        {
        case RankArea.Top:
            rowStart = 0;
            rowEnd   = SquareGrids.ROW_COUNT_HALF;
            break;

        case RankArea.Down:
            rowStart = SquareGrids.ROW_COUNT_HALF;
            rowEnd   = SquareGrids.ROW_COUNT;
            break;

        default:
            throw SmileLib.EnumTool.OutOfEnum <RankArea>();
        }


        #region 評分_絕對位置
#if false
        myReport.newLine("絕對位置:");
        double absoluteError = 0.0;
        for (int row = 0; row < rowEnd; row++)
        {
            string rowReport = "";
            for (int column = 0; column < SquareGrids.columnCount; column++)
            {
                Tile   tempTile  = new Tile(Tiles[column, row]);
                double tempError = 0.0;
                tempError += myGrid.mmFormPixel(myMath.GetDistance(tempTile.conerLT, myGrid.TileModelLT(column, row)));
                tempError += myGrid.mmFormPixel(myMath.GetDistance(tempTile.conerLD, myGrid.TileModelLD(column, row)));
                tempError += myGrid.mmFormPixel(myMath.GetDistance(tempTile.conerRT, myGrid.TileModelRT(column, row)));
                tempError += myGrid.mmFormPixel(myMath.GetDistance(tempTile.conerRD, myGrid.TileModelRD(column, row)));

                rowReport     += "\t" + tempError;
                absoluteError += tempError;
            }
            myReport.newLine(rowReport);
        }
        myReport.newLine("絕對位置總誤差:\t" + absoluteError);
#endif
        #endregion 評分_絕對位置

        #region 評分_溝縫

        myReport.newLine("");
        myReport.newLine("溝縫間隔:");

        List <double> gap = new List <double>();
        Dictionary <LineSegment2DF, double> gapAndDis = new Dictionary <LineSegment2DF, double>();
        #region 列與列間溝縫

        myReport.newLine("列與列間溝縫:");
        List <double> allRowError = new List <double>();
        for (int rowNum = rowStart; rowNum < rowEnd - 1; rowNum++)
        {
            string   rowReport = "第" + rowNum.ToString("D2") + "條:";
            double[] rowError  = new double[SquareGrids.COLUMN_COUNT * 2];
            for (int columnNum = 0; columnNum < SquareGrids.COLUMN_COUNT; columnNum++)
            {
                Tile tempTileUp   = new Tile(Tiles[columnNum, rowNum]);
                Tile tempTileDown = new Tile(Tiles[columnNum, rowNum + 1]);
                rowError[columnNum * 2] = myGrid.mmFormPixel(myMath.GetDis <float>(tempTileDown.conerLT.Y - tempTileUp.conerLD.Y));
                LineSegment2DF leftLine = new LineSegment2DF(tempTileDown.conerLT, tempTileUp.conerLD);
                rowError[columnNum * 2 + 1] = myGrid.mmFormPixel(myMath.GetDis <float>(tempTileDown.conerRT.Y - tempTileUp.conerRD.Y));
                LineSegment2DF rightLine = new LineSegment2DF(tempTileDown.conerRT, tempTileUp.conerRD);
                rowReport += "\t" + rowError[columnNum * 2] + "\t" + rowError[columnNum * 2 + 1];
                double gapA = rowError[columnNum * 2];
                double gapB = rowError[columnNum * 2 + 1];
                gapAndDis.Add(leftLine, gapA);
                gapAndDis.Add(rightLine, gapB);
                allRowError.Add(gapA);
                allRowError.Add(gapB);
                gap.Add(gapA);
                gap.Add(gapB);
            }
            rowReport += "\t平均:\t" + rowError.Average() + "\t標準差:\t" + rowError.StandardDeviation();
            myReport.newLine(rowReport);
        }
        myReport.GapHSD = allRowError.ToArray().StandardDeviation();

        #endregion 列與列間溝縫

        #region 行與行間溝縫

        myReport.newLine("行與行間溝縫:");
        List <double> allColumnError = new List <double>();
        for (int columnNum = 0; columnNum < SquareGrids.COLUMN_COUNT - 1; columnNum++)
        {
            string        columnReport = "第" + columnNum.ToString("D2") + "條:";
            List <double> columnError  = new List <double>();

            for (int rowNum = rowStart; rowNum < rowEnd; rowNum++)
            {
                Tile   tempTileLeft  = new Tile(Tiles[columnNum, rowNum]);
                Tile   tempTileRight = new Tile(Tiles[columnNum + 1, rowNum]);
                double gapC          = myGrid.mmFormPixel(myMath.GetDis <float>(tempTileRight.conerLT.X - tempTileLeft.conerRT.X));
                columnError.Add(gapC);
                LineSegment2DF topLine = new LineSegment2DF(tempTileRight.conerLT, tempTileLeft.conerRT);
                double         gapD    = myGrid.mmFormPixel(myMath.GetDis <float>(tempTileRight.conerLD.X - tempTileLeft.conerRD.X));
                columnError.Add(gapD);
                LineSegment2DF downLine = new LineSegment2DF(tempTileRight.conerLD, tempTileLeft.conerRD);
                columnReport += "\t" + gapC + "\t" + gapD;
                gapAndDis.Add(topLine, gapC);
                gapAndDis.Add(downLine, gapD);
                allColumnError.Add(gapC);
                allColumnError.Add(gapD);
                gap.Add(gapC);
                gap.Add(gapD);
            }

            columnReport += "\t平均:\t" + columnError.Average() + "\t標準差\t" + columnError.ToArray().StandardDeviation();
            myReport.newLine(columnReport);
        }
        myReport.GapVSD = allColumnError.ToArray().StandardDeviation();

        #endregion 行與行間溝縫

        #region  分方向評分

        double gapSD            = gap.ToArray().StandardDeviation();
        double gapAvg           = gap.Average();
        double gapMax           = gap.Max();
        double gapMin           = gap.Min();
        double gapRange         = gapMax - gapMin;
        double gapRangeAvgRatio = gapRange / gapAvg;
        myReport.newLine("勾縫標準差:/t" + gapSD);
        myReport.GapSD = gapSD;
        myReport.newLine("勾縫極差:/t" + gapRange);
        myReport.GapRange = gapRange;
        myReport.newLine("平均勾縫寬:/t" + gapAvg);
        myReport.GapAvg = gapAvg;
        myReport.newLine("極差平均比/t" + gapAvg);
        myReport.GapRangeAvgRatio = gapRangeAvgRatio;

        var ErrGap = from outputGap in gapAndDis
                     where !outputGap.Value.IsBetween(gapAvg - ErrMark.GapSquareTh, gapAvg + ErrMark.GapSquareTh)
                     select outputGap.Key;
        outPutErrMark.GapErr = ErrGap.ToList();

        #endregion  分方向評分

        #endregion 評分_溝縫

        #region 評分_磁磚角趨勢線
#if false
        myReport.newLine("");
        myReport.newLine("磁磚角趨勢線");

        #region 水平趨勢線

        myReport.newLine("水平趨勢線");
        for (int rowNum = rowStart; rowNum < rowEnd; rowNum++)
        {
            double[] tempTopXs            = new double[SquareGrids.columnCount * 2];
            double[] tempTopYs            = new double[SquareGrids.columnCount * 2];
            string   HorizontalTrendLineX = "";
            string   HorizontalTrendLineY = "";
            for (int columnNum = 0; columnNum < SquareGrids.columnCount; columnNum++)
            {
                Tile tempTile = new Tile(Tiles[columnNum, rowNum]);

                tempTopXs[columnNum * 2]     = tempTile.conerLT.X;
                tempTopXs[columnNum * 2 + 1] = tempTile.conerRT.X;
                HorizontalTrendLineX        += "\t" + tempTile.conerLT.X + "\t" + tempTile.conerRT.X;
                tempTopYs[columnNum * 2]     = tempTile.conerLT.Y * -1;
                tempTopYs[columnNum * 2 + 1] = tempTile.conerRT.Y * -1;
                HorizontalTrendLineY        += "\t" + tempTile.conerLT.Y + "\t" + tempTile.conerRT.Y;
            }
            myStatistics.TrendLine TrendLineTop = new myStatistics.TrendLine(tempTopXs, tempTopYs);
            myReport.newLine("第" + rowNum.ToString("D2") + "列上:");
            myReport.newLine("角度(度數):\t" + TrendLineTop.Angle());
            myReport.newLine("Xdata:\t" + HorizontalTrendLineX);
            myReport.newLine("Ydata:\t" + HorizontalTrendLineY);

            double[] tempDownXs = new double[SquareGrids.columnCount * 2];
            double[] tempDownYs = new double[SquareGrids.columnCount * 2];
            HorizontalTrendLineX = "";
            HorizontalTrendLineY = "";
            for (int columnNum = 0; columnNum < SquareGrids.columnCount; columnNum++)
            {
                Tile tempTile = new Tile(Tiles[columnNum, rowNum]);

                tempTopXs[columnNum * 2]     = tempTile.conerLD.X;
                tempTopXs[columnNum * 2 + 1] = tempTile.conerRD.X;
                HorizontalTrendLineX        += "\t" + tempTile.conerLD.X + "\t" + tempTile.conerRD.X;
                tempTopYs[columnNum * 2]     = tempTile.conerLD.Y * -1;
                tempTopYs[columnNum * 2 + 1] = tempTile.conerRD.Y * -1;
                HorizontalTrendLineY        += "\t" + tempTile.conerLD.Y + "\t" + tempTile.conerRD.Y;
            }
            myStatistics.TrendLine TrendLineDown = new myStatistics.TrendLine(tempTopXs, tempTopYs);
            myReport.newLine("第" + rowNum.ToString("D2") + "列下:");
            myReport.newLine("角度(度數):\t" + TrendLineDown.Angle());
            myReport.newLine("Xdata:\t" + HorizontalTrendLineX);
            myReport.newLine("Ydata:\t" + HorizontalTrendLineY);
        }

        #endregion 水平趨勢線

        #region 垂直趨勢線

        myReport.newLine("垂直趨勢線");
        for (int columnNum = 0; columnNum < SquareGrids.columnCount; columnNum++)
        {
            double[] tempTopXs          = new double[rowEnd * 2];
            double[] tempTopYs          = new double[rowEnd * 2];
            string   VerticalTrendLineX = "";
            string   VerticalTrendLineY = "";
            for (int rowNum = rowStart; rowNum < rowEnd; rowNum++)
            {
                Tile tempTile = new Tile(Tiles[columnNum, rowNum]);

                tempTopXs[rowNum * 2]     = tempTile.conerLT.X;
                tempTopXs[rowNum * 2 + 1] = tempTile.conerLD.X;
                VerticalTrendLineX       += "\t" + tempTile.conerLT.X + "\t" + tempTile.conerLD.X;
                tempTopYs[rowNum * 2]     = tempTile.conerLT.Y * -1;
                tempTopYs[rowNum * 2 + 1] = tempTile.conerLD.Y * -1;
                VerticalTrendLineY       += "\t" + tempTile.conerLT.Y + "\t" + tempTile.conerLD.Y;
            }
            myStatistics.TrendLine TrendLineTop = new myStatistics.TrendLine(tempTopYs, tempTopXs);
            myReport.newLine("第" + columnNum.ToString("D2") + "行左:");
            myReport.newLine("角度(度數):\t" + myTool.CorrectingAngle_YXtoXY(TrendLineTop.Angle()));
            myReport.newLine("Xdata:\t" + VerticalTrendLineX);
            myReport.newLine("Ydata:\t" + VerticalTrendLineY);

            double[] tempDownXs = new double[rowEnd * 2];
            double[] tempDownYs = new double[rowEnd * 2];
            VerticalTrendLineX = "";
            VerticalTrendLineY = "";
            for (int rowNum = rowStart; rowNum < rowEnd; rowNum++)
            {
                Tile tempTile = new Tile(Tiles[columnNum, rowNum]);

                tempTopXs[rowNum * 2]     = tempTile.conerRT.X;
                tempTopXs[rowNum * 2 + 1] = tempTile.conerRD.X;
                VerticalTrendLineX       += "\t" + tempTile.conerRT.X + "\t" + tempTile.conerRD.X;
                tempTopYs[rowNum * 2]     = tempTile.conerRT.Y * -1;
                tempTopYs[rowNum * 2 + 1] = tempTile.conerRD.Y * -1;
                VerticalTrendLineY       += "\t" + tempTile.conerRT.Y + "\t" + tempTile.conerRD.Y;
            }
            myStatistics.TrendLine TrendLineDown = new myStatistics.TrendLine(tempTopYs, tempTopXs);
            myReport.newLine("第" + columnNum.ToString("D2") + "行右:");
            myReport.newLine("角度(度數):\t" + myTool.CorrectingAngle_YXtoXY(TrendLineDown.Angle()));
            myReport.newLine("Xdata:\t" + VerticalTrendLineX);
            myReport.newLine("Ydata:\t" + VerticalTrendLineY);
        }

        #endregion 垂直趨勢線
#endif
        #endregion 評分_磁磚角趨勢線

        #region 評分_磁磚中心趨勢線

        myReport.newLine("");
        myReport.newLine("磁磚中心趨勢線夾角");

        #region 水平趨勢線

        myReport.newLine("水平趨勢線夾角");
        List <double> HorizontalTrendLineaAngle = new List <double>();
        for (int rowNum = rowStart; rowNum < rowEnd; rowNum++)
        {
            double[] Xdata = new double[SquareGrids.COLUMN_COUNT];
            double[] Ydata = new double[SquareGrids.COLUMN_COUNT];
            string   HorizontalTrendLineX = "";
            string   HorizontalTrendLineY = "";
            for (int columnNum = 0; columnNum < SquareGrids.COLUMN_COUNT; columnNum++)
            {
                Xdata[columnNum]      = Tiles[columnNum, rowNum].center.X;
                HorizontalTrendLineX += "\t" + Xdata[columnNum];
                Ydata[columnNum]      = Tiles[columnNum, rowNum].center.Y * -1;
                HorizontalTrendLineY += "\t" + Ydata[columnNum];
            }
            myStatistics.TrendLine TrendLine = new myStatistics.TrendLine(Xdata, Ydata);
            double angle = TrendLine.Angle();
            myReport.newLine("第" + rowNum.ToString("D2") + "列:");
            myReport.newLine("角度(度數):\t" + angle);
            HorizontalTrendLineaAngle.Add(angle);
            myReport.newLine("Xdata:\t" + HorizontalTrendLineX);
            myReport.newLine("Ydata:\t" + HorizontalTrendLineY);
        }
        double rowAngleSD = HorizontalTrendLineaAngle.ToArray().StandardDeviation();
        myReport.RowAngleSD = rowAngleSD;
        myReport.newLine("水平趨勢線夾角標準差" + rowAngleSD);

        #endregion 水平趨勢線

        #region 垂直趨勢線

        myReport.newLine("垂直趨勢線");
        List <double> VerticalTrendLineAngle = new List <double>();
        for (int columnNum = 0; columnNum < SquareGrids.COLUMN_COUNT; columnNum++)
        {
            List <double> Xdata = new List <double>();
            List <double> Ydata = new List <double>();
            string        VerticalTrendLineX = "";
            string        VerticalTrendLineY = "";
            for (int rowNum = rowStart; rowNum < rowEnd; rowNum++)
            {
                float x = Tiles[columnNum, rowNum].center.X;
                Xdata.Add(x);
                VerticalTrendLineX += "\t" + x;
                float y = Tiles[columnNum, rowNum].center.Y * -1;
                Ydata.Add(y);
                VerticalTrendLineY += "\t" + y;
            }
            myStatistics.TrendLine TrendLine = new myStatistics.TrendLine(Ydata.ToArray(), Xdata.ToArray());
            double angle = myTool.CorrectingAngle_YXtoXY(TrendLine.Angle());
            VerticalTrendLineAngle.Add(angle);
            myReport.newLine("第" + columnNum.ToString("D2") + "行:");
            myReport.newLine("角度(度數):\t" + angle);
            myReport.newLine("Xdata:\t" + VerticalTrendLineX);
            myReport.newLine("Ydata:\t" + VerticalTrendLineY);
        }
        double columnAngleSD = VerticalTrendLineAngle.ToArray().StandardDeviation();
        myReport.ColumnAngleSD = columnAngleSD;
        myReport.newLine("垂直趨勢線夾角標準差" + columnAngleSD);

        #endregion 垂直趨勢線

        #endregion 評分_磁磚中心趨勢線

        #region 評分_座標標準差
#if false
        myReport.newLine("");
        myReport.newLine("座標標準差");

        #region 列中磁磚的Y方向

        myReport.newLine("列中磁磚的Y方向");
        List <double> RowY       = new List <double>();
        List <double> RowSpacing = new List <double>();

        for (int rowNum = rowStart; rowNum < rowEnd; rowNum++)
        {
            double[] TileYC      = new double[SquareGrids.COLUMN_COUNT];
            double[] TileYE      = new double[SquareGrids.COLUMN_COUNT];
            string   TileYReport = "第" + rowNum.ToString("D2") + "列:";
            for (int columnNum = 0; columnNum < SquareGrids.COLUMN_COUNT; columnNum++)
            {
                TileYC[columnNum] = myGrid.mmFormPixel(Tiles[columnNum, rowNum].center.Y);
                TileYReport      += "\t" + TileYC[columnNum];
            }

            double TileYC_avg = TileYC.Average();
            TileYReport +=
                "\t平均:\t" + TileYC_avg
                + "\t標準差\t" + TileYC.StandardDeviation() + "\t差:";

            for (int columnNum = 0; columnNum < SquareGrids.COLUMN_COUNT; columnNum++)
            {
                TileYE[columnNum] = TileYC[columnNum] - TileYC_avg;
                TileYReport      += "\t" + TileYE[columnNum];
            }
            myReport.newLine(TileYReport);
            RowY.Add(TileYC.Average());
        }

        myReport.newLine("列與列間隔:");
        string RowSpacingReport = "\t";
        for (int rowNum = 0; rowNum < RowY.Count - 1; rowNum++)
        {
            double spacing = RowY[rowNum + 1] - RowY[rowNum];
            RowSpacing.Add(spacing);
            RowSpacingReport += "\t" + spacing;
        }
        myReport.newLine(RowSpacingReport
                         + "\t平均\t" + RowSpacing.Average()
                         + "\t標準差\t" + myStatistics.StandardDeviation(RowSpacing.ToArray()));

        #endregion 列中磁磚的Y方向

        #region 行中磁磚的X方向

        myReport.newLine("行中磁磚的X方向");
        double[] ColumnX       = new double[SquareGrids.COLUMN_COUNT];
        double[] ColumnSpacing = new double[SquareGrids.COLUMN_COUNT - 1];

        for (int columnNum = 0; columnNum < SquareGrids.COLUMN_COUNT; columnNum++)
        {
            List <double> TileXC      = new List <double>();
            List <double> TileXE      = new List <double>();
            string        TileXReport = "第" + columnNum.ToString("D2") + "行:";
            for (int rowNum = rowStart; rowNum < rowEnd; rowNum++)
            {
                double x = myGrid.mmFormPixel(Tiles[columnNum, rowNum].center.X);
                TileXC.Add(x);
                TileXReport += "\t" + x;
            }
            double TileXC_avg = TileXC.Average();
            TileXReport +=
                "\t平均:\t" + TileXC.Average()
                + "\t標準差\t" + TileXC.StandardDeviation() + "\t差:";
            for (int rowNum = 0; rowNum < TileXC.Count(); rowNum++)
            {
                double err = TileXC[rowNum] - TileXC_avg;
                TileXE.Add(err);
                TileXReport += "\t" + err;
            }
            myReport.newLine(TileXReport);

            ColumnX[columnNum] = TileXC.Average();
        }

        myReport.newLine("行與行間隔:");
        string ColumnSpacingReport = "\t";
        for (int columnNum = 0; columnNum < SquareGrids.COLUMN_COUNT - 1; columnNum++)
        {
            ColumnSpacing[columnNum] = ColumnX[columnNum + 1] - ColumnX[columnNum];
            ColumnSpacingReport     += "\t" + ColumnSpacing[columnNum];
        }
        myReport.newLine(ColumnSpacingReport
                         + "\t平均\t" + ColumnSpacing.Average()
                         + "\t標準差\t" + myStatistics.StandardDeviation(ColumnSpacing));

        #endregion 行中磁磚的X方向
#endif
        #endregion 評分_座標標準差

        myReport.newLine("筆直度:");

        #region 平均Y方向離差

        myReport.newLine("Y方向離差:");
        double sumOfTileCenterToTrendLineH = 0;
        for (int rowNum = rowStart; rowNum < rowEnd; rowNum++)
        {
            string   rowReport = "第" + rowNum + "列";
            double[] Xdata     = new double[SquareGrids.COLUMN_COUNT];
            double[] Ydata     = new double[SquareGrids.COLUMN_COUNT];
            for (int column = 0; column < SquareGrids.COLUMN_COUNT; column++)
            {
                Xdata[column] = Tiles[column, rowNum].center.X;
                Ydata[column] = Tiles[column, rowNum].center.Y * -1;
            }
            myStatistics.TrendLine theTrendLine = new myStatistics.TrendLine(Xdata, Ydata);
            for (int column = 0; column < SquareGrids.COLUMN_COUNT; column++)
            {
                double Residual = Math.Abs(theTrendLine.PointToLineDis(Xdata[column], Ydata[column]));
                Residual = myGrid.mmFormPixel(Residual);
                sumOfTileCenterToTrendLineH += Residual;
                rowReport += "\t" + Residual;
            }
            myReport.newLine(rowReport);
        }
        double rowResidualAvg = sumOfTileCenterToTrendLineH / (SquareGrids.ROW_COUNT_HALF * SquareGrids.COLUMN_COUNT);
        string TotalRowReport = "平均Y方向離差:" + rowResidualAvg.ToString("0.000");

        myReport.newLine(TotalRowReport);
        myReport.RowResidualAvg = rowResidualAvg;

        #endregion 平均Y方向離差

        #region 平均X方向離差

        myReport.newLine("X方向離差:");
        double sumOfTileCenterToTrendLineV = 0;
        for (int column = 0; column < SquareGrids.COLUMN_COUNT; column++)
        {
            string        ColumnReport = "第" + column + "行";
            List <double> Xdata        = new List <double>();
            List <double> Ydata        = new List <double>();

            for (int row = rowStart; row < rowEnd; row++)
            {
                Xdata.Add(Tiles[column, row].center.X);
                Ydata.Add(Tiles[column, row].center.Y * -1);
            }
            myStatistics.TrendLine theTrendLine = new myStatistics.TrendLine(Ydata.ToArray(), Xdata.ToArray());
            for (int row = 0; row < Xdata.Count; row++)
            {
                double Residual = Math.Abs(theTrendLine.PointToLineDis(Ydata[row], Xdata[row]));
                Residual = myGrid.mmFormPixel(Residual);
                sumOfTileCenterToTrendLineV += Residual;
                ColumnReport += "\t" + Residual;
            }
            myReport.newLine(ColumnReport);
        }
        double columnResidualAvg = sumOfTileCenterToTrendLineV / (SquareGrids.ROW_COUNT_HALF * SquareGrids.COLUMN_COUNT);
        string TotalColumnReport = "平均X方向離差:" + columnResidualAvg.ToString("0.000");

        myReport.newLine(TotalColumnReport);
        myReport.ColumnResidualAvg = columnResidualAvg;

        #endregion 平均X方向離差

        #region 評分_磁磚旋轉角

        myReport.newLine("");
        myReport.newLine("磁磚旋轉角");

        #region 印出每列

        for (int rowNum = rowStart; rowNum < rowEnd; rowNum++)
        {
            string   angleReport    = "第" + rowNum.ToString("D2") + "列";
            double[] angleDataInRow = new double[SquareGrids.COLUMN_COUNT];
            for (int columnNum = 0; columnNum < SquareGrids.COLUMN_COUNT; columnNum++)
            {
                angleDataInRow[columnNum] = Tiles[columnNum, rowNum].angle;
                angleReport += "\t" + angleDataInRow[columnNum];
            }
            myReport.newLine(angleReport
                             + "\t平均:\t" + angleDataInRow.Average()
                             + "\t標準差:\t" + angleDataInRow.StandardDeviation());
        }

        #endregion 印出每列

        #region 統計每行

        string angleAvgInColumn = "平均:";
        string angleSDInColumn  = "標準差:";
        for (int columnNum = 0; columnNum < SquareGrids.COLUMN_COUNT; columnNum++)
        {
            List <double> angleData = new List <double>();
            for (int rowNum = rowStart; rowNum < rowEnd; rowNum++)
            {
                angleData.Add(Tiles[columnNum, rowNum].angle);
            }
            angleAvgInColumn += "\t" + angleData.Average();
            angleSDInColumn  += "\t" + angleData.StandardDeviation();
        }
        myReport.newLine(angleAvgInColumn);
        myReport.newLine(angleSDInColumn);

        #endregion 統計每行

        #region 統計整個

        List <double> wholeAngleData = new List <double>();
        for (int columnNum = 0; columnNum < SquareGrids.COLUMN_COUNT; columnNum++)
        {
            for (int row = rowStart; row < rowEnd; row++)
            {
                wholeAngleData.Add(Tiles[columnNum, row].angle);
            }
        }

        #endregion 統計整個

        myReport.newLine("總平均:\t" + wholeAngleData.Average());
        double AngleSD = wholeAngleData.StandardDeviation();
        myReport.newLine("總標準差:\t" + AngleSD);
        myReport.AngleSD = AngleSD;

        #endregion 評分_磁磚旋轉角

        #region 林國良法(磁磚角離差)

        #region 垂直離差
        myReport.newLine("磁磚角離差Y方向:");
        List <double> residualSetY = new List <double>();
        for (int rowNum = rowStart; rowNum < rowEnd; rowNum++)
        {
            List <PointF> pointSetInLineUpper = new List <PointF>();
            List <PointF> pointSetInLineLower = new List <PointF>();
            for (int column = 0; column < SquareGrids.COLUMN_COUNT; column++)
            {
                Tile currentTile = new Tile(Tiles[column, rowNum]);
                pointSetInLineUpper.Add(currentTile.conerLT);
                pointSetInLineUpper.Add(currentTile.conerRT);
                pointSetInLineLower.Add(currentTile.conerLD);
                pointSetInLineLower.Add(currentTile.conerRD);
            }
            myStatistics.TrendLine currentTrendLineUpper = new myStatistics.TrendLine(pointSetInLineUpper);
            myStatistics.TrendLine currentTrendLineLower = new myStatistics.TrendLine(pointSetInLineLower);
            foreach (var point in pointSetInLineUpper)
            {
                double residual = Math.Abs(currentTrendLineUpper.PointToLineDis(point.X, point.Y));
                residualSetY.Add(residual);
            }
            foreach (var point in pointSetInLineLower)
            {
                double residual = Math.Abs(currentTrendLineLower.PointToLineDis(point.X, point.Y));
                residualSetY.Add(residual);
            }
        }
        double residualAvgY           = residualSetY.Average();
        double residualYPerImageWidth = myGrid.mmFormPixel(residualAvgY);
        myReport.newLine("平均垂直離差(mm):" + residualYPerImageWidth);
        myReport.CornerResidualY = residualYPerImageWidth;

        double imageWidthInMm     = myGrid.mmFormPixel(myGrid.WidthInPixel);
        double residualYPer3mInMm = residualYPerImageWidth / imageWidthInMm * 3000;
        myReport.newLine("3m垂直離差(mm):" + residualYPer3mInMm);
        myReport.ResidualAvgY3m = residualYPer3mInMm;
        #endregion

        #region 水平離差
        myReport.newLine("磁磚角離差X方向:");
        List <double> residualSetX = new List <double>();
        for (int column = 0; column < SquareGrids.COLUMN_COUNT; column++)
        {
            List <PointF> pointSetInLineLeft  = new List <PointF>();
            List <PointF> pointSetInLineRight = new List <PointF>();
            for (int rowNum = rowStart; rowNum < rowEnd; rowNum++)
            {
                Tile currentTile = new Tile(Tiles[column, rowNum]);
                pointSetInLineLeft.Add(currentTile.conerLT);
                pointSetInLineLeft.Add(currentTile.conerLD);
                pointSetInLineRight.Add(currentTile.conerRT);
                pointSetInLineRight.Add(currentTile.conerRD);
            }
            myStatistics.TrendLine currentTrendLineLeft  = new myStatistics.TrendLine(pointSetInLineLeft, true);
            myStatistics.TrendLine currentTrendLineRight = new myStatistics.TrendLine(pointSetInLineRight, true);
            foreach (var point in pointSetInLineLeft)
            {
                double residual = Math.Abs(currentTrendLineLeft.PointToLineDis(point.Y, point.X));
                residualSetX.Add(residual);
            }
            foreach (var point in pointSetInLineRight)
            {
                double residual = Math.Abs(currentTrendLineRight.PointToLineDis(point.Y, point.X));
                residualSetX.Add(residual);
            }
        }
        double residualAvgX            = residualSetX.Average();
        double residualXPerImageHeight = myGrid.mmFormPixel(residualAvgX);
        myReport.newLine("平均水平離差(mm):" + residualXPerImageHeight);
        myReport.CornerResidualX = residualXPerImageHeight;
        double imageHeightInMm    = myGrid.mmFormPixel(myGrid.HeightInPixel);
        double residualXPer3mInMm = residualXPerImageHeight / imageHeightInMm * 3000;
        myReport.newLine("3m水平離差(mm):" + residualXPer3mInMm);
        myReport.ResidualAvgX3m = residualXPer3mInMm;
        #endregion

        #endregion

        myReport.SaveReport(rankArea);
        //return myReport.ScoringByVariance(TilesType.Square);
        return(myReport);

        //myReport.doToReport("評分報告");

        //return myReport.SaveReport(rankTopOnly);

        #endregion 評分
    }