Doc,

Unless you're inhabiting a universe orthogonal to this one, latitude is N and longitude is E.

How does it work (linear pulls aside the curtain):

The basic Mercator transformation eq for latitude is :

Northing = A*ln( tan( pi/4 + lat/2) ) (latitude in radians, A is a scale factor)

To plot into a Cartesian coordinate space, you need to define 2 parameters: the vertical extents of the map in degrees, and the width of the map in pixels. Latitude converts to Nothing as described above, and longitude converts ot Easting by a linear (!) scale factor of 2pi. Map height is found by 2*A*ln(tan(pi/4+ maxlat/2)) (where max latitude is the vertical extent of the map, and A is your scale factor).

So now we are scaled to coordinates with the origin at the center. Pixel coordinates have the origin at upper left, and the Y axis inverted. So another scale transformation follows. I whacked together a spreadsheet to help me get the transformations correct before writing the code.

**All that stuff assumes the Earth is spherical. It is, right?

Here are the JavaScript functions that handle the coordinate transformation:

code:

/**** coordinate conversion utilities ****/

function latitude2y(lat, height) {

//** this assumes 75 degree map extents !!

with (Math) {

// convert to radians

var latRadians = lat*PI/180;

// the actual Mercator transformation

// log() is natural log in JS

northing = log(tan((PI/4) + (latRadians/2)));

}

// then scale to our coordinate system

// with the origin in the upper left

// 4.055 is the distance between the 75 degree

// lines, unscaled [2*ln(tan(pi/4 + 75deg/2))]

return( Math.round(height/2 - northing * (height/4.055)) );

}

function longitude2x(longitude, width){

with (Math) {

// convert to radians

var longRadians = longitude*PI/180;

// the actual Mercator transformation

// quite boring for longitude, eh?

easting = longRadians;

}

// then scale to our coordinate system

// with the origin in the upper left

// 6.283 is 2*pi (circumference in radians)

return( Math.round( width/2 + easting * (width/6.283)) );

}

4.055 is a magic constant derived from the fact that the map extents are 75 degrees.

So the rest of the script is pretty simple:

a) set up an array of inmate objects who have lat, long, x, y, email, and url properties

b) iterate over the array and create three DIVs for each inmate

c) position all the DIVS inside that loop

d) handle mouseOver and onClick for the detail DIVs

Creating the DIVs in script is the cool part. It save me from having to code a bunch of stuff. I just add new inmates to the array, and walk away whistling.

I have a 2400 px and 3200 px map also. The way this is coded, I just need to change two definitions at the top of the script and drop in the new gif. Current resuolution of the 1600 px map is 5miles per pixel at the equator.