Example #1
0
        /// <summary>
        /// 取得點到線的量測模型
        /// </summary>
        /// <param name="firstModel"></param>
        /// <param name="secondModel"></param>
        /// <returns></returns>
        public static MeasureViewModel GetPointToLineMeasureModel(IMeasureGeoModel firstModel, IMeasureGeoModel secondModel)
        {
            MeasureViewModel model = null;

            if (isMeasureModelValid(firstModel) && isMeasureModelValid(secondModel))
            {
                var isLineModel = (_lineTypes.Contains(firstModel.GeoType));
                var pointModel  = (isLineModel) ? secondModel : firstModel;
                var lineModel   = (isLineModel) ? firstModel : secondModel;

                //取得投影點
                double projectionRow, projectionCol;
                getProjectionPoint(pointModel, lineModel, out projectionRow, out projectionCol);

                //計算距離
                if (projectionRow > 0 && projectionCol > 0)
                {
                    HTuple distanceMin;
                    HOperatorSet.DistancePp(pointModel.Row1, pointModel.Col1, projectionRow, projectionCol, out distanceMin);
                    model = new MeasureViewModel()
                    {
                        Distance = distanceMin,
                        Row1     = pointModel.Row1,
                        Col1     = pointModel.Col1,
                        Row2     = projectionRow,
                        Col2     = projectionCol,
                    };
                }
            }
            return(model);
        }
Example #2
0
        public static MeasureViewModel Get3PointToCircleModel(IMeasureGeoModel pAModel
                                                              , IMeasureGeoModel pBModel
                                                              , IMeasureGeoModel pCModel)
        {
            MeasureViewModel model = null;
            var modelValid         = isMeasureModelValid(pAModel) && isMeasureModelValid(pBModel) && isMeasureModelValid(pCModel);

            if (modelValid)
            {
                double circleX, circleY;
                caculateCenterOfCircle(pAModel, pBModel, pCModel, out circleX, out circleY);
                if (circleX > -1 && circleY > -1)
                {
                    //radius
                    HTuple radius;
                    HOperatorSet.DistancePp(pAModel.Row1, pAModel.Col1, circleY, circleX, out radius);
                    model = new MeasureViewModel()
                    {
                        Row1     = circleY,
                        Col1     = circleX,
                        Distance = radius,
                    };
                }
            }
            return(model);
        }
Example #3
0
        /// <summary>
        /// 計算兩元素距離
        /// </summary>
        /// <param name="firstModel"></param>
        /// <param name="secondModel"></param>
        /// <returns></returns>
        public static MeasureViewModel CaculateDistance(IMeasureGeoModel firstModel, IMeasureGeoModel secondModel)
        {
            int sum = 0;

            if (_pointTypes.Contains(firstModel.GeoType))
            {
                sum += 1;
            }
            if (_pointTypes.Contains(secondModel.GeoType))
            {
                sum += 1;
            }
            if (_lineTypes.Contains(firstModel.GeoType))
            {
                sum += 2;
            }
            if (_lineTypes.Contains(secondModel.GeoType))
            {
                sum += 2;
            }

            MeasureViewModel newModel = null;
            double           distance = -1;

            switch (sum)
            {
            case 2:
                // Point to Point
                distance = PointToPoint(firstModel, secondModel);
                if (distance > -1)
                {
                    newModel = new MeasureViewModel()
                    {
                        Distance = distance,
                        Row1     = firstModel.Row1,
                        Col1     = firstModel.Col1,
                        Row2     = secondModel.Row1,
                        Col2     = secondModel.Col1,
                    };
                }
                break;

            case 3:
                // Point to Line or line to point
                newModel = GetPointToLineMeasureModel(firstModel, secondModel);
                break;

            case 4:
                // line to line
                newModel = GetTwoLineShortestPointModel(firstModel, secondModel) as MeasureViewModel;
                break;
            }
            return(newModel);
        }
 /// <summary>
 /// 量測結果的 ViewModel
 /// </summary>
 /// <returns></returns>
 public override MeasureViewModel GetViewModel()
 {
     MeasureViewModel model = null;
     if (_Result != null)
     {
         model = new MeasureViewModel()
         {
             Row1 = _Result.Row1,
             Col1 = _Result.Col1,
         };
     }
     return model;
 }
Example #5
0
        /// <summary>
        /// 量測結果的 ViewModel
        /// </summary>
        /// <returns></returns>
        public override MeasureViewModel GetViewModel()
        {
            MeasureViewModel model = null;

            if (_Result != null)
            {
                model = new MeasureViewModel()
                {
                    Row1 = _Result.Row1,
                    Col1 = _Result.Col1,
                };
            }
            return(model);
        }
 /// <summary>
 /// 量測結果的 ViewModel
 /// </summary>
 /// <returns></returns>
 public override MeasureViewModel GetViewModel()
 {
     MeasureViewModel model = null;
     if (_Result != null)
     {
         model = new MeasureViewModel()
         {
             Row1 = _Result.Row1,
             Col1 = _Result.Col1,
             Row2 = _Result.Row2,
             Col2 = _Result.Col2,
             Distance = _Result.Distance,
         };
     }
     return model;
 }
 /// <summary>
 /// 量測結果的 ViewModel
 /// </summary>
 /// <returns></returns>
 public override MeasureViewModel GetViewModel()
 {
     MeasureViewModel model = null;
     if (_Result != null)
     {
         model = new MeasureViewModel()
         {
             Row1 = _Result.Row,
             Col1 = _Result.Col,
             StartPhi = _Result.StartPhi,
             EndPhi = _Result.EndPhi,
             Angle = _Result.Angle,
             Distance = _Result.Distance
         };
     }
     return model;
 }
        public override MeasureViewModel GetViewModel()
        {
            //init value
            MeasureViewModel viewMoel = new MeasureViewModel()
            {
                Row1     = new HTuple(),
                Col1     = new HTuple(),
                Row2     = new HTuple(),
                Col2     = new HTuple(),
                Distance = new HTuple(),
            };

            if (mResult.rowEdge != null && mResult.rowEdge.TupleLength() > 0)
            {
                HXLDCont edgeXLD;
                HTuple   rows, cols;
                if (mROIType == ROI.ROI_TYPE_POINT)
                {
                    edgeXLD = DetermineCrossPoint(mResult.rowEdge.D, mResult.colEdge.D, _crossPointSize, 0.5);
                    edgeXLD.GetContourXld(out rows, out cols);
                    viewMoel = new MeasureViewModel()
                    {
                        Row1    = rows[0],
                        Col1    = cols[0],
                        GeoType = MeasureType.Point,
                    };
                }
                else
                {
                    var phi   = mMeasROI[2].D;
                    var width = mMeasROI[4].D;
                    edgeXLD = DetermineEdgeLine(mResult.rowEdge.D, mResult.colEdge.D, phi, width);
                    edgeXLD.GetContourXld(out rows, out cols);
                    viewMoel = new MeasureViewModel()
                    {
                        Row1     = rows[0],
                        Col1     = cols[0],
                        Row2     = rows.TupleLength() > 1 ? rows[1] : null,
                        Col2     = cols.TupleLength() > 1 ? cols[1] : null,
                        Distance = mResult.distance,
                        GeoType  = MeasureType.Line,
                    };
                }
            }
            return(viewMoel);
        }
 public override MeasureViewModel GetViewModel()
 {
     //init value
     MeasureViewModel viewMoel = new MeasureViewModel()
     {
         Row1 = new HTuple(),
         Col1 = new HTuple(),
         Row2 = new HTuple(),
         Col2 = new HTuple(),
         Distance = new HTuple(),
     };
     if (mResult.rowEdge != null && mResult.rowEdge.TupleLength() > 0)
     {
         HXLDCont edgeXLD;
         HTuple rows, cols;
         if (mROIType == ROI.ROI_TYPE_POINT)
         {
             edgeXLD = DetermineCrossPoint(mResult.rowEdge.D, mResult.colEdge.D, _crossPointSize, 0.5);
             edgeXLD.GetContourXld(out rows, out cols);
             viewMoel = new MeasureViewModel()
             {
                 Row1 = rows[0],
                 Col1 = cols[0],
                 GeoType = MeasureType.Point,
             };
         }
         else
         {
             var phi = mMeasROI[2].D;
             var width = mMeasROI[4].D;
             edgeXLD = DetermineEdgeLine(mResult.rowEdge.D, mResult.colEdge.D, phi, width);
             edgeXLD.GetContourXld(out rows, out cols);
             viewMoel = new MeasureViewModel()
             {
                 Row1 = rows[0],
                 Col1 = cols[0],
                 Row2 = rows.TupleLength() > 1 ? rows[1] : null,
                 Col2 = cols.TupleLength() > 1 ? cols[1] : null,
                 Distance = mResult.distance,
                 GeoType = MeasureType.Line,
             };
         }
     }
     return viewMoel;
 }
        /// <summary>
        /// 量測結果的 ViewModel
        /// </summary>
        /// <returns></returns>
        public override MeasureViewModel GetViewModel()
        {
            MeasureViewModel model = null;

            if (_Result != null)
            {
                model = new MeasureViewModel()
                {
                    Row1     = _Result.Row,
                    Col1     = _Result.Col,
                    StartPhi = _Result.StartPhi,
                    EndPhi   = _Result.EndPhi,
                    Angle    = _Result.Angle,
                    Distance = _Result.Distance
                };
            }
            return(model);
        }
Example #11
0
        /// <summary>
        /// 有中心點及長度,制作幾何線段
        /// </summary>
        /// <param name="centerRow">中心點 row</param>
        /// <param name="centerCol">中心點 col</param>
        /// <param name="phi">角度</param>
        /// <param name="halfDistance">一半的長度</param>
        public static MeasureViewModel MakeLine(HTuple centerRow, HTuple centerCol, HTuple phi, HTuple halfDistance)
        {
            double row1, row2, col1, col2;

            row1 = centerRow - halfDistance * Math.Sin(phi + 0.5 * Math.PI);
            col1 = centerCol + halfDistance * Math.Cos(phi + 0.5 * Math.PI);
            row2 = centerRow - halfDistance * Math.Sin(phi + 1.5 * Math.PI);
            col2 = centerCol + halfDistance * Math.Cos(phi + 1.5 * Math.PI);
            MeasureViewModel result = new MeasureViewModel()
            {
                Row1     = row1,
                Row2     = row2,
                Col1     = col1,
                Col2     = col2,
                Distance = halfDistance * 2
            };

            return(result);
        }
Example #12
0
        /// <summary>
        /// 取得點到線的投影點模型
        /// </summary>
        /// <param name="point"></param>
        /// <param name="line"></param>
        /// <returns>point to Projection point Model ( 2 point, projectionPoint at (col2, row2))</returns>
        private static IMeasureGeoModel getProjectionPlModel(IMeasureGeoModel point, IMeasureGeoModel line)
        {
            HTuple rowProj, colProj, distance;

            HOperatorSet.ProjectionPl(point.Row1, point.Col1, line.Row1, line.Col1, line.Row2, line.Col2
                                      , out rowProj, out colProj);
            HOperatorSet.DistancePp(point.Row1, point.Col1, rowProj, colProj
                                    , out distance);
            MeasureViewModel model = new MeasureViewModel()
            {
                Row1     = new HTuple(point.Row1),
                Col1     = new HTuple(point.Col1),
                Row2     = new HTuple(rowProj),
                Col2     = new HTuple(colProj),
                Distance = new HTuple(distance),
            };

            return(model);
        }
        /// <summary>
        /// 計算兩元素距離
        /// </summary>
        /// <param name="firstModel"></param>
        /// <param name="secondModel"></param>
        /// <returns></returns>
        public static MeasureViewModel CaculateDistance(IMeasureGeoModel firstModel, IMeasureGeoModel secondModel)
        {
            int sum = 0;
            if (_pointTypes.Contains(firstModel.GeoType)) sum += 1;
            if (_pointTypes.Contains(secondModel.GeoType)) sum += 1;
            if (_lineTypes.Contains(firstModel.GeoType)) sum += 2;
            if (_lineTypes.Contains(secondModel.GeoType)) sum += 2;

            MeasureViewModel newModel = null;
            double distance = -1;
            switch (sum)
            {
                case 2:
                    // Point to Point
                    distance = PointToPoint(firstModel, secondModel);
                    if (distance > -1)
                    {
                        newModel = new MeasureViewModel()
                        {
                            Distance = distance,
                            Row1 = firstModel.Row1,
                            Col1 = firstModel.Col1,
                            Row2 = secondModel.Row1,
                            Col2 = secondModel.Col1,
                        };
                    }
                    break;
                case 3:
                    // Point to Line or line to point
                    newModel = GetPointToLineMeasureModel(firstModel, secondModel);
                    break;
                case 4:
                    // line to line
                    newModel = GetTwoLineShortestPointModel(firstModel, secondModel) as MeasureViewModel;
                    break;
            }
            return newModel;
        }
Example #14
0
        /// <summary>
        /// 取得兩線段之間最短的兩點模型
        /// </summary>
        /// <param name="line1"></param>
        /// <param name="line2"></param>
        /// <returns>line model</returns>
        public static IMeasureGeoModel GetTwoLineShortestPointModel(IMeasureGeoModel line1, IMeasureGeoModel line2)
        {
            MeasureViewModel shortestModel = null;

            var modelValid = (isMeasureModelValid(line1) && isMeasureModelValid(line2));

            if (modelValid)
            {
                var modelList = new List <IMeasureGeoModel>();
                //線段 1 的中點
                var line1CP = getMidPoint(line1);

                //線段 1 的中點在線段 2 上的投影模型
                var line1CPModel = getProjectionPlModel(line1CP, line2);
                modelList.Add(line1CPModel);


                //線段 1 起始點在線段 2 上的投影
                var line1StartPoint = new MeasureViewModel()
                {
                    Row1 = line1.Row1, Col1 = line1.Col1
                };
                var line1StartProjModel = getProjectionPlModel(line1StartPoint, line2);
                modelList.Add(line1StartProjModel);


                //線段 1 終點在線段 2 上的投影
                var line1EndPoint = new MeasureViewModel()
                {
                    Row1 = line1.Row2, Col1 = line1.Col2
                };
                var line1EndProjModel = getProjectionPlModel(line1EndPoint, line2);
                modelList.Add(line1EndProjModel);


                //線段 2 的中點
                var line2CP = getMidPoint(line2);

                //線段 2 的中點在線段 1 上的投影
                var line2CPProjModel = getProjectionPlModel(line2CP, line1);
                modelList.Add(line2CPProjModel);

                //線段 2 起始點在線段 1 上的投影
                var line2StartPoint = new MeasureViewModel()
                {
                    Row1 = line2.Row1, Col1 = line2.Col1
                };
                var line2StartProjModel = getProjectionPlModel(line2StartPoint, line1);
                modelList.Add(line2StartProjModel);

                //線段 2 終點在線段 1 上的投影
                var line2EndPoint = new MeasureViewModel()
                {
                    Row1 = line2.Row2, Col1 = line2.Col2
                };
                var line2EndProjModel = getProjectionPlModel(line2EndPoint, line1);
                modelList.Add(line2EndProjModel);

                //線段
                shortestModel = modelList.OrderBy(p => p.Distance.D).Take(1).SingleOrDefault() as MeasureViewModel;
            }
            return(shortestModel);
        }
        public MeasureViewModel GetMidLine()
        {
            #region 輸出結果
            LineResult mResult = null;
            MeasureViewModel midLineModel = 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 = 528.064453125;
            HTuple f_ROI_Col = 802.751633986928;
            HTuple f_angle = 0;
            HTuple f_ROI_Length1 = 38.2679738562091;
            HTuple f_ROI_Length2 = 99.6328125;

            HTuple f_angle_offset = 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);

            //第二個 線段 ROI
            HTuple s_ROI_Row = 523.408203125;
            HTuple s_ROI_Col = 853.542483660131;
            HTuple s_angle = 3.14159265358979;
            HTuple s_ROI_Length1 = 27.4509803921568;
            HTuple s_ROI_Length2 = 105.341796875;

            HTuple s_angle_offset = s_angle - hv_Img_Rotate_Angle;
            HTuple s_ROI_Cur_Row, s_ROI_Cur_Col;
            PositionLocater.ReLocater(hv_STD_Row, hv_STD_Col, hv_AllModelAngle, hv_OffsetRow, hv_OffsetCol
                    , s_ROI_Row, s_ROI_Col, out s_ROI_Cur_Row, out s_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 = "bilinear";
            cAssistant.mSelPair = false;
            cAssistant.mTransition = "all";
            cAssistant.mPosition = "last";
            cAssistant.mDispEdgeLength = 30;
            cAssistant.mDispROIWidth = true;
            cAssistant.setUnit("cm");

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

            var roiF = new ROIRectangle2() { ROIMeasureType = MeasureType.Line };
            //roiF.MakeROI(416, 998, 0, 26.5, 71.2);
            roiF.MakeROI(f_ROI_Cur_Row, f_ROI_Cur_Col, f_angle_offset, f_ROI_Length1, f_ROI_Length2);

            var roiS = new ROIRectangle2() { ROIMeasureType = MeasureType.Line };
            //roiS.MakeROI(400, 1041, 0, 13.3, 75.7);
            roiS.MakeROI(s_ROI_Cur_Row, s_ROI_Cur_Col, s_angle_offset, s_ROI_Length1, s_ROI_Length2);

            var lineF = new MeasurementEdge(roiF, cAssistant);
            var lineS = new MeasurementEdge(roiS, cAssistant);
            mResult = DistanceHelper.CalculateSymmetryLine(lineF.GetViewModel(), lineS.GetViewModel());
            //mResult = DistanceHelper.LineToLine(lineF, lineS, this.hv_AllModelAngle, LineDirection.Horizontal);

            midLineModel = new MeasureViewModel()
            {
                Row1 = mResult.Row1,
                Row2 = mResult.Row2,
                Col1 = mResult.Col1,
                Col2 = mResult.Col2,
                Distance = mResult.Distance,
            };

            //var firstModel = lineF.GetViewModel();
            //var secondModel = lineS.GetViewModel();
            //if (firstModel != null && secondModel != null && firstModel.Distance != null && secondModel.Distance != null
            //	&& firstModel.Distance.TupleLength() > 0 && secondModel.Distance.TupleLength() > 0)
            //{
            //	//作線段
            //	var centerRow = (f_ROI_Cur_Row + s_ROI_Cur_Row) / 2.0;
            //	var centerCol = (f_ROI_Cur_Col + s_ROI_Cur_Col) / 2.0;

            //	midLineModel = DistanceHelper.MakeLine(centerRow, centerCol, hv_AllModelAngle, mResult.Distance / 2.0);
            //}

            return midLineModel;
            #endregion
        }
        /// <summary>
        /// 組成 GeoDataViewModel
        /// <para>把 ROI 轉成GeoDataViewModel</para>
        /// </summary>
        /// <param name="roiIndex">active ROI index</param>
        /// <param name="viewModel">MeasureViewModel</param>
        /// <param name="roi">ROI</param>
        /// <returns></returns>
        private GeoDataGridViewModel transferROIToGeoDataViewModel(MeasureViewModel viewModel, ROI roi, bool isAddNew)
        {
            var number = _DataList.Count + 1;
            var measureName = number.ToString("d2") + " " + roi.ROIMeasureType;
            var exportUnit = roi.ROIMeasureType == MeasureType.Angle ? "Angle" :
                            roi.ROIMeasureType == MeasureType.Point ? "" : _ExportUnit;

            var distance = (viewModel.Distance != null && viewModel.Distance.TupleLength() > 0) ?
                        viewModel.Distance.D : 0.0;

            //圓類型, 距離為半徑 or 直徑
            var isCircleType = (viewModel.GeoType == MeasureType.PointCircle || viewModel.GeoType == MeasureType.Circle);
            distance = (isCircleType) ? distance * _circleDistanceSetting : distance;

            var curCoordinate = _refCoordinate.SingleOrDefault(p => p.ID == _currentCoordinateID);
            var curSkew = _refSkew.SingleOrDefault(p => p.ID == _currentSkewID);
            GeoDataGridViewModel geoModel = new GeoDataGridViewModel()
            {
                Icon = getGeoViewModelIcon(roi),
                Name = measureName,
                ROIID = roi.ID,
                ROIModel = roi.ToROIViewModel(),
                Col1 = (viewModel.Col1 != null && viewModel.Col1.TupleLength() > 0) ?
                        viewModel.Col1.D : -1.0,
                Row1 = (viewModel.Row1 != null && viewModel.Row1.TupleLength() > 0) ?
                        viewModel.Row1.D : -1.0,
                Distance = distance,
                WorldDistance = pixelToRealWorldValue(distance),

                Col2 = (viewModel.Col2 != null && viewModel.Col2.TupleLength() > 0) ?
                        viewModel.Col2.D : -1.0,

                Row2 = (viewModel.Row2 != null && viewModel.Row2.TupleLength() > 0) ?
                        viewModel.Row2.D : -1.0,
                Selected = false,
                Unit = exportUnit,
                GeoType = roi.ROIMeasureType,
            };
            var arcRoi = roi as SmartArc;
            if (arcRoi != null)
            {
                var roiModelData = arcRoi.getModelData();
                geoModel.StartPhi = roiModelData[3];
                geoModel.EndPhi = roiModelData[4];
            }

            if (isAddNew)
            {
                if (curCoordinate != null)
                {
                    geoModel.CoordinateID = curCoordinate.ID;
                    geoModel.CoordinateName = curCoordinate.Name;
                }
            }
            //設定參考座標值
            double refCoordinateCol, refCoordinateRow;
            getRefCoordinate(geoModel, out refCoordinateCol, out refCoordinateRow);
            geoModel.CoordinateCol = refCoordinateCol;
            geoModel.CoordinateRow = refCoordinateRow;

            //計算軸擺正
            if (curSkew != null)
            {
                geoModel.SkewID = curSkew.ID;
                geoModel.SkewName = curSkew.Name;
                geoModel.Skew = getSkew(geoModel.SkewID);
            }
            return geoModel;
        }
        /// <summary>
        /// 有中心點及長度,制作幾何線段
        /// </summary>
        /// <param name="centerRow">中心點 row</param>
        /// <param name="centerCol">中心點 col</param>
        /// <param name="phi">角度</param>
        /// <param name="halfDistance">一半的長度</param>
        public static MeasureViewModel MakeLine(HTuple centerRow, HTuple centerCol, HTuple phi, HTuple halfDistance)
        {
            double row1, row2, col1, col2;

            row1 = centerRow - halfDistance * Math.Sin(phi + 0.5 * Math.PI);
            col1 = centerCol + halfDistance * Math.Cos(phi + 0.5 * Math.PI);
            row2 = centerRow - halfDistance * Math.Sin(phi + 1.5 * Math.PI);
            col2 = centerCol + halfDistance * Math.Cos(phi + 1.5 * Math.PI);
            MeasureViewModel result = new MeasureViewModel()
            {
                Row1 = row1,
                Row2 = row2,
                Col1 = col1,
                Col2 = col2,
                Distance = halfDistance * 2
            };
            return result;
        }
 /// <summary>
 /// 取得點到線的投影點模型
 /// </summary>
 /// <param name="point"></param>
 /// <param name="line"></param>
 /// <returns>point to Projection point Model ( 2 point, projectionPoint at (col2, row2))</returns>
 private static IMeasureGeoModel getProjectionPlModel(IMeasureGeoModel point, IMeasureGeoModel line)
 {
     HTuple rowProj, colProj, distance;
     HOperatorSet.ProjectionPl(point.Row1, point.Col1, line.Row1, line.Col1, line.Row2, line.Col2
                             , out rowProj, out colProj);
     HOperatorSet.DistancePp(point.Row1, point.Col1, rowProj, colProj
                             , out distance);
     MeasureViewModel model = new MeasureViewModel()
     {
         Row1 = new HTuple(point.Row1),
         Col1 = new HTuple(point.Col1),
         Row2 = new HTuple(rowProj),
         Col2 = new HTuple(colProj),
         Distance = new HTuple(distance),
     };
     return model;
 }
        /// <summary>
        /// 取得兩線段之間最短的兩點模型
        /// </summary>
        /// <param name="line1"></param>
        /// <param name="line2"></param>
        /// <returns>line model</returns>
        public static IMeasureGeoModel GetTwoLineShortestPointModel(IMeasureGeoModel line1, IMeasureGeoModel line2)
        {
            MeasureViewModel shortestModel = null;

            var modelValid = (isMeasureModelValid(line1) && isMeasureModelValid(line2));

            if (modelValid)
            {
                var modelList = new List<IMeasureGeoModel>();
                //線段 1 的中點
                var line1CP = getMidPoint(line1);

                //線段 1 的中點在線段 2 上的投影模型
                var line1CPModel = getProjectionPlModel(line1CP, line2);
                modelList.Add(line1CPModel);

                //線段 1 起始點在線段 2 上的投影
                var line1StartPoint = new MeasureViewModel() { Row1 = line1.Row1, Col1 = line1.Col1 };
                var line1StartProjModel = getProjectionPlModel(line1StartPoint, line2);
                modelList.Add(line1StartProjModel);

                //線段 1 終點在線段 2 上的投影
                var line1EndPoint = new MeasureViewModel() { Row1 = line1.Row2, Col1 = line1.Col2 };
                var line1EndProjModel = getProjectionPlModel(line1EndPoint, line2);
                modelList.Add(line1EndProjModel);

                //線段 2 的中點
                var line2CP = getMidPoint(line2);

                //線段 2 的中點在線段 1 上的投影
                var line2CPProjModel = getProjectionPlModel(line2CP, line1);
                modelList.Add(line2CPProjModel);

                //線段 2 起始點在線段 1 上的投影
                var line2StartPoint = new MeasureViewModel() { Row1 = line2.Row1, Col1 = line2.Col1 };
                var line2StartProjModel = getProjectionPlModel(line2StartPoint, line1);
                modelList.Add(line2StartProjModel);

                //線段 2 終點在線段 1 上的投影
                var line2EndPoint = new MeasureViewModel() { Row1 = line2.Row2, Col1 = line2.Col2 };
                var line2EndProjModel = getProjectionPlModel(line2EndPoint, line1);
                modelList.Add(line2EndProjModel);

                //線段
                shortestModel = modelList.OrderBy(p => p.Distance.D).Take(1).SingleOrDefault() as MeasureViewModel;
            }
            return shortestModel;
        }
        /// <summary>
        /// 取得點到線的量測模型
        /// </summary>
        /// <param name="firstModel"></param>
        /// <param name="secondModel"></param>
        /// <returns></returns>
        public static MeasureViewModel GetPointToLineMeasureModel(IMeasureGeoModel firstModel, IMeasureGeoModel secondModel)
        {
            MeasureViewModel model = null;
            if (isMeasureModelValid(firstModel) && isMeasureModelValid(secondModel))
            {
                var isLineModel = (_lineTypes.Contains(firstModel.GeoType));
                var pointModel = (isLineModel) ? secondModel : firstModel;
                var lineModel = (isLineModel) ? firstModel : secondModel;

                //取得投影點
                double projectionRow, projectionCol;
                getProjectionPoint(pointModel, lineModel, out projectionRow, out projectionCol);

                //計算距離
                if (projectionRow > 0 && projectionCol > 0)
                {
                    HTuple distanceMin;
                    HOperatorSet.DistancePp(pointModel.Row1, pointModel.Col1, projectionRow, projectionCol, out distanceMin);
                    model = new MeasureViewModel()
                    {
                        Distance = distanceMin,
                        Row1 = pointModel.Row1,
                        Col1 = pointModel.Col1,
                        Row2 = projectionRow,
                        Col2 = projectionCol,
                    };
                }
            }
            return model;
        }
 public static MeasureViewModel Get3PointToCircleModel(IMeasureGeoModel pAModel
     , IMeasureGeoModel pBModel
     , IMeasureGeoModel pCModel)
 {
     MeasureViewModel model = null;
     var modelValid = isMeasureModelValid(pAModel) && isMeasureModelValid(pBModel) && isMeasureModelValid(pCModel);
     if (modelValid)
     {
         double circleX, circleY;
         caculateCenterOfCircle(pAModel, pBModel, pCModel, out circleX, out circleY);
         if (circleX > -1 && circleY > -1)
         {
             //radius
             HTuple radius;
             HOperatorSet.DistancePp(pAModel.Row1, pAModel.Col1, circleY, circleX, out radius);
             model = new MeasureViewModel()
             {
                 Row1 = circleY,
                 Col1 = circleX,
                 Distance = radius,
             };
         }
     }
     return model;
 }
        /// <summary>
        /// 新增 ViewModel or 更新 ViewModel
        /// </summary>
        /// <param name="model"></param>
        /// <param name="roi"></param>
        public void UpdateViewModel(MeasureViewModel model, ROI roi)
        {
            if (model == null || roi == null) return;

            var roiRecord = GetViewModel(roi.ID);
            var isAddNew = (roiRecord == null);
            GeoDataGridViewModel tmpROIRecord = transferROIToGeoDataViewModel(model, roi, isAddNew);
            var updateTreeNodeID = isAddNew ? tmpROIRecord.RecordID : roiRecord.RecordID;
            if (isAddNew)
            {
                addROIRecord(roi, tmpROIRecord);
            }
            else
            {
                updateROIRecord(roiRecord.RecordID, tmpROIRecord);
            }
            this.Refresh();
            setTreeNodeFocus(updateTreeNodeID);
            notifyRecordChanged(GeoDataGridViewNotifyType.UpdateData, tmpROIRecord);
        }
        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;
        }