/// <summary>
 /// 更新量測結果.
 /// 量測演算法放這裡
 /// </summary>
 public override void UpdateResults()
 {
     try
     {
         _Result = DistanceHelper.DistanceY(_geoModelOne, _geoModelTwo);
         if (_Result != null)
         {
             if (mMeasAssist.mIsCalibValid && mMeasAssist.mTransWorldCoord)
             {
                 Rectify(_Result.Row1, _Result.Col1, out _ResultWorld.Row1, out _ResultWorld.Col1);
             }
             else
             {
                 _ResultWorld = new LineResult(_Result);
             }
         }
     }
     catch (HOperatorException ex)
     {
         mMeasAssist.exceptionText = ex.Message;
         _ResultWorld = new LineResult();
         _Result      = new LineResult();
     }
     UpdateXLD();
 }
 /// <summary>
 /// 更新量測結果.
 /// 量測演算法放這裡
 /// </summary>
 public override void UpdateResults()
 {
     try
     {
         _Result = DistanceHelper.CalculateSymmetryLine(_geoModelOne, _geoModelTwo);
         if (_Result != null)
         {
             if (mMeasAssist.mIsCalibValid && mMeasAssist.mTransWorldCoord)
             {
                 //Rectify(_Result.Row, _Result.Col, out _ResultWorld.Row, out _ResultWorld.Col);
             }
             else
             {
                 _ResultWorld = new LineResult(_Result);
             }
         }
     }
     catch (HOperatorException ex)
     {
         mMeasAssist.exceptionText = ex.Message;
         _ResultWorld = new LineResult();
         _Result = new LineResult();
     }
     UpdateXLD();
 }
 private void initialize(IMeasureGeoModel geoModelOne, IMeasureGeoModel geoModelTwo, MeasureAssistant mAssist)
 {
     _geoModelOne   = geoModelOne;
     _geoModelTwo   = geoModelTwo;
     ROIMeasureType = MeasureType.DistanceY;
     _ResultWorld   = new LineResult();
     UpdateResults();
 }
Exemple #4
0
        /// <summary>
        /// 計算兩點 Y 方向距離
        /// </summary>
        /// <param name="pointOne">點 1</param>
        /// <param name="pointTwo">點 2</param>
        /// <returns></returns>
        public static LineResult DistanceY(IMeasureGeoModel pointOne, IMeasureGeoModel pointTwo)
        {
            LineResult result     = null;
            var        modelValid = isMeasureModelValid(pointOne) && isMeasureModelValid(pointTwo);

            if (modelValid)
            {
                var distanceY = Math.Abs(pointOne.Row1.D - pointTwo.Row1.D);
                result = new LineResult()
                {
                    Col1     = pointOne.Col1,
                    Col2     = pointOne.Col1,
                    Row1     = pointOne.Row1,
                    Row2     = pointTwo.Row1,
                    Distance = distanceY,
                };
            }
            return(result);
        }
Exemple #5
0
        /// <summary>
        /// 計算兩線段的對稱線
        /// </summary>
        /// <param name="modelOne"></param>
        /// <param name="modelTwo"></param>
        /// <returns></returns>
        public static LineResult CalculateSymmetryLine(IMeasureGeoModel modelOne, IMeasureGeoModel modelTwo)
        {
            LineResult result     = null;
            var        modelValid = isMeasureModelValid(modelOne) && isMeasureModelValid(modelTwo);

            if (modelValid)
            {
                //取得第一條線段的中點
                var pointModel = getMidPoint(modelOne);

                var lineModel = modelTwo;

                //計算第一線段中點到第二線段上的投影點(垂直距離)
                HTuple rowProj, colProj;
                HOperatorSet.ProjectionPl(pointModel.Row1, pointModel.Col1, lineModel.Row1, lineModel.Col1, lineModel.Row2, lineModel.Col2, out rowProj, out colProj);

                //計算第一線段中點與第二線段上的投影點距離 (point to point)
                HTuple distance;
                HOperatorSet.DistancePp(rowProj, colProj, pointModel.Row1, pointModel.Col1, out distance);

                //取兩線中點
                var cRow = (pointModel.Row1 + rowProj) / 2.0;
                var cCol = (pointModel.Col1 + colProj) / 2.0;

                //取角度
                HTuple angle;
                HOperatorSet.AngleLx(lineModel.Row1, lineModel.Col1, lineModel.Row2, lineModel.Col2, out angle);

                //線段
                double[] rows, cols;
                DetermineLine(cRow, cCol, angle, distance, out rows, out cols);
                result = new LineResult()
                {
                    Row1     = rows[0],
                    Row2     = rows[1],
                    Col1     = cols[0],
                    Col2     = cols[1],
                    Distance = distance,
                };
            }
            return(result);
        }
 public override void ClearResultData()
 {
     _ResultWorld = new LineResult();
 }
 public override void ClearResultData()
 {
     _ResultWorld = new LineResult();
 }
 private void initialize(IMeasureGeoModel geoModelOne, IMeasureGeoModel geoModelTwo, MeasureAssistant mAssist)
 {
     _geoModelOne = geoModelOne;
     _geoModelTwo = geoModelTwo;
     ROIMeasureType = MeasureType.SymmetryLine;
     _ResultWorld = new LineResult();
     UpdateResults();
 }
Exemple #9
0
 public LineResult(LineResult result)
     : this(result.Row1, result.Col1, result.Row2, result.Col2, result.Distance)
 {
 }
        public MeasureResult Action()
        {
            #region 輸出結果
            LineResult mResult = null;
            #endregion
            // Local iconic variables

            HObject ho_A1Rectangle = null;
            HObject ho_A1_ROI = null, ho_A1Edges = null, ho_A1ContoursSplit = null;
            HObject ho_SelectedA1Contours = null, ho_TopLineContour = null;
            HObject ho_B_Rectangle = null, ho_B__ROI = null, ho_B_Edges = null;
            HObject ho_B_ContoursSplit = null, ho_SelectedB_ContoursSplit = null;
            HObject ho_B_LeftLine_Contour = null, ho_Cross, ho_A1_RRectangle = null;
            HObject ho_A1_R_ROI = null, ho_A1_REdges = null, ho_A1_RContoursSplit = null;
            HObject ho_SelectedA1_RContoursSplit = null, ho_B_RightLine_Contour = null;
            HObject ho_CrossQ;

            // Local control variables

            HTuple hv_msgOffsetY, hv_msgOffsetX;
            //HTuple hv_AllModelId, hv_AllModelRow, hv_AllModelColumn;
            HTuple hv_STD_Row;
            HTuple hv_STD_Col, hv_Img_Row, hv_Img_Col, hv_Img_Rotate_Angle;
            HTuple hv_OffsetRow, hv_OffsetCol, hv_STD_A1_1_1_Row, hv_STD_A1_1_1_Col;
            HTuple hv_STD_A1_1_1_V_Row, hv_STD_A1_1_1_V_Col, hv_A1_1_1_X;
            HTuple hv_A1_1_1_Y, hv_A1_1_1_Pos_Row, hv_A1_1_1_Pos_Col;
            HTuple hv_ROI_W = new HTuple(), hv_ROI_H = new HTuple();
            HTuple hv_low = new HTuple(), hv_high = new HTuple(), hv_Attrib = new HTuple();
            HTuple hv_A1RowBegin = new HTuple(), hv_A1ColBegin = new HTuple();
            HTuple hv_A1RowEnd = new HTuple(), hv_A1ColEnd = new HTuple();
            HTuple hv_A1Nr = new HTuple(), hv_A1Nc = new HTuple(), hv_A1Dist = new HTuple();
            HTuple hv_STD_B1_1_1_Row, hv_STD_B1_1_1_Col, hv_STD_B1_1_1_V_Row;
            HTuple hv_STD_B1_1_1_V_Col, hv_B1_1_1_X, hv_B1_1_1_Y, hv_B1_1_1_Pos_Row;
            HTuple hv_B1_1_1_Pos_Col, hv_B_ROI_W = new HTuple(), hv_B_ROI_H = new HTuple();
            HTuple hv_B_EdgesNumber = new HTuple(), hv_inc = new HTuple();
            HTuple hv_B_RowBegin = new HTuple(), hv_B_ColBegin = new HTuple();
            HTuple hv_B_RowEnd = new HTuple(), hv_B_ColEnd = new HTuple();
            HTuple hv_B_Nr = new HTuple(), hv_B_Nc = new HTuple(), hv_B_Dist = new HTuple();
            HTuple hv_B1_InterY, hv_B1_InterX, hv_B1_IsParallel1, hv_STD_B_1_1_Row;
            HTuple hv_STD_B_1_1_Col, hv_STD_B_1_1_V_Row, hv_STD_B_1_1_V_Col;
            HTuple hv_B_1_1_X, hv_B_1_1_Y, hv_B_1_1_Pos_Row, hv_B_1_1_Pos_Col;
            HTuple hv_A1_RNumber = new HTuple(), hv_A1_RRowBegin = new HTuple();
            HTuple hv_A1_RColBegin = new HTuple(), hv_A1_RRowEnd = new HTuple();
            HTuple hv_A1_RColEnd = new HTuple(), hv_A1_RNr = new HTuple();
            HTuple hv_A1_RNc = new HTuple(), hv_A1_RDist = new HTuple();
            HTuple hv_Q_InterY, hv_Q_InterX, hv_Q_IsParallel1, hv_DistanceMin;
            HTuple hv_DistanceMax, hv_DistanceMinP, hv_DistanceMaxP;
            HTuple hv_DistanceMin1, hv_DistanceMin1P, hv_DistanceMin2;
            HTuple hv_X1 = new HTuple(), hv_X2 = new HTuple(), hv_Y1 = new HTuple();
            HTuple hv_Y2 = new HTuple(), hv_STD_Mark_A1_C_Row = new HTuple();
            HTuple hv_STD_Mark_A1_C_Col = new HTuple(), hv_STD_Mark_A1_Start_Row = new HTuple();
            HTuple hv_STD_Mark_A1_Start_Col = new HTuple(), hv_STD_Mark_A1_End_Row = new HTuple();
            HTuple hv_STD_Mark_A1_End_Col = new HTuple(), hv_STD_Mark_A1_C_V_Row = new HTuple();
            HTuple hv_STD_Mark_A1_C_V_Col = new HTuple(), hv_Mark_A1_C_X = new HTuple();
            HTuple hv_Mark_A1_C_Y = new HTuple(), hv_Mark_A1_C_Pos_Row = new HTuple();
            HTuple hv_Mark_A1_C_Pos_Col = new HTuple(), hv_STD_Mark_A1_Start_V_Row = new HTuple();
            HTuple hv_STD_Mark_A1_Start_V_Col = new HTuple(), hv_Mark_A1_Start_X = new HTuple();
            HTuple hv_Mark_A1_Start_Y = new HTuple(), hv_Mark_A1_Start_Pos_Row = new HTuple();
            HTuple hv_Mark_A1_Start_Pos_Col = new HTuple(), hv_STD_Mark_A1_End_V_Row = new HTuple();
            HTuple hv_STD_Mark_A1_End_V_Col = new HTuple(), hv_Mark_A1_End_X = new HTuple();
            HTuple hv_Mark_A1_End_Y = new HTuple(), hv_Mark_A1_End_Pos_Row = new HTuple();
            HTuple hv_Mark_A1_End_Pos_Col = new HTuple();

            // Initialize local and output iconic variables
            //HOperatorSet.GenEmptyObj(out ho_Image);
            //HOperatorSet.GenEmptyObj(out ho_AllModelContours);
            HOperatorSet.GenEmptyObj(out ho_A1Rectangle);
            HOperatorSet.GenEmptyObj(out ho_A1_ROI);
            HOperatorSet.GenEmptyObj(out ho_A1Edges);
            HOperatorSet.GenEmptyObj(out ho_A1ContoursSplit);
            HOperatorSet.GenEmptyObj(out ho_SelectedA1Contours);
            HOperatorSet.GenEmptyObj(out ho_TopLineContour);
            HOperatorSet.GenEmptyObj(out ho_B_Rectangle);
            HOperatorSet.GenEmptyObj(out ho_B__ROI);
            HOperatorSet.GenEmptyObj(out ho_B_Edges);
            HOperatorSet.GenEmptyObj(out ho_B_ContoursSplit);
            HOperatorSet.GenEmptyObj(out ho_SelectedB_ContoursSplit);
            HOperatorSet.GenEmptyObj(out ho_B_LeftLine_Contour);
            HOperatorSet.GenEmptyObj(out ho_Cross);
            HOperatorSet.GenEmptyObj(out ho_A1_RRectangle);
            HOperatorSet.GenEmptyObj(out ho_A1_R_ROI);
            HOperatorSet.GenEmptyObj(out ho_A1_REdges);
            HOperatorSet.GenEmptyObj(out ho_A1_RContoursSplit);
            HOperatorSet.GenEmptyObj(out ho_SelectedA1_RContoursSplit);
            HOperatorSet.GenEmptyObj(out ho_B_RightLine_Contour);
            HOperatorSet.GenEmptyObj(out ho_CrossQ);

            //Measure: SDMS_A1
            //Author: John Hsieh
            //Date: 2012
            //ho_Image.Dispose();
            //HOperatorSet.ReadImage(out ho_Image, "Images/STD.bmp");
            //dev_open_window_fit_image(ho_Image, 0, 0, -1, -1, out hv_WindowHandle);
            // dev_update_off(...); only in hdevelop
            HOperatorSet.SetSystem("border_shape_models", "false");

            //****Message Args
            hv_msgOffsetY = 100;
            hv_msgOffsetX = 100;

            //****Model All
            //HOperatorSet.ReadShapeModel("D:/Projects/Halcon/SDMS/SDMS_Measure/Model/MatchingAll.shm",
            //	out hv_AllModelId);
            //ho_AllModelContours.Dispose();
            //HOperatorSet.GetShapeModelContours(out ho_AllModelContours, hv_AllModelId, 1);
            //HOperatorSet.FindShapeModel(ho_Image, hv_AllModelId, (new HTuple(0)).TupleRad()
            //	, (new HTuple(360)).TupleRad(), 0.5, 1, 0.5, "least_squares", 6, 0.75, out hv_AllModelRow,
            //	out hv_AllModelColumn, out hv_AllModelAngle, out hv_AllModelScore);

            //****Model Args

            //STD 中心點
            hv_STD_Row = 772;
            hv_STD_Col = 1003;

            //目前圖形 中心點
            hv_Img_Row = hv_AllModelRow.Clone();
            hv_Img_Col = hv_AllModelColumn.Clone();

            //目前圖形 Rotate Angle
            hv_Img_Rotate_Angle = hv_AllModelAngle.Clone();

            //目前圖形偏移量
            hv_OffsetRow = hv_Img_Row - hv_STD_Row;
            hv_OffsetCol = hv_Img_Col - hv_STD_Col;

            ////****Display
            //if (HDevWindowStack.IsOpen())
            //{
            //	HOperatorSet.ClearWindow(HDevWindowStack.GetActive());
            //}
            //if (HDevWindowStack.IsOpen())
            //{
            //	HOperatorSet.DispObj(ho_Image, HDevWindowStack.GetActive());
            //}
            //*****A1
            //(1)A1 線段 與 B1線段的交點,取得 點 P
            //****A1_1_1
            //STD A1_1_1_ 位置
            hv_STD_A1_1_1_Row = 240;
            hv_STD_A1_1_1_Col = 1080;

            //STD 向量 STD_A1_1_1_
            hv_STD_A1_1_1_V_Row = hv_STD_A1_1_1_Row - hv_STD_Row;
            hv_STD_A1_1_1_V_Col = hv_STD_A1_1_1_Col - hv_STD_Col;

            //A1_1_1_X, A1_1_1_Y 分量
            hv_A1_1_1_X = (hv_STD_A1_1_1_V_Col * (hv_Img_Rotate_Angle.TupleCos())) + (hv_STD_A1_1_1_V_Row * (hv_Img_Rotate_Angle.TupleSin()
                ));
            hv_A1_1_1_Y = (hv_STD_A1_1_1_V_Row * (hv_Img_Rotate_Angle.TupleCos())) - (hv_STD_A1_1_1_V_Col * (hv_Img_Rotate_Angle.TupleSin()
                ));

            //目前圖形 A1_1_1_ 位置
            hv_A1_1_1_Pos_Row = (hv_STD_Row + hv_A1_1_1_Y) + hv_OffsetRow;
            hv_A1_1_1_Pos_Col = (hv_STD_Col + hv_A1_1_1_X) + hv_OffsetCol;

            //for (hv_MatchingObjIdx = 0; (int)hv_MatchingObjIdx <= (int)((new HTuple(hv_AllModelScore.TupleLength()
            //	)) - 1); hv_MatchingObjIdx = (int)hv_MatchingObjIdx + 1)
            //{
            //step 1 由 matchingObj 得知目標區域中心座標 (A1ModelRow, A1ModelColumn... 等資訊) 建立 ROI
            hv_ROI_W = 200;
            hv_ROI_H = 20;
            ho_A1Rectangle.Dispose();
            HOperatorSet.GenRectangle2(out ho_A1Rectangle, hv_A1_1_1_Pos_Row, hv_A1_1_1_Pos_Col,
                hv_Img_Rotate_Angle, hv_ROI_W, hv_ROI_H);
            ho_A1_ROI.Dispose();
            HOperatorSet.ReduceDomain(ho_Image, ho_A1Rectangle, out ho_A1_ROI);
            //step 2 Extract contours and segment it
            hv_low = 70;
            hv_high = 135;
            ho_A1Edges.Dispose();
            HOperatorSet.EdgesSubPix(ho_A1_ROI, out ho_A1Edges, "lanser2", 1.5, hv_low,
                hv_high);
            ho_A1ContoursSplit.Dispose();
            HOperatorSet.SegmentContoursXld(ho_A1Edges, out ho_A1ContoursSplit, "lines_circles",
                9, 4, 2);
            ho_SelectedA1Contours.Dispose();
            HOperatorSet.SelectShapeXld(ho_A1ContoursSplit, out ho_SelectedA1Contours,
                "contlength", "and", 150, 99999);

            //step 3 取得目標線段
            ho_TopLineContour.Dispose();
            HOperatorSet.SelectObj(ho_SelectedA1Contours, out ho_TopLineContour, 1);
            HOperatorSet.GetContourGlobalAttribXld(ho_TopLineContour, "cont_approx", out hv_Attrib);
            //線段 A1 的資訊
            HOperatorSet.FitLineContourXld(ho_TopLineContour, "tukey", -1, 0, 5, 2, out hv_A1RowBegin,
                out hv_A1ColBegin, out hv_A1RowEnd, out hv_A1ColEnd, out hv_A1Nr, out hv_A1Nc,
                out hv_A1Dist);
            //	if (HDevWindowStack.IsOpen())
            //	{
            //		HOperatorSet.DispObj(ho_TopLineContour, HDevWindowStack.GetActive());
            //	}
            //	//stop ()
            //}

            //*找線段 B1
            //****B1_1_1
            //STD B1_1_1_ 位置
            hv_STD_B1_1_1_Row = 400;
            hv_STD_B1_1_1_Col = 700;

            //STD 向量 STD_B1_1_1_
            hv_STD_B1_1_1_V_Row = hv_STD_B1_1_1_Row - hv_STD_Row;
            hv_STD_B1_1_1_V_Col = hv_STD_B1_1_1_Col - hv_STD_Col;

            //B1_1_1_X, B1_1_1_Y 分量
            hv_B1_1_1_X = (hv_STD_B1_1_1_V_Col * (hv_Img_Rotate_Angle.TupleCos())) + (hv_STD_B1_1_1_V_Row * (hv_Img_Rotate_Angle.TupleSin()
                ));
            hv_B1_1_1_Y = (hv_STD_B1_1_1_V_Row * (hv_Img_Rotate_Angle.TupleCos())) - (hv_STD_B1_1_1_V_Col * (hv_Img_Rotate_Angle.TupleSin()
                ));

            //目前圖形 B1_1_1_ 位置
            hv_B1_1_1_Pos_Row = (hv_STD_Row + hv_B1_1_1_Y) + hv_OffsetRow;
            hv_B1_1_1_Pos_Col = (hv_STD_Col + hv_B1_1_1_X) + hv_OffsetCol;
            //for (hv_MatchingObjIdx = 0; (int)hv_MatchingObjIdx <= (int)((new HTuple(hv_AllModelScore.TupleLength()
            //	)) - 1); hv_MatchingObjIdx = (int)hv_MatchingObjIdx + 1)
            //{
            //step 1 由 matchingObj 得知目標區域中心座標 (B_ModelRow, B_ModelColumn... 等資訊) 建立 ROI
            hv_B_ROI_W = 40;
            hv_B_ROI_H = 90;
            ho_B_Rectangle.Dispose();
            HOperatorSet.GenRectangle2(out ho_B_Rectangle, hv_B1_1_1_Pos_Row, hv_B1_1_1_Pos_Col,
                hv_Img_Rotate_Angle, hv_B_ROI_W, hv_B_ROI_H);
            //stop ()
            ho_B__ROI.Dispose();
            HOperatorSet.ReduceDomain(ho_Image, ho_B_Rectangle, out ho_B__ROI);
            //step 2 Extract contours and segment it
            hv_low = 60;
            hv_high = 140;
            ho_B_Edges.Dispose();
            HOperatorSet.EdgesSubPix(ho_B__ROI, out ho_B_Edges, "lanser2", 0.3, hv_low,
                hv_high);
            HOperatorSet.CountObj(ho_B_Edges, out hv_B_EdgesNumber);

            //stop ()
            //修正上限
            hv_inc = -3;
            while ((int)(new HTuple(hv_B_EdgesNumber.TupleLess(1))) != 0)
            {
                hv_high = hv_high + hv_inc;
                ho_B_Edges.Dispose();
                HOperatorSet.EdgesSubPix(ho_B__ROI, out ho_B_Edges, "lanser2", 0.3, hv_low,
                    hv_high);
                HOperatorSet.CountObj(ho_B_Edges, out hv_B_EdgesNumber);
            }
            //stop ()
            ho_B_ContoursSplit.Dispose();
            HOperatorSet.SegmentContoursXld(ho_B_Edges, out ho_B_ContoursSplit, "lines",
                9, 4, 2);
            ho_SelectedB_ContoursSplit.Dispose();
            HOperatorSet.SelectShapeXld(ho_B_ContoursSplit, out ho_SelectedB_ContoursSplit,
                "contlength", "and", 20, 99999);
            //step 3 取得目標線段
            ho_B_LeftLine_Contour.Dispose();
            HOperatorSet.SelectObj(ho_SelectedB_ContoursSplit, out ho_B_LeftLine_Contour,
                1);
            HOperatorSet.GetContourGlobalAttribXld(ho_B_LeftLine_Contour, "cont_approx",
                out hv_Attrib);
            //線段 B_ 的資訊
            HOperatorSet.FitLineContourXld(ho_B_LeftLine_Contour, "tukey", -1, 0, 5, 2,
                out hv_B_RowBegin, out hv_B_ColBegin, out hv_B_RowEnd, out hv_B_ColEnd,
                out hv_B_Nr, out hv_B_Nc, out hv_B_Dist);
            //	if (HDevWindowStack.IsOpen())
            //	{
            //		HOperatorSet.DispObj(ho_B_LeftLine_Contour, HDevWindowStack.GetActive());
            //	}
            //	//stop ()
            //}

            //計算 A1 與 B 之交點 P
            HOperatorSet.IntersectionLl(hv_B_RowBegin, hv_B_ColBegin, hv_B_RowEnd, hv_B_ColEnd,
                hv_A1RowBegin, hv_A1ColBegin, hv_A1RowEnd, hv_A1ColEnd, out hv_B1_InterY,
                out hv_B1_InterX, out hv_B1_IsParallel1);

            mResult = new LineResult()
            {
                Row1 = new HTuple(hv_B1_InterY),
                Col1 = new HTuple(hv_B1_InterX)
            };

            //ho_Cross.Dispose();
            //HOperatorSet.GenCrossContourXld(out ho_Cross, hv_B1_InterY, hv_B1_InterX, 0,
            //	0);
            //if (HDevWindowStack.IsOpen())
            //{
            //	//dev_display (Image)
            //}
            //if (HDevWindowStack.IsOpen())
            //{
            //	HOperatorSet.DispObj(ho_Cross, HDevWindowStack.GetActive());
            //}
            //stop ()
            //part 2 ,  計算另一邊的交點 Q
            //****B_1_1
            //STD B_1_1_ 位置
            hv_STD_B_1_1_Row = 800;
            hv_STD_B_1_1_Col = 1400;

            //STD 向量 STD_B_1_1_
            hv_STD_B_1_1_V_Row = hv_STD_B_1_1_Row - hv_STD_Row;
            hv_STD_B_1_1_V_Col = hv_STD_B_1_1_Col - hv_STD_Col;

            //B_1_1_X, B_1_1_Y 分量
            hv_B_1_1_X = (hv_STD_B_1_1_V_Col * (hv_Img_Rotate_Angle.TupleCos())) + (hv_STD_B_1_1_V_Row * (hv_Img_Rotate_Angle.TupleSin()
                ));
            hv_B_1_1_Y = (hv_STD_B_1_1_V_Row * (hv_Img_Rotate_Angle.TupleCos())) - (hv_STD_B_1_1_V_Col * (hv_Img_Rotate_Angle.TupleSin()
                ));

            //目前圖形 B_1_1_ 位置
            hv_B_1_1_Pos_Row = (hv_STD_Row + hv_B_1_1_Y) + hv_OffsetRow;
            hv_B_1_1_Pos_Col = (hv_STD_Col + hv_B_1_1_X) + hv_OffsetCol;

            //for (hv_MatchingObjIdx = 0; (int)hv_MatchingObjIdx <= (int)((new HTuple(hv_AllModelScore.TupleLength()
            //	)) - 1); hv_MatchingObjIdx = (int)hv_MatchingObjIdx + 1)
            //{
            //step 1 由 matchingObj 得知目標區域中心座標 (A1_RModelRow, A1_RModelColumn... 等資訊) 建立 ROI
            hv_ROI_W = 50;
            hv_ROI_H = 150;
            ho_A1_RRectangle.Dispose();
            HOperatorSet.GenRectangle2(out ho_A1_RRectangle, hv_B_1_1_Pos_Row, hv_B_1_1_Pos_Col,
                hv_Img_Rotate_Angle, hv_ROI_W, hv_ROI_H);
            ho_A1_R_ROI.Dispose();
            HOperatorSet.ReduceDomain(ho_Image, ho_A1_RRectangle, out ho_A1_R_ROI);
            //stop ()
            //step 2 Extract contours and segment it
            hv_low = 60;
            hv_high = 140;
            ho_A1_REdges.Dispose();
            HOperatorSet.EdgesSubPix(ho_A1_R_ROI, out ho_A1_REdges, "lanser2", 0.3, hv_low,
                hv_high);
            HOperatorSet.CountObj(ho_A1_REdges, out hv_A1_RNumber);
            //修正上限
            hv_inc = -2;
            while ((int)(new HTuple(hv_A1_RNumber.TupleLess(1))) != 0)
            {
                hv_high = hv_high + hv_inc;
                ho_A1_REdges.Dispose();
                HOperatorSet.EdgesSubPix(ho_A1_R_ROI, out ho_A1_REdges, "lanser2", 0.3, hv_low,
                    hv_high);
                HOperatorSet.CountObj(ho_A1_REdges, out hv_A1_RNumber);
            }
            ho_A1_RContoursSplit.Dispose();
            HOperatorSet.SegmentContoursXld(ho_A1_REdges, out ho_A1_RContoursSplit, "lines",
                9, 4, 2);
            ho_SelectedA1_RContoursSplit.Dispose();
            HOperatorSet.SelectShapeXld(ho_A1_RContoursSplit, out ho_SelectedA1_RContoursSplit,
                "contlength", "and", 20, 99999);
            //stop ()
            //step 3 取得目標線段
            ho_B_RightLine_Contour.Dispose();
            HOperatorSet.SelectObj(ho_SelectedA1_RContoursSplit, out ho_B_RightLine_Contour,
                1);
            //if (HDevWindowStack.IsOpen())
            //{
            //	//dev_set_color ('yellow')
            //}
            HOperatorSet.GetContourGlobalAttribXld(ho_B_RightLine_Contour, "cont_approx",
                out hv_Attrib);
            //線段 A1_R 的資訊
            HOperatorSet.FitLineContourXld(ho_B_RightLine_Contour, "tukey", -1, 0, 5, 2,
                out hv_A1_RRowBegin, out hv_A1_RColBegin, out hv_A1_RRowEnd, out hv_A1_RColEnd,
                out hv_A1_RNr, out hv_A1_RNc, out hv_A1_RDist);
            //	if (HDevWindowStack.IsOpen())
            //	{
            //		HOperatorSet.DispObj(ho_B_RightLine_Contour, HDevWindowStack.GetActive());
            //	}
            //	//stop ()
            //}
            //交點 Q

            //計算 A1 與 A1_R 之交點 Q'
            HOperatorSet.IntersectionLl(hv_A1_RRowBegin, hv_A1_RColBegin, hv_A1_RRowEnd,
                hv_A1_RColEnd, hv_A1RowBegin, hv_A1ColBegin, hv_A1RowEnd, hv_A1ColEnd, out hv_Q_InterY,
                out hv_Q_InterX, out hv_Q_IsParallel1);

            mResult.Row2 = new HTuple(hv_Q_InterY);
            mResult.Col2 = new HTuple(hv_Q_InterX);

            //ho_CrossQ.Dispose();
            //HOperatorSet.GenCrossContourXld(out ho_CrossQ, hv_Q_InterY, hv_Q_InterX, 0, 0);
            //if (HDevWindowStack.IsOpen())
            //{
            //	//dev_display (Image)
            //}
            //if (HDevWindowStack.IsOpen())
            //{
            //	HOperatorSet.DispObj(ho_CrossQ, HDevWindowStack.GetActive());
            //}
            HOperatorSet.DistanceCc(ho_Cross, ho_CrossQ, "point_to_point", out hv_DistanceMin,
                out hv_DistanceMax);
            HOperatorSet.DistanceCc(ho_Cross, ho_CrossQ, "point_to_segment", out hv_DistanceMinP,
                out hv_DistanceMaxP);
            HOperatorSet.DistanceCcMin(ho_Cross, ho_CrossQ, "fast_point_to_segment", out hv_DistanceMin1);
            HOperatorSet.DistanceCcMin(ho_Cross, ho_CrossQ, "point_to_segment", out hv_DistanceMin1P);
            HOperatorSet.DistanceCcMin(ho_B_LeftLine_Contour, ho_B_RightLine_Contour, "fast_point_to_segment",
                out hv_DistanceMin2);

            #region 距離
            HOperatorSet.DistancePp(mResult.Row1, mResult.Col1, mResult.Row2, mResult.Col2, out mResult.Distance);
            #endregion

            //687.113
            //699.113
            //HDevelopStop();
            //Final, 計算 PQ 線段

            //if ((int)((new HTuple(hv_B1_InterY.TupleGreater(0))).TupleAnd(new HTuple(hv_Q_InterY.TupleGreater(
            //	0)))) != 0)
            //{
            //	//轉正
            //	hv_X1 = (hv_B1_InterX * (hv_AllModelAngle.TupleCos())) - (hv_B1_InterY * (hv_AllModelAngle.TupleSin()
            //		));
            //	hv_X2 = (hv_Q_InterX * (hv_AllModelAngle.TupleCos())) - (hv_Q_InterY * (hv_AllModelAngle.TupleSin()
            //		));

            //	hv_Y1 = (hv_B1_InterX * (hv_AllModelAngle.TupleSin())) + (hv_B1_InterY * (hv_AllModelAngle.TupleCos()
            //		));
            //	hv_Y2 = (hv_Q_InterX * (hv_AllModelAngle.TupleSin())) + (hv_Q_InterY * (hv_AllModelAngle.TupleCos()
            //		));

            //	hv_A1Dist = ((hv_X1 - hv_X2)).TupleAbs();

            //	//****Mark_A1_C
            //	//STD Mark_A1_C_ 位置
            //	hv_STD_Mark_A1_C_Row = 102;
            //	hv_STD_Mark_A1_C_Col = 1035;

            //	//STD Mark_A1_Start_ 位置
            //	hv_STD_Mark_A1_Start_Row = 102;
            //	hv_STD_Mark_A1_Start_Col = 690;

            //	//STD Mark_A1_End_ 位置
            //	hv_STD_Mark_A1_End_Row = 102;
            //	hv_STD_Mark_A1_End_Col = 1410;

            //	//STD 向量 STD_Mark_A1_C_
            //	hv_STD_Mark_A1_C_V_Row = hv_STD_Mark_A1_C_Row - hv_STD_Row;
            //	hv_STD_Mark_A1_C_V_Col = hv_STD_Mark_A1_C_Col - hv_STD_Col;

            //	//Mark_A1_C_X, Mark_A1_C_Y 分量
            //	hv_Mark_A1_C_X = (hv_STD_Mark_A1_C_V_Col * (hv_Img_Rotate_Angle.TupleCos())) + (hv_STD_Mark_A1_C_V_Row * (hv_Img_Rotate_Angle.TupleSin()
            //		));
            //	hv_Mark_A1_C_Y = (hv_STD_Mark_A1_C_V_Row * (hv_Img_Rotate_Angle.TupleCos())) - (hv_STD_Mark_A1_C_V_Col * (hv_Img_Rotate_Angle.TupleSin()
            //		));

            //	//目前圖形 Mark_A1_C_ 位置
            //	hv_Mark_A1_C_Pos_Row = (hv_STD_Row + hv_Mark_A1_C_Y) + hv_OffsetRow;
            //	hv_Mark_A1_C_Pos_Col = (hv_STD_Col + hv_Mark_A1_C_X) + hv_OffsetCol;

            //	//STD 向量 STD_Mark_A1_Start_
            //	hv_STD_Mark_A1_Start_V_Row = hv_STD_Mark_A1_Start_Row - hv_STD_Row;
            //	hv_STD_Mark_A1_Start_V_Col = hv_STD_Mark_A1_Start_Col - hv_STD_Col;

            //	//Mark_A1_Start_X, Mark_A1_Start_Y 分量
            //	hv_Mark_A1_Start_X = (hv_STD_Mark_A1_Start_V_Col * (hv_Img_Rotate_Angle.TupleCos()
            //		)) + (hv_STD_Mark_A1_Start_V_Row * (hv_Img_Rotate_Angle.TupleSin()));
            //	hv_Mark_A1_Start_Y = (hv_STD_Mark_A1_Start_V_Row * (hv_Img_Rotate_Angle.TupleCos()
            //		)) - (hv_STD_Mark_A1_Start_V_Col * (hv_Img_Rotate_Angle.TupleSin()));

            //	//目前圖形 Mark_A1_Start_ 位置
            //	hv_Mark_A1_Start_Pos_Row = (hv_STD_Row + hv_Mark_A1_Start_Y) + hv_OffsetRow;
            //	hv_Mark_A1_Start_Pos_Col = (hv_STD_Col + hv_Mark_A1_Start_X) + hv_OffsetCol;

            //	//STD 向量 STD_Mark_A1_End_
            //	hv_STD_Mark_A1_End_V_Row = hv_STD_Mark_A1_End_Row - hv_STD_Row;
            //	hv_STD_Mark_A1_End_V_Col = hv_STD_Mark_A1_End_Col - hv_STD_Col;

            //	//Mark_A1_End_X, Mark_A1_End_Y 分量
            //	hv_Mark_A1_End_X = (hv_STD_Mark_A1_End_V_Col * (hv_Img_Rotate_Angle.TupleCos()
            //		)) + (hv_STD_Mark_A1_End_V_Row * (hv_Img_Rotate_Angle.TupleSin()));
            //	hv_Mark_A1_End_Y = (hv_STD_Mark_A1_End_V_Row * (hv_Img_Rotate_Angle.TupleCos()
            //		)) - (hv_STD_Mark_A1_End_V_Col * (hv_Img_Rotate_Angle.TupleSin()));

            //	//目前圖形 Mark_A1_End_ 位置
            //	hv_Mark_A1_End_Pos_Row = (hv_STD_Row + hv_Mark_A1_End_Y) + hv_OffsetRow;
            //	hv_Mark_A1_End_Pos_Col = (hv_STD_Col + hv_Mark_A1_End_X) + hv_OffsetCol;

            //	//HOperatorSet.SetTposition(hv_WindowHandle, hv_Mark_A1_C_Pos_Row - 25, hv_Mark_A1_C_Pos_Col);
            //	//HOperatorSet.WriteString(hv_WindowHandle, "A1");
            //	//HOperatorSet.DispArrow(hv_WindowHandle, hv_Mark_A1_C_Pos_Row, hv_Mark_A1_C_Pos_Col - 50,
            //	//	hv_Mark_A1_Start_Pos_Row, hv_Mark_A1_Start_Pos_Col, 5);
            //	//HOperatorSet.DispArrow(hv_WindowHandle, hv_Mark_A1_C_Pos_Row, hv_Mark_A1_C_Pos_Col + 50,
            //	//	hv_Mark_A1_End_Pos_Row, hv_Mark_A1_End_Pos_Col, 5);

            //}
            //hv_MeasureReasult = hv_A1Dist.Clone();
            //*****A1 End
            //ho_Image.Dispose();
            //ho_AllModelContours.Dispose();
            ho_A1Rectangle.Dispose();
            ho_A1_ROI.Dispose();
            ho_A1Edges.Dispose();
            ho_A1ContoursSplit.Dispose();
            ho_SelectedA1Contours.Dispose();
            ho_TopLineContour.Dispose();
            ho_B_Rectangle.Dispose();
            ho_B__ROI.Dispose();
            ho_B_Edges.Dispose();
            ho_B_ContoursSplit.Dispose();
            ho_SelectedB_ContoursSplit.Dispose();
            ho_B_LeftLine_Contour.Dispose();
            ho_Cross.Dispose();
            ho_A1_RRectangle.Dispose();
            ho_A1_R_ROI.Dispose();
            ho_A1_REdges.Dispose();
            ho_A1_RContoursSplit.Dispose();
            ho_SelectedA1_RContoursSplit.Dispose();
            ho_B_RightLine_Contour.Dispose();
            ho_CrossQ.Dispose();

            return mResult;
        }
        public MeasureResult Action()
        {
            #region 輸出結果
            LineResult mResult = null;
            #endregion
            // Local iconic variables

            HObject ho_A2_Region = null;
            HObject ho_A2_Reduced = null, ho_A2Region = null, ho_A2_RegionBorder = null;
            HObject ho_A2_RegionDilation = null, ho_A2_Edges = null, ho_A2_Rectangles = null;
            HObject ho_A2Cross = null, ho_A3_Region = null, ho_A3_Reduced = null;
            HObject ho_A3Region = null, ho_A3_RegionBorder = null, ho_A3_RegionDilation = null;
            HObject ho_A3_Edges = null, ho_A3_Rectangles = null, ho_A3Object = null;
            HObject ho_A3Cross = null;

            // Local control variables

            HTuple hv_msgOffsetY, hv_msgOffsetX;
            HTuple hv_STD_Row;
            HTuple hv_STD_Col, hv_Img_Row, hv_Img_Col, hv_Img_Rotate_Angle;
            HTuple hv_OffsetRow, hv_OffsetCol, hv_A2_Center_X, hv_A2_Center_Y;
            HTuple hv_STD_A2_1_1_Row, hv_STD_A2_1_1_Col, hv_STD_A2_1_1_V_Row;
            HTuple hv_STD_A2_1_1_V_Col, hv_A2_1_1_X, hv_A2_1_1_Y, hv_A2_1_1_Pos_Row;
            HTuple hv_A2_1_1_Pos_Col, hv_A2_ROI_W = new HTuple();
            HTuple hv_A2_ROI_H = new HTuple(), hv_Rec_W = new HTuple();
            HTuple hv_Rec_H = new HTuple(), hv_A2_Alpha = new HTuple();
            HTuple hv_a2low = new HTuple(), hv_a2high = new HTuple(), hv_a2Limit = new HTuple();
            HTuple hv_A2_RecNumber = new HTuple(), hv_A2Row = new HTuple();
            HTuple hv_A2Column = new HTuple(), hv_A2Phi = new HTuple();
            HTuple hv_A2Length1 = new HTuple(), hv_A2Length2 = new HTuple();
            HTuple hv_A2PointOrder = new HTuple(), hv_A2Number = new HTuple();
            HTuple hv_A3_Center_X, hv_A3_Center_Y, hv_STD_A3_Row, hv_STD_A3_Col;
            HTuple hv_STD_A3_V_Row, hv_STD_A3_V_Col, hv_A3_X, hv_A3_Y;
            HTuple hv_A3_Pos_Row, hv_A3_Pos_Col, hv_A3_ROI_W = new HTuple();
            HTuple hv_A3_ROI_H = new HTuple(), hv_A3_Alpha = new HTuple();
            HTuple hv_low = new HTuple(), hv_high = new HTuple(), hv_a3Limit = new HTuple();
            HTuple hv_A3RecNumber = new HTuple(), hv_A3Row = new HTuple();
            HTuple hv_A3Column = new HTuple(), hv_A3Phi = new HTuple();
            HTuple hv_A3Length1 = new HTuple(), hv_A3Length2 = new HTuple();
            HTuple hv_A3PointOrder = new HTuple(), hv_A3Number = new HTuple();
            HTuple hv_X1 = new HTuple(), hv_X2 = new HTuple();
            HTuple hv_Y1 = new HTuple(), hv_Y2 = new HTuple(), hv_STD_Mark_A3_C_Row = new HTuple();
            HTuple hv_STD_Mark_A3_C_Col = new HTuple(), hv_STD_Mark_A3_Start_Row = new HTuple();
            HTuple hv_STD_Mark_A3_Start_Col = new HTuple(), hv_STD_Mark_A3_End_Row = new HTuple();
            HTuple hv_STD_Mark_A3_End_Col = new HTuple(), hv_STD_Mark_A3_C_V_Row = new HTuple();
            HTuple hv_STD_Mark_A3_C_V_Col = new HTuple(), hv_Mark_A3_C_X = new HTuple();
            HTuple hv_Mark_A3_C_Y = new HTuple(), hv_Mark_A3_C_Pos_Row = new HTuple();
            HTuple hv_Mark_A3_C_Pos_Col = new HTuple(), hv_STD_Mark_A3_Start_V_Row = new HTuple();
            HTuple hv_STD_Mark_A3_Start_V_Col = new HTuple(), hv_Mark_A3_Start_X = new HTuple();
            HTuple hv_Mark_A3_Start_Y = new HTuple(), hv_Mark_A3_Start_Pos_Row = new HTuple();
            HTuple hv_Mark_A3_Start_Pos_Col = new HTuple(), hv_STD_Mark_A3_End_V_Row = new HTuple();
            HTuple hv_STD_Mark_A3_End_V_Col = new HTuple(), hv_Mark_A3_End_X = new HTuple();
            HTuple hv_Mark_A3_End_Y = new HTuple(), hv_Mark_A3_End_Pos_Row = new HTuple();
            HTuple hv_Mark_A3_End_Pos_Col = new HTuple();

            // Initialize local and output iconic variables
            HOperatorSet.GenEmptyObj(out ho_A2_Region);
            HOperatorSet.GenEmptyObj(out ho_A2_Reduced);
            HOperatorSet.GenEmptyObj(out ho_A2Region);
            HOperatorSet.GenEmptyObj(out ho_A2_RegionBorder);
            HOperatorSet.GenEmptyObj(out ho_A2_RegionDilation);
            HOperatorSet.GenEmptyObj(out ho_A2_Edges);
            HOperatorSet.GenEmptyObj(out ho_A2_Rectangles);
            HOperatorSet.GenEmptyObj(out ho_A2Cross);
            HOperatorSet.GenEmptyObj(out ho_A3_Region);
            HOperatorSet.GenEmptyObj(out ho_A3_Reduced);
            HOperatorSet.GenEmptyObj(out ho_A3Region);
            HOperatorSet.GenEmptyObj(out ho_A3_RegionBorder);
            HOperatorSet.GenEmptyObj(out ho_A3_RegionDilation);
            HOperatorSet.GenEmptyObj(out ho_A3_Edges);
            HOperatorSet.GenEmptyObj(out ho_A3_Rectangles);
            HOperatorSet.GenEmptyObj(out ho_A3Object);
            HOperatorSet.GenEmptyObj(out ho_A3Cross);

            //Measure: SDMS_A3
            //Author: John Hsieh
            //Date: 2012
            //Note: A3 related to A2
            //ho_Image.Dispose();
            //HOperatorSet.ReadImage(out ho_Image, "Images/STD.bmp");
            //dev_open_window_fit_image(ho_Image, 0, 0, -1, -1, out hv_WindowHandle);
            // dev_update_off(...); only in hdevelop
            HOperatorSet.SetSystem("border_shape_models", "false");

            //****Message Args
            hv_msgOffsetY = 100;
            hv_msgOffsetX = 100;

            //****Model Args

            //STD 中心點
            hv_STD_Row = 772;
            hv_STD_Col = 1003;

            //目前圖形 中心點
            hv_Img_Row = hv_AllModelRow.Clone();
            hv_Img_Col = hv_AllModelColumn.Clone();

            //目前圖形 Rotate Angle
            hv_Img_Rotate_Angle = hv_AllModelAngle.Clone();

            //目前圖形偏移量
            hv_OffsetRow = hv_Img_Row - hv_STD_Row;
            hv_OffsetCol = hv_Img_Col - hv_STD_Col;

            #region 找左邊數來第一個金手指的中心點 Finger
            /*
             	//*****A3
            //Step 1
             */

            hv_A2_Center_X = 0;
            hv_A2_Center_Y = 0;
            //****A2_1_1
            //STD A2_1_1_ 位置
            hv_STD_A2_1_1_Row = 410;
            hv_STD_A2_1_1_Col = 780;

            //STD 向量 STD_A2_1_1_
            hv_STD_A2_1_1_V_Row = hv_STD_A2_1_1_Row - hv_STD_Row;
            hv_STD_A2_1_1_V_Col = hv_STD_A2_1_1_Col - hv_STD_Col;

            //A2_1_1_X, A2_1_1_Y 分量
            hv_A2_1_1_X = (hv_STD_A2_1_1_V_Col * (hv_Img_Rotate_Angle.TupleCos())) + (hv_STD_A2_1_1_V_Row * (hv_Img_Rotate_Angle.TupleSin()
                ));
            hv_A2_1_1_Y = (hv_STD_A2_1_1_V_Row * (hv_Img_Rotate_Angle.TupleCos())) - (hv_STD_A2_1_1_V_Col * (hv_Img_Rotate_Angle.TupleSin()
                ));

            //目前圖形 A2_1_1_ 位置
            hv_A2_1_1_Pos_Row = (hv_STD_Row + hv_A2_1_1_Y) + hv_OffsetRow;
            hv_A2_1_1_Pos_Col = (hv_STD_Col + hv_A2_1_1_X) + hv_OffsetCol;

            //A2_ROI
            hv_A2_ROI_W = 40;
            hv_A2_ROI_H = 120;
            ho_A2_Region.Dispose();
            HOperatorSet.GenRectangle2(out ho_A2_Region, hv_A2_1_1_Pos_Row, hv_A2_1_1_Pos_Col,
                hv_Img_Rotate_Angle, hv_A2_ROI_W, hv_A2_ROI_H);
            //stop ()
            ho_A2_Reduced.Dispose();
            HOperatorSet.ReduceDomain(ho_Image, ho_A2_Region, out ho_A2_Reduced);
            //fit_Rectangle

            //stop ()
            //
            ho_A2Region.Dispose();
            HOperatorSet.FastThreshold(ho_A2_Reduced, out ho_A2Region, 50, 150, 20);
            ho_A2_RegionBorder.Dispose();
            HOperatorSet.Boundary(ho_A2Region, out ho_A2_RegionBorder, "inner");

            hv_Rec_W = 11;
            hv_Rec_H = 11;
            ho_A2_RegionDilation.Dispose();
            HOperatorSet.DilationRectangle1(ho_A2_RegionBorder, out ho_A2_RegionDilation,
                hv_Rec_W, hv_Rec_H);
            hv_A2_Alpha = 0.9;
            hv_a2low = 20;
            hv_a2high = 110;
            ho_A2_Edges.Dispose();
            HOperatorSet.EdgesSubPix(ho_A2_Reduced, out ho_A2_Edges, "canny", hv_A2_Alpha,
                hv_a2low, hv_a2high);

            //stop ()
            hv_a2Limit = 200;
            ho_A2_Rectangles.Dispose();
            HOperatorSet.SelectShapeXld(ho_A2_Edges, out ho_A2_Rectangles, "contlength",
                "and", hv_a2Limit, 99999);
            HOperatorSet.CountObj(ho_A2_Rectangles, out hv_A2_RecNumber);
            while ((int)(new HTuple(hv_A2_RecNumber.TupleGreater(1))) != 0)
            {
                hv_a2Limit = hv_a2Limit + 10;
                ho_A2_Rectangles.Dispose();
                HOperatorSet.SelectShapeXld(ho_A2_Edges, out ho_A2_Rectangles, "contlength",
                    "and", hv_a2Limit, 99999);
                HOperatorSet.CountObj(ho_A2_Rectangles, out hv_A2_RecNumber);
            }
            //stop ()
            HOperatorSet.FitRectangle2ContourXld(ho_A2_Rectangles, "regression", -1, 0,
                0, 3, 2, out hv_A2Row, out hv_A2Column, out hv_A2Phi, out hv_A2Length1,
                out hv_A2Length2, out hv_A2PointOrder);
            HOperatorSet.CountObj(ho_A2_Rectangles, out hv_A2Number);
            //取A2
            if ((int)(new HTuple(hv_A2Number.TupleGreater(0))) != 0)
            {
                hv_A2_Center_X = hv_A2Column[0];
                hv_A2_Center_Y = hv_A2Row[0];
                ho_A2Cross.Dispose();
                HOperatorSet.GenCrossContourXld(out ho_A2Cross, hv_A2Row, hv_A2Column, 10, 0);
                mResult = new LineResult()
                {
                    Row1 = new HTuple(hv_A2Row),
                    Col1 = new HTuple(hv_A2Column),
                };

            }
            #endregion

            //step 2 取點 A3,金手指由右數來第一個的中心點
            hv_A3_Center_X = 0;
            hv_A3_Center_Y = 0;
            //****A3
            //STD A3_ 位置
            hv_STD_A3_Row = 393;
            hv_STD_A3_Col = 1330;

            //STD 向量 STD_A3_
            hv_STD_A3_V_Row = hv_STD_A3_Row - hv_STD_Row;
            hv_STD_A3_V_Col = hv_STD_A3_Col - hv_STD_Col;

            //A3_X, A3_Y 分量
            hv_A3_X = (hv_STD_A3_V_Col * (hv_Img_Rotate_Angle.TupleCos())) + (hv_STD_A3_V_Row * (hv_Img_Rotate_Angle.TupleSin()
                ));
            hv_A3_Y = (hv_STD_A3_V_Row * (hv_Img_Rotate_Angle.TupleCos())) - (hv_STD_A3_V_Col * (hv_Img_Rotate_Angle.TupleSin()
                ));

            //目前圖形 A3_ 位置
            hv_A3_Pos_Row = (hv_STD_Row + hv_A3_Y) + hv_OffsetRow;
            hv_A3_Pos_Col = (hv_STD_Col + hv_A3_X) + hv_OffsetCol;

            //A3_ROI
            hv_A3_ROI_W = 40;
            hv_A3_ROI_H = 140;
            ho_A3_Region.Dispose();
            HOperatorSet.GenRectangle2(out ho_A3_Region, hv_A3_Pos_Row, hv_A3_Pos_Col,
                hv_Img_Rotate_Angle, hv_A3_ROI_W, hv_A3_ROI_H);
            //stop ()
            ho_A3_Reduced.Dispose();
            HOperatorSet.ReduceDomain(ho_Image, ho_A3_Region, out ho_A3_Reduced);
            //fit_Rectangle, 找金手指
            ho_A3Region.Dispose();
            HOperatorSet.FastThreshold(ho_A3_Reduced, out ho_A3Region, 100, 250, 20);
            ho_A3_RegionBorder.Dispose();
            HOperatorSet.Boundary(ho_A3Region, out ho_A3_RegionBorder, "inner");
            if (HDevWindowStack.IsOpen())
            {
                //dev_display (A3_RegionBorder)
            }
            hv_Rec_W = 11;
            hv_Rec_H = 11;
            ho_A3_RegionDilation.Dispose();
            HOperatorSet.DilationRectangle1(ho_A3_RegionBorder, out ho_A3_RegionDilation,
                hv_Rec_W, hv_Rec_H);
            //alpha 大容錯大
            hv_A3_Alpha = 4;
            hv_low = 10;
            hv_high = 100;
            ho_A3_Edges.Dispose();
            HOperatorSet.EdgesSubPix(ho_A3_Reduced, out ho_A3_Edges, "canny", hv_A3_Alpha,
                hv_low, hv_high);
            //stop ()
            hv_a3Limit = 200;
            ho_A3_Rectangles.Dispose();
            HOperatorSet.SelectShapeXld(ho_A3_Edges, out ho_A3_Rectangles, "contlength",
                "and", hv_a3Limit, 99999);
            HOperatorSet.CountObj(ho_A3_Rectangles, out hv_A3RecNumber);
            while ((int)(new HTuple(hv_A3RecNumber.TupleGreater(1))) != 0)
            {
                hv_a3Limit = hv_a3Limit + 10;
                ho_A3_Rectangles.Dispose();
                HOperatorSet.SelectShapeXld(ho_A3_Edges, out ho_A3_Rectangles, "contlength",
                    "and", hv_a3Limit, 99999);
                HOperatorSet.CountObj(ho_A3_Rectangles, out hv_A3RecNumber);
            }
            HOperatorSet.FitRectangle2ContourXld(ho_A3_Rectangles, "regression", -1, 0,
                0, 3, 2, out hv_A3Row, out hv_A3Column, out hv_A3Phi, out hv_A3Length1,
                out hv_A3Length2, out hv_A3PointOrder);
            //取A3 中心點
            HOperatorSet.CountObj(ho_A3_Rectangles, out hv_A3Number);
            if ((int)(new HTuple(hv_A3Number.TupleGreater(0))) != 0)
            {
                ho_A3Object.Dispose();
                HOperatorSet.SelectObj(ho_A3_Rectangles, out ho_A3Object, 1);
                //stop ()
                //取 A2Object 資訊
                hv_A3_Center_X = hv_A3Column[0];
                hv_A3_Center_Y = hv_A3Row[0];
                ho_A3Cross.Dispose();
                HOperatorSet.GenCrossContourXld(out ho_A3Cross, hv_A3Row, hv_A3Column, 10, 0);

                if (hv_A3Row.TupleLength() > 0 && hv_A2Row.TupleLength() > 0)
                {
                    mResult.Row2 = new HTuple(hv_A3Row);
                    mResult.Col2 = new HTuple(hv_A3Column);
                    HOperatorSet.DistancePp(hv_A2Row, hv_A2Column, hv_A3Row, hv_A3Column, out mResult.Distance);
                }
            }

            //*****A3 End

            ho_A2_Region.Dispose();
            ho_A2_Reduced.Dispose();
            ho_A2Region.Dispose();
            ho_A2_RegionBorder.Dispose();
            ho_A2_RegionDilation.Dispose();
            ho_A2_Edges.Dispose();
            ho_A2_Rectangles.Dispose();
            ho_A2Cross.Dispose();
            ho_A3_Region.Dispose();
            ho_A3_Reduced.Dispose();
            ho_A3Region.Dispose();
            ho_A3_RegionBorder.Dispose();
            ho_A3_RegionDilation.Dispose();
            ho_A3_Edges.Dispose();
            ho_A3_Rectangles.Dispose();
            ho_A3Object.Dispose();
            ho_A3Cross.Dispose();

            return mResult;
        }
 public LineResult(LineResult result)
     : this(result.Row1, result.Col1, result.Row2, result.Col2, result.Distance)
 {
 }
 /// <summary>
 /// 計算兩點 Y 方向距離
 /// </summary>
 /// <param name="pointOne">點 1</param>
 /// <param name="pointTwo">點 2</param>
 /// <returns></returns>
 public static LineResult DistanceY(IMeasureGeoModel pointOne, IMeasureGeoModel pointTwo)
 {
     LineResult result = null;
     var modelValid = isMeasureModelValid(pointOne) && isMeasureModelValid(pointTwo);
     if (modelValid)
     {
         var distanceY = Math.Abs(pointOne.Row1.D - pointTwo.Row1.D);
         result = new LineResult()
         {
             Col1 = pointOne.Col1,
             Col2 = pointOne.Col1,
             Row1 = pointOne.Row1,
             Row2 = pointTwo.Row1,
             Distance = distanceY,
         };
     }
     return result;
 }
        /// <summary>
        /// 計算兩線段的對稱線
        /// </summary>
        /// <param name="modelOne"></param>
        /// <param name="modelTwo"></param>
        /// <returns></returns>
        public static LineResult CalculateSymmetryLine(IMeasureGeoModel modelOne, IMeasureGeoModel modelTwo)
        {
            LineResult result = null;
            var modelValid = isMeasureModelValid(modelOne) && isMeasureModelValid(modelTwo);

            if (modelValid)
            {
                //取得第一條線段的中點
                var pointModel = getMidPoint(modelOne);

                var lineModel = modelTwo;

                //計算第一線段中點到第二線段上的投影點(垂直距離)
                HTuple rowProj, colProj;
                HOperatorSet.ProjectionPl(pointModel.Row1, pointModel.Col1, lineModel.Row1, lineModel.Col1, lineModel.Row2, lineModel.Col2, out rowProj, out colProj);

                //計算第一線段中點與第二線段上的投影點距離 (point to point)
                HTuple distance;
                HOperatorSet.DistancePp(rowProj, colProj, pointModel.Row1, pointModel.Col1, out distance);

                //取兩線中點
                var cRow = (pointModel.Row1 + rowProj) / 2.0;
                var cCol = (pointModel.Col1 + colProj) / 2.0;

                //取角度
                HTuple angle;
                HOperatorSet.AngleLx(lineModel.Row1, lineModel.Col1, lineModel.Row2, lineModel.Col2, out angle);

                //線段
                double[] rows, cols;
                DetermineLine(cRow, cCol, angle, distance, out rows, out cols);
                result = new LineResult()
                {
                    Row1 = rows[0],
                    Row2 = rows[1],
                    Col1 = cols[0],
                    Col2 = cols[1],
                    Distance = distance,
                };
            }
            return result;
        }
        public MeasureResult Action()
        {
            #region 輸出結果
            LineResult mResult = null;
            #endregion
            HObject ho_A2_Region = null;
            HObject ho_A2_Reduced = null, ho_A2Region = null, ho_A2_RegionBorder = null;
            HObject ho_A2_RegionDilation = null, ho_A2_Edges = null, ho_A2_Rectangles = null;
            HObject ho_A2Cross = null;

            // Local control variables

            HTuple hv_msgOffsetY, hv_msgOffsetX;
            //HTuple hv_AllModelId, hv_AllModelRow, hv_AllModelColumn;
            HTuple hv_STD_Row;
            HTuple hv_STD_Col, hv_Img_Row, hv_Img_Col, hv_Img_Rotate_Angle;
            HTuple hv_OffsetRow, hv_OffsetCol, hv_CL_X, hv_CL_Y, hv_STD_CL_1_Row;
            HTuple hv_STD_CL_1_Col, hv_STD_CL_1_V_Row, hv_STD_CL_1_V_Col;
            HTuple hv_CL_1_X, hv_CL_1_Y, hv_CL_1_Pos_Row, hv_CL_1_Pos_Col;
            HTuple hv_A2_Center_X, hv_A2_Center_Y, hv_STD_A2_1_1_Row;
            HTuple hv_STD_A2_1_1_Col, hv_STD_A2_1_1_V_Row, hv_STD_A2_1_1_V_Col;
            HTuple hv_A2_1_1_X, hv_A2_1_1_Y, hv_A2_1_1_Pos_Row, hv_A2_1_1_Pos_Col;
            HTuple hv_A2_ROI_W = new HTuple(), hv_A2_ROI_H = new HTuple();
            HTuple hv_Rec_W = new HTuple(), hv_Rec_H = new HTuple(), hv_A2_Alpha = new HTuple();
            HTuple hv_a2low = new HTuple(), hv_a2high = new HTuple(), hv_a2Limit = new HTuple();
            HTuple hv_A2_RecNumber = new HTuple(), hv_A2Row = new HTuple();
            HTuple hv_A2Column = new HTuple(), hv_A2Phi = new HTuple();
            HTuple hv_A2Length1 = new HTuple(), hv_A2Length2 = new HTuple();
            HTuple hv_A2PointOrder = new HTuple(), hv_A2Number = new HTuple();
            HTuple hv_A2_Dist, hv_X1 = new HTuple(), hv_X2 = new HTuple();
            HTuple hv_Y1 = new HTuple(), hv_Y2 = new HTuple(), hv_STD_Mark_A2_C_Row = new HTuple();
            HTuple hv_STD_Mark_A2_C_Col = new HTuple(), hv_STD_Mark_A2_Start_Row = new HTuple();
            HTuple hv_STD_Mark_A2_Start_Col = new HTuple(), hv_STD_Mark_A2_End_Row = new HTuple();
            HTuple hv_STD_Mark_A2_End_Col = new HTuple(), hv_STD_Mark_A2_C_V_Row = new HTuple();
            HTuple hv_STD_Mark_A2_C_V_Col = new HTuple(), hv_Mark_A2_C_X = new HTuple();
            HTuple hv_Mark_A2_C_Y = new HTuple(), hv_Mark_A2_C_Pos_Row = new HTuple();
            HTuple hv_Mark_A2_C_Pos_Col = new HTuple(), hv_STD_Mark_A2_Start_V_Row = new HTuple();
            HTuple hv_STD_Mark_A2_Start_V_Col = new HTuple(), hv_Mark_A2_Start_X = new HTuple();
            HTuple hv_Mark_A2_Start_Y = new HTuple(), hv_Mark_A2_Start_Pos_Row = new HTuple();
            HTuple hv_Mark_A2_Start_Pos_Col = new HTuple(), hv_STD_Mark_A2_End_V_Row = new HTuple();
            HTuple hv_STD_Mark_A2_End_V_Col = new HTuple(), hv_Mark_A2_End_X = new HTuple();
            HTuple hv_Mark_A2_End_Y = new HTuple(), hv_Mark_A2_End_Pos_Row = new HTuple();
            HTuple hv_Mark_A2_End_Pos_Col = new HTuple();

            // Initialize local and output iconic variables
            //HOperatorSet.GenEmptyObj(out ho_Image);
            //HOperatorSet.GenEmptyObj(out ho_AllModelContours);
            HOperatorSet.GenEmptyObj(out ho_A2_Region);
            HOperatorSet.GenEmptyObj(out ho_A2_Reduced);
            HOperatorSet.GenEmptyObj(out ho_A2Region);
            HOperatorSet.GenEmptyObj(out ho_A2_RegionBorder);
            HOperatorSet.GenEmptyObj(out ho_A2_RegionDilation);
            HOperatorSet.GenEmptyObj(out ho_A2_Edges);
            HOperatorSet.GenEmptyObj(out ho_A2_Rectangles);
            HOperatorSet.GenEmptyObj(out ho_A2Cross);

            //Measure: SDMS_A2
            //Author: John Hsieh
            //Date: 2012
            //ho_Image.Dispose();
            //HOperatorSet.ReadImage(out ho_Image, "Images/STD.bmp");
            //dev_open_window_fit_image(ho_Image, 0, 0, -1, -1, out hv_WindowHandle);
            // dev_update_off(...); only in hdevelop
            HOperatorSet.SetSystem("border_shape_models", "false");

            //****Message Args
            hv_msgOffsetY = 100;
            hv_msgOffsetX = 100;

            ////****Model All
            //HOperatorSet.ReadShapeModel("D:/Projects/Halcon/SDMS/SDMS_Measure/Model/MatchingAll.shm",
            //	out hv_AllModelId);
            //ho_AllModelContours.Dispose();
            //HOperatorSet.GetShapeModelContours(out ho_AllModelContours, hv_AllModelId, 1);
            //HOperatorSet.FindShapeModel(ho_Image, hv_AllModelId, (new HTuple(0)).TupleRad()
            //	, (new HTuple(360)).TupleRad(), 0.5, 1, 0.5, "least_squares", 6, 0.75, out hv_AllModelRow,
            //	out hv_AllModelColumn, out hv_AllModelAngle, out hv_AllModelScore);

            //****Model Args

            //STD 中心點
            hv_STD_Row = 772;
            hv_STD_Col = 1003;

            //目前圖形 中心點
            hv_Img_Row = hv_AllModelRow.Clone();
            hv_Img_Col = hv_AllModelColumn.Clone();

            //目前圖形 Rotate Angle
            hv_Img_Rotate_Angle = hv_AllModelAngle.Clone();

            //目前圖形偏移量
            hv_OffsetRow = hv_Img_Row - hv_STD_Row;
            hv_OffsetCol = hv_Img_Col - hv_STD_Col;

            ////****Display
            //if (HDevWindowStack.IsOpen())
            //{
            //	HOperatorSet.ClearWindow(HDevWindowStack.GetActive());
            //}
            //if (HDevWindowStack.IsOpen())
            //{
            //	HOperatorSet.DispObj(ho_Image, HDevWindowStack.GetActive());
            //}
            //*****A2
            //step 1.
            //尋找中心點 CL model matching (CL_X, CL_Y)
            hv_CL_X = 0;
            hv_CL_Y = 0;
            //****CL_1
            //STD CL_1_ 位置
            hv_STD_CL_1_Row = 403;
            hv_STD_CL_1_Col = 1054;

            //STD 向量 STD_CL_1_
            hv_STD_CL_1_V_Row = hv_STD_CL_1_Row - hv_STD_Row;
            hv_STD_CL_1_V_Col = hv_STD_CL_1_Col - hv_STD_Col;

            //CL_1_X, CL_1_Y 分量
            hv_CL_1_X = (hv_STD_CL_1_V_Col * (hv_Img_Rotate_Angle.TupleCos())) + (hv_STD_CL_1_V_Row * (hv_Img_Rotate_Angle.TupleSin()
                ));
            hv_CL_1_Y = (hv_STD_CL_1_V_Row * (hv_Img_Rotate_Angle.TupleCos())) - (hv_STD_CL_1_V_Col * (hv_Img_Rotate_Angle.TupleSin()
                ));

            //目前圖形 CL_1_ 位置
            hv_CL_1_Pos_Row = (hv_STD_Row + hv_CL_1_Y) + hv_OffsetRow;
            hv_CL_1_Pos_Col = (hv_STD_Col + hv_CL_1_X) + hv_OffsetCol;

            hv_CL_X = hv_CL_1_Pos_Col.Clone();
            hv_CL_Y = hv_CL_1_Pos_Row.Clone();

            //Step 1
            //找左邊數來第一個金手指的中心點 Finger
            hv_A2_Center_X = 0;
            hv_A2_Center_Y = 0;
            //****A2_1_1
            //STD A2_1_1_ 位置
            hv_STD_A2_1_1_Row = 410;
            hv_STD_A2_1_1_Col = 780;

            //STD 向量 STD_A2_1_1_
            hv_STD_A2_1_1_V_Row = hv_STD_A2_1_1_Row - hv_STD_Row;
            hv_STD_A2_1_1_V_Col = hv_STD_A2_1_1_Col - hv_STD_Col;

            //A2_1_1_X, A2_1_1_Y 分量
            hv_A2_1_1_X = (hv_STD_A2_1_1_V_Col * (hv_Img_Rotate_Angle.TupleCos())) + (hv_STD_A2_1_1_V_Row * (hv_Img_Rotate_Angle.TupleSin()
                ));
            hv_A2_1_1_Y = (hv_STD_A2_1_1_V_Row * (hv_Img_Rotate_Angle.TupleCos())) - (hv_STD_A2_1_1_V_Col * (hv_Img_Rotate_Angle.TupleSin()
                ));

            //目前圖形 A2_1_1_ 位置
            hv_A2_1_1_Pos_Row = (hv_STD_Row + hv_A2_1_1_Y) + hv_OffsetRow;
            hv_A2_1_1_Pos_Col = (hv_STD_Col + hv_A2_1_1_X) + hv_OffsetCol;

            //for (hv_MatchingObjIdx = 0; (int)hv_MatchingObjIdx <= (int)((new HTuple(hv_AllModelScore.TupleLength()
            //	)) - 1); hv_MatchingObjIdx = (int)hv_MatchingObjIdx + 1)
            //{
            //A2_ROI
            hv_A2_ROI_W = 40;
            hv_A2_ROI_H = 120;
            ho_A2_Region.Dispose();
            HOperatorSet.GenRectangle2(out ho_A2_Region, hv_A2_1_1_Pos_Row, hv_A2_1_1_Pos_Col,
                hv_Img_Rotate_Angle, hv_A2_ROI_W, hv_A2_ROI_H);
            //stop ()
            ho_A2_Reduced.Dispose();
            HOperatorSet.ReduceDomain(ho_Image, ho_A2_Region, out ho_A2_Reduced);
            //fit_Rectangle
            //if (HDevWindowStack.IsOpen())
            //{
            //	//dev_display (Image)
            //}
            //if (HDevWindowStack.IsOpen())
            //{
            //	//dev_display (A2_Region)
            //}
            //stop ()
            //
            ho_A2Region.Dispose();
            HOperatorSet.FastThreshold(ho_A2_Reduced, out ho_A2Region, 50, 150, 20);
            ho_A2_RegionBorder.Dispose();
            HOperatorSet.Boundary(ho_A2Region, out ho_A2_RegionBorder, "inner");
            if (HDevWindowStack.IsOpen())
            {
                //dev_display (A2_RegionBorder)
            }
            hv_Rec_W = 11;
            hv_Rec_H = 11;
            ho_A2_RegionDilation.Dispose();
            HOperatorSet.DilationRectangle1(ho_A2_RegionBorder, out ho_A2_RegionDilation,
                hv_Rec_W, hv_Rec_H);
            hv_A2_Alpha = 0.9;
            hv_a2low = 20;
            hv_a2high = 110;
            ho_A2_Edges.Dispose();
            HOperatorSet.EdgesSubPix(ho_A2_Reduced, out ho_A2_Edges, "canny", hv_A2_Alpha,
                hv_a2low, hv_a2high);
            //stop ()
            hv_a2Limit = 200;
            ho_A2_Rectangles.Dispose();
            HOperatorSet.SelectShapeXld(ho_A2_Edges, out ho_A2_Rectangles, "contlength",
                "and", hv_a2Limit, 99999);
            HOperatorSet.CountObj(ho_A2_Rectangles, out hv_A2_RecNumber);
            while ((int)(new HTuple(hv_A2_RecNumber.TupleGreater(1))) != 0)
            {
                hv_a2Limit = hv_a2Limit + 10;
                ho_A2_Rectangles.Dispose();
                HOperatorSet.SelectShapeXld(ho_A2_Edges, out ho_A2_Rectangles, "contlength",
                    "and", hv_a2Limit, 99999);
                HOperatorSet.CountObj(ho_A2_Rectangles, out hv_A2_RecNumber);
            }
            //stop ()
            HOperatorSet.FitRectangle2ContourXld(ho_A2_Rectangles, "regression", -1, 0,
                0, 3, 2, out hv_A2Row, out hv_A2Column, out hv_A2Phi, out hv_A2Length1,
                out hv_A2Length2, out hv_A2PointOrder);
            HOperatorSet.CountObj(ho_A2_Rectangles, out hv_A2Number);
            //取A2
            if ((int)(new HTuple(hv_A2Number.TupleGreater(0))) != 0)
            {
                hv_A2_Center_X = hv_A2Column[0];
                hv_A2_Center_Y = hv_A2Row[0];
                ho_A2Cross.Dispose();
                HOperatorSet.GenCrossContourXld(out ho_A2Cross, hv_A2Row, hv_A2Column, 10,
                    0);
                //if (HDevWindowStack.IsOpen())
                //{
                //	HOperatorSet.DispObj(ho_A2Cross, HDevWindowStack.GetActive());
                //}
                //stop ()
            }

            //}
            HOperatorSet.DistancePp(hv_A2_Center_Y, hv_A2_Center_X, hv_CL_Y, hv_CL_X, out hv_A2_Dist);
            mResult = new LineResult(hv_A2_Center_Y, hv_A2_Center_X, hv_CL_Y, hv_CL_X, hv_A2_Dist);

            //step 3
            //show Result
            //hv_A2_Dist = 0;
            //if ((int)((new HTuple(hv_A2_Center_X.TupleGreater(0))).TupleAnd(new HTuple(hv_A2_Center_Y.TupleGreater(
            //	0)))) != 0)
            //{
            //	//轉正
            //	hv_X1 = (hv_A2_Center_X * (hv_AllModelAngle.TupleCos())) - (hv_A2_Center_Y * (hv_AllModelAngle.TupleSin()
            //		));
            //	hv_X2 = (hv_CL_X * (hv_AllModelAngle.TupleCos())) - (hv_CL_Y * (hv_AllModelAngle.TupleSin()
            //		));

            //	hv_Y1 = (hv_A2_Center_X * (hv_AllModelAngle.TupleSin())) + (hv_A2_Center_Y * (hv_AllModelAngle.TupleCos()
            //		));
            //	hv_Y2 = (hv_CL_X * (hv_AllModelAngle.TupleSin())) + (hv_CL_Y * (hv_AllModelAngle.TupleCos()
            //		));

            //	//disp_cross (WindowHandle, CL_Y, CL_X, 10, 0)
            //	//disp_cross (WindowHandle, A2_Center_Y, A2_Center_X, 10, 0)
            //	hv_A2_Dist = ((hv_X1 - hv_X2)).TupleAbs();
            //	//****Mark_A2_C
            //	//STD Mark_A2_C_ 位置
            //	hv_STD_Mark_A2_C_Row = 420;
            //	hv_STD_Mark_A2_C_Col = 890;

            //	//STD Mark_A2_Start_ 位置
            //	hv_STD_Mark_A2_Start_Row = 420;
            //	hv_STD_Mark_A2_Start_Col = 780;

            //	//STD Mark_A2_End_ 位置
            //	hv_STD_Mark_A2_End_Row = 420;
            //	hv_STD_Mark_A2_End_Col = 1055;

            //	//STD 向量 STD_Mark_A2_C_
            //	hv_STD_Mark_A2_C_V_Row = hv_STD_Mark_A2_C_Row - hv_STD_Row;
            //	hv_STD_Mark_A2_C_V_Col = hv_STD_Mark_A2_C_Col - hv_STD_Col;

            //	//Mark_A2_C_X, Mark_A2_C_Y 分量
            //	hv_Mark_A2_C_X = (hv_STD_Mark_A2_C_V_Col * (hv_Img_Rotate_Angle.TupleCos())) + (hv_STD_Mark_A2_C_V_Row * (hv_Img_Rotate_Angle.TupleSin()
            //		));
            //	hv_Mark_A2_C_Y = (hv_STD_Mark_A2_C_V_Row * (hv_Img_Rotate_Angle.TupleCos())) - (hv_STD_Mark_A2_C_V_Col * (hv_Img_Rotate_Angle.TupleSin()
            //		));

            //	//目前圖形 Mark_A2_C_ 位置
            //	hv_Mark_A2_C_Pos_Row = (hv_STD_Row + hv_Mark_A2_C_Y) + hv_OffsetRow;
            //	hv_Mark_A2_C_Pos_Col = (hv_STD_Col + hv_Mark_A2_C_X) + hv_OffsetCol;

            //	//STD 向量 STD_Mark_A2_Start_
            //	hv_STD_Mark_A2_Start_V_Row = hv_STD_Mark_A2_Start_Row - hv_STD_Row;
            //	hv_STD_Mark_A2_Start_V_Col = hv_STD_Mark_A2_Start_Col - hv_STD_Col;

            //	//Mark_A2_Start_X, Mark_A2_Start_Y 分量
            //	hv_Mark_A2_Start_X = (hv_STD_Mark_A2_Start_V_Col * (hv_Img_Rotate_Angle.TupleCos()
            //		)) + (hv_STD_Mark_A2_Start_V_Row * (hv_Img_Rotate_Angle.TupleSin()));
            //	hv_Mark_A2_Start_Y = (hv_STD_Mark_A2_Start_V_Row * (hv_Img_Rotate_Angle.TupleCos()
            //		)) - (hv_STD_Mark_A2_Start_V_Col * (hv_Img_Rotate_Angle.TupleSin()));

            //	//目前圖形 Mark_A2_Start_ 位置
            //	hv_Mark_A2_Start_Pos_Row = (hv_STD_Row + hv_Mark_A2_Start_Y) + hv_OffsetRow;
            //	hv_Mark_A2_Start_Pos_Col = (hv_STD_Col + hv_Mark_A2_Start_X) + hv_OffsetCol;

            //	//STD 向量 STD_Mark_A2_End_
            //	hv_STD_Mark_A2_End_V_Row = hv_STD_Mark_A2_End_Row - hv_STD_Row;
            //	hv_STD_Mark_A2_End_V_Col = hv_STD_Mark_A2_End_Col - hv_STD_Col;

            //	//Mark_A2_End_X, Mark_A2_End_Y 分量
            //	hv_Mark_A2_End_X = (hv_STD_Mark_A2_End_V_Col * (hv_Img_Rotate_Angle.TupleCos()
            //		)) + (hv_STD_Mark_A2_End_V_Row * (hv_Img_Rotate_Angle.TupleSin()));
            //	hv_Mark_A2_End_Y = (hv_STD_Mark_A2_End_V_Row * (hv_Img_Rotate_Angle.TupleCos()
            //		)) - (hv_STD_Mark_A2_End_V_Col * (hv_Img_Rotate_Angle.TupleSin()));

            //	//目前圖形 Mark_A2_End_ 位置
            //	hv_Mark_A2_End_Pos_Row = (hv_STD_Row + hv_Mark_A2_End_Y) + hv_OffsetRow;
            //	hv_Mark_A2_End_Pos_Col = (hv_STD_Col + hv_Mark_A2_End_X) + hv_OffsetCol;

            //	//HOperatorSet.SetTposition(hv_WindowHandle, hv_Mark_A2_C_Pos_Row - 25, hv_Mark_A2_C_Pos_Col);
            //	//HOperatorSet.WriteString(hv_WindowHandle, "A2");
            //	//HOperatorSet.DispArrow(hv_WindowHandle, hv_Mark_A2_C_Pos_Row, hv_Mark_A2_C_Pos_Col - 50,
            //	//	hv_Mark_A2_Start_Pos_Row, hv_Mark_A2_Start_Pos_Col, 5);
            //	//HOperatorSet.DispArrow(hv_WindowHandle, hv_Mark_A2_C_Pos_Row, hv_Mark_A2_C_Pos_Col + 50,
            //	//	hv_Mark_A2_End_Pos_Row, hv_Mark_A2_End_Pos_Col, 5);
            //}
            //hv_MeasureReasult = hv_A2_Dist.Clone();
            //*****A2 End
            //ho_Image.Dispose();
            //ho_AllModelContours.Dispose();
            ho_A2_Region.Dispose();
            ho_A2_Reduced.Dispose();
            ho_A2Region.Dispose();
            ho_A2_RegionBorder.Dispose();
            ho_A2_RegionDilation.Dispose();
            ho_A2_Edges.Dispose();
            ho_A2_Rectangles.Dispose();
            ho_A2Cross.Dispose();

            return mResult;
        }
        public MeasureResult Action()
        {
            #region 輸出結果
            LineResult mResult = null;
            #endregion

            HTuple hv_STD_Row;
            HTuple hv_STD_Col, hv_Img_Row, hv_Img_Col, hv_Img_Rotate_Angle;
            HTuple hv_OffsetRow, hv_OffsetCol;
            HOperatorSet.SetSystem("border_shape_models", "false");

            //STD 中心點
            hv_STD_Row = 839.5;
            hv_STD_Col = 1046.5;

            //目前圖形 中心點
            hv_Img_Row = hv_AllModelRow.Clone();
            hv_Img_Col = hv_AllModelColumn.Clone();

            //目前圖形 Rotate Angle
            hv_Img_Rotate_Angle = hv_AllModelAngle.Clone();

            //目前圖形偏移量
            hv_OffsetRow = hv_Img_Row - hv_STD_Row;
            hv_OffsetCol = hv_Img_Col - hv_STD_Col;

            //第一個 線段 ROI
            //HTuple f_ROI_Row = 341.21875;
            //HTuple f_ROI_Col = 803.078431372549;
            //HTuple f_angle = 1.5707963267949;
            //HTuple f_ROI_Length1 = 77.5390625;
            //HTuple f_ROI_Length2 = 148.705882352941;
            HTuple f_ROI_Row = 357.08984375;
            HTuple f_ROI_Col = 816.555555555556;
            HTuple f_angle = 1.5707963267949;
            HTuple f_ROI_Length1 = 69.8359375;
            HTuple f_ROI_Length2 = 122.277777777778;

            HTuple f_angleOffset = f_angle - hv_Img_Rotate_Angle;
            HTuple f_ROI_Cur_Row, f_ROI_Cur_Col;
            PositionLocater.ReLocater(hv_STD_Row, hv_STD_Col, hv_AllModelAngle, hv_OffsetRow, hv_OffsetCol, f_ROI_Row, f_ROI_Col, out f_ROI_Cur_Row, out f_ROI_Cur_Col);

            //兩線段交點
            HTuple p1_ROI_Row = 715.40234375;
            HTuple p1_ROI_Col = 744.222222222222;
            HTuple p1_angle = 0.764250656215704;
            HTuple p1_ROI_Length1 = 68.0072446324003;
            HTuple p1_ROI_Length2 = 105.756749157524;

            HTuple p1_angleOffset = p1_angle - hv_Img_Rotate_Angle;
            HTuple p1_ROI_Cur_Row, p1_ROI_Cur_Col;
            PositionLocater.ReLocater(hv_STD_Row, hv_STD_Col, hv_AllModelAngle, hv_OffsetRow, hv_OffsetCol
                    , p1_ROI_Row, p1_ROI_Col, out p1_ROI_Cur_Row, out p1_ROI_Cur_Col);

            HTuple p2_ROI_Row = 794.64453125;
            HTuple p2_ROI_Col = 702.888888888889;
            HTuple p2_angle = 0;
            HTuple p2_ROI_Length1 = 100;
            HTuple p2_ROI_Length2 = 50;
            HTuple p2_angleOffset = p2_angle - hv_Img_Rotate_Angle;
            HTuple p2_ROI_Cur_Row, p2_ROI_Cur_Col;
            PositionLocater.ReLocater(hv_STD_Row, hv_STD_Col, hv_AllModelAngle, hv_OffsetRow, hv_OffsetCol
                    , p2_ROI_Row, p2_ROI_Col, out p2_ROI_Cur_Row, out p2_ROI_Cur_Col);

            #region Measure
            var cROIController = new ROIController();
            var cAssistant = new MeasureAssistant(cROIController);

            var hImage = ho_Image as HImage;
            cAssistant.setImage(hImage);

            /*參數值*/
            cAssistant.mThresh = 40.0;
            cAssistant.mSigma = 1.0;
            cAssistant.mRoiWidth = 10;
            cAssistant.mInterpolation = "nearest_neighbor";
            cAssistant.mSelPair = false;
            cAssistant.mTransition = "all";
            cAssistant.mPosition = "all";
            cAssistant.mDispEdgeLength = 30;
            cAssistant.mDispROIWidth = true;
            cAssistant.setUnit("cm");

            cAssistant.mInitThresh = 40.0;
            cAssistant.mInitSigma = 1.0;
            cAssistant.mInitRoiWidth = 10;

            var p1Line = new ROIRectangle2() { ROIMeasureType = MeasureType.Line };
            //roiF.MakeROI(416, 998, 0, 26.5, 71.2);
            p1Line.MakeROI(p1_ROI_Cur_Row, p1_ROI_Cur_Col, p1_angleOffset, p1_ROI_Length1, p1_ROI_Length2);

            var p2Line = new ROIRectangle2() { ROIMeasureType = MeasureType.Line };
            //roiS.MakeROI(400, 1041, 0, 13.3, 75.7);
            p2Line.MakeROI(p2_ROI_Cur_Row, p2_ROI_Cur_Col, p2_angleOffset, p2_ROI_Length1, p2_ROI_Length2);

            var p1F = new MeasurementEdge(p1Line, cAssistant);
            var p2S = new MeasurementEdge(p2Line, cAssistant);
            var angleResult = DistanceHelper.AngleLineToLine(p1F, p2S);

            var roiF = new ROIRectangle2() { ROIMeasureType = MeasureType.Line };
            roiF.MakeROI(f_ROI_Cur_Row, f_ROI_Cur_Col, f_angleOffset, f_ROI_Length1, f_ROI_Length2);
            var lineF = new MeasurementEdge(roiF, cAssistant);

            if (angleResult != null && lineF != null)
            {
                var pointViewModel = new MeasureViewModel()
                {
                    Row1 = angleResult.Row,
                    Col1 = angleResult.Col,
                };
                var lineViewModel = lineF.GetViewModel();
                var distance = DistanceHelper.PointToLine(lineViewModel, pointViewModel);
                mResult = new LineResult()
                {
                    Row1 = lineViewModel.Row2,
                    Col1 = lineViewModel.Col2,
                    Row2 = pointViewModel.Row1,
                    Col2 = pointViewModel.Col1,
                    Distance = distance,
                };
            }

            #endregion

            return mResult;
        }