However the VirtualEarth Viewer is written for Silverlight 1.1, and I want RaceReplay.net to be able to display & animate maps in Silverlight 1.0. Hence the work on a custom TileClient for Silverlight - the most recent sample of which uses a few lines of Greg's codes (converted from C# to Javascript) to dynamically translate screen coordinates to latitude/longitude values (and vice versa)

See it in action here, and check out the ported code below.

`/* Original Author http://blogs.msdn.com/greg_schechter `

License http://msdn.microsoft.com/vstudio/eula.aspx?id=c8bf88e7-841c-43fd-c63d-379943617f36 */

function RadiansToDegrees (rad)

{

return (rad / Math.PI * 180.0);

}

function DegreesToRadians (deg)

{

return (deg * Math.PI / 180.0);

}

/* SLVirtualEarthViewer */

// Extent maps to +-180 for Longitude and +-85 for Latitude

function LongLatFromCoordinate (coordinate, worldRect)

{

var x = ((coordinate.X - worldRect.Left) * 360.0 / worldRect.Width) - 180.0;

var y = RadiansToDegrees (2 * Math.atan(Math.exp(Math.PI * (1.0 - 2.0 * (coordinate.Y - worldRect.Top) / worldRect.Height))) - Math.PI * 0.5);

var point = eval('({"X":'+x+', "Y":'+y+'})');

return point;

}

function CoordinateFromLongLat (longLat, worldRect)

{

var coordinate = eval('({"X":0, "Y":0})');

coordinate.X = worldRect.Left + (longLat.X + 180.0) * worldRect.Width / 360.0;

coordinate.Y = worldRect.Top + (worldRect.Width * 0.5) * (1 - (Math.log(Math.tan(DegreesToRadians(longLat.Y) * 0.5 + Math.PI * 0.25))) / Math.PI);

return coordinate;

}

And to use it...

`var world = eval('({"Left":0, "Top":0, "Width":512, "Height":512})');`

/* wired up to Silverlight event */

function onMouseMove (sender, mouseEventArgs)

{

var currX = mouseEventArgs.getPosition(null).x;

var currY = mouseEventArgs.getPosition(null).y;

var coo = eval('({"Y":'+currY+', "X":'+currX+'})');

var ll= LongLatFromCoordinate(coo, world);

document.getElementById('output').innerHTML = 'Lat/long: ' + ll.X + ', ' + ll.Y;

var coord = CoordinateFromLongLat(ll, world);

document.getElementById('output').innerHTML += '

Screen: ' + coord.X + ', ' + coord.Y;

}

Now to hook this up with a conversion to Virtual Earth image tile 'quadkey' values...

p.s. if you are interested in a slightly different version of the lat/long-coordinate conversion, download the sample code for Roll Your Own Tile Server and examine the XToLongitudeAtZoom() and YToLatitudeAtZoom() javascript functions. It's also a very cool sample.

do you know what projections this will work for?

ReplyDeleteMercator i think, which is the big flat square (+/-85 latitude) that microsoft and google use for their respective mapping sites.

ReplyDeleteCan you tell me where I can get the code for zoom for the current lat lon to xy conversion.

ReplyDeletePavan - not sure what you mean: zoom is just a function of the width/height of the map. In the above example it's 512x512 - but if you modify those values you will get the 'zoom'ed coordinates...

ReplyDeleteI think there is a small bug (width/height swapped).

ReplyDeleteInstead of:

coordinate.Y = worldRect.Top + (worldRect.Width * 0.5) * (1 - (Math.log(Math.tan(DegreesToRadians(longLat.Y) * 0.5 + Math.PI * 0.25))) / Math.PI);

it should be:

coordinate.Y = worldRect.Top + (worldRect.Height * 0.5) * (1 - (Math.log(Math.tan(DegreesToRadians(longLat.Y) * 0.5 + Math.PI * 0.25))) / Math.PI);