Bearing from one coordinate to another - java

I implemented the "bearing" formula from http://www.movable-type.co.uk/scripts/latlong.html. But it seems highly inaccurate - I suspect some mistakes in my implementation. Could you help me with finding it? My code is below:
protected static double bearing(double lat1, double lon1, double lat2, double lon2){
double longDiff= lon2-lon1;
double y = Math.sin(longDiff)*Math.cos(lat2);
double x = Math.cos(lat1)*Math.sin(lat2)-Math.sin(lat1)*Math.cos(lat2)*Math.cos(longDiff);
return Math.toDegrees((Math.atan2(y, x))+360)%360;
}

Here is the final code:
protected static double bearing(double lat1, double lon1, double lat2, double lon2){
double longitude1 = lon1;
double longitude2 = lon2;
double latitude1 = Math.toRadians(lat1);
double latitude2 = Math.toRadians(lat2);
double longDiff= Math.toRadians(longitude2-longitude1);
double y= Math.sin(longDiff)*Math.cos(latitude2);
double x=Math.cos(latitude1)*Math.sin(latitude2)-Math.sin(latitude1)*Math.cos(latitude2)*Math.cos(longDiff);
return (Math.toDegrees(Math.atan2(y, x))+360)%360;
}

You just have your parentheses () in the wrong place.
You are adding degrees to a value in radians, which won't work. toDegrees() will do the conversion from radians to degrees for you, then you do the normalisation once you have a value in degrees.
You have:
Math.toDegrees( (Math.atan2(y, x))+360 ) % 360;
But you need:
( Math.toDegrees(Math.atan2(y, x)) + 360 ) % 360;
Remember also that all inputs to Math.sin(), Math.cos() and all the other trigonometric functions must be in radians. If your inputs are degrees you'll need to convert them using Math.toRadians() first.

Bearing from one coordinate to another And Find North,East,south,weast :)
public class FindBearing {
public static void main(String[] args) {
System.out.println(" Your Result >>> "+FindBearing.bearing(19.2859590, 73.4966430, 19.2861020, 73.4988090));
}
protected static String bearing(double lat1, double lon1, double lat2, double lon2){
double longitude1 = lon1;
double longitude2 = lon2;
double latitude1 = Math.toRadians(lat1);
double latitude2 = Math.toRadians(lat2);
double longDiff= Math.toRadians(longitude2-longitude1);
double y= Math.sin(longDiff)*Math.cos(latitude2);
double x=Math.cos(latitude1)*Math.sin(latitude2)-Math.sin(latitude1)*Math.cos(latitude2)*Math.cos(longDiff);
double resultDegree= (Math.toDegrees(Math.atan2(y, x))+360)%360;
String coordNames[] = {"N","NNE", "NE","ENE","E", "ESE","SE","SSE", "S","SSW", "SW","WSW", "W","WNW", "NW","NNW", "N"};
double directionid = Math.round(resultDegree / 22.5);
// no of array contain 360/16=22.5
if (directionid < 0) {
directionid = directionid + 16;
//no. of contains in array
}
String compasLoc=coordNames[(int) directionid];
return resultDegree+" "+compasLoc;
}
}

A little bit cleaned up version of #IvanT answer:
public static double bearingInRadians(LatLng src, LatLng dst) {
double srcLat = Math.toRadians(src.getLatitude());
double dstLat = Math.toRadians(dst.getLatitude());
double dLng = Math.toRadians(dst.getLongitude() - src.getLongitude());
return Math.atan2(Math.sin(dLng) * Math.cos(dstLat),
Math.cos(srcLat) * Math.sin(dstLat) -
Math.sin(srcLat) * Math.cos(dstLat) * Math.cos(dLng));
}
public static double bearingInDegrees(LatLng src, LatLng dst) {
return Math.toDegrees((bearingInRadians(src, dst) + Math.PI) % Math.PI);
}
Where LatLng is:
public final class LatLng {
private final double latitude;
private final double longitude;
public LatLng(double latitude, double longitude) {
this.latitude = latitude;
this.longitude = longitude;
}
public double getLatitude() {
return latitude;
}
public double getLongitude() {
return longitude;
}
}

Related

Android Implementing distance between two locations, Place class

I had a previous question where I was wondering how I could find the distance between two locations based on latitude and longitude. I was linked to an answer and now I am trying to implement SortPlaces.java but it cannot resolve the symbol Place. The IDE also does not give me an option to import the class. Does this mean I have to create the Place class myself? If so what would that like or? Or does the Place class already exist and I can't import it because I don't have the proper library?
Thanks, here is the code.
import com.google.android.gms.maps.model.LatLng;
public class SortPlaces implements Comparator<Place> {
LatLng currentLoc;
public SortPlaces(LatLng current){
currentLoc = current;
}
#Override
public int compare(final Place place1, final Place place2) {
double lat1 = place1.latlng.latitude;
double lon1 = place1.latlng.longitude;
double lat2 = place2.latlng.latitude;
double lon2 = place2.latlng.longitude;
double distanceToPlace1 = distance(currentLoc.latitude, currentLoc.longitude, lat1, lon1);
double distanceToPlace2 = distance(currentLoc.latitude, currentLoc.longitude, lat2, lon2);
return (int) (distanceToPlace1 - distanceToPlace2);
}
public double distance(double fromLat, double fromLon, double toLat, double toLon) {
double radius = 6378137; // approximate Earth radius, *in meters*
double deltaLat = toLat - fromLat;
double deltaLon = toLon - fromLon;
double angle = 2 * Math.asin( Math.sqrt(
Math.pow(Math.sin(deltaLat/2), 2) +
Math.cos(fromLat) * Math.cos(toLat) *
Math.pow(Math.sin(deltaLon/2), 2) ) );
return radius * angle;
}
}
Looking at your other question, you will need to replace the Place class with your Campsite class in the sorting code:
public class SortCampgrounds implements Comparator<Campsite> {
LatLng currentLoc;
public SortCampgrounds(LatLng current){
currentLoc = current;
}
#Override
public int compare(final Campsite campsite1, final Campsite campsite2) {
double lat1 = campsite1.getLatitude();
double lon1 = campsite1.getLongitude();
double lat2 = campsite2.getLatitude();
double lon2 = campsite2.getLongitude();
double distanceToCampsite1 = distance(currentLoc.latitude, currentLoc.longitude, lat1, lon1);
double distanceToCampsite2 = distance(currentLoc.latitude, currentLoc.longitude, lat2, lon2);
return (int) (distanceToCampsite1 - distanceToCampsite2);
}
public double distance(double fromLat, double fromLon, double toLat, double toLon) {
double radius = 6378137; // approximate Earth radius, *in meters*
double deltaLat = toLat - fromLat;
double deltaLon = toLon - fromLon;
double angle = 2 * Math.asin( Math.sqrt(
Math.pow(Math.sin(deltaLat/2), 2) +
Math.cos(fromLat) * Math.cos(toLat) *
Math.pow(Math.sin(deltaLon/2), 2) ) );
return radius * angle;
}
}
Then use the custom comparator in order to sort the Campsites by distance to current location, and get the closest:
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
// GET ALL CAMPSITES FROM DATABASE
ArrayList<Campsite> campsites = db.getAllCampsites();
// LOOP THROUGH EACH CAMPSITE AND ADD A MARKER FOR EACH CAMPSITE
for (Campsite campsite : campsites) {
LatLng latLng = new LatLng(campsite.getLatitude(), campsite.getLongitude());
mMap.addMarker(new MarkerOptions().position(latLng).title(campsite.getName()));
}
// PLACE MARKER FOR CURRENT LOCATION (STATIC LOCATION)
LatLng currentLocation = new LatLng(34.1691, -118.4167);
mMap.addMarker(new MarkerOptions().position(currentLocation).title("Your location"));
// Add this to sort and get the closest Campsite:
Collections.sort(campsites, new SortCampgrounds(currentLocation));
// Get the first one from the list, this will be the closest:
Campsite closestCampsite = campsites.get(0);
}

SohCahToa Project

I need some help with a project I'm working on the side to help me in my physics and chemistry class.
This is the code that I have produced so far and it seems to give me an answer that are incorrect for all trials I have given it. All help is appreciated!
public double sinSinUnknown(double opp, double hyp)
{
double sin = 0;
sin = Math.asin((opp / hyp));
return sin;
}
public double sinOppUnknown(double sin, double hyp)
{
double opp = 0;
opp = Math.sin(sin) * hyp;
return opp;
}
public double sinHypUnknown(double sin, double opp)
{
double hyp = 0;
hyp = opp / Math.sin(sin);
return hyp;
}
public double cosCosUnknown(double adj, double hyp)
{
double cos = 0;
cos = Math.acos((adj / hyp));
return cos;
}
public double cosAdjUnknown(double cos, double hyp)
{
double adj = 0;
adj = hyp * Math.cos(cos);
return adj;
}
public double cosHypUnknown(double cos, double adj)
{
double hyp = 0;
hyp = adj / Math.cos(cos);
return hyp;
}
public double tanTanUnknown(double opp, double adj)
{
double tan = 0;
tan = Math.atan((opp / adj));
return tan;
}
public double tanOppUnknown(double tan, double adj)
{
double opp = 0;
opp = adj * Math.tan(tan);
return opp;
}
public double tanAdjUnknown(double tan, double opp)
{
double adj = 0;
adj = opp / Math.tan(tan);
return adj;
}
}
The trigonometric functions in java.lang.Math require inputs in radians, rather than degrees. This can be done using the toRadians function.
You'll need to convert your answers back to degrees, using the toDegrees function.
public double sinSinUnknown(double opp, double hyp)
{
double sin = 0;
sin = Math.asin((Math.toRadians(opp) / Math.toRadians(hyp)));
return Math.toDegrees(sin);
}

find closest marker to my current location

I have an arrayList of markers and I want to find the closest marker to my current location.
I had no idea how to find that marker so I searched and found same problem in here.
Google Maps Api v3 - find nearest markers
then I tried to convert those code to java but it doesn't work now.
closest doesn't change and always it is -1.
Is there any better solution for this problem or I can make the following code usable?
public void findNearMarker(){
double pi = Math.PI;
int R = 6371; //equatorial radius
double[] distances = new double[2];
double d = 0;
int i;
int closest = -1;
for ( i = 0; i == markerArrayList.size(); i++){
double lat2 = markerArrayList.get(i).getPosition().latitude;
double lon2 = markerArrayList.get(i).getPosition().longitude;
double chLat = lat2 - currentLocation.getLatitude();
double chLon = lon2 - currentLocation.getLongitude();
double dLat = chLat*(pi/180);
double dLon = chLon*(pi/180);
double rLat1 = currentLocation.getLatitude()*(pi/180);
double rLat2 = lat2 * (pi/180);
double a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.sin(dLon/2)
* Math.sin(dLon /2) * Math.cos(rLat1) * Math.cos(rLat2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
d = R * c;
distances[i] = d;
if (closest == -1 || d< distances[closest]){
closest = i;
}
}
}
first you need to import the location class of the android sdk
import android.location.Location;
ArrayList<Marker> markers = new ArrayList<>();
markers = sortListbyDistance(markers, currentLocation.getLocation());
public static ArrayList<Marker> sortListbyDistance(ArrayList<Marker> markers, final LatLng location){
Collections.sort(markers, new Comparator<Marker>() {
#Override
public int compare(Marker marker2, Marker marker1) {
//
if(getDistanceBetweenPoints(marker1.getLocation(),location)>getDistanceBetweenPoints(marker2.getLocation(),location)){
return -1;
} else {
return 1;
}
}
});
return markers;
}
public static float getDistanceBetweenPoints(double firstLatitude, double firstLongitude, double secondLatitude, double secondLongitude) {
float[] results = new float[1];
Location.distanceBetween(firstLatitude, firstLongitude, secondLatitude, secondLongitude, results);
return results[0];
}
and to get the nearest marker just get first item in markers, cheers :)
If you follow
Comparing two locations using their Longitude and Latitude
/** calculates the distance between two locations in MILES */
private double distance(double lat1, double lng1, double lat2, double lng2) {
double earthRadius = 3958.75; // in miles, change to 6371 for kilometer output
double dLat = Math.toRadians(lat2-lat1);
double dLng = Math.toRadians(lng2-lng1);
double sindLat = Math.sin(dLat / 2);
double sindLng = Math.sin(dLng / 2);
double a = Math.pow(sindLat, 2) + Math.pow(sindLng, 2)
* Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2));
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
double dist = earthRadius * c;
return dist; // output distance, in MILES
}
loop through your list with this function and get the lowest return value.
You can also use the Maps API
Location locationA = new Location("point A");
locationA.setLatitude(latA);
locationA.setLongitude(lngA);
Location locationB = new Location("point B");
locationB.setLatitude(latB);
locationB.setLongitude(lngB);
float distance = locationA.distanceTo(locationB);

How to get angle from point1 to point2 in earth

I've spend much time internet for finding a way to do this. By exist documention I wrote below code, But it does not show correct angle.
What's problem?
private double angleFromCoordinate(double lat1, double long1, double lat2,
double long2) {
double dLon = (long2 - long1);
double y = Math.sin(dLon) * Math.cos(lat2);
double x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1)
* Math.cos(lat2) * Math.cos(dLon);
double brng = Math.atan2(y, x);
brng = Math.toDegrees(brng);
brng %= 360;
// brng = 360 - brng;
return brng;
}
UPDATED
result of below code:
int angle = (int) angleFromCoordinate(36.288024, 59.615656
, 39.033659, 48.662504);
angle is '58'
The methods Math.cos and Math.sin take a number of radians for their arguments. You are passing degrees into this method. You need to convert your degrees into radians at the start of the method.
private double angleFromCoordinate(double lat1, double long1, double lat2,
double long2) {
double lat1Rad = Math.toRadians(lat1);
double long1Rad = Math.toRadians(long1);
double lat2Rad = Math.toRadians(lat2);
double long2Rad = Math.toRadians(long2);
then use the new variables lat1Rad and so on for the remaining mathematics.

Getting incorrect distance using gps latitude longitude

This is my code:
private final static double[] multipliers = {
1.0, 1.0936133, 0.001, 0.000621371192
};
private final static String[] unitstrings = {
"m", "y", "km", "mi"
};
private void updateMeasurement() {
double distance = calcGeoDistance(startLat, startLon, currentLat, currentLon) * multipliers[unitindex];
String distanceText = "" + RoundDecimal(distance, 2) + " " + unitstrings[unitindex];
((TextView)findViewById(R.id.distance)).setText(distanceText);
}
private double calcGeoDistance(final double lat1, final double lon1, final double lat2, final double lon2)
{
double distance = 0.0;
try
{
final float[] results = new float[3];
Location.distanceBetween(lat1, lon1, lat2, lon2, results);
distance = (double)results[0];
}
catch (final Exception ex)
{
distance = 0.0;
}
return distance;
}
I get 8310 km even when I shake the mobile.
public float distanceFrom(float lat1, float lng1, float lat2, float lng2) {
double earthRadius = 3958.75;
double dLat = Math.toRadians(lat2-lat1);
double dLng = Math.toRadians(lng2-lng1);
double a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(Math.toRadians(lat1)) *Math.cos(Math.toRadians(lat2)) * Math.sin(dLng/2) * Math.sin(dLng/2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
double dist = earthRadius * c;
int meterConversion = 1609;
return new Float(dist * meterConversion).floatValue();
}
Are you using Long and Lat in degrees of the correct format? It would help to see the values you are passing in
double startLatitude = pointStart.getLatitudeE6() / DEG_RATE;
double startLongitude= pointStart.getLongitudeE6() / DEG_RATE;
double endLatitude = pointEnd.getLatitudeE6() / DEG_RATE;
double endLongitude= pointEnd.getLongitudeE6() / DEG_RATE;
float[] result = new float[1];
Location.distanceBetween(startLatitude, startLongitude, endLatitude, endLongitude, result);
Where pointStart and pointEnd are com.google.android.maps.GeoPoint
Reference -
http://www.java2s.com/Code/Android/Core-Class/GetDistancebetweentwoGeoPoint.htm

Categories