/// <summary> /// Adapted from http://msdn.microsoft.com/en-us/library/cc451895.aspx /// </summary> /// <param name="geo"></param> /// <param name="region"></param> /// <returns></returns> public static bool IsInside(this Geo geo, GeoArray region) { if (region == null) throw new ArgumentNullException("region"); if (!region.IsClosed) throw new ArgumentException("Region must be closed", "region"); var points = region.ToArray(); var j = points.Length - 1; var inPoly = false; for (var i = 0; i < points.Length; i++) { if (points[i].Longitude < geo.Longitude && points[j].Longitude >= geo.Longitude || points[j].Longitude < geo.Longitude && points[i].Longitude >= geo.Longitude) if (points[i].Latitude + (geo.Longitude - points[i].Longitude) / (points[j].Longitude - points[i].Longitude) * (points[j].Latitude - points[i].Latitude) < geo.Latitude) inPoly = !inPoly; j = i; } return inPoly; }
public static bool IsInsideOld(this Geo geo, GeoArray region) { if (region == null) throw new ArgumentNullException("region"); if (!region.BoundingBox.Contains(geo)) return false; if (!region.IsClosed) throw new ArgumentException("Region must be closed", "region"); var c = region.Center; // bail out if the point is more than 90 degrees off the centroid if (geo.DistanceRadians(c) >= MoreMath.PiOverTwo) throw new ArgumentException("Point cannot be more than 90 degrees from center of region to test", "geo"); var n = region.Length - 1; var v = region.ToArray(); var wn = 0; // the winding number counter // loop through all edges of the polygon for (var i = 0; i < n; i++) { // edge from V[i] to V[i+1] if (v[i].Latitude <= geo.Latitude) { // start y <= P.y if ((v[i + 1].Latitude > geo.Latitude) && // an upward crossing and (IsLeft(v[i], v[i + 1], geo) > 0)) // P left of edge ++wn; // have a valid up intersect } else { // start y > P.y (no test needed) if ((v[i + 1].Latitude <= geo.Latitude) && // a downward crossing (IsLeft(v[i], v[i + 1], geo) < 0)) // P right of edge --wn; // have a valid down intersect } } return wn != 0; }