2
$\begingroup$

I want to display a point with a latitude and a longitude value in an isometric world map using JavaScript and jQuery.

For a rectangular map, I use the following code to calculate the x and y position of the marker:

marker.y = map_range(position.lat, 90, -90, 0, $('#map').height()); marker.x = map_range(position.lng, -180, 180, 0, $('#map').width());  function map_range(value, low1, high1, low2, high2) {     return low2 + (high2 - low2) * (value - low1) / (high1 - low1); } 

How do I transfer this formula to a pseudo-isometric map? (skewed 45 degrees, height = .5 * width)?

enter image description here

P.S. I first posted this question on StackOverflow, and people directed me here to ask for an answer. For those not familiar with JavaScript or jQuery: $('#map').height() represents the height of the map, the same goes for the width. If you have any other questions about the code, please ask.

  • 0
    I've taken the liberty of editing in the image from your StackOverflow question. I had a really hard time understanding your question until I saw it.2011-05-17

2 Answers 2

2

Having previously done this kind of isometric transforming in my own programming, I think what will be useful to you is a function that converts from rectangular to isometric. I believe something like this is what you're looking for (feel free to tweak as needed).

(Let $x$ and $y$ be the original rectangular coordinates and $u$ and $v$ be the transformed isometric coordinates.)

$u = \displaystyle \frac{(2x+2y)(x+3y)}{\sqrt{2}}$

$v = \displaystyle \frac{(x-y)(3x-y)}{\sqrt{2}}$

I derived this by transforming from rectangular into isometric ($x \mapsto 2x+2y$ and $y \mapsto x-y$) and then rotating by 45 degrees around the origin (using sum and difference identities to simplify).

Is that sufficient for your needs?

  • 0
    Actually, u and v are Cartesian values as well. Also, that image seems to be a rotate-then-transform kind of thing, so my formulas may be wrong, although I haven't checked.2011-05-17
2

Here's a simple solution which can be adapted to handle any map orientation:

// scale lat and lng to range -1 .. 1 var lat = position.lat / 90; var lng = position.lng / 180;  // get map image width and height var w = $('#map').width(); var h = $('#map').height();  // origin is at center of map var x0 = w/2; var y0 = h/2; // lat axis points top left from origin var dx_lat = -w/4; var dy_lat = -h/4; // and lng axis points top right from origin var dx_lng = +w/4; var dy_lng = -h/4;  marker.x = x0 + (lat * dx_lat) + (lng * dx_lng); marker.y = y0 + (lat * dy_lat) + (lng * dy_lng); 

Of course, you could just substitute the values of x0, y0, dx_lat, dy_lat, dx_lng and dy_lng into the final expressions (and pull out the common factors of 1/4), but I've written them out like this so that it's easier to see what's going on.

Also, since this is math.stackexchange, I should point out that those values, in effect, define an affine transformation: $\begin{bmatrix} x \\ y \end{bmatrix} = \begin{bmatrix} x_0 \\ y_0 \end{bmatrix} + \begin{bmatrix} \tfrac{\partial x}{\partial u} & \tfrac{\partial x}{\partial v} \\ \tfrac{\partial y}{\partial u} & \tfrac{\partial y}{\partial v} \end{bmatrix} \begin{bmatrix} u \\ v \end{bmatrix}, $ where $u$ and $v$ are the scaled latitude and longitude respectively. Such affine transformations are quite common and useful when dealing with computer graphics.