midpoint between two latitude and longitude
Asked Answered
C

7

37

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

Couple answered 11/1, 2011 at 10:50 Comment(0)
G
81

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));
}
Gale answered 11/1, 2011 at 11:8 Comment(1)
hi @Gale i need one help. #11759082Twinge
L
25

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();
Linneman answered 24/8, 2017 at 18:37 Comment(4)
Works well, and saved me some coding. Thanks.Firooc
@Linneman OK but not perfect [antimeridian transgression not handled] - see my answer below. Thanks for putting me on the right track.Zirkle
As far as I remember the constructor even complains, when you put NE before SW so definitely use the builder. I probably kept my answer too simple just to point people in the right direction. Thanks for the hint.Linneman
Thank you very much for the 'update' section. Solved my problem.Disqualification
Z
3

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!

Zirkle answered 6/9, 2018 at 12:24 Comment(0)
I
1

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

Idolla answered 11/1, 2011 at 11:7 Comment(0)
B
1

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}`
  );
}
Beta answered 9/12, 2020 at 7:52 Comment(0)
K
0

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;
}
Knownothing answered 25/11, 2020 at 15:11 Comment(0)
S
-2

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
Slovenly answered 11/1, 2011 at 11:8 Comment(2)
But I need to find the latitude and longitude of the midpoint. How to do that?Couple
@scooby did u find any solution for the same ?Scheers

© 2022 - 2024 — McMap. All rights reserved.