OpenRoad + Mod7
Two pioneering organizations, together at last.
OpenRoad is pleased to announce the acquisition of creative agency Mod7.
Read the letter from our PrincipalOpenRoad + Mod7
OpenRoad is pleased to announce the acquisition of creative agency Mod7.
Read the letter from our PrincipalPosted on June 22, 2006 in Technology by Mod7
Working on some dynamic Flash mapping, I found out how nuts the mapping world is. "Oh yeah, converting from UTM coordinates (those used in many GPS systems) to Lat and Long in Flash, dynamically and in real-time, won't be a big deal."
It was a little trickier than anticipated.
But hard work prevailed!
And luck---for this particular project, the conversions were limited to one geographic area of the world (British Columbia, Canada), so the usual fudging that happens in making map calculations work is limited. I managed to work through this, culling from various cartography sites (they do this stuff in high school??), and got my head wrapped around this... in about three hours. So much for a simple formula. Who would have thought that the earth is not a perfect sphere ?
Anyways, for any of you that need to do something similar someday, I present these three ActionScript functions to help you along (but please don't ask me for tech support!).
function UTMtoLatLong (zone, easting, northing) {
// GRS 80 datum
a = 6378137; // equatorial radius
// b = 6356752.3141 // polar radius
// Flattening : 1/298.257222101
long0 = ((UTMzonetoNum(zone)-1)*6)-180+3; // central meridian of zone
k0 = 0.9996; // scale along long0
onef = 298.257223563;
e2 = 2*(1/onef)-Math.pow((1/onef),2);
// This is the eccentricity of the earth's elliptical cross-section.
ex2 = e2/(1-e2);
ny = northing;
nx = easting-500000; // (relative to central meridian; subtract 500,000 from conventional UTM coordinate).
// Calculate the Meridional Arc
M = ny/k0;
// Calculate Footprint Latitude (fp)
mu = M/(a*(1 - e2/4 - 3*Math.pow(e2,2)/64 - 5*Math.pow(e2,3)/256));
e1 = (1-Math.sqrt(1-e2))/(1+Math.sqrt(1-e2));
J1 = (3*e1/2 - 27*Math.pow(e1,3)/32);
J2 = (21*Math.pow(e1,2)/16 - 55*Math.pow(e1,4)/32);
J3 = (151*Math.pow(e1,3)/96);
J4 = (1097*Math.pow(e1,4)/512);
fp = mu + J1*Math.sin(2*mu) + J2*Math.sin(4*mu) + J3*Math.sin(6*mu) + J4*Math.sin(8*mu);
// Calculate Latitude and Longitude
C1 = ex2*Math.pow((Math.cos(fp)),2);
T1 = Math.pow((Math.tan(fp)),2);
R1 = a*(1-e2)/Math.pow((1-e2*Math.pow((Math.sin(fp)),2)),3/2);
N1 = a/Math.pow((1-e2*Math.pow(Math.sin(fp),2)),1/2);
D = nx/(N1*k0);
Q1 = N1*Math.tan(fp)/R1;
Q2 = (Math.pow(D,2)/2);
Q3 = (5 + (3*T1) + (10*C1) - Math.pow((4*C1),2) - 9*ex2)*Math.pow(D,4)/24;
Q4 = (61 + 90*T1 + 298*C1 + 45*Math.pow(T1,2) - 3*Math.pow(C1,2) - 252*ex2)*Math.pow(D,6)/720;
Q5 = D;
Q6 = (1 + 2*T1 + C1)*Math.pow(D,3)/6;
Q7 = (5 - 2*C1 + 28*T1 - 3*Math.pow(C1,2) + 8*ex2 + 24*Math.pow(T1,2))*Math.pow(D,5)/120;
lat = radiansToDegrees(fp - Q1 * (Q2 - Q3 + Q4));
long = long0 + radiansToDegrees((D-(1+2*T1+C1)*(Math.pow(D,3))/6 + (5-2*C1+28*T1-3*Math.pow(C1,2)+8*ex2+24*Math.pow(T1,2))*(Math.pow(D,5))/120)/Math.cos(fp));
return (lat+'|'+long);
};
function UTMzonetoNum (zone:String) {
// note: currently returns a string, not an integer
for (i=0; i if (zone.charAt(i) == ' ') {
zoneNum = (zone.slice(0,i));
return zoneNum;
break;
}
}
};
function radiansToDegrees (radians:Number) {
degrees = radians/(Math.PI/180);
return (degrees);
};
There you go---enjoy!