/*
* $Header: /cvs/distapps/openmap/src/openmap/com/bbn/openmap/proj/RhumbCalculator.java,v 1.5 2005/12/09 21:09:01 dietrick Exp $
*
* Copyright 2004 OBR Centrum Techniki Morskiej, All rights reserved.
*
*/
package com.bbn.openmap.proj;
import com.bbn.openmap.MoreMath;
import com.bbn.openmap.proj.coords.LatLonPoint;
/**
*
* @version $Header:
* /cvs/distapps/openmap/src/openmap/com/bbn/openmap/proj/RhumbCalculator
* .java,v 1.1 2004/05/10 20:53:58 dietrick Exp $
* @author pawkub
*
* This class contains methods that helps you make calculations
* performed ASSOCIATED The so-called. Rhumbline. This class contains
* several oglnych wzorw and beyond OpenMap is ASSOCIATED with nothing.
* You can drop into OpenMap and contained in it, where will you need
* (and it is places a few).
*/
public class RhumbCalculator {
/**
* The constructor is private, because (for now) class contains only A few
* static methods.
*/
private RhumbCalculator() {
}
/**
* This method allows public location point on the Rhumb Line, znajc
* Location reference point, the azimuth and Distance.
*
* @param point LatLonPoint the staring point.
* @param azimuth in radians, clockwise from North (0.0).
* @param dist distance in radians.
* @return LatLonPoint on the rhumb line at the azimuth and distance
* specified.
*/
public static LatLonPoint calculatePointOnRhumbLine(LatLonPoint point, double azimuth,
double dist) {
double az = MoreMath.TWO_PI_D - azimuth;
double lat1 = point.getRadLat();
double lon1 = point.getRadLon();
double lat = lat1 + dist * Math.cos(az);
double dphi = Math.log(Math.abs((1 + Math.sin(lat)) / Math.cos(lat)))
- Math.log(Math.abs((1 + Math.sin(lat1)) / Math.cos(lat1)));
double dlon = 0.0;
if (Math.abs(Math.cos(az)) > Math.sqrt(0.00000000000001)) {
dlon = dphi * Math.tan(az);
} else { // along parallel
dlon = Math.sin(az) * dist / Math.cos(lat1);
}
double lon = mod(lon1 - dlon + Math.PI, 2 * Math.PI) - Math.PI;
return new LatLonPoint.Double(lat, lon, true);
}
/**
* This method allows znormowa worth to the given
*
* @param y
* @param x
* @return regulated worth
*/
private static double mod(double y, double x) {
double ret;
if (y >= 0) {
ret = y - x * (int) (y / x);
} else {
ret = y + x * ((int) (-y / x) + 1);
}
return ret;
}
/**
*
* @param p1 LatLonPoint the first point.
* @param p2 LatLonPoint to the second point.
* @return distance in radians
*/
public static double getDistanceBetweenPoints(LatLonPoint p1, LatLonPoint p2) {
double lat1 = p1.getRadLat();
double lon1 = p1.getRadLon();
double lat2 = p2.getRadLat();
double lon2 = p2.getRadLon();
double d = 0.0;
double tc = 0.0;
double dlon_W = mod(lon2 - lon1, 2 * Math.PI);
double dlon_E = mod(lon1 - lon2, 2 * Math.PI);
tc = getAzimuthBetweenPoints(p1, p2);
if (Math.abs(lat1 - lat2) < Math.sqrt(0.00000000000001)) {
// distance along parallel
d = Math.min(dlon_W, dlon_E) * Math.cos(lat1);
} else {
d = Math.abs((lat2 - lat1) / Math.cos(tc));
}
return d;
}
/**
* This method allows you to calculate the azimuth between the points.
*
* @param p1 LatLonPoint the first point.
* @param p2 LatLonPoint to the second point.
* @return azimuth in radians of the bearing from the first point to the
* second point.
*/
public static double getAzimuthBetweenPoints(LatLonPoint p1, LatLonPoint p2) {
double lat1 = p1.getRadLat();
double lon1 = p1.getRadLon();
double lat2 = p2.getRadLat();
double lon2 = p2.getRadLon();
double tc = 0.0;
double dlon_W = mod(lon2 - lon1, 2.0 * Math.PI);
double dlon_E = mod(lon1 - lon2, 2.0 * Math.PI);
double dphi = Math.log(Math.abs((1 + Math.sin(lat2)) / Math.cos(lat2)))
- Math.log(Math.abs((1 + Math.sin(lat1)) / Math.cos(lat1)));
if (dlon_W < dlon_E) {// West is the shortest
tc = mod(Math.atan2(-dlon_W, dphi), 2.0 * Math.PI);
} else {
tc = mod(Math.atan2(dlon_E, dphi), 2.0 * Math.PI);
}
return MoreMath.TWO_PI_D - tc;
}
}