Calculating angle in isometric view

I have an angle where I need to convert a 'normal' angle to an isometric angle (116 degrees), and I came up with this function. It works, but I was wondering if the math could be optimized/simplified, or if this is the way to go. It's for a mobile game.

public static inline var ISO:Float = 0.45378560551; // (116-90) / 180 * PI=;

function convert(angle:Float):Float
{
angle -= Math.PI; // corrected angle

var randomChoosenDistance = 2.0; // could be anything, I'm only interested in final angle.

// calculate new line, using isometic angle.
var x1 = Math.cos(angle - ISO);
var x2 = Math.cos(angle - ISO) * randomChoosenDistance;
var y1 = Math.sin(angle);
var y2 = Math.sin(angle) * randomChoosenDistance;

var dx = x1 - x2;
var dy = y1 - y2;

angle = Math.atan2(dy, dx);
return angle;
}


Can I get the new angle, without calculating the angle between the temporary points I'm creating at the moment?

@neo pointed out that dx can be calculated as (1 - r) * Math.cos(a - b). Similarly, dy = (1 - r) * Math.sin(a). However, when you take dy / dx, which is what Math.atan2(dy, dx) implicitly does with its arguments, the (1 - r) factor cancels out. You can also see, using a geometric argument, that (x2, y2) is pointless (pardon the pun).

Therefore, Math.atan2(y1, x1) would work just the same as Math.atan2(dy, dx).

So far, your function can be simplified to the following. Since you repurposed angle twice, I need to disambiguate them as alpha, beta, and theta for this discussion.

public static inline var ISO:Float = 0.45378560551; // (116-90) / 180 * PI=;

function convert(alpha:Float):Float
{
var beta = alpha - Math.PI; // corrected angle

// calculate new line, using isometic angle.
var x1 = Math.cos(beta - ISO);
var y1 = Math.sin(beta);

var theta = Math.atan2(y1, x1);
return theta;
}


But wait, there's more! There's a mysterious correction from alpha to beta, and the cosine expression is complicated.

Let's start with Math.sin(beta). That's Math.sin(-alpha), or -Math.sin(alpha).

It would be nice to say Math.atan2(Math.sin(alpha), something) instead of Math.atan2(-Math.sin(alpha), something). Let's move the negation into the denominator then, for var theta = Math.atan2(Math.sin(alpha), -x1).

Can we simplify -x1?

-x1 = -Math.cos(beta - ISO)
= Math.cos(beta - ISO + 180°)
= Math.cos(alpha - 180° - ISO + 180°)
= Math.cos(alpha - ISO)


public static inline var ISO:Float = 0.45378560551; // = (116-90) / 180 * PI

function convert(angle:Float):Float
{
return Math.atan2(Math.sin(angle), Math.cos(angle - ISO));
}


Not only is the code more efficient, it's also less mysterious: the transformation is taking the x-coordinate of each point as if it were rotated 26° clockwise!

I have to question the motivation behind this function, though. This isn't an angle-preserving transformation, so why are you operating on an angle? Normally, you transform points' coordinates using matrix multiplication.

• Thanks for taking time to this in-depth answer! It's very clear. About how I'm using this function: I have spritesheets from an old game that are drawn in isometric perspective, but my game itself runs in normal perspective (it only looks isometric). I'm using this function to get the right index on the spritesheet. So yes; I have to admit this function is very project specific. – Mark Knol Jan 20 '14 at 14:19

It seems to me that this is a math related question rather than code review. Let's simplified the code first,

var dx = Math.cos(a - b) - Math.cos(a - b) * r;


The above can be simplified to

var dx = (1 - r) * Math.cos(a - b);


One less Math.cos and one less multiplication is being called, which could be CPU consuming.

• Thanks, I was looking for simplified code, this helps a lot. – Mark Knol Jan 15 '14 at 19:20