/// <summary>
        /// Finds the nearest point on the specified polyline.
        /// </summary>
        /// <param name="point">The point.</param>
        /// <param name="points">The points.</param>
        /// <returns>The nearest point.</returns>
        public static ScreenPoint FindNearestPointOnPolyline(ScreenPoint point, IList <ScreenPoint> points)
        {
            double minimumDistance = double.MaxValue;
            var    nearestPoint    = default(ScreenPoint);

            for (int i = 0; i + 1 < points.Count; i++)
            {
                var p1 = points[i];
                var p2 = points[i + 1];
                if (ScreenPoint.IsUndefined(p1) || ScreenPoint.IsUndefined(p2))
                {
                    continue;
                }

                // Find the nearest point on the line segment.
                var nearestPointOnSegment = FindPointOnLine(point, p1, p2);

                if (ScreenPoint.IsUndefined(nearestPointOnSegment))
                {
                    continue;
                }

                double l2 = (point - nearestPointOnSegment).LengthSquared;

                if (l2 < minimumDistance)
                {
                    nearestPoint    = nearestPointOnSegment;
                    minimumDistance = l2;
                }
            }

            return(nearestPoint);
        }
        /// <summary>
        /// Gets the point on the curve that is nearest the specified point.
        /// </summary>
        /// <param name="points">
        /// The point list.
        /// </param>
        /// <param name="point">
        /// The point.
        /// </param>
        /// <returns>
        /// A tracker hit result if a point was found.
        /// </returns>
        protected TrackerHitResult GetNearestInterpolatedPointInternal(IList <IDataPoint> points, ScreenPoint point)
        {
            if (points == null)
            {
                return(null);
            }

            var    spn   = default(ScreenPoint);
            var    dpn   = default(DataPoint);
            double index = -1;

            double minimumDistance = double.MaxValue;

            for (int i = 0; i + 1 < points.Count; i++)
            {
                var p1 = points[i];
                var p2 = points[i + 1];
                if (!this.IsValidPoint(p1, this.XAxis, this.YAxis) || !this.IsValidPoint(p2, this.XAxis, this.YAxis))
                {
                    continue;
                }

                var sp1 = this.Transform(p1);
                var sp2 = this.Transform(p2);

                // Find the nearest point on the line segment.
                var spl = ScreenPointHelper.FindPointOnLine(point, sp1, sp2);

                if (ScreenPoint.IsUndefined(spl))
                {
                    // P1 && P2 coincident
                    continue;
                }

                double l2 = (point - spl).LengthSquared;

                if (l2 < minimumDistance)
                {
                    double u = (spl - sp1).Length / (sp2 - sp1).Length;
                    dpn             = new DataPoint(p1.X + (u * (p2.X - p1.X)), p1.Y + (u * (p2.Y - p1.Y)));
                    spn             = spl;
                    minimumDistance = l2;
                    index           = i + u;
                }
            }

            if (minimumDistance < double.MaxValue)
            {
                object item = this.GetItem((int)index);
                return(new TrackerHitResult(this, dpn, spn, item)
                {
                    Index = index
                });
            }

            return(null);
        }