Exemplo n.º 1
0
        //	@parm	The point feature that correspond to the search location.
        //			Defined only if a better intersection is actually found.

        /// <summary>
        /// Calculates whether the supplied point is closer to the intersections defined
        /// in this results object.
        /// </summary>
        /// <param name="point">The point to test</param>
        /// <param name="mindsq">The best distance (squared) so far. This should be initially passed in
        /// as a very big value.</param>
        /// <param name="xsect">The intersection. This will be defined only if a better intersection is
        /// actually found.</param>
        /// <returns>True if a <paramref name="point"/> is closer to an intersection (in that case,
        /// <paramref name="mindsq"/> and <paramref name="xsect"/> will have been updated). False
        /// if the point is no closer.</returns>
        /// <remarks>This replaces the old CeArc.GetCloserPoint method</remarks>
        internal bool GetCloserPoint(IPosition point, ref double mindsq, ref IPosition xsect)
        {
            // Scan the set of intersections to find the closest, disallowing
            // any intersections that are coincident with the search location
            // (to within some very small tolerance).
            IPosition xi;

            if (!GetClosest(point, out xi, Constants.XYTOLSQ))
            {
                return(false);
            }

            // Get the distance (squared) to the intersection,
            double dsq = Geom.DistanceSquared(xi, point);

            if (mindsq < dsq)
            {
                return(false);
            }

            // The newly found intersection is the best so far.
            mindsq = dsq;
            xsect  = xi;
            return(true);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Returns the distance (squared) between 2 link points.
        /// </summary>
        /// <param name="other">The other link to get the distance to.</param>
        /// <returns></returns>
        internal double DistanceSquared(PolygonLink other)
        {
            // 22-MAR-00 There may be no point at a corner.

            if (m_Point == null || other.Point == null)
            {
                return(0.0);
            }
            else
            {
                return(Geom.DistanceSquared(m_Point, other.Point));
            }
        }
Exemplo n.º 3
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>
        /// <returns>The closest position (null if the line is further away than the specified
        /// max distance)</returns>
        internal override IPosition GetClosest(IPointGeometry p, ILength tol)
        {
            // Get the distance from the centre of the circle to the search point.
            IPointGeometry center = m_Circle.Center;
            double         dist   = Geom.Distance(center, p);

            // Return if the search point is beyond tolerance.
            double radius = m_Circle.Radius;
            double diff   = Math.Abs(dist - radius);

            if (diff > tol.Meters)
            {
                return(null);
            }

            // If the vertex lies in the curve sector, the closest position
            // is along the bearing from the centre through the search
            // position. Otherwise the closest position is the end of
            // the curve that's closest (given that it's within tolerance).

            if (CircularArcGeometry.IsInSector(this, p, 0.0))
            {
                double bearing = Geom.BearingInRadians(center, p);
                return(Geom.Polar(center, bearing, radius));
            }

            double d1 = Geom.DistanceSquared(p, BC);
            double d2 = Geom.DistanceSquared(p, EC);

            double t = tol.Meters;

            if (Math.Min(d1, d2) < (t * t))
            {
                if (d1 < d2)
                {
                    return(BC);
                }
                else
                {
                    return(EC);
                }
            }

            return(null);
        }
Exemplo n.º 4
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));
        }
Exemplo n.º 5
0
        /// <summary>
        /// Finds the line segment that a position lies on (if any).
        /// </summary>
        /// <param name="data">The data to search</param>
        /// <param name="doFirst">Should the start of the first segment be considered? (default=true)</param>
        /// <param name="startIndex">The array index of the element in <c>data</c> where
        /// the search should start (default=0).</param>
        /// <param name="find">The position to find</param>
        /// <returns>The index of the segment which the search point is coincident with (-1 if not found)</returns>
        static int FindSegment(IPointGeometry[] data, bool doFirst, int startIndex, IPointGeometry find)
        {
            // There have to be at least 2 positions.
            if (data.Length < 2)
            {
                return(-1);
            }

            // Get the position of the vertex to find
            double x = find.X;
            double y = find.Y;

            // Loop through each line segment. The search point must lie somewhere
            // on, or within the window of the segment.

            int    seg;                 // Index to the vertex at the END of a segment
            double xs, ys;              // Start of segment
            double xe, ye;              // End of segment

            // If the first point is to be excluded, and it matches the
            // search position, start on the second line segment instead.
            if (!doFirst && data[startIndex].IsCoincident(find))
            {
                xs  = data[startIndex + 1].X;
                ys  = data[startIndex + 1].Y;
                seg = startIndex + 2;
            }
            else
            {
                xs  = data[startIndex].X;
                ys  = data[startIndex].Y;
                seg = startIndex + 1;
            }

            for (; seg < data.Length; seg++)
            {
                // Get the easting and northing at the end of the segment
                xe = data[seg].X;
                ye = data[seg].Y;

                // If the point to find lies within the window of the segment,
                // determine the perpendicular distance (squared) between the
                // vertex and the line segment. If within tol, return the
                // current segment number.

                if (x >= Math.Min(xs, xe) - Constants.XYTOL &&
                    x <= Math.Max(xs, xe) + Constants.XYTOL &&
                    y >= Math.Min(ys, ye) - Constants.XYTOL &&
                    y <= Math.Max(ys, ye) + Constants.XYTOL)
                {
                    if (Geom.DistanceSquared(x, y, xs, ys, xe, ye) < Constants.XYTOLSQ)
                    {
                        return(seg - 1);
                    }
                }

                // The end of this line segment is the start of the next one.
                xs = xe;
                ys = ye;
            }

            // No match found
            return(-1);
        }
Exemplo n.º 6
0
 /// <summary>
 /// Checks whether a position is coincident with a line segment, using a tolerance that's
 /// consistent with the resolution of data.
 /// </summary>
 /// <param name="testX">The position to test</param>
 /// <param name="testY"></param>
 /// <param name="xs">Start of line segment.</param>
 /// <param name="ys"></param>
 /// <param name="xe">End of line segment.</param>
 /// <param name="ye"></param>
 /// <returns>True if the distance from the test position to the line segment is less
 /// than <c>Constants.XYTOL</c> (3 microns on the ground)</returns>
 // Redundant?
 private static bool IsCoincident(double testX, double testY, double xs, double ys, double xe, double ye)
 {
     return(Geom.DistanceSquared(testX, testY, xs, ys, xe, ye) < Constants.XYTOLSQ);
 }