Fast Distance Threshold Formula AS3, C++, Java, Python
Posted November 17, 2010 by Nick Vogt in Programming
Most game programmers are familiar with the distance (magnitude) equation and how inefficient it is. Using a square root is a costly function that usually can't be afforded many times per frame. Here is a much more efficient distance equation for situations in which you want to check the distance against a threshold (such as determining if two bounding spheres collide).

Here is the original distance formula:

Distance = Sqrt( (x2 - x1)² + (y2 - y1)² )

And here it is expanded into simple multiplication :

Distance * Distance = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)

(For 3D be sure to add the z part of the formula)

Using simple multiplication results in extremely fast calculations. Here are some performance tests I ran in Actionscript 3. Other programming languages should be similar. I started with the traditional distance equation:

dist = Math.sqrt(Math.pow(x2 - x1,2) + Math.pow(y2 - y1,2));
if(dist < minDist)
{
  // Perform action
}

Looping the above code 10,000,000 iterations resulted in a total process time of 4387 milliseconds. Now here is the simple multiplication version:

dist = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
if(dist < minDist * minDist)
{
  // Perform action
}

The above only took 172 milliseconds!

Note: For both tests I initialized the required variables before any timing, to eliminate initialization time from the test.

I'm sure most game programmers have used the above formula or something similar before, but for those still struggling I hope it will help. Unfortunately it doesn't help as much when you need to use the distance to scale another value (such as using distance to determine how much splash damage to take), as you will be scaling it exponentially! (you can use threshold steps to work around this of course)

Comment on this post


Legacy Comments (4)

futureResident | February 6, 2011 | 12:43 AM PST
a = X1 - X2;
b = Y1 - Y2;
sqNum = ((a * a) + (b * b)) + .208;


if (sqNum < 1) {
initVal = 1 / sqNum;
invVal = true;
} else {
initVal = sqNum;
invVal = false;
}
apprxInit = initVal;
if (apprxInit > 7) {
if (apprxInit < 32768) {
if (apprxInit < 128) {
if (apprxInit < 32) {
apprxInit >>= 2;
if (apprxInit < 4) apprxInit++;
} else {
apprxInit >>= 3;
}
} else {
if (apprxInit < 2048) {
if (apprxInit < 512) {
apprxInit >>= 4;
} else {
apprxInit >>= 5;
}
} else {
if (apprxInit < 8096) {
apprxInit >>= 6;
} else {
apprxInit >>= 7;
}
}
}
futureResident | February 6, 2011 | 12:43 AM PST
} else {
if (apprxInit < 8388608) {
if (apprxInit < 524288) {
if (apprxInit < 131072) {
apprxInit >>= 8;
} else {
apprxInit >>= 9;
}
} else {
if (apprxInit < 2097152) {
apprxInit >>= 10;
} else {
apprxInit >>= 11;
}
}
} else {
if (apprxInit < 134217728) {
if (apprxInit < 33554432) {
apprxInit >>= 12;
} else {
apprxInit >>= 13;
}
} else {
apprxInit >>= 14;
}
}
}
apprxRoot = (apprxInit + initVal / apprxInit) * 0.5;
} else if (apprxInit < 2) apprxRoot = initVal * 0.5 + 0.5
else apprxRoot = initVal * 0.25 + 1;
if (invVal) { apprxRoot = 1 / apprxRoot; }


c = int(apprxRoot);
futureResident | February 6, 2011 | 12:38 AM PST
Man.. damn... I saw this and plopped a few bricks.
I've been working on the exact same problem in AS3, and had thought about breaking the formula apart and looking for a better way, but was.. well, too lazy...
I plugged your code into my benchmark program and found it was 96% slower then the method I arrived at. I thought for sure this would be quicker, but there was 4% to be gained somewhere.
I was looking into using bitwise methods instead. Your code made for a very cool comparison. I want to see the function that puts either of these to shame.
Rydik | February 1, 2011 | 12:39 PM PST
Awesome! I have never really had to worry about performance until recently, and had never considered the iterations required for sqrt. I used this new equation and had a huge performance boost.

Also if the distance checking statement is in a loop it may save even more time to calculate minDist*minDist outside the loop rather than 10,000,000 times in the loop. Thanks!
Features
Free Web MP3 PlayerComputer Build GuidePHP Beginner Tutorials
Post Series
ActionScript 3 TutorialsHard Drive Cost Charts
Popular Tags
actionscriptajaxcall of dutycrysisebayfacebookgooglejavascriptminecraftneweggphprageskyrimtutorialyoutube


H3XED © 2012 Nick Vogt | Web Design
Saturday, May 19, 2012 | Privacy Policy | Disclosure Policy | Contact