Convert Latitude/Longitude Point to a Pixels (X,Y) on Mercator Projection

Conversion of lat/lng coordinates to pixels on a given map (with JavaScript)

Latitude and Longitude are imaginary lines drawn on earth so that you can accurately pinpoint any location on the world . simply put they are the X and Y coords of a plane.
Latitude is a vertical line running from north to south with its 90 deg at the north pole and -90deg at the south pole.

Longitude on the other hand is a horizontal line running east to south with -180deg in the west and 180deg in the east.

you can convert the latLng into pixel coords as by assuming that the width of the html container is the width of the world and the same applies to the the height.

Formula - Longitude - pixel

(givenLng*widthOfContainerElement)/360

where 360 is the total longitude in degrees

Formula -Latitude - pixed

(givenLat*heightOfContainerElement)/180

where 360 is the total longitude in degree

//Height is calculated from the bottom

let me know if you still need any clarifications.

Convert geolocation to pixels on a mercator projection image

So after doing some testing, i discovered that the image i had was misaligned out of the box. I then opened the reference image in https://github.com/mfeldheim/hermap ("Normal" Mercator map 85 deg) and aligned them together, since both were Mercator projection.

These aligned perfectly.

My image does not contain antarctica, and is therefore rectangular, not square as the reference image. To accomodate this, i set the image-height property to the image width, making the formula work as intended.

The final code looks somthing like this:

public mapWidth: number = 2400;
public mapHeight: number = this.mapWidth
public lat = -12.090940;
public long = 49.2645833;
public x: number;
public y: number;

public calculatePixels() {
let latitudeToRadians = ((this.lat * Math.PI) / 180);
let mercN = Math.log(Math.tan((Math.PI / 4) + (latitudeToRadians / 2)));

this.x = ((this.long + 180) * (this.mapWidth / 360));
this.y = ((this.mapHeight / 2) - ((this.mapWidth * mercN) / (2 * Math.PI)))
console.log("node position x / y", this.x, this.y);
}

Convert Longitude and Latitude to image X, Y pixel coordinates on Alber's projection

This albers projection WKT projects from EPSG 4326 to distance in meters from the zero-point (see the parameters). How do we know if it's meters? because the WKT there is a set UNIT label showing it as metre unit.

So how did I use it?

My company gave me two files, the map JPEG file and an XML file for map's constants.

That map constants XML file contains the distance from the zero-point of that map to the corners of the map. So if you have atleast one point on the map, you can find everything.

Things that you need to know to convert it to map X/Y:

  • How many Kilometers is each pixel (in my case its 1.6 exactly 1 mile)
  • atleast one known point on the map in distance from zero point

This is how I did it:

        MathTransform transform = CRS.findMathTransform(epsg4326, targetWKT, true);

DirectPosition2D srcDirectPosition2D
= new DirectPosition2D(epsg4326, latitude, longitude);
DirectPosition2D destDirectPosition2D
= new DirectPosition2D();
transform.transform(srcDirectPosition2D, destDirectPosition2D);

double transX = destDirectPosition2D.x;
double transY = destDirectPosition2D.y;

int kmPerPixel = mapImage.getWidth / 1024; // It is known to me that my map is 1024x1024km ...

double x = zeroPointX + ( (transX * 0.001) * kmPerPixel);
double y = zeroPointY + ( ( (transX * -1) * 0.001) * kmPerPixel);

The zeroPointX and Y you can get from doing the same calculation without adding, on the point you have on the map in distance, like I did with my corner.

Might help some people so I posted what I figured out.

Convert lat/lon to pixel coordinate?

Where did those variables come from

These variables are chosen to match the computed coordinates to the background image of the map. If the projection parameters of the map were known, they could be computed. But I believe it is far more likely that they were obtained through trial and error.

How to compute a Mercator projection

If you want a more general method to describe the section of the world a given (not transverse) Mercator map shows, you can use this code:

// This map would show Germany:
$south = deg2rad(47.2);
$north = deg2rad(55.2);
$west = deg2rad(5.8);
$east = deg2rad(15.2);

// This also controls the aspect ratio of the projection
$width = 1000;
$height = 1500;

// Formula for mercator projection y coordinate:
function mercY($lat) { return log(tan($lat/2 + M_PI/4)); }

// Some constants to relate chosen area to screen coordinates
$ymin = mercY($south);
$ymax = mercY($north);
$xFactor = $width/($east - $west);
$yFactor = $height/($ymax - $ymin);

function mapProject($lat, $lon) { // both in radians, use deg2rad if neccessary
global $xFactor, $yFactor, $west, $ymax;
$x = $lon;
$y = mercY($lat);
$x = ($x - $west)*$xFactor;
$y = ($ymax - $y)*$yFactor; // y points south
return array($x, $y);
}

A demo run of this code is available at http://ideone.com/05OhG6.

Regarding aspect ratio

A setup with $xFactor != $yFactor produces a kind of stretched Mercator projection. This is not conformal (angle-preserving) any more. If one wants a true Mercator projection, one can omit any of the first six variable assignments, i.e. those defining the bounding box or those describing the size of the resulting map, and then use some computation too choose it satisfying $xFactor == $yFactor. But since the choice which to omit is kind of arbitrary, I feel that the above code is the most symmetric way to describe things.

Converting longitude and latitude coordinates to map pixels (X and Y) the right way

The Mercator projection is a cylindrical projection, i.e. the generalized coordinates can be calculated as:

a = longitude
b = tan(latitude)

These are unscaled coordinates, i.e. they do not correspond to pixel positions.

Let's say you have an image of w x h pixels that represents the area between (min_long, min_lat) - (max_long, max_lat). These coordinates can be converted to generalized projected coordinates with the above formulas, which yields (min_a, min_b) - (max_a, max_b).

Now you need a linear mapping of the generalized coordinates to pixel positions. This linear mapping can be expressed with four parameters (two scaling parameters and two offset parameters):

x = s_a * a + o_a
y = s_b * b = o_a

Therefore, you need to find the four parameters. You know that the top left corner has pixel coordinates (0, 0) and generalized coordinates (min_a, max_b). Similarly for the bottom right corner. This gives you four constraints and a linear system of equations:

0 = s_a * min_a + o_a
0 = s_b * max_b + o_b
w = s_a * max_a + o_a
h = s_b * min_b + o_b

The solution of this system is:

s_a =  w / (max_a - min_a)
o_a = -w * min_a / (max_a - min_a)
s_b = -h / (max_b - min_b)
o_b = h * max_b / (max_b - min_b)

And this is it. If you want the pixel coordinates for some arbitrary point `(long, lat), then do the following:

  1. Calculate the generalized coordinates a and b (be careful to use radians when calculating the tangens).
  2. Use the linear map to convert a and b to pixel coordinates x and y with the pre-calculated parameters.

Inversion

To get latitude and longitude from pixel coordinates, do the following:

Calculate the generalized coordinates:

a = (x - o_a) / s_a
b = (x - o_b) / s_b

Calculate the geo-coordinates:

longitude = a
latitude = arc tan (b)

Again, be careful about radians/degrees.

how to convert latitude and longitude to pixels

You should know what geodetic projection has been used to create that map and how rectangular coordinates correspond to geographic ones.

For small map pieces you can use linear approximation, so coordinates might be calculated with linear interpolation.

Example for x-coordinate and longitude:

Lon = LonLeft + X * (LonRight - LonLeft) / Width 

Convert long/lat to pixel x/y on a given picture

The key to all of this is understanding map projections. As others have pointed out, the cause of the distortion is the fact that the spherical (or more accurately ellipsoidal) earth is projected onto a plane.

In order to achieve your goal, you first must know two things about your data:

  1. The projection your maps are in. If they are purely derived from Google Maps, then chances are they are using a spherical Mercator projection.
  2. The geographic coordinate system your latitude/longitude coordinates are using. This can vary, because there are different ways of locating lat/longs on the globe. The most common GCS, used in most web-mapping applications and for GPS's, is WGS84.

I'm assuming your data is in these coordinate systems.

The spherical Mercator projection defines a coordinate pair in meters, for the surface of the earth. This means, for every lat/long coordinate there is a matching meter/meter coordinate. This enables you to do the conversion using the following procedure:

  1. Find the WGS84 lat/long of the corners of the image.
  2. Convert the WGS lat/longs to the spherical Mercator projection. There conversion tools out there, my favorite is to use the cs2cs tool that is part of the PROJ4 project.
  3. You can safely do a simple linear transform to convert between points on the image, and points on the earth in the spherical Mercator projection, and back again.

In order to go from a WGS84 point to a pixel on the image, the procedure is now:

  1. Project lat/lon to spherical Mercator. This can be done using the proj4js library.
  2. Transform spherical Mercator coordinate into image pixel coordinate using the linear relationship discovered above.

You can use the proj4js library like this:

// include the library
<script src="lib/proj4js-combined.js"></script> //adjust the path for your server
//or else use the compressed version
// creating source and destination Proj4js objects
// once initialized, these may be re-used as often as needed
var source = new Proj4js.Proj('EPSG:4326'); //source coordinates will be in Longitude/Latitude, WGS84
var dest = new Proj4js.Proj('EPSG:3785'); //destination coordinates in meters, global spherical mercators projection, see http://spatialreference.org/ref/epsg/3785/

// transforming point coordinates
var p = new Proj4js.Point(-76.0,45.0); //any object will do as long as it has 'x' and 'y' properties
Proj4js.transform(source, dest, p); //do the transformation. x and y are modified in place

//p.x and p.y are now EPSG:3785 in meters

Convert longitude and latitude coordinates to image of a map pixels X and Y coordinates Java

You need to add offsets and lengths of the map in longitude/latitude in addition to pixels. Then you can just do a conversion.

static final int mapWidth = 614, mapHeight = 1141;
// offsets
static final double mapLongitudeStart = 33.5, mapLatitudeStart = 33.5;
// length of map in long/lat
static final double mapLongitude = 36.5-mapLongitudeStart,
// invert because it decreases as you go down
mapLatitude = mapLatitudeStart-29.5;

private static Point getPositionOnScreen(double longitude, double latitude){
// use offsets
longitude -= mapLongitudeStart;
// do inverse because the latitude increases as we go up but the y decreases as we go up.
// if we didn't do the inverse then all the y values would be negative.
latitude = mapLatitudeStart-latitude;

// set x & y using conversion
int x = (int) (mapWidth*(longitude/mapLongitude));
int y = (int) (mapHeight*(latitude/mapLatitude));

return new Point(x, y);
}

public static void main(String[] args) {
System.out.println(getPositionOnScreen(33.5, 33.5).toString());
System.out.println(getPositionOnScreen(35, 32).toString());
System.out.println(getPositionOnScreen(36.5, 29.5).toString());
}

This will print out the following:

java.awt.Point[x=0,y=0]
java.awt.Point[x=307,y=427]
java.awt.Point[x=614,y=1141]


Related Topics



Leave a reply



Submit