Skip to content

Instantly share code, notes, and snippets.

@shiffman
Created February 10, 2017 18:43
Show Gist options
  • Save shiffman/a0d2fde31f571163c730ba0da4a01c82 to your computer and use it in GitHub Desktop.
Save shiffman/a0d2fde31f571163c730ba0da4a01c82 to your computer and use it in GitHub Desktop.
// https://api.mapbox.com/styles/v1/mapbox/streets-v8/static/0,0,2/600x600?access_token=pk.eyJ1IjoiY29kaW5ndHJhaW4iLCJhIjoiY2l6MDJ0Mjk5MDQ1dzJ3bzRiM29zaW16ayJ9.guiqnHMGUq196Zxa1d3UPg
var mapimg;
var zoom = 1;
var data;
var ww = 900;
var hh = 900;
var clat = 0; //37.7749;
var clon = 0; //-122.4194;
function preload() {
mapimg = loadImage('https://api.mapbox.com/styles/v1/mapbox/dark-v9/static/' + clon + ',' + clat + ',' + zoom + '/' + ww + 'x' + hh + '?access_token=pk.eyJ1IjoiY29kaW5ndHJhaW4iLCJhIjoiY2l6MDJ0Mjk5MDQ1dzJ3bzRiM29zaW16ayJ9.guiqnHMGUq196Zxa1d3UPg');
data = loadStrings('http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.csv');
}
// Web Mercator Math
// https://en.wikipedia.org/wiki/Web_Mercator
function mercX(lon) {
lon = radians(lon);
return (256 / PI) * pow(2, zoom) * (lon + PI);
}
function mercY(lat) {
lat = radians(lat);
return (256 / PI) * pow(2, zoom) * (PI - log(tan((PI / 4.0) + (lat / 2.0))));
}
function webMercX(lon, zoom) {
lon = radians(lon);
var w = 256; //width / 2;
var a = (w / PI) * pow(2, zoom);
var b = (lon + PI);
return a * b;
}
function webMercY(lat, zoom) {
lat = radians(lat);
var w = 256; //height / 2;
var a = (w / PI) * pow(2, zoom);
var c = tan(PI / 4 + lat / 2);
var b = PI - log(c)
return a * b;
}
function setup() {
createCanvas(ww, hh);
angleMode(RADIANS);
translate(width / 2, height / 2);
imageMode(CENTER);
image(mapimg, 0, 0);
var cx = webMercX(clon, zoom);
var cy = webMercY(clat, zoom);
//37.7749° N, 122.4194° W
var lat = 40.7128;
var lon = -74.0059;
var x = webMercX(lon, zoom) - cx;
var y = webMercY(lat, zoom) - cy;
noStroke();
fill(255, 0, 0, 200);
ellipse(x, y, 32, 32);
fill(255, 0, 0, 200);
ellipse(cx - cx, cy - cy, 32, 32);
for (var i = 1; i < data.length; i++) {
var stuff = data[i].split(/,/);
console.log(stuff[1], stuff[2]);
var lat = Number(stuff[1]);
var lon = Number(stuff[2]);
var x = webMercX(lon, zoom) - cx;
var y = webMercY(lat, zoom) - cy;
noStroke();
fill(255, 0, 0, 200);
ellipse(x, y, 4, 4);
}
}
@hyojjxipitug
Copy link

I did some cleanup and testing regarding the coordinates conversion to pixel location (see forked gist) and it now displays information that seem realistic.

The problem for me is that the formulas from wikipedia assumes that the converted pixels will be displayed on a complete map of the earth. However, below 1280x1280 mapbox doesn't return a full map, hence the display issues.

@artur31415
Copy link

The problem lies on the zoom thing, it seems that the 2 to the power of zoom "pow(2, zoom)" is not showing it right
when testing, for zoom = 1, for me it worked using "pow(2, zoom - 1)", and for zoom = 2, "pow(2, zoom - 1.3)"
as "pow(2, zoom - v)", v is proportional to zoom

@andia89
Copy link

andia89 commented Feb 11, 2017

Isn't for line 42 a semicolon missing?

@JuanIrache
Copy link

JuanIrache commented Nov 24, 2017

It would be useful to convert form pixels to lat long coordinates too, for mouse interaction.

Edit:
Here's where I got. It works well for converting x to lon, but y to lat fails. I probably didn't solve the equations for c and lat right. Maybe someone with a background in maths can help:

function inverseWebMercX(x,zoom) {
	var w = 256; //width / 2;
  	var a = (w / PI) * pow(2, zoom);
  	var b = x/a;
  	var lon = b-PI;
	lon = degrees(lon);
	return lon;
}

function inverseWebMercY(y,zoom) {
	var w = 256; //width / 2;
 	var a = (w / PI) * pow(2, zoom);
	var b = y/a;
 	var c = -(exp(b) + PI);
 	var lat = (atan2(c) - (PI / 4))*2;
	lat = degrees(lat);
	return lat;
}

@JuanIrache
Copy link

This works now:

function inverseWebMercX(x,zoom) {
    var w = height / 2;
    var a = (w / PI) * pow(2, zoom);
    var b = x/a;
    var lon = b-PI;
    lon = degrees(lon);
    return lon;
}

function inverseWebMercY(y,zoom) {
  var w = height / 2;
  var a = (w / PI) * pow(2, zoom);
  var b = (y/a);
  var c = exp(PI-b);
  var lat = (atan(c) - (PI / 4))*2;
  lat = degrees(lat);
  return lat;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment