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; } double bearingRAD = DistanceUtils.ToRadians(bearingDEG); double x = from.GetX() + Math.Sin(bearingRAD)*distDEG; double y = from.GetY() + Math.Cos(bearingRAD)*distDEG; if (reuse == null) { return ctx.MakePoint(x, y); } else { reuse.Reset(x, y); return reuse; } }
/** * Given a start point (startLat, startLon) and a bearing on a sphere of radius <i>sphereRadius</i>, return the destination point. * * * @param startLat The starting point latitude, in radians * @param startLon The starting point longitude, in radians * @param distanceRAD The distance to travel along the bearing in radians. * @param bearingRAD The bearing, in radians. North is a 0, moving clockwise till radians(360). * @param result A preallocated array to hold the results. If null, a new one is constructed. * @return The destination point, in radians. First entry is latitude, second is longitude */ public static Point PointOnBearingRAD(double startLat, double startLon, double distanceRAD, double bearingRAD, SpatialContext ctx, Point reuse) { /* lat2 = asin(sin(lat1)*cos(d/R) + cos(lat1)*sin(d/R)*cos(θ)) lon2 = lon1 + atan2(sin(θ)*sin(d/R)*cos(lat1), cos(d/R)−sin(lat1)*sin(lat2)) */ double cosAngDist = Math.Cos(distanceRAD); double cosStartLat = Math.Cos(startLat); double sinAngDist = Math.Sin(distanceRAD); double sinStartLat = Math.Sin(startLat); double lat2 = Math.Asin(sinStartLat*cosAngDist + cosStartLat*sinAngDist*Math.Cos(bearingRAD)); double lon2 = startLon + Math.Atan2(Math.Sin(bearingRAD)*sinAngDist*cosStartLat, cosAngDist - sinStartLat*Math.Sin(lat2)); // normalize lon first if (lon2 > DEG_180_AS_RADS) { lon2 = -1.0*(DEG_180_AS_RADS - (lon2 - DEG_180_AS_RADS)); } else if (lon2 < -DEG_180_AS_RADS) { lon2 = (lon2 + DEG_180_AS_RADS) + DEG_180_AS_RADS; } // normalize lat - could flip poles if (lat2 > DEG_90_AS_RADS) { lat2 = DEG_90_AS_RADS - (lat2 - DEG_90_AS_RADS); if (lon2 < 0) { lon2 = lon2 + DEG_180_AS_RADS; } else { lon2 = lon2 - DEG_180_AS_RADS; } } else if (lat2 < -DEG_90_AS_RADS) { lat2 = -DEG_90_AS_RADS - (lat2 + DEG_90_AS_RADS); if (lon2 < 0) { lon2 = lon2 + DEG_180_AS_RADS; } else { lon2 = lon2 - DEG_180_AS_RADS; } } if (reuse == null) { return ctx.MakePoint(lon2, lat2); } else { reuse.Reset(lon2, lat2); //x y return reuse; } }
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; }