Пример #1
0
        /// <summary>
        /// Gets the point on this line that is closest to a specified position.
        /// </summary>
        /// <param name="p">The position to search from.</param>
        /// <param name="tol">Maximum distance from line to the search position</param>
        /// <param name="doLast">Specify true to consider the last segment. False to ignore the
        /// last segment.</param>
        /// <returns>The closest position (null if the line is further away than the specified
        /// max distance)</returns>
        IPosition FindClosest(IPointGeometry p, ILength tol, bool doLast)
        {
            IPointGeometry[] data = Data;

            // Initial "best" distance squared cannot be greater than the square of the match tolerance.
            double tm      = tol.Meters;
            double bestdsq = tm * tm;

            // Best segment number so far (valid segment numbers start at 1).
            int best = 0;

            // Pull out the XY of the search vertex
            double vx = p.X;
            double vy = p.Y;

            // Get start of the initial line segment
            double x1 = data[0].X;
            double y1 = data[0].Y;

            // Only do the last segment when required.
            int nv = data.Length;

            if (!doLast)
            {
                nv--;
            }

            for (int i = 1; i < nv; i++)
            {
                // Pick up the end of the segment & get the window of
                // the segment, expanded by the match tolerance.
                double x2 = data[i].X;
                double y2 = data[i].Y;

                double xmin = Math.Min(x1, x2) - tm;
                double ymin = Math.Min(y1, y2) - tm;
                double xmax = Math.Max(x1, x2) + tm;
                double ymax = Math.Max(y1, y2) + tm;

                // If the search vertex falls within the expanded window,
                // and the distance (squared) to the perpendicular point
                // is better than what we already got, remember the index
                // number of this segment.

                if (vx > xmin && vx < xmax && vy > ymin && vy < ymax)
                {
                    double dsq = Geom.DistanceSquared(vx, vy, x1, y1, x2, y2);
                    if (dsq < bestdsq)
                    {
                        bestdsq = dsq;
                        best    = i;
                    }
                }

                // End of segment is start of next one
                x1 = x2;
                y1 = y2;
            }

            // Return if we did not locate a suitable point
            if (best == 0)
            {
                return(null);
            }

            // Get the position of the perpendicular point.
            double         xp, yp;
            IPointGeometry s = data[best - 1];
            IPointGeometry e = data[best];

            Geom.GetPerpendicular(vx, vy, s.X, s.Y, e.X, e.Y, out xp, out yp);
            return(new Position(xp, yp));
        }