/** * Computes the great circle distance (in radians) between two points. * Uses the Haversine formula. */ protected static double _computeDistanceInRadiansBetween(LatLng LatLng1, LatLng LatLng2) { double p1RadLat = deg2rad(LatLng1.Lat); double p1RadLng = deg2rad(LatLng1.Lng); double p2RadLat = deg2rad(LatLng2.Lat); double p2RadLng = deg2rad(LatLng2.Lng); return 2 * Math.Asin( Math.Sqrt(Math.Pow(Math.Sin((p1RadLat - p2RadLat) / 2), 2) + Math.Cos(p1RadLat) * Math.Cos(p2RadLat) * Math.Pow(Math.Sin((p1RadLng - p2RadLng) / 2), 2))); }
/** * Computes the spherical excess. * Uses L'Huilier's Theorem. */ protected static double _computeSphericalExcess(LatLng LatLng1, LatLng LatLng2, LatLng LatLng3, bool signed) { LatLng[] latLngsArray = new LatLng[]{LatLng1, LatLng2, LatLng3, LatLng1}; double[] distances = new double[3]; double sumOfDistances = 0; for (int i = 0; i < 3; ++i) { distances[i] = _computeDistanceInRadiansBetween(latLngsArray[i], latLngsArray[i + 1]); sumOfDistances += distances[i]; } double semiPerimeter = sumOfDistances / 2; double tan = Math.Tan(semiPerimeter / 2); for (int i = 0; i < 3; ++i) { tan *= Math.Tan((semiPerimeter - distances[i]) / 2); } double sphericalExcess = 4 * Math.Atan( Math.Sqrt( Math.Abs(tan))); if (!signed) { return sphericalExcess; } // Negative or positive sign? //latLngsArray.RemoveAt(latLngsArray.Length-1); Array.Copy (latLngsArray, latLngsArray, latLngsArray.Length - 1); double[,] v = new double[3,3]; for (int i = 0; i < 3; ++i) { LatLng LatLng = latLngsArray[i]; double lat = deg2rad(LatLng.Lat); double lng = deg2rad(LatLng.Lng); //v[i] = array(); v[i,0] = Math.Cos(lat) * Math.Cos(lng); v[i,1] = Math.Cos(lat) * Math.Sin(lng); v[i,2] = Math.Sin(lat); } double sign = (v[0,0] * v[1,1] * v[2,2] + v[1,0] * v[2,1] * v[0,2] + v[2,0] * v[0,1] * v[1,2] - v[0,0] * v[2,1] * v[1,2] - v[1,0] * v[0,1] * v[2,2] - v[2,0] * v[1,1] * v[0,2]) > 0 ? 1 : -1; return sphericalExcess * sign; }
public static LatLng computeOffset(LatLng fromLatLng, double distance, double heading) { distance /= EARTH_RADIUS; heading = deg2rad(heading); double fromLat = deg2rad(fromLatLng.Lat); double cosDistance = Math.Cos(distance); double sinDistance = Math.Sin(distance); double sinFromLat = Math.Sin(fromLat); double cosFromLat = Math.Cos(fromLat); double sc = cosDistance * sinFromLat + sinDistance * cosFromLat * Math.Cos(heading); double lat = rad2deg(Math.Asin(sc)); double lng = rad2deg(deg2rad(fromLatLng.Lng) + Math.Atan2(sinDistance * cosFromLat * Math.Sin(heading), cosDistance - sinFromLat * sc)); return new LatLng(lat, lng); }
public static LatLng interpolate(LatLng fromLatLng, LatLng toLatLng, double fraction) { double radFromLat = deg2rad(fromLatLng.Lat); double radFromLng = deg2rad(fromLatLng.Lng); double radToLat = deg2rad(toLatLng.Lat); double radToLng = deg2rad(toLatLng.Lng); double cosFromLat = Math.Cos(radFromLat); double cosToLat = Math.Cos(radToLat); double radDist = _computeDistanceInRadiansBetween(fromLatLng, toLatLng); double sinRadDist = Math.Sin(radDist); if (sinRadDist < 1.0E-6) { return new LatLng(fromLatLng.Lat, fromLatLng.Lng); } double a = Math.Sin((1 - fraction) * radDist) / sinRadDist; double b = Math.Sin(fraction * radDist) / sinRadDist; double c = a * cosFromLat * Math.Cos(radFromLng) + b * cosToLat * Math.Cos(radToLng); double d = a * cosFromLat * Math.Sin(radFromLng) + b * cosToLat * Math.Sin(radToLng); double lat = rad2deg(Math.Atan2(a * Math.Sin(radFromLat) + b * Math.Sin(radToLat), Math.Sqrt(Math.Pow(c,2) + Math.Pow(d,2)))); double lng = rad2deg(Math.Atan2(d, c)); return new LatLng(lat, lng); }
public static double computeDistanceBetween(LatLng LatLng1, LatLng LatLng2) { return _computeDistanceInRadiansBetween(LatLng1, LatLng2) * EARTH_RADIUS; }
public static double computeHeading(LatLng fromLatLng, LatLng toLatLng) { double fromLat = deg2rad(fromLatLng.Lat); double toLat = deg2rad(toLatLng.Lat); double lng = deg2rad(toLatLng.Lng) - deg2rad(fromLatLng.Lng); return wrapLongitude(rad2deg(Math.Atan2(Math.Sin(lng) * Math.Cos(toLat), Math.Cos(fromLat) * Math.Sin(toLat) - Math.Sin(fromLat) * Math.Cos(toLat) * Math.Cos(lng)))); }
/** * Computes a bounding rectangle (LatLngBounds instance) from a point and a given radius. * Reference: http://www.movable-type.co.uk/scripts/latlong-db.html * * -------------NE * | | * | radius| * | o------| * | | * | | * SW------------- * * @param object LatLng * @param int|float radius (In meters) */ public static LatLngBounds computeBounds(LatLng latlng, double radius) { double latRadiansDistance = radius / EARTH_RADIUS; double latDegreesDistance = rad2deg(latRadiansDistance); double lngDegreesDistance = rad2deg(latRadiansDistance / Math.Cos(deg2rad(latlng.Lat))); // SW point double swLat = latlng.Lat - latDegreesDistance; double swLng = latlng.Lng - lngDegreesDistance; LatLng sw = new LatLng(swLat, swLng); // NE point double neLat = latlng.Lat + latDegreesDistance; double neLng = latlng.Lng + lngDegreesDistance; LatLng ne = new LatLng(neLat, neLng); return new LatLngBounds(sw, ne); }
public LatLngBounds extend(LatLng LatLng) { this._LatBounds.extend(LatLng.Lat); this._LngBounds.extend(LatLng.Lng); return this; }
public bool contains(LatLng LatLng) { return this._LatBounds.contains(LatLng.Lat) && this._LngBounds.contains(LatLng.Lng); }
/** * LatLngSw South West LatLng object * LatLngNe North East LatLng object */ public LatLngBounds(LatLng LatLngSw = null, LatLng LatLngNe = null) { if (LatLngSw != null) { LatLngNe = (LatLngNe!=null) ? LatLngSw : LatLngNe; double sw = SphericalGeometry.clampLatitude(LatLngSw.Lat); double ne = SphericalGeometry.clampLatitude(LatLngNe.Lat); this._LatBounds = new LatBounds(sw, ne); sw = LatLngSw.Lng; ne = LatLngNe.Lng; if (360 <= ne - sw) { this._LngBounds = new LngBounds(-180, 180); } else { sw = SphericalGeometry.wrapLongitude(sw); ne = SphericalGeometry.wrapLongitude(ne); this._LngBounds = new LngBounds(sw, ne); } } else { this._LatBounds = new LatBounds(1, -1); this._LngBounds = new LngBounds(180, -180); } }
public bool equals(LatLng LatLng) { if (LatLng == null) { return false; } return (Math.Abs(this._lat-LatLng.Lat) + Math.Abs(this._lng-LatLng.Lng)) <= SphericalGeometry.EQUALS_MARGIN_ERROR; }