/// <summary> /// Calculates the degrees longitude distance at latitude <paramref name="lat"/> to cover /// a distance <paramref name="dist"/>. /// <para> /// Used to calculate a new expanded buffer distance to account for skewing /// effects for shapes that use the lat-lon space as a 2D plane instead of a /// sphere. The expanded buffer will be sure to cover the intended area, but /// the shape is still skewed and so it will cover a larger area. For latitude /// 0 (the equator) the result is the same buffer. At 60 (or -60) degrees, the /// result is twice the buffer, meaning that a shape at 60 degrees is twice as /// high as it is wide when projected onto a lat-lon plane even if in the real /// world it's equal all around. /// </para> /// If the result added to abs(<paramref name="lat"/>) is >= 90 degrees, then skewing is /// so severe that the caller should consider tossing the shape and /// substituting a spherical cap instead. /// </summary> /// <param name="lat">latitude in degrees</param> /// <param name="dist">distance in degrees</param> /// <returns>longitudinal degrees (x delta) at input latitude that is >= /// <paramref name="dist"/> distance. Will be >= dist and <= 90.</returns> public static double CalcLonDegreesAtLat(double lat, double dist) { //This code was pulled out of DistanceUtils.pointOnBearingRAD() and // optimized // for bearing = 90 degrees, and so we can get an intermediate calculation. double distanceRAD = DistanceUtils.ToRadians(dist); double startLat = DistanceUtils.ToRadians(lat); double cosAngDist = Math.Cos(distanceRAD); double cosStartLat = Math.Cos(startLat); double sinAngDist = Math.Sin(distanceRAD); double sinStartLat = Math.Sin(startLat); double lonDelta = Math.Atan2(sinAngDist * cosStartLat, cosAngDist * (1 - sinStartLat * sinStartLat)); return(DistanceUtils.ToDegrees(lonDelta)); }
private void AssertDistanceConversionImpl(double dist) { double radius = DistanceUtils.EARTH_MEAN_RADIUS_KM; //test back & forth conversion for both double distRAD = DistanceUtils.Dist2Radians(dist, radius); CustomAssert.EqualWithDelta(dist, DistanceUtils.Radians2Dist(distRAD, radius), EPS); double distDEG = DistanceUtils.Dist2Degrees(dist, radius); CustomAssert.EqualWithDelta(dist, DistanceUtils.Degrees2Dist(distDEG, radius), EPS); //test across rad & deg CustomAssert.EqualWithDelta(distDEG, DistanceUtils.ToDegrees(distRAD), EPS); //test point on bearing CustomAssert.EqualWithDelta( DistanceUtils.PointOnBearingRAD(0, 0, DistanceUtils.Dist2Radians(dist, radius), DistanceUtils.DEG_90_AS_RADS, ctx, new Point(0, 0, ctx)).X, distRAD, 10e-5); }
private readonly double radiusDEG = DistanceUtils.ToDegrees(1); //in degrees public override Point PointOnBearing(Point @from, double distDEG, double bearingDEG, SpatialContext ctx, Point reuse) { if (distDEG == 0) { if (reuse == null) { return(from); } reuse.Reset(from.GetX(), from.GetY()); return(reuse); } Point result = DistanceUtils.PointOnBearingRAD( DistanceUtils.ToRadians(from.GetY()), DistanceUtils.ToRadians(from.GetX()), DistanceUtils.ToRadians(distDEG), DistanceUtils.ToRadians(bearingDEG), ctx, reuse);//output result is in radians result.Reset(DistanceUtils.ToDegrees(result.GetX()), DistanceUtils.ToDegrees(result.GetY())); return(result); }
public override double Distance(Point @from, double toX, double toY) { return(DistanceUtils.ToDegrees(DistanceLatLonRAD(DistanceUtils.ToRadians(from.GetY()), DistanceUtils.ToRadians(from.GetX()), DistanceUtils.ToRadians(toY), DistanceUtils.ToRadians(toX)))); }