Midpoint Between Two Latitude and Longitude

midpoint between two latitude and longitude

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

Geographic Midpoint between two coordinates

You placed some parentheses wrong. I marked the place in the code.

private Geocoordinate MidPoint(Geocoordinate posA, Geocoordinate posB)
{
Geocoordinate midPoint = new Geocoordinate();

double dLon = DegreesToRadians(posB.Longitude - posA.Longitude);
double Bx = Math.Cos(DegreesToRadians(posB.Latitude)) * Math.Cos(dLon);
double By = Math.Cos(DegreesToRadians(posB.Latitude)) * Math.Sin(dLon);

midPoint.Latitude = RadiansToDegrees(Math.Atan2(
Math.Sin(DegreesToRadians(posA.Latitude)) + Math.Sin(DegreesToRadians(posB.Latitude)),
Math.Sqrt(
(Math.Cos(DegreesToRadians(posA.Latitude)) + Bx) *
(Math.Cos(DegreesToRadians(posA.Latitude)) + Bx) + By * By)));
// (Math.Cos(DegreesToRadians(posA.Latitude))) + Bx) + By * By)); // Your Code

midPoint.Longitude = posA.Longitude + RadiansToDegrees(Math.Atan2(By, Math.Cos(DegreesToRadians(posA.Latitude)) + Bx));

return midPoint;
}

Calculate the mid point of latitude and longitude co-ordinates

Apologies for the long script - it just seemed fun to draw stuff :-). I've marked off sections that are not required

// your latitude / longitude
var co2 = [70, 48];
var co1 = [-70, -28];

// NOT REQUIRED
var ctx = document.getElementById("myChart").getContext("2d");

function drawPoint(color, point) {
ctx.fillStyle = color;
ctx.beginPath();
ctx.arc(point.x, point.y, 5, 0, 2 * Math.PI, false);
ctx.fill();
}

function drawCircle(point, r) {
ctx.strokeStyle = 'gray';
ctx.setLineDash([5, 5]);
ctx.beginPath();
ctx.arc(point.x, point.y, r, 0, 2 * Math.PI, false);
ctx.stroke();
}

// REQUIRED
// convert to cartesian
var projection = d3.geo.equirectangular()

var cot1 = projection(co1);
var cot2 = projection(co2);

var p0 = { x: cot1[0], y: cot1[1] };
var p1 = { x: cot2[0], y: cot2[1] };

// NOT REQUIRED
drawPoint('green', p0);
drawPoint('green', p1);

// REQUIRED
function dfn(p0, p1) {
return Math.pow(Math.pow(p0.x - p1.x, 2) + Math.pow(p0.y - p1.y, 2), 0.5);
}

// from http://math.stackexchange.com/a/87374
var d = dfn(p0, p1);
var m = {
x: (p0.x + p1.x) / 2,
y: (p0.y + p1.y) / 2,
}

var u = (p1.x - p0.x) / d
var v = (p1.y - p0.y) / d;

// increase 1, if you want a larger curvature
var r = d * 1;
var h = Math.pow(Math.pow(r, 2) - Math.pow(d, 2) / 4, 0.5);

// 2 possible centers
var c1 = {
x: m.x - h * v,
y: m.y + h * u
}
var c2 = {
x: m.x + h * v,
y: m.y - h * u
}

// NOT REQUIRED
drawPoint('gray', c1)
drawPoint('gray', c2)

drawCircle(c1, r)
drawCircle(c2, r)

// REQUIRED

// from http://math.stackexchange.com/a/919423
function mfn(p0, p1, c) {
// the -c1 is for moving the center to 0 and back again
var mt1 = {
x: r * (p0.x + p1.x - c.x * 2) / Math.pow(Math.pow(p0.x + p1.x - c.x * 2, 2) + Math.pow(p0.y + p1.y - c.y * 2, 2), 0.5)
};
mt1.y = (p0.y + p1.y - c.y * 2) / (p0.x + p1.x - c.x * 2) * mt1.x;

var ma = {
x: mt1.x + c.x,
y: mt1.y + c.y,
}

var mb = {
x: -mt1.x + c.x,
y: -mt1.y + c.y,
}

return (dfn(ma, p0) < dfn(mb, p0)) ? ma : mb;
}

var m1 = mfn(p0, p1, c1);
var m2 = mfn(p0, p1, c2);

var mo1 = projection.invert([m1.x, m1.y]);
var mo2 = projection.invert([m2.x, m2.y]);

// NOT REQUIRED
drawPoint('blue', m1);
drawPoint('blue', m2);

// your final output (in lat long)
console.log(mo1);
console.log(mo2);

Fiddle - https://jsfiddle.net/srjuc2gd/


Sample Image


And here's just the relevant portion (most of it is just copy-pasta from the beginning of this answer)

var Q31428016 = (function () {

// adjust curvature
var CURVATURE = 1;

// project to convert from lat / long to cartesian
var projection = d3.geo.equirectangular();

// distance between p0 and p1
function dfn(p0, p1) {
return Math.pow(Math.pow(p0.x - p1.x, 2) + Math.pow(p0.y - p1.y, 2), 0.5);
}

// mid point between p0 and p1
function cfn(p0, p1) {
return {
x: (p0.x + p1.x) / 2,
y: (p0.y + p1.y) / 2,
}
}

// get arc midpoint given end points, center and radius - http://math.stackexchange.com/a/919423
function mfn(p0, p1, c, r) {

var m = cfn(p0, p1);

// the -c1 is for moving the center to 0 and back again
var mt1 = {
x: r * (m.x - c.x) / Math.pow(Math.pow(m.x - c.x, 2) + Math.pow(m.y - c.y, 2), 0.5)
};
mt1.y = (m.y - c.y) / (m.x - c.x) * mt1.x;

var ma = {
x: mt1.x + c.x,
y: mt1.y + c.y,
}

var mb = {
x: -mt1.x + c.x,
y: -mt1.y + c.y,
}

return (dfn(ma, p0) < dfn(mb, p0)) ? ma : mb;
}

var Q31428016 = {};
Q31428016.convert = function (co1, co2) {

// convert to cartesian
var cot1 = projection(co1);
var cot2 = projection(co2);

var p0 = { x: cot1[0], y: cot1[1] };
var p1 = { x: cot2[0], y: cot2[1] };

// get center - http://math.stackexchange.com/a/87374
var d = dfn(p0, p1);
var m = cfn(p0, p1);

var u = (p1.x - p0.x) / d
var v = (p1.y - p0.y) / d;

var r = d * CURVATURE;
var h = Math.pow(Math.pow(r, 2) - Math.pow(d, 2) / 4, 0.5);

// 2 possible centers
var c1 = {
x: m.x - h * v,
y: m.y + h * u
}
var c2 = {
x: m.x + h * v,
y: m.y - h * u
}

// get arc midpoints
var m1 = mfn(p0, p1, c1, r);
var m2 = mfn(p0, p1, c2, r);

// convert back to lat / long
var mo1 = projection.invert([m1.x, m1.y]);
var mo2 = projection.invert([m2.x, m2.y]);

return [mo1, mo2]
}

return Q31428016;
})();

// your latitude / longitude
var co1 = [-70, -28];
var co2 = [70, 48];

var mo = Q31428016.convert(co1, co2)

// your output
console.log(mo[0]);
console.log(mo[1]);

Determining Midpoint Between 2 Coordinates

Just a hunch, but I noticed your lon2 and lat2 variables are being computed with M_PI/100 and not M_PI/180.

double lon1 = _lo1.longitude * M_PI / 180;
double lon2 = _loc2.longitude * M_PI / 100;

double lat1 = _lo1.latitude * M_PI / 180;
double lat2 = _loc2.latitude * M_PI / 100;

Changing those to 180 might help you out a bit.

Python lat/long midpoint calculation gives wrong result when longitude 90

Replace your arg set up code by:

lat1, lon1 = p1
lat2, lon2 = p2
assert -90 <= lat1 <= 90
assert -90 <= lat2 <= 90
assert -180 <= lon1 <= 180
assert -180 <= lon2 <= 180
lat1, lon1, lat2, lon2 = map(math.radians, (lat1, lon1, lat2, lon2))

and run your code again.

Update A few hopefully-helpful general suggestions about calculations involving latitude/longitude:

  1. Input lat/lon in degrees or radians?
  2. Check input lat/lon for valid range
  3. Check OUTPUT lat/lon for valid range. Longitude has a discontinuity at the international dateline.

The last part of the midpoint routine could be usefully changed to avoid a potential problem with long-distance use:

lon3 = lon1 + math.atan2(dy, math.cos(lat1) + dx)
# replacement code follows:
lon3d = math.degrees(lon3)
if lon3d < -180:
print "oops1", lon3d
lon3d += 360
elif lon3d > 180:
print "oops2", lon3d
lon3d -= 360
return(math.degrees(lat3), lon3d)

For example, finding a midpoint between Auckland, New Zealand (-36.9, 174.8) and Papeete, Tahiti (-17.5, -149.5) produces oops2 194.270430902 on the way to a valid answer (-28.355951246746923, -165.72956909809082)

Mid point of two point where latitude and longitude given

This was covered by Dr. Math. Latitude and Longitude of a Point Halfway between Two Points

C# Find Midpoint of two Latitude / Longitudes

It appears that your output is correct, except that it is in radians and you are expecting degrees? you may need to convert from radian to degrees to meet the expected output.

-(2.1321400763480485 radians) = -122.162628 degrees
0.65970036060147585 radians = 37.7980464 degrees

It looks like you are already using the great-circle algorithm that Jon Martin and IanDotKelly mentioned.

Geokit LatLng midpoint between two points

In your example, the two points are the same, to a very close approximation. It is worth identifying the difference - i.e. why you do not get the same object:

a.midpoint_to(b) 
<Geokit::LatLng:0x0000000292f368 @lat=12.95888590853612, @lng=80.25053859693796>

b.midpoint_to(a)
<Geokit::LatLng:0x00000002933f80 @lat=12.958885908536992, @lng=80.250538596>
  • The first numbers, 0x0000000292f368 and 0x00000002933f80 are the object identities (it is not clear whether you already knew that). They will always be different in any new object instance, and do not measure anything related to distances or locations. There are a few other classes where this number is not shown, or is the same when answers are equal.

  • The difference in @lat and @lng is due to limits of floating-point precision. The results are not the same because the calculation to get the mid-point does not use the two sets of input numbers in exactly equivalent ways. In fact, even with very simple maths in floating point, a + (b - c) may not be the same as (a + b) - c. When you look at the difference in longitude you have between the two calculated mid-points, it is 9.379590437674779e-10 degrees. On the surface of the Earth, that is roughly a distance of 0.0001 metres (0.1 millimetres), whilst your input points are roughly 14.7 kilometres apart.

If you measure the distance using geokit, you get a reassuring 0.0, which you could probably use to confirm that two calculations are close enough to count as exactly the same point:

a = Geokit::LatLng.new(13.0627081,80.274658)
b = Geokit::LatLng.new(12.8550615,80.2264393)
m1 = a.midpoint_to(b)
m2 = b.midpoint_to(a)
if m1.distance_to( m2 ) > 0
puts "Mid-points are separate"
else
puts "Mid-points are the same location"
end

Output is:

Mid-points are the same location

If you did more complicated calculations, you might prefer to use a number slightly higher than 0.0, e.g 1e-5 (to nearest centimetre).



Related Topics



Leave a reply



Submit