6
votes

I have put together a cities database from MaxMind and it includes the lat/lng values for each city in the database. I have also put together a map of North/America and I would like to have a icon appear on the x/y coordinates of the map which are derived from the lat/lng coordinates of the city database record.

From my understanding I need to find the left/top bounds of the map first (lat/lng -> x/y) and then use that as a difference for the linear relationship between any of the north american city x/y coords. Finally, depending on the size of the map, its just a few simple division and subtraction operations to figure out where to place the point.

However I can't seem to figure out how todo the following:

  1. I'm not sure what the lat/lng mapping system is. How do I find this out?
  2. Using a JavaScript library, how do I convert the lat/lng to pixels for the 0,0 coord and each of the city coords. I've tried Proj4js, but they require that you specify your coordinate map types and so on. Here is another question that asked something similar. Convert long/lat to pixel x/y on a given picture

Any ideas?

-- EDIT --

The output map (of North America) is a continuous cylinder: "Miller cylindrical projection". http://en.wikipedia.org/wiki/Miller_cylindrical_projection

3
The math can be pretty simple, but it depends on the type of map, that is, which projection is the map rendered in? en.wikipedia.org/wiki/Map_projectionUmbrella
The output map is a continuous cylinder: "Miller cylindrical projection". en.wikipedia.org/wiki/Miller_cylindrical_projectionmatsko
The Wikipedia article you linked gives the formulas… why don't you use those?derobert
check this tool: trimaps.comGilbou

3 Answers

11
votes

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.

3
votes

Here is a Javascript implementation of a Mercator projection that returns only positive values (cartesian coordinate system of screens) and accounts for the sphere > flat conversion:

// get x   
var x = (lng + 180) * (mapWidth / 360);
// convert from degrees to radians
var latRad = lat * Math.PI / 180;
// get y value
var mercN = Math.log(Math.tan((Math.PI / 4) + (latRad / 2)));
var y = (mapHeight / 2) - (mapWidth * mercN / (2 * Math.PI));
0
votes

This is a very old question, but the accepted answer has some... nuances...

Typically, this is done for satellite/aerial imagery, which is usually accompanied by a "zoom-level."

This zoom-level roughly (and I mean roughly) translates to the "ground-sample-distance" or GSD, which, when provided, represents the centimeters per pixel in an image.

You'll often see zoom-levels of 18, 19, 20, or 21.

One of the issues to note is that the Earth is not flat nor perfectly spherical, therefore, there are many different "projection" methods available to translate from a three-dimensional coordinate of the Earth's surface to a two-dimensional image on a screen. The most popular and widely used of these projection methods is the Mercator projection.

Google provides a method that uses the Mercator projection to provide a pixel coordinate of x and y.

We can then use the "zoom-level" to scale the coordinate to fit our image.

interface LatLngLiteral {
    lat: number;
    lng: number;
}

interface Coordinate {
    x: number;
    y: number;
}

const project = (latLng: LatLngLiteral): Coordinate => {
    const TILE_SIZE: number = 256;
    let siny: number = Math.sin((latLng.lat * Math.PI) / 180);

    // Truncating to 0.9999 effectively limits latitude to 89.189. This is
    // about a third of a tile past the edge of the world tile.
    siny = Math.min(Math.max(siny, -0.9999), 0.9999);

    return {
        x: TILE_SIZE * (0.5 + latLng.lng / 360),
        y: TILE_SIZE * (0.5 - Math.log((1 + siny) / (1 - siny)) / (4 * Math.PI))
    };
};
export function formatToPoint(latLng: LatLngLiteral, zoom: number): Coordinate {
    // Get the world coordinates in pixels
    const worldCoordinate: Coordinate = project(latLng);
    // Scale to fit our image
    const scale: number = Math.pow(2, zoom);

    // Apply scale to world coordinates to get image coordinates
    return {
        x: Math.floor(worldCoordinate.x * scale),
        y: Math.floor(worldCoordinate.y * scale)
    }
}