Example #1
0
            /// <summary>
            ///
            /// </summary>
            /// <param name="o"></param>
            /// <param name="p"></param>
            /// <param name="q"></param>
            /// <returns></returns>
            private static int PolarCompare(Coordinate o, Coordinate p, Coordinate q)
            {
                double dxp = p.X - o.X;
                double dyp = p.Y - o.Y;
                double dxq = q.X - o.X;
                double dyq = q.Y - o.Y;

                var orient = Orientation.Index(o, p, q);

                if (orient == OrientationIndex.CounterClockwise)
                {
                    return(1);
                }
                if (orient == OrientationIndex.Clockwise)
                {
                    return(-1);
                }

                // points are collinear - check distance
                double op = dxp * dxp + dyp * dyp;
                double oq = dxq * dxq + dyq * dyq;

                if (op < oq)
                {
                    return(-1);
                }
                if (op > oq)
                {
                    return(1);
                }
                return(0);
            }
Example #2
0
        /*
         * /// <summary>
         * ///
         * /// </summary>
         * /// <param name="ps"></param>
         * /// <returns></returns>
         * private Stack<Coordinate> ReverseStack(Stack<Coordinate> ps)
         * {
         *  // Do a manual reverse of the stack
         *  int size = ps.Count;
         *  var tempArray = new Coordinate[size];
         *  for (int i = 0; i < size; i++)
         *      tempArray[i] = ps.Pop();
         *  var returnStack = new Stack<Coordinate>(size);
         *  foreach (Coordinate obj in tempArray)
         *      returnStack.Push(obj);
         *  return returnStack;
         * }
         */

        /// <summary>
        ///
        /// </summary>
        /// <param name="c1"></param>
        /// <param name="c2"></param>
        /// <param name="c3"></param>
        /// <returns>
        /// Whether the three coordinates are collinear
        /// and c2 lies between c1 and c3 inclusive.
        /// </returns>
        private static bool IsBetween(Coordinate c1, Coordinate c2, Coordinate c3)
        {
            if (Orientation.Index(c1, c2, c3) != 0)
            {
                return(false);
            }
            if (c1.X != c3.X)
            {
                if (c1.X <= c2.X && c2.X <= c3.X)
                {
                    return(true);
                }
                if (c3.X <= c2.X && c2.X <= c1.X)
                {
                    return(true);
                }
            }
            if (c1.Y != c3.Y)
            {
                if (c1.Y <= c2.Y && c2.Y <= c3.Y)
                {
                    return(true);
                }
                if (c3.Y <= c2.Y && c2.Y <= c1.Y)
                {
                    return(true);
                }
            }
            return(false);
        }
 /// <summary>
 ///
 /// </summary>
 /// <param name="p"></param>
 /// <param name="p1"></param>
 /// <param name="p2"></param>
 public override void ComputeIntersection(Coordinate p, Coordinate p1, Coordinate p2)
 {
     IsProper = false;
     // do between check first, since it is faster than the orientation test
     if (Envelope.Intersects(p1, p2, p))
     {
         if ((Orientation.Index(p1, p2, p) == OrientationIndex.Collinear) &&
             (Orientation.Index(p2, p1, p) == OrientationIndex.Collinear))
         {
             IsProper = true;
             if (p.Equals(p1) || p.Equals(p2))
             {
                 IsProper = false;
             }
             Result = PointIntersection;
             return;
         }
     }
     Result = NoIntersection;
 }
Example #4
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        private static Stack <Coordinate> GrahamScan(Coordinate[] c)
        {
            var ps = new Stack <Coordinate>(c.Length);

            ps.Push(c[0]);
            ps.Push(c[1]);
            ps.Push(c[2]);
            for (int i = 3; i < c.Length; i++)
            {
                var p = ps.Pop();

                // check for empty stack to guard against robustness problems
                while (
                    ps.Count > 0 /*(IsEmpty Hack)*/ &&
                    Orientation.Index(ps.Peek(), p, c[i]) > 0)
                {
                    p = ps.Pop();
                }
                ps.Push(p);
                ps.Push(c[i]);
            }
            ps.Push(c[0]);
            return(ps);
        }
        public override int ComputeIntersect(Coordinate p1, Coordinate p2, Coordinate q1, Coordinate q2)
        {
            IsProper = false;

            // first try a fast test to see if the envelopes of the lines intersect
            if (!Envelope.Intersects(p1, p2, q1, q2))
            {
                return(NoIntersection);
            }

            // for each endpoint, compute which side of the other segment it lies
            // if both endpoints lie on the same side of the other segment,
            // the segments do not intersect
            var Pq1 = Orientation.Index(p1, p2, q1);
            var Pq2 = Orientation.Index(p1, p2, q2);

            if ((Pq1 > 0 && Pq2 > 0) ||
                (Pq1 < 0 && Pq2 < 0))
            {
                return(NoIntersection);
            }

            var Qp1 = Orientation.Index(q1, q2, p1);
            var Qp2 = Orientation.Index(q1, q2, p2);

            if ((Qp1 > 0 && Qp2 > 0) ||
                (Qp1 < 0 && Qp2 < 0))
            {
                return(NoIntersection);
            }

            bool collinear = Pq1 == 0 && Pq2 == 0 && Qp1 == 0 && Qp2 == 0;

            if (collinear)
            {
                return(ComputeCollinearIntersection(p1, p2, q1, q2));
            }

            /*
             * At this point we know that there is a single intersection point
             * (since the lines are not collinear).
             */

            /*
             *  Check if the intersection is an endpoint. If it is, copy the endpoint as
             *  the intersection point. Copying the point rather than computing it
             *  ensures the point has the exact value, which is important for
             *  robustness. It is sufficient to simply check for an endpoint which is on
             *  the other line, since at this point we know that the inputLines must
             *  intersect.
             */
            if (Pq1 == 0 || Pq2 == 0 || Qp1 == 0 || Qp2 == 0)
            {
                IsProper = false;

                /*
                 * Check for two equal endpoints.
                 * This is done explicitly rather than by the orientation tests
                 * below in order to improve robustness.
                 *
                 * [An example where the orientation tests fail to be consistent is
                 * the following (where the true intersection is at the shared endpoint
                 * POINT (19.850257749638203 46.29709338043669)
                 *
                 * LINESTRING ( 19.850257749638203 46.29709338043669, 20.31970698357233 46.76654261437082 )
                 * and
                 * LINESTRING ( -48.51001596420236 -22.063180333403878, 19.850257749638203 46.29709338043669 )
                 *
                 * which used to produce the INCORRECT result: (20.31970698357233, 46.76654261437082, NaN)
                 *
                 */
                if (p1.Equals2D(q1) || p1.Equals2D(q2))
                {
                    IntersectionPoint[0] = p1;
                }
                else if (p2.Equals2D(q1) || p2.Equals2D(q2))
                {
                    IntersectionPoint[0] = p2;
                }
                else if (Pq1 == 0)
                {
                    IntersectionPoint[0] = q1.Copy();
                }
                else if (Pq2 == 0)
                {
                    IntersectionPoint[0] = q2.Copy();
                }
                else if (Qp1 == 0)
                {
                    IntersectionPoint[0] = p1.Copy();
                }
                else if (Qp2 == 0)
                {
                    IntersectionPoint[0] = p2.Copy();
                }
            }
            else
            {
                IsProper             = true;
                IntersectionPoint[0] = Intersection(p1, p2, q1, q2);
            }
            return(PointIntersection);
        }
        /// <summary>
        /// Counts a segment
        /// </summary>
        /// <param name="p1">An endpoint of the segment</param>
        /// <param name="p2">Another endpoint of the segment</param>
        public void CountSegment(Coordinate p1, Coordinate p2)
        {
            /*
             * For each segment, check if it crosses
             * a horizontal ray running from the test point in the positive x direction.
             */

            // check if the segment is strictly to the left of the test point
            if (p1.X < _p.X && p2.X < _p.X)
            {
                return;
            }

            // check if the point is equal to the current ring vertex
            if (_p.X == p2.X && _p.Y == p2.Y)
            {
                _isPointOnSegment = true;
                return;
            }

            /*
             * For horizontal segments, check if the point is on the segment.
             * Otherwise, horizontal segments are not counted.
             */
            if (p1.Y == _p.Y && p2.Y == _p.Y)
            {
                double minx = p1.X;
                double maxx = p2.X;
                if (minx > maxx)
                {
                    minx = p2.X;
                    maxx = p1.X;
                }
                if (_p.X >= minx && _p.X <= maxx)
                {
                    _isPointOnSegment = true;
                }
                return;
            }

            /*
             * Evaluate all non-horizontal segments which cross a horizontal ray to the
             * right of the test pt. To avoid double-counting shared vertices, we use the
             * convention that
             * <ul>
             * <li>an upward edge includes its starting endpoint, and excludes its
             * final endpoint
             * <li>a downward edge excludes its starting endpoint, and includes its
             * final endpoint
             * </ul>
             */
            if (((p1.Y > _p.Y) && (p2.Y <= _p.Y)) ||
                ((p2.Y > _p.Y) && (p1.Y <= _p.Y)))
            {
                var orient = Orientation.Index(p1, p2, _p);
                if (orient == OrientationIndex.Collinear)
                {
                    _isPointOnSegment = true;
                    return;
                }
                // Re-orient the result if needed to ensure effective segment direction is upwards
                if (p2.Y < p1.Y)
                {
                    orient = Orientation.ReOrient(orient);
                }
                // The upward segment crosses the ray if the test point lies to the left (CCW) of the segment.
                if (orient == OrientationIndex.Left)
                {
                    _crossingCount++;
                }
            }
        }