예제 #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        private Stack <ICoordinate> GrahamScan(ICoordinate[] c)
        {
            ICoordinate         p;
            Stack <ICoordinate> ps = new Stack <ICoordinate>(c.Length);

            ps.Push(c[0]);
            ps.Push(c[1]);
            ps.Push(c[2]);
            for (int i = 3; i < c.Length; i++)
            {
                p = ps.Pop();
                while (CGAlgorithms.ComputeOrientation(ps.Peek(), p, c[i]) > 0)
                {
                    p = ps.Pop();
                }
                ps.Push(p);
                ps.Push(c[i]);
            }
            ps.Push(c[0]);
            return(ps);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="p"></param>
        /// <param name="poly"></param>
        /// <returns></returns>
        public static bool ContainsPointInPolygon(ICoordinate p, IPolygon poly)
        {
            if (poly.IsEmpty)
            {
                return(false);
            }
            ILinearRing shell = (ILinearRing)poly.ExteriorRing;

            if (!CGAlgorithms.IsPointInRing(p, shell.Coordinates))
            {
                return(false);
            }
            // now test if the point lies in or on the holes
            for (int i = 0; i < poly.NumInteriorRings; i++)
            {
                ILinearRing hole = (ILinearRing)poly.GetInteriorRingN(i);
                if (CGAlgorithms.IsPointInRing(p, hole.Coordinates))
                {
                    return(false);
                }
            }
            return(true);
        }
예제 #3
0
        /// <summary>
        /// Uses a heuristic to reduce the number of points scanned to compute the hull.
        /// The heuristic is to find a polygon guaranteed to
        /// be in (or on) the hull, and eliminate all points inside it.
        /// A quadrilateral defined by the extremal points
        /// in the four orthogonal directions
        /// can be used, but even more inclusive is
        /// to use an octilateral defined by the points in the 8 cardinal directions.
        /// Note that even if the method used to determine the polygon vertices
        /// is not 100% robust, this does not affect the robustness of the convex hull.
        /// </summary>
        /// <param name="pts"></param>
        /// <returns></returns>
        private ICoordinate[] Reduce(ICoordinate[] pts)
        {
            ICoordinate[] polyPts = ComputeOctRing(inputPts);

            // unable to compute interior polygon for some reason
            if (polyPts == null)
            {
                return(inputPts);
            }

            // add points defining polygon
            SortedSet <ICoordinate> reducedSet = new SortedSet <ICoordinate>();

            for (int i = 0; i < polyPts.Length; i++)
            {
                reducedSet.Add(polyPts[i]);
            }

            /*
             * Add all unique points not in the interior poly.
             * CGAlgorithms.IsPointInRing is not defined for points actually on the ring,
             * but this doesn't matter since the points of the interior polygon
             * are forced to be in the reduced set.
             */
            for (int i = 0; i < inputPts.Length; i++)
            {
                if (!CGAlgorithms.IsPointInRing(inputPts[i], polyPts))
                {
                    reducedSet.Add(inputPts[i]);
                }
            }

            ICoordinate[] arr = new ICoordinate[reducedSet.Count];
            reducedSet.CopyTo(arr, 0);
            return(arr);
        }
예제 #4
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="pt"></param>
 /// <returns></returns>
 public bool IsInside(ICoordinate pt)
 {
     return(CGAlgorithms.IsPointInRing(pt, pts));
 }
예제 #5
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <param name="q1"></param>
        /// <param name="q2"></param>
        /// <returns></returns>
        public override int ComputeIntersect(ICoordinate p1, ICoordinate p2, ICoordinate q1, ICoordinate 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(DontIntersect);
            }

            // 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
            int Pq1 = CGAlgorithms.OrientationIndex(p1, p2, q1);
            int Pq2 = CGAlgorithms.OrientationIndex(p1, p2, q2);

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

            int Qp1 = CGAlgorithms.OrientationIndex(q1, q2, p1);
            int Qp2 = CGAlgorithms.OrientationIndex(q1, q2, p2);

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

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

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

            /*
             *  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;
                if (Pq1 == 0)
                {
                    intPt[0] = new Coordinate(q1);
                }
                if (Pq2 == 0)
                {
                    intPt[0] = new Coordinate(q2);
                }
                if (Qp1 == 0)
                {
                    intPt[0] = new Coordinate(p1);
                }
                if (Qp2 == 0)
                {
                    intPt[0] = new Coordinate(p2);
                }
            }
            else
            {
                isProper = true;
                intPt[0] = Intersection(p1, p2, q1, q2);
            }
            return(DoIntersect);
        }