/// <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. /// Notice 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 static Coordinate[] Reduce(Coordinate[] pts) { Coordinate[] polyPts = ComputeOctRing(pts); // unable to compute interior polygon for some reason if (polyPts == null) { return(pts); } // add points defining polygon Iesi.Collections.Generic.SortedSet <Coordinate> reducedSet = new Iesi.Collections.Generic.SortedSet <Coordinate>(); 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 < pts.Length; i++) { if (!CgAlgorithms.IsPointInRing(pts[i], polyPts)) { reducedSet.Add(pts[i]); } } Coordinate[] arr = new Coordinate[reducedSet.Count]; reducedSet.CopyTo(arr, 0); return(arr); }
/// <summary> /// /// </summary> /// <param name="p"></param> /// <param name="ring"></param> /// <returns></returns> private static LocationType LocateInPolygonRing(Coordinate p, IBasicGeometry ring) { // can this test be folded into IsPointInRing? if (CgAlgorithms.IsOnLine(p, ring.Coordinates)) { return(LocationType.Boundary); } if (CgAlgorithms.IsPointInRing(p, ring.Coordinates)) { return(LocationType.Interior); } return(LocationType.Exterior); }
/// <summary> /// /// </summary> /// <param name="p"></param> /// <param name="poly"></param> /// <returns></returns> public static bool ContainsPointInPolygon(Coordinate p, IPolygon poly) { if (poly.IsEmpty) { return(false); } LinearRing shell = (LinearRing)poly.Shell; 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.NumHoles; i++) { LinearRing hole = (LinearRing)poly.GetInteriorRingN(i); if (CgAlgorithms.IsPointInRing(p, hole.Coordinates)) { return(false); } } return(true); }
/// <summary> /// /// </summary> /// <param name="pt"></param> /// <returns></returns> public virtual bool IsInside(Coordinate pt) { return(CgAlgorithms.IsPointInRing(pt, _pts)); }