/// <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); }
/// <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); }
/// <summary> /// /// </summary> /// <param name="pt"></param> /// <returns></returns> public bool IsInside(ICoordinate pt) { return(CGAlgorithms.IsPointInRing(pt, pts)); }
/// <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); }