Location { public Location rhumbLocation(double azimuthDegrees, double distanceRadians, Location result) { if (result == null) { throw new IllegalArgumentException( Logger.logMessage(Logger.ERROR, "Location", "rhumbLocation", "missingResult")); } if (distanceRadians == 0) { result.latitude = this.latitude; result.longitude = this.longitude; return result; } double latRadians = Math.toRadians(this.latitude); double lonRadians = Math.toRadians(this.longitude); double azimuthRadians = Math.toRadians(azimuthDegrees); double endLatRadians = latRadians + distanceRadians * Math.cos(azimuthRadians); double endLonRadians; double dLat = endLatRadians - latRadians; double q; if (Math.abs(dLat) < NEAR_ZERO_THRESHOLD) { q = Math.cos(latRadians); } else { double dPhi = Math.log(Math.tan(endLatRadians / 2 + Math.PI / 4) / Math.tan(latRadians / 2 + Math.PI / 4)); q = dLat / dPhi; } double dLon = distanceRadians * Math.sin(azimuthRadians) / q; if (Math.abs(endLatRadians) > Math.PI / 2) { endLatRadians = endLatRadians > 0 ? Math.PI - endLatRadians : -Math.PI - endLatRadians; } endLonRadians = (lonRadians + dLon + Math.PI) % (2 * Math.PI) - Math.PI; if (Double.isNaN(endLatRadians) || Double.isNaN(endLonRadians)) { result.latitude = this.latitude; result.longitude = this.longitude; } else { result.latitude = normalizeLatitude(Math.toDegrees(endLatRadians)); result.longitude = normalizeLongitude(Math.toDegrees(endLonRadians)); } return result; } Location();  Location(double latitude, double longitude);  Location(Location location); static Location fromDegrees(double latitudeDegrees, double longitudeDegrees); static Location fromRadians(double latitudeRadians, double longitudeRadians); static Location fromTimeZone(TimeZone timeZone); static double normalizeLatitude(double degrees); static double normalizeLongitude(double degrees); static double clampLatitude(double degrees); static double clampLongitude(double degrees); static boolean locationsCrossAntimeridian(List<? extends Location> locations); @Override boolean equals(Object o); @Override int hashCode(); @Override String toString(); Location set(double latitude, double longitude); Location set(Location location); Location interpolateAlongPath(Location endLocation, @WorldWind.PathType int pathType, double amount,
                                         Location result); double greatCircleAzimuth(Location location); double greatCircleDistance(Location location); Location greatCircleLocation(double azimuthDegrees, double distanceRadians, Location result); double rhumbAzimuth(Location location); double rhumbDistance(Location location); Location rhumbLocation(double azimuthDegrees, double distanceRadians, Location result); double linearAzimuth(Location location); double linearDistance(Location location); Location linearLocation(double azimuthDegrees, double distanceRadians, Location result); public double latitude; public double longitude; }
@Test public void testRhumbLocation() throws Exception { Location lax = Location.fromRadians(0.592539, -2.066470); Location jfk = Location.fromRadians(0.709185, -1.287762); final double distanceFromLaxToJfk = 0.6296498957149533; final double course = 79.32398087460811; Location location = new Location(); lax.rhumbLocation(course, distanceFromLaxToJfk, location); assertEquals("jfk latitude", jfk.latitude, location.latitude, TOLERANCE); assertEquals("jfk longitude", jfk.longitude, location.longitude, TOLERANCE); }