public void GenerateMesh(int[,] map, float squareSize)
    {
        triangleDictionary.Clear();
        outlines.Clear();
        checkedVertices.Clear();

        squareGrid = new SquareGrids(map, squareSize);

        vertices  = new List <Vector3>();
        triangles = new List <int>();
        walls     = new MeshFilter[squareGrid.squares.Length];
        for (int i = 0; i < squareGrid.squares.Length; i++)
        {
            for (int x = 0; x < squareGrid.squares[i].GetLength(0); x++)
            {
                for (int y = 0; y < squareGrid.squares[i].GetLength(1); y++)
                {
                    TriangulateSquare(squareGrid.squares[i][x, y]);
                }
            }
            Mesh mesh = new Mesh();
            GetComponent <MeshFilter>().mesh = mesh;

            mesh.vertices  = vertices.ToArray();
            mesh.triangles = triangles.ToArray();
            mesh.RecalculateNormals();
            walls[i].mesh = CreateWallMesh(i);
        }
    }
 /// <summary>正方磁磚墻建構式</summary>
 public SquareTiles(Point theGridRD, Point theGridLT, List <MCvBox2D> BaseMcvBox2DList, string fileName, RankArea rankArea)
 {
     myGrid         = new SquareGrids(theGridRD, theGridLT);
     Tiles          = TileArrayToTile2DArray(theGridRD, theGridLT, BaseMcvBox2DList);
     CurrentErrMark = new ErrMark();
     //進行評分
     Report = RankSquareTile(fileName, Tiles, myGrid, rankArea, ref CurrentErrMark);
 }
    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 評分
    }