Created
February 10, 2017 18:43
-
-
Save shiffman/a0d2fde31f571163c730ba0da4a01c82 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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); | |
} | |
} |
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
Isn't for line 42 a semicolon missing?
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;
}
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
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.