Mercator Projection Slightly Off
Solution 1:
The earth is not a true ellipsoid, there are a high number of coordinate systems, and passing from one system to another one is far from simple. You could have a look to pyproj a Python interface to the well known proj.4 library to convert from Lat-Lon (I assume WGS84 ...) to almost any other coordinate including of course Mercator. You could try to roll your own, but there are so many caveats such as different origin meridians, slight differences in reference ellipsoid, that you have little hope to have correct and accurate results.
But you have some reference material on WGS84 on wikipedia
Solution 2:
I made an object that does similar calculations. Maybe it might give you some inspiration. Basically I treat the earth as an ellipsoid. earthCirc along the equator is not the same as earthCirc through the poles. I try to make conversions between distances in meter <-> angles of lat & lng.
See if my object is more accurate than yours (mine surely has bugs, if you use some extreme values)
/**
* @file: Javascript object to help calculate with latitude, longitude, together with distances (in meter) and angles.
* The initial goal was to calculate the end point (in lat and latitude & longitude) of a line perpendicular to another line.
*
* Planet Earth is approximately an ellipsoid. The circumference along the equator is
* somewhat greater than the equator through both poles.
* this javascript object makes calculations that are useful for Google Maps.
* This will allow to use pythagoras for coordinates, as if earth is a flat rectangle.
* The precision of the results decreases when the distances increase; and near the poles.
* Any calculation where the latitude goes beyond the poles ( > 90 or < -90 ) will probably return complete nonsence.
*
* @author: Emmanuel Delay, emmanueldelay@gmail.com
* copyleft 2014. Feel free to use, copy, share, improve
* Please send me the code, if you make improvements.
*
* Examples:
<script>
function log(message) {
document.getElementById('log').innerHTML += message + '<br>';
}
window.onload = function() {
var dLatLng = Earth.xy2LatLng(5000000, 5000000, 0.0);
latLng = [dLatLng.lat, dLatLng.lng ];
log(
'Start from 0,0 ; move 5000km to the north, 5000km to the east: ' +
latLng[0] +','+ latLng[1]
);
var eifel = {lat: 48.8582186, lng: 2.2946114};
var dLatLng = Earth.xy2LatLng(1000, 2000, eifel.lat);
latLng = [dLatLng.lat, dLatLng.lng ];
var dest = [eifel.lat + latLng[0], eifel.lng + latLng[1] ];
log(
'Move 1km to the north, 2km to the east of the Eifel Tower: ' +
dest[0] +','+ dest[1]
);
var dLatLng = Earth.setHeading(eifel.lat, eifel.lng, 10000, 30);
latLng = [dLatLng.lat, dLatLng.lng ];
log(
'Move 10km from the Eifel Tower, heading 30° (North = 0; east = 90°; ...): ' +
latLng[0] +','+ latLng[1]
);
}
</script>
<div id="log"></div>
* note:
* - all distances are in meter. all angles are in degree
* - the d in dLat and dLng stands for delta, being a change in coordinates
* - x is along the longitude, y is along latitude
*/
Earth = {
// @see http://www.space.com/17638-how-big-is-earth.html for the data// along the equator
circumference_equator: 40075000,
// throught both poles.// Note: this is basically the original definition of the meter; they were 2km off on a distance from pole to equator ( http://en.wikipedia.org/wiki/History_of_the_metre )
circumference_poles: 40008000,
// given a change in latitude, how many meters did you move?
lat2Y: function(dLat) {
returnthis.circumference_poles / 360 * dLat;
},
// given a change in longitude and a given latitude, how many meters did you move?
lng2X: function(dLng, lat) {
return Math.cos( this.deg2rad(lat) ) * (this.circumference_poles / 360 * dLng);
},
// given a distance you move due North (or South), what's the new coordinates?// returns a change in latitude
y2Lat: function(y) {
return y * 360 / this.circumference_poles;
},
// given a distance you move due East (or West) and a given latitude, what's the new coordinates?// returns a change in longitude
x2Lng: function(x, lat) {
return x * 360 / ( Math.cos( this.deg2rad(lat) ) * this.circumference_poles);
},
// (360°) degrees to radials
deg2rad: function(deg) {
return deg * Math.PI / 180;
},
// returns a change in position
xy2LatLng: function(y, x, lat) {
return {
lat: this.y2Lat(y),
lng: this.x2Lng(x, lat)
};
},
// @param heading: North = 0; east = 90°; ...// returns a change in position
setHeading: function(lat, lng, dist, heading) {
var latDestination = lat + this.y2Lat(dist * Math.cos(this.deg2rad(heading)));
var lngDestination = lng + this.x2Lng(dist * Math.sin(this.deg2rad(heading)), lat);
return {
lat: latDestination,
lng: lngDestination
};
},
// returns the absolute position
moveByXY: function(lat, lng, x, y) {
var dLatLng = Earth.xy2LatLng(x, y, lat);
latLng = [dLatLng.lat, dLatLng.lng ];
return {
lat: lat + latLng[0],
lng: lng + latLng[1]
}
}
}
Post a Comment for "Mercator Projection Slightly Off"