I would have thought this is trivial, but here at the end of the day my brain is dead.
getting distance in meters seems to work, miles seems to be broken, and speed seems to be broken.
any help would be appreciated.
public static double distFromInMiles(double lat1, double lng1, double lat2, double lng2)
{
double earthRadius = 3959;
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;
return dist;
}
public static double distFromInMeters(double lat1, double lng1, double lat2, double lng2)
{
double earthRadius = 6378137;
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;
return dist;
}
public static double distFromInKiloMeters(double lat1, double lng1, double lat2, double lng2)
{
double earthRadius = 6371;
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;
return dist;
}
protected void checkDistanceFromPOI(LatLng latLng)
{
long thistime = System.currentTimeMillis();
long deltatime = lasttime - thistime;
double hours = (double)deltatime / ((double)1000.0 * (double)60.0 * (double)60.0);
String s;
double distFromInMeters = LocationGPSServices.distFromInMeters(lastLocationPoint.latitude, lastLocationPoint.longitude, latLng.latitude, latLng.longitude);
double distFromInMiles = LocationGPSServices.distFromInMiles(lastLocationPoint.latitude, lastLocationPoint.longitude, latLng.latitude, latLng.longitude);
double speed = distFromInMiles/hours;
double speed2 = distFromInMeters/hours;
s = "*****************distance from last point \n"
+ " lat/lng 1 = " + lastLocationPoint.toString() + "\n"
+ " lat/lng 2 = "+ latLng.toString() + "\n"
+ " in meters = " + distFromInMeters + "} \n in miles = " + distFromInMiles + " }\n "
+ " elapsed time = " + deltatime + "secs \n"
+ " speed = " + speed2 + "meters per hour \n"
+ " speed = " + speed + "miles per hour";
Toast.makeText(getActivity(), s, Toast.LENGTH_SHORT).show();
Writer.appendText(s, "gps.txt", getActivity());
lasttime = thistime;
}
You can just use the static method
Location.distanceBetween (double startLatitude, double startLongitude, double endLatitude, double endLongitude, float[] results)
Also you can use the getSpeed () method in the Location class.
Related
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
I have a app where I am showing the nearest event (place) distance in km using the Latitude and Longitude. Users latitude and longitude is variable but events latitude and longitude are fixed.However, I am not able to get the correct distance is km. for example correct distance is 6.7 km in google map but its showing 8663.90 km. I am novice in android so unable to get the solution. any help will be great!! my codes are
{ double doubleInstance = d.getDistance(Lat1, Lon1, d.getLatitude(), d.getLongitude(), "N");
String dInstance = String.format("%.2f",doubleInstance);
lblview1.setText(" " + String.valueOf(dInstance) + " Km"); }
and
{ public double getDistance(double lat1, double lon1, double lat2, double lon2, String unit) {
int Radius = 6371;// radius of earth in Km
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;
} }
Set your Event location. And get your current location using location manager.
double latitude=lat;
double longitude=lng;
float distance=0;
Location crntLocation=new Location("crntlocation");
crntLocation.setLatitude(currentLatitude);
crntLocation.setLongitude(currentLongitude);
Location eventLocation=new Location("eventlocation");
eventLocation.setLatitude(latitude);
eventLocation.setLongitude(longitude);
//float distance = crntLocation.distanceTo(eventLocation); in meters
distance =crntLocation.distanceTo(eventLocation) / 1000; // in kms
Use Location class method to get distance between two coordinates like;
Location.distanceBetween(obj.getLatitude(), obj.getLongitude(),
mapCircle.getCenter().latitude, mapCircle.getCenter().longitude, distance);
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...
Goal... Given a Zip code and a number of miles... get all zip codes within N miles.
Found one utility here in .NET: http://www.codeproject.com/Articles/9198/ZIP-Code-Utility
Found another utility in PHP.
Also found this: http://api.geonames.org/findNearbyPostalCodes?postalcode=53714&country=USA&radius=50&username=demo
Is there such a client in java?
UPDATE: I couldn't find one and no one responded, so I went ahead and created one.
I went ahead and wrote one.
package ndd;
public class RadiusBox {
static final Double kEarthRadiusMiles = 3956.0;
public static RadiusBox create(Double latitude, Double longitude, Double radiusInMiles)
{
/*
A point {lat,lon} is a distance d out on the tc radial from point 1 if:
lat = asin (sin (lat1) * cos (d) + cos (lat1) * sin (d) * cos (tc))
dlon = atan2 (sin (tc) * sin (d) * cos (lat1), cos (d) - sin (lat1) * sin (lat))
lon = mod (lon1 + dlon + pi, 2 * pi) - pi
Where:
* d is the distance in radians (an arc), so the desired radius divided by
the radius of the Earth.
* tc = 0 is N, tc = pi is S, tc = pi/2 is E, tc = 3*pi/2 is W.
*/
double lat;
double dlon;
double dLatInRads = latitude * (Math.PI / 180.0);
double dLongInRads = longitude * (Math.PI / 180.0);
double dDistInRad = radiusInMiles / kEarthRadiusMiles;
RadiusBox box = new RadiusBox ();
box.setRadius(radiusInMiles);
// N (tc == 0):
// lat = asin (sin(lat1)*cos(d) + cos(lat1)*sin(d))
// = asin (sin(lat1 + d))
// = lat1 + d
// Unused:
// lon = lon1, because north-south lines follow lines of longitude.
box.setTopLine((dLatInRads + dDistInRad) * (180.0 / Math.PI));
// S (tc == pi):
// lat = asin (sin(lat1)*cos(d) - cos(lat1)*sin(d))
// = asin (sin(lat1 - d))
// = lat1 - d
// Unused:
// lon = lon1, because north-south lines follow lines of longitude.
box.setBottomLine((dLatInRads - dDistInRad) * (180.0 / Math.PI));
// E (tc == pi/2):
// lat = asin (sin(lat1)*cos(d))
// dlon = atan2 (sin(tc)*sin(d)*cos(lat1), cos(d) - sin(lat1)*sin(lat))
// lon = mod (lon1 + dlon + pi, 2*pi) - pi
lat = Math.asin (Math.sin(dLatInRads) * Math.cos (dDistInRad));
dlon = Math.atan2 (Math.sin(Math.PI / 2.0) * Math.sin (dDistInRad) * Math.cos (dLatInRads), Math.cos (dDistInRad) - Math.sin (dLatInRads)* Math.sin (lat));
box.setRightLine( (((dLongInRads + dlon + Math.PI) % (2.0 * Math.PI)) - Math.PI) * (180.0 / Math.PI));
// W (tc == 3*pi/2):
// lat = asin (sin(lat1)*cos(d))
// dlon = atan2 (sin(tc)*sin(d)*cos(lat1), cos(d) - sin(lat1)*sin(lat))
// lon = mod (lon1 + dlon + pi, 2*pi) - pi
dlon = Math.atan2 (Math.sin (3.0 * Math.PI / 2.0) * Math.sin (dDistInRad) * Math.cos (dLatInRads), Math.cos (dDistInRad) - Math.sin (dLatInRads)* Math.sin (lat));
box.setLeftLine((((dLongInRads + dlon + Math.PI) % (2.0 * Math.PI)) - Math.PI) * (180.0 / Math.PI));
return box;
}
private double bottomLine;
private double topLine;
private double leftLine;
private double rightLine;
private double radius;
public double getBottomLine() {
return bottomLine;
}
public void setBottomLine(double bottomLine) {
this.bottomLine = bottomLine;
}
public double getTopLine() {
return topLine;
}
public void setTopLine(double topLine) {
this.topLine = topLine;
}
public double getLeftLine() {
return leftLine;
}
public void setLeftLine(double leftLine) {
this.leftLine = leftLine;
}
public double getRightLine() {
return rightLine;
}
public void setRightLine(double rightLine) {
this.rightLine = rightLine;
}
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
#Override
public String toString() {
return "RadiusBox [bottomLine=" + bottomLine + ", leftLine=" + leftLine
+ ", radius=" + radius + ", rightLine=" + rightLine
+ ", topLine=" + topLine + "]";
}
public String getSqlQuery() {
StringBuilder sb = new StringBuilder();
sb.append ("SELECT * FROM ZIP_CODES WHERE ");
sb.append ("LATITUDE >= ");
sb.append(bottomLine);
sb.append (" AND LATITUDE <= ");
sb.append(topLine);
sb.append (" AND LONGITUDE >= ");
sb.append(leftLine);
sb.append (" AND LONGITUDE <= ");
sb.append(rightLine);
sb.append (" ORDER BY CITY, STATE, ZIP");
return sb.toString();
}
}
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