midpoint between two latitude and longitude - java

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

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

distance not showing correctly using the latitude and longitude android

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

Convert Java code to Delphi about midpoint calculation

I found this Java code to calculate the midpoint between two latitude and longitude:
midpoint between two latitude and longitude
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));
}
Anyone can help me to convert this piece of code to Borland Delphi?
With the input like this format:
lat1 = 48.865223,
lon1 = 2.318974
lat2 = 48.865983,
lon2 = 2.321475
I am not sure if that is already in "radian".
lat1 = 48.865223, lon1 = 2.318974
lat2 = 48.865983, lon2 = 2.321475
These coordinates appear to be in degrees. The latitude is too large for radians. You can convert between degrees and radians using DegToRad and RadToDeg. Of course, it's not very hard to multiply and divide by π/180.
The trig functions, sin and cos can be found in the System unit, as can sqrt. For atan2 you need arctan2 from Math.

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...

Get zipcodes within N miles java client

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

Categories