What is the most accurate calculation for new GPS coordinate? - java

Sir,
I have referred to this website for calculating new coordinate from given old starting point (22.36818013084568,114.11599405109882) , bearing (in Rad) 1.1583078679283372 , and distance (in meters) :134.07025146484375
). When it comes to execution , it wrongly gives (0.3904068271541288,1.9917206728639663) . Would you please tell me the which part I get it wrong or any revised algorithm for calculating the new position ?
public static double getDistanceInMeters(LatLng sp1, LatLng sp2) {
int lat = (int) (sp1.latitude * 1E6);
int lng = (int) (sp1.longitude * 1E6);
GeoPoint p1 = new GeoPoint(lat, lng);
int latX = (int) (sp2.latitude * 1E6);
int lngX = (int) (sp2.longitude * 1E6);
GeoPoint p2 = new GeoPoint(latX, lngX);
double lat1 = ((double)p1.getLatitudeE6()) / 1e6;
double lng1 = ((double)p1.getLongitudeE6()) / 1e6;
double lat2 = ((double)p2.getLatitudeE6()) / 1e6;
double lng2 = ((double)p2.getLongitudeE6()) / 1e6;
float [] dist = new float[1];
Location.distanceBetween(lat1, lng1, lat2, lng2, dist);
return dist[0] ;
}
double distance = SystemUtils.getDistanceInMeters(dronePosition, devicePos )- followDist;
public static LatLng fromBearingDistance(LatLng originalPosition, double brng, double d) {
double lat1 = Math.toRadians(originalPosition.latitude) ;
double lon1 = Math.toRadians(originalPosition.longitude);
long R = 6371000; // distance of earth's radius in meters
d = d /(double) R;
System.out.println("d/R :" + d/R ) ;
System.out.println(" Math.cos(d/R) :" + Math.cos(d/R) ) ;
System.out.println(" Math.sin(d/R) :" + Math.sin(d/R) ) ;
//(in km)
double lat2 = Math.asin( Math.sin(lat1)*Math.cos( d ) + Math.cos(lat1)*Math.sin( d )*Math.cos(brng) );
double lon2 = lon1 + Math.atan2(Math.sin(brng)*Math.sin(d )*Math.cos(lat1),
Math.cos(d )-Math.sin(lat1)*Math.sin(lat2));
return new LatLng(lat2,lon2);
}

Related

Generate a random geopoint from a fixed distance from a given latitude and longitude

I am writing a java program to generate a all the longitude and latitude with a fixed distance from my my given point. the distance must be exact 2000km, not withub 2000km.
this is my code
public static void getLocation(double x0, double y0, int meters) {
Random random = new Random();
// Convert radius from meters to degrees
double radiusInDegrees = meters / 111000f;
double u = random.nextDouble();
double v = random.nextDouble();
double w = radiusInDegrees * Math.sqrt(u);
double t = 2 * Math.PI * v;
double x = w * Math.cos(t);
double y = w * Math.sin(t);
// Adjust the x-coordinate for the shrinking of the east-west distances
// double new_x = x / Math.cos(Math.toRadians(y0));
double foundLongitude = x + x0;
double foundLatitude = y + y0;
System.out.println("Longitude: " + foundLongitude + " Latitude: " + foundLatitude );
}
How do I make all the point generate equal distance from the geo point, like forming a circle?
public static void generatePoint(double latitude, double longitude, double distanceInMetres, double bearing) {
Random random = new Random();
//int bear = random.nextInt(360);
double brngRad = Math.toRadians(bearing);
double latRad = Math.toRadians(latitude);
double lonRad = Math.toRadians(longitude);
int earthRadiusInMetres = 6371000;
double distFrac = distanceInMetres / earthRadiusInMetres;
double latitudeResult = Math.asin(Math.sin(latRad) * Math.cos(distFrac) + Math.cos(latRad) * Math.sin(distFrac) * Math.cos(brngRad));
double a = Math.atan2(Math.sin(brngRad) * Math.sin(distFrac) * Math.cos(latRad), Math.cos(distFrac) - Math.sin(latRad) * Math.sin(latitudeResult));
double longitudeResult = (lonRad + a + 3 * Math.PI) % (2 * Math.PI) - Math.PI;
System.out.println("bearing: "+bearing+ ", latitude: " + Math.toDegrees(latitudeResult) + ", longitude: " + Math.toDegrees(longitudeResult));
}
need to add bearing
For anyone looking, this is how I implemented this code in JavaScript:
function generatePoint(
latitude,
longitude,
distanceInMetres,
bearing = Math.floor(Math.random() * (360 - 1) + 1)
) {
const brngRad = deg2Rad(bearing);
const latRad = deg2Rad(latitude);
const lonRad = deg2Rad(longitude);
const EARTH_RADIUS_IN_METRES = 6371000;
const distFrac = distanceInMetres / EARTH_RADIUS_IN_METRES;
const latitudeResult = Math.asin(
Math.sin(latRad) * Math.cos(distFrac) +
Math.cos(latRad) * Math.sin(distFrac) * Math.cos(brngRad)
);
const a = Math.atan2(
Math.sin(brngRad) * Math.sin(distFrac) * Math.cos(latRad),
Math.cos(distFrac) - Math.sin(latRad) * Math.sin(latitudeResult)
);
const longitudeResult =
((lonRad + a + 3 * Math.PI) % (2 * Math.PI)) - Math.PI;
return {
latitude: rad2Deg(latitudeResult),
longitude: rad2Deg(longitudeResult),
bearing,
};
}
function deg2Rad(deg) {
return deg * (Math.PI / 180);
}
function rad2Deg(rad) {
return rad * (180 / Math.PI);
}
It will also generate a random bearing if none is provided

How to find the nearest location of array of latlng to my location and front of me not behind me

Hello everyone I am developing an android application , while the device moving there is a saved location (latlng object ) in array , I want it to alert user of nearest place from his device , but it maybe the nearest place behind hem not front of hem , like the figure here :
enter image description here
here is the list of location
List<LatLng> cameraLocation = new ArrayList<>();
and here how i calculate the distance
for (LatLng location : cameraLocation) {
closestCamera = location;
smallestDistance = distance;
Log.e("distanceTest", distance + "");
Log.d("closestCamera" , location+"" );
distanceList.add(CalculationByDistance(myLocation, location));
distance = Collections.min(distanceList);
}
the CalculationByDistance function is like this
public double CalculationByDistance(LatLng StartP, LatLng EndP) {
int Radius = 6371;// radius of earth in Km
double lat1 = StartP.latitude;
double lat2 = EndP.latitude;
double lon1 = StartP.longitude;
double lon2 = EndP.longitude;
double dLat = Math.toRadians(lat2 - lat1);
double dLon = Math.toRadians(lon2 - lon1);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
+ Math.cos(Math.toRadians(lat1))
* Math.cos(Math.toRadians(lat2)) * Math.sin(dLon / 2)
* Math.sin(dLon / 2);
double c = 2 * Math.asin(Math.sqrt(a));
double valueResult = Radius * c;
double km = valueResult / 1;
DecimalFormat newFormat = new DecimalFormat("#");
int kmInDec = Integer.valueOf(newFormat.format(km));
double meter = valueResult % 1000;
int meterInDec = Integer.valueOf(newFormat.format(meter));
Log.i("Radius Value", "" + valueResult + " KM " + kmInDec
+ " Meter " + meterInDec);
return Radius * c;
}
any help please ..
You could have two Location instances in your class, first currentLocation and second lastLocation. Calculate distance of your place from currentLocation and lastLocation. is the distance between currentLocation and your place is greater than the distance between lastLocation and your place, than you are moving away from that place. i.e that place is behind your current location.
Example Code:
private Location currentLocation;
private Location lastLocation;
public void onLocationUpdate(Location location){
lastLocation = currentLocation;
currentLocation = location;
calculateDistance();
}
private double smallestDistance;
private LatLng closestCamera;
private void calculateDistance(){
for (LatLng location : cameraLocation) {
double distanceFromLastLocation = CalculationByDistance(new LatLng(lastLocation.lat, lastLocation.lng), location);
double distanceFromCurrentLocation = CalculationByDistance(new LatLng(lastLocation.lat, lastLocation.lng), location);
if (distanceFromCurrentLocation < distanceFromLastLocation) {
continue; // User is going away from location i.e location is behind user. No need to calculate distance between user and cameraLocation.
}
distanceList.add(CalculationByDistance(myLocation, location));
if (Collections.min(distanceList) == distanceFromCurrentLocation) {
// this location is nearest amongst all the cameraLocations.
smallestDistance = distanceFromCurrentLocation;
closestCamera = location;
}
}
}

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);

Calculate distance in miles only between two latitude and longitude

I have some confusion about calculation distance in miles. Whenever i am going to calculate in online it giving different result rather than i am using the below methods.
I need the distance in only miles. What the correction required in the below methods.
public double calculationByDistance(Location loc1, Location loc2) {
int Radius = 6371;// radius of earth in Km
double lat1 = loc1.getLatitude();
double lat2 = loc2.getLatitude();
double lon1 = loc1.getLongitude();
double lon2 = loc2.getLongitude();
double dLat = Math.toRadians(lat2 - lat1);
double dLon = Math.toRadians(lon2 - lon1);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
+ Math.cos(Math.toRadians(lat1))
* Math.cos(Math.toRadians(lat2)) * Math.sin(dLon / 2)
* Math.sin(dLon / 2);
double c = 2 * Math.asin(Math.sqrt(a));
double valueResult = Radius * c;
double km = valueResult / 1;
km = km * 0.62137;
DecimalFormat newFormat = new DecimalFormat("####");
int kmInDec = Integer.valueOf(newFormat.format(km));
double meter = valueResult % 1000;
int meterInDec = Integer.valueOf(newFormat.format(meter));
Log.e("Radius Value", "" + valueResult + " KM " + kmInDec
+ " Meter " + meterInDec);
return Radius * c;
}
If anyone have idea please reply.
Thanks in advance...

midpoint between two latitude and longitude

I am trying to convert the code snippet given in this http://www.movable-type.co.uk/scripts/latlong.html into java. But I am not getting same result as that of site. Here is my code to find the midpoint between two points where their latitudes and longitudes are given
midPoint(12.870672,77.658964,12.974831,77.60935);
public static void midPoint(double lat1,double lon1,double lat2,double lon2)
{
double dLon = Math.toRadians(lon2-lon1);
double Bx = Math.cos(lat2) * Math.cos(dLon);
double By = Math.cos(lat2) * Math.sin(dLon);
double lat3 = Math.atan2(Math.sin(lat1)+Math.sin(lat2),Math.sqrt( (Math.cos(lat1)+Bx)*(Math.cos(lat1)+Bx) + By*By) );
double lon3 = lon1 + Math.atan2(By, Math.cos(lat1) + Bx);
System.out.print(lat3 +" " + lon3 );
}
I am not sure whethe dLon is correct or not. So please help me guys to figure it out. P.S.I need to find the latitude and longitude of the midpoint
You need to convert to radians. Change it to the following:
public static void midPoint(double lat1,double lon1,double lat2,double lon2){
double dLon = Math.toRadians(lon2 - lon1);
//convert to radians
lat1 = Math.toRadians(lat1);
lat2 = Math.toRadians(lat2);
lon1 = Math.toRadians(lon1);
double Bx = Math.cos(lat2) * Math.cos(dLon);
double By = Math.cos(lat2) * Math.sin(dLon);
double lat3 = Math.atan2(Math.sin(lat1) + Math.sin(lat2), Math.sqrt((Math.cos(lat1) + Bx) * (Math.cos(lat1) + Bx) + By * By));
double lon3 = lon1 + Math.atan2(By, Math.cos(lat1) + Bx);
//print out in degrees
System.out.println(Math.toDegrees(lat3) + " " + Math.toDegrees(lon3));
}
Even easier with Android Google Maps Utilities:
LatLngBounds bounds = new LatLngBounds(start, dest);
bounds.getCenter();
Update:
Better use the builder (for why see Bad Losers Answer):
LatLngBounds.builder().include(start).include(dest).build().getCenter();
Please use LatLngBounds with the builder rather than the constructor if you want to correctly handle transgression of the antimeridian (longitude +/-180).
Here is the test illustrating the problem:
LatLng mp = midPoint(new LatLng(-43.95139,-176.56111),new LatLng(-36.397816,174.663496));
public static LatLng midPoint (LatLng SW, LatLng NE) {
LatLngBounds bounds = new LatLngBounds(SW, NE);
Log.d("BAD!", bounds.toString() + " CENTRE: " + bounds.getCenter().toString());
bounds = LatLngBounds.builder().include(SW).include(NE).build();
Log.d("GOOD", bounds.toString() + " CENTRE: " + bounds.getCenter().toString());
return bounds.getCenter();
}
Actual results:
BAD!: LatLngBounds{southwest=lat/lng: (-43.95139,-176.56111), northeast=lat/lng: (-36.397816,174.663496)} CENTRE: lat/lng: (-40.174603,-0.948807)
GOOD: LatLngBounds{southwest=lat/lng: (-43.95139,174.663496), northeast=lat/lng: (-36.397816,-176.56111)} CENTRE: lat/lng: (-40.174603,179.051193)
The constructor technique produces a central longitude out by 180 degrees!
You need to convert you lat and lon values used in the other formulas to Radians also. You can see this in the code ~3/5ths of the way down the page. The clue was given at the end of the spherical law of cosines distance formula:
(Note that here and in all subsequent code fragments, for simplicity I do not show conversions from degrees to radians; see below for complete versions).
Here's #dogbane's Java code converted to TypeScript.
type LatLng = {
lat: number;
lng: number;
};
function calculateMidPoint(latLngA: LatLng, latLngB: LatLng) {
function toRadians(degress: number): number {
return degress * (Math.PI / 180);
}
function toDegrees(radians: number): string {
return (radians * (180 / Math.PI)).toFixed(4);
}
const lngDiff = toRadians(latLngB.lng - latLngA.lng);
const latA = toRadians(latLngA.lat);
const latB = toRadians(latLngB.lat);
const lngA = toRadians(latLngA.lng);
const bx = Math.cos(latB) * Math.cos(lngDiff);
const by = Math.cos(latB) * Math.sin(lngDiff);
const latMidway = toDegrees(
Math.atan2(
Math.sin(latA) + Math.sin(latB),
Math.sqrt((Math.cos(latA) + bx) * (Math.cos(latA) + bx) + by * by)
)
);
const lngMidway = toDegrees(lngA + Math.atan2(by, Math.cos(latA) + bx));
console.log(
`Midway point between ${latLngA} and ${latLngB} is: Lat: ${latMidway}, lng: ${lngMidway}`
);
}
Following is #dogbane 's java code converted to Kotlin:
private fun midPoint(lat1: Double, lon1: Double, lat2: Double, lon2: Double) : String {
var lat1 = lat1
var lon1 = lon1
var lat2 = lat2
val dLon: Double = Math.toRadians(lon2 - lon1)
//convert to radians
lat1 = Math.toRadians(lat1)
lat2 = Math.toRadians(lat2)
lon1 = Math.toRadians(lon1)
val Bx: Double = Math.cos(lat2) * Math.cos(dLon)
val By: Double = Math.cos(lat2) * Math.sin(dLon)
val lat3: Double = Math.atan2(Math.sin(lat1) + Math.sin(lat2), Math.sqrt((Math.cos(lat1) + Bx) * (Math.cos(lat1) + Bx) + By * By))
val lon3: Double = lon1 + Math.atan2(By, Math.cos(lat1) + Bx)
var result: String = ""
result = Math.toDegrees(lat3).toString() + "," + Math.toDegrees(lon3).toString()
return result;
}
My last job I made a tracking module and I was using this formula to calculate the distance between 2 coordinates.
//Location lat and lon
double locLat = -23.548333;
double locLon = -46.636111;
//Destination lat and lon
double dstLat = -22.902778;
double dstLon = -43.206667;
double arcoAB = 90 - (dstLat);
double arcoAC = 90 - (locLat);
double difLon = locLon - (dstLon);
double cosA = Math.cos(Math.toRadians(arcoAC)) * Math.cos(Math.toRadians(arcoAB)) + Math.sin(Math.toRadians(arcoAC)) * Math.sin(Math.toRadians(arcoAB)) * Math.cos(Math.toRadians(difLon));
double acosCosA = Math.toDegrees(Math.acos(cosA));
double raio = 2 * Math.PI * 6371;
double distance = (raio * acosCosA) / 360;
return distance; //Distance in KM, convert to anything else (miles, meters..) if you need..
You can get the mid point dividing the distance by 2.
Ah, this another formula works too:
double dLat = Math.toRadians(dstLat - locLat);
double dLon = Math.toRadians(dstLon - locLon);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
+ Math.cos(Math.toRadians(locLat)) * Math.cos(Math.toRadians(dstLat))
* Math.sin(dLon / 2) * Math.sin(dLon / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
double d = 6371 * c;
return d; //Distance in KM

Categories