public static void CalculateTargetCurrentPos(LineModel targetLine, TextBox targetPosition1Text, TextBox observeDate1Text, TextBox targetPosition2Text, TextBox observeDate2Text, TextBox targetObserveSpeedText, ref TextBox targetEstimatedPosText)
        {
            if (targetLine == null || string.IsNullOrEmpty(targetPosition1Text.Text) || string.IsNullOrEmpty(observeDate1Text.Text) || string.IsNullOrEmpty(targetPosition2Text.Text) || string.IsNullOrEmpty(observeDate2Text.Text) || string.IsNullOrEmpty(targetObserveSpeedText.Text))
            {
                return;
            }

            PointModel pos1 = PointModel.Parse(targetPosition1Text.Text);
            PointModel pos2 = PointModel.Parse(targetPosition2Text.Text);

            if (pos1 == null || pos2 == null)
            {
                return;
            }

            DateTime pos1Date, pos2Date;

            try
            {
                pos1Date = DateTime.ParseExact(observeDate1Text.Text, "yyyy-MM-dd HH:mm:ss", null);
                pos2Date = DateTime.ParseExact(observeDate2Text.Text, "yyyy-MM-dd HH:mm:ss", null);
            }
            catch
            {
                return;
            }

            DateTime   latestPosDate;
            PointModel latestPos;

            if (pos1Date > pos2Date)
            {
                latestPosDate = pos1Date;
                latestPos     = pos1;
            }
            else
            {
                latestPosDate = pos2Date;
                latestPos     = pos2;
            }
            var time = (DateTime.Now - latestPosDate).TotalSeconds;


            double speedByKnot;

            try
            {
                speedByKnot = Convert.ToDouble(targetObserveSpeedText.Text);
            }
            catch
            {
                return;
            }

            var speedByMeter    = speedByKnot / 1.94;
            var passingDistance = time * speedByMeter;
            var currentPos      = CoordinateSystemOperation.CalculatePointByLineAndLength(targetLine, latestPos, passingDistance, targetLine.lineDirection);

            targetEstimatedPosText.Text = currentPos.ToString();
        }
        public static void CalculateTargetLine(TextBox targetPos1Text, TextBox observeDate1Text, TextBox targetPos2Text, TextBox observeDate2Text, TextBox targetPos3Text, ref TextBox targetLineText, ref LineModel targetLine, ref TextBox targetHeadingText)
        {
            var pos1 = PointModel.Parse(targetPos1Text.Text);
            var pos2 = PointModel.Parse(targetPos2Text.Text);
            var pos3 = PointModel.Parse(targetPos3Text.Text);

            if (pos1 == null || pos2 == null)
            {
                return;
            }

            DateTime pos1Date, pos2Date;

            try
            {
                pos1Date = DateTime.ParseExact(observeDate1Text.Text, "yyyy-MM-dd HH:mm:ss", null);
                pos2Date = DateTime.ParseExact(observeDate2Text.Text, "yyyy-MM-dd HH:mm:ss", null);
            }
            catch
            {
                MessageBox.Show("invalid date time:" + observeDate1Text.Text + ", " + observeDate2Text.Text);
                return;
            }

            PointModel earlyPoint, laterPoint;

            if (pos1Date < pos2Date)
            {
                earlyPoint = pos1;
                laterPoint = pos2;
            }
            else
            {
                earlyPoint = pos2;
                laterPoint = pos1;
            }

            var line = CoordinateSystemOperation.CalculateLineFromTwoPoint(earlyPoint, laterPoint);

            targetLine          = line;
            targetLineText.Text = line.ToString();

            var targetHeading = CoordinateSystemOperation.CalculateDirectionFromLine(line);

            targetHeadingText.Text = targetHeading.ToString();
        }
        public static void CalculateCorrectionPointDistance(LineModel targetLine, TextBox targetPosition3Text, ref TextBox correctionPointDistanceText)
        {
            if (targetLine == null || string.IsNullOrEmpty(targetPosition3Text.Text))
            {
                return;
            }

            var pos3 = PointModel.Parse(targetPosition3Text.Text);

            if (pos3 == null)
            {
                return;
            }

            var correctionDistance = CoordinateSystemOperation.CalculateLengthBetweenPointAndLine(pos3, targetLine);

            correctionPointDistanceText.Text = Math.Round(correctionDistance, 2).ToString();
        }
        public static void CalculateDirectionLine(TextBox subHeadingText, TextBox directionText, TextBox observePos1PositionText, ref LineModel directionLine, ref TextBox directionLineText, bool isObservePos1DirectionLine = true)
        {
            if (string.IsNullOrEmpty(directionText.Text) || string.IsNullOrEmpty(subHeadingText.Text))
            {
                return;
            }

            double direction, subHeading;

            try
            {
                direction  = Convert.ToDouble(directionText.Text);
                subHeading = Convert.ToDouble(subHeadingText.Text);
            }
            catch
            {
                MessageBox.Show("invalid number: " + directionText.Text + ", " + subHeadingText.Text);
                return;
            }

            direction = DirectionOperation.CalculateSubActualDirection(subHeading, direction);

            PointModel observePos = new PointModel(0, 0);

            if (isObservePos1DirectionLine && !string.IsNullOrEmpty(observePos1PositionText.Text))
            {
                observePos = PointModel.Parse(observePos1PositionText.Text);

                if (observePos == null)
                {
                    return;
                }
            }

            directionLine          = CoordinateSystemOperation.CalculateLineFromPointAndDirection(observePos, direction);
            directionLineText.Text = directionLine.ToString();
        }
        public static void CalculateEstimatedDirectionLine(LineModel directionLine1, LineModel directionLine2, LineModel directionLine3, LineModel randomTargetLine, TextBox observePos1Text, TextBox observePos1TimeDiffText, TextBox observePos2TimeDiffText, ref LineModel estimatedDirectionLine, ref TextBox estimatedDirectionLineText, ref TextBox targetHeadingText)
        {
            if (directionLine1 == null || directionLine2 == null || directionLine3 == null || randomTargetLine == null)
            {
                return;
            }

            double pos2LengthRatio = 1;

            if (!string.IsNullOrEmpty(observePos1TimeDiffText.Text) && !string.IsNullOrEmpty(observePos2TimeDiffText.Text))
            {
                try
                {
                    double pos1TimeDiff = Convert.ToDouble(observePos1TimeDiffText.Text);
                    double pos2TimeDiff = Convert.ToDouble(observePos2TimeDiffText.Text);
                    pos2LengthRatio = pos2TimeDiff / pos1TimeDiff;
                }
                catch
                {  }
            }

            var intercept1 = CoordinateSystemOperation.CalculatePointByTwoLines(directionLine1, randomTargetLine);
            var intercept2 = CoordinateSystemOperation.CalculatePointByTwoLines(directionLine2, randomTargetLine);
            var intercept3 = CoordinateSystemOperation.CalculatePointByTwoLines(directionLine3, randomTargetLine);

            var length1 = CoordinateSystemOperation.CalculateLengthBetweenPoints(intercept1, intercept2);
            var length2 = CoordinateSystemOperation.CalculateLengthBetweenPoints(intercept2, intercept3);
            var length  = (length1 + length2) / 2;

            length = length * pos2LengthRatio;

            LineDirection direction;

            if (intercept2.x > intercept1.x)
            {
                direction = LineDirection.LEFT_TO_RIGHT;
            }
            else
            {
                direction = LineDirection.RIGHT_TO_LEFT;
            }

            PointModel observePos = new PointModel(0, 0);

            if (!string.IsNullOrEmpty(observePos1Text.Text))
            {
                observePos = PointModel.Parse(observePos1Text.Text);
                if (observePos == null)
                {
                    return;
                }
            }

            var estimatedPoint = CoordinateSystemOperation.CalculatePointByLineAndLength(randomTargetLine, intercept3, length, direction);

            estimatedDirectionLine          = CoordinateSystemOperation.CalculateLineFromTwoPoint(observePos, estimatedPoint);
            estimatedDirectionLineText.Text = estimatedDirectionLine.ToString();

            var headingLine = CoordinateSystemOperation.CalculateLineFromTwoPoint(intercept1, intercept2);
            var heading     = CoordinateSystemOperation.CalculateDirectionFromLine(headingLine);

            targetHeadingText.Text = Math.Round(heading, 2).ToString();
        }
        private void PaintNauticalChart()
        {
            Graphics graphic = this.CreateGraphics();

            graphic.Clear(Color.LightGray);

            PaintCoordinateSystem(ref graphic);

            #region direction distance aiming form
            if (!string.IsNullOrEmpty(directionDistanceAimingForm.subHeadingText.Text))
            {
                try
                {
                    var heading = Convert.ToDouble(directionDistanceAimingForm.subHeadingText.Text);
                    PaintEntity(ref graphic, ChartEntityType.SUB, 0, 0, heading);
                }
                catch
                { }
            }

            if (!string.IsNullOrEmpty(directionDistanceAimingForm.targetPosition1Text.Text))
            {
                PointModel point = PointModel.Parse(directionDistanceAimingForm.targetPosition1Text.Text);
                if (point != null)
                {
                    PaintPosition(ref graphic, point);
                }
            }

            if (!string.IsNullOrEmpty(directionDistanceAimingForm.targetPosition2Text.Text))
            {
                PointModel point = PointModel.Parse(directionDistanceAimingForm.targetPosition2Text.Text);
                if (point != null)
                {
                    PaintPosition(ref graphic, point);
                }
            }

            if (!string.IsNullOrEmpty(directionDistanceAimingForm.targetPosition3Text.Text))
            {
                PointModel point = PointModel.Parse(directionDistanceAimingForm.targetPosition3Text.Text);
                if (point != null)
                {
                    PaintPosition(ref graphic, point);
                }
            }

            if (directionDistanceAimingForm.targetLine != null)
            {
                PaintTargetLine(ref graphic, directionDistanceAimingForm.targetLine, ChartEntityType.TARGET);
            }

            if (!string.IsNullOrEmpty(directionDistanceAimingForm.targetEstimatedPositionText.Text) && !string.IsNullOrEmpty(directionDistanceAimingForm.targetHeadingText.Text))
            {
                var targetPos = PointModel.Parse(directionDistanceAimingForm.targetEstimatedPositionText.Text);
                if (targetPos != null)
                {
                    try
                    {
                        var targetHeading = Convert.ToDouble(directionDistanceAimingForm.targetHeadingText.Text);
                        PaintEntity(ref graphic, ChartEntityType.TARGET, targetPos, targetHeading);
                    }
                    catch
                    { }
                }
            }

            if (directionDistanceAimingForm.targetLine != null && !string.IsNullOrEmpty(directionDistanceAimingForm.subHeadingText.Text) && !string.IsNullOrEmpty(directionDistanceAimingForm.attackDirectionText.Text))
            {
                try
                {
                    var subHeading  = Convert.ToDouble(directionDistanceAimingForm.subHeadingText.Text);
                    var attackAngle = Convert.ToDouble(directionDistanceAimingForm.attackDirectionText.Text);
                    PaintAttackLine(ref graphic, directionDistanceAimingForm.targetLine, subHeading, attackAngle);
                }
                catch
                { }
            }
            #endregion

            #region direction aiming form
            if (!string.IsNullOrEmpty(directionAimingForm.subPos1HeadingText.Text))
            {
                try
                {
                    double heading = Convert.ToDouble(directionAimingForm.subPos1HeadingText.Text);
                    PaintEntity(ref graphic, ChartEntityType.SUB, new PointModel(0, 0), heading);
                }
                catch
                {  }
            }

            if (directionAimingForm.directionLine1 != null)
            {
                Pen pen = new Pen(Color.Black, 2);
                DrawLineByLine(ref graphic, pen, directionAimingForm.directionLine1);
                pen.Dispose();
            }

            if (directionAimingForm.directionLine2 != null)
            {
                Pen pen = new Pen(Color.Black, 2);
                DrawLineByLine(ref graphic, pen, directionAimingForm.directionLine2);
                pen.Dispose();
            }

            if (directionAimingForm.directionLine3 != null)
            {
                Pen pen = new Pen(Color.Black, 2);
                DrawLineByLine(ref graphic, pen, directionAimingForm.directionLine3);
                pen.Dispose();
            }

            if (directionAimingForm.directionLine4 != null)
            {
                Pen pen = new Pen(Color.Black, 2);
                DrawLineByLine(ref graphic, pen, directionAimingForm.directionLine4);
                pen.Dispose();
            }

            if (directionAimingForm.targetRandomLine != null)
            {
                Pen pen = new Pen(Color.Blue, 2);
                DrawLineByLine(ref graphic, pen, directionAimingForm.targetRandomLine);
                pen.Dispose();
            }

            if (directionAimingForm.estimatedDirectionLine != null)
            {
                try
                {
                    Pen pen = new Pen(Color.Blue, 2);
                    DrawLineByLine(ref graphic, pen, directionAimingForm.estimatedDirectionLine);
                    pen.Dispose();
                }
                catch
                { }
            }

            if (directionAimingForm.targetActualLine != null)
            {
                try
                {
                    Pen pen = new Pen(Color.Black, 2);
                    DrawLineByLine(ref graphic, pen, directionAimingForm.targetActualLine);
                    pen.Dispose();
                }
                catch
                {  }
            }

            if (!string.IsNullOrEmpty(directionAimingForm.observePoint1PositionText.Text))
            {
                var observePoint1 = PointModel.Parse(directionAimingForm.observePoint1PositionText.Text);
                if (observePoint1 != null)
                {
                    PaintPosition(ref graphic, observePoint1);
                }
            }

            if (directionAimingForm.targetConfirmedPos != null)
            {
                PaintPosition(ref graphic, directionAimingForm.targetConfirmedPos);
            }

            if (!string.IsNullOrEmpty(directionAimingForm.targetEstimatedPosText.Text) && !string.IsNullOrEmpty(directionAimingForm.targetHeadingText.Text))
            {
                var targetPos = PointModel.Parse(directionAimingForm.targetEstimatedPosText.Text);
                if (targetPos != null)
                {
                    try
                    {
                        var targetHeading = Convert.ToDouble(directionAimingForm.targetHeadingText.Text);
                        PaintEntity(ref graphic, ChartEntityType.TARGET, targetPos, targetHeading);
                    }
                    catch
                    { }
                }
            }

            if (directionAimingForm.targetActualLine != null && !string.IsNullOrEmpty(directionAimingForm.subPos1HeadingText.Text) && !string.IsNullOrEmpty(directionAimingForm.attackDirectionText.Text))
            {
                try
                {
                    var subHeading  = Convert.ToDouble(directionAimingForm.subPos1HeadingText.Text);
                    var attackAngle = Convert.ToDouble(directionAimingForm.attackDirectionText.Text);
                    PaintAttackLine(ref graphic, directionAimingForm.targetActualLine, subHeading, attackAngle);
                }
                catch
                { }
            }
            #endregion


            #region test paints

            #endregion

            graphic.Dispose();
        }