Very fast 3D distance check?

后端 未结 13 1899
南方客
南方客 2021-01-31 15:40

Is there a way to do a quick and dirty 3D distance check where the results are rough, but it is very very fast? I need to do depth sorting. I use STL sort like this

13条回答
  •  滥情空心
    2021-01-31 16:20

    I'm disappointed that the great old mathematical tricks seem to be getting lost. Here is the answer you're asking for. Source is Paul Hsieh's excellent web site: http://www.azillionmonkeys.com/qed/sqroot.html . Note that you don't care about distance; you will do fine for your sort with square of distance, which will be much faster.


    In 2D, we can get a crude approximation of the distance metric without a square root with the formula:

    distanceapprox (x, y) =

    which will deviate from the true answer by at most about 8%. A similar derivation for 3 dimensions leads to:

    distanceapprox (x, y, z) =

    with a maximum error of about 16%.

    However, something that should be pointed out, is that often the distance is only required for comparison purposes. For example, in the classical mandelbrot set (z←z2+c) calculation, the magnitude of a complex number is typically compared to a boundary radius length of 2. In these cases, one can simply drop the square root, by essentially squaring both sides of the comparison (since distances are always non-negative). That is to say:

        √(Δx2+Δy2) < d is equivalent to Δx2+Δy2 < d2, if d ≥ 0
    

    I should also mention that Chapter 13.2 of Richard G. Lyons's "Understanding Digital Signal Processing" has an incredible collection of 2D distance algorithms (a.k.a complex number magnitude approximations). As one example:

    Max = x > y ? x : y;

    Min = x < y ? x : y;

    if ( Min < 0.04142135Max )

    |V| = 0.99 * Max + 0.197 * Min;
    

    else

    |V| = 0.84 * Max + 0.561 * Min;
    

    which has a maximum error of 1.0% from the actual distance. The penalty of course is that you're doing a couple branches; but even the "most accepted" answer to this question has at least three branches in it.

    If you're serious about doing a super fast distance estimate to a specific precision, you could do so by writing your own simplified fsqrt() estimate using the same basic method as the compiler vendors do, but at a lower precision, by doing a fixed number of iterations. For example, you can eliminate the special case handling for extremely small or large numbers, and/or also reduce the number of Newton-Rapheson iterations. This was the key strategy underlying the so-called "Quake 3" fast inverse square root implementation -- it's the classic Newton algorithm with exactly one iteration.

    Do not assume that your fsqrt() implementation is slow without benchmarking it and/or reading the sources. Most modern fsqrt() library implementations are branchless and really damned fast. Here for example is an old IBM floating point fsqrt implementation. Premature optimization is, and always will be, the root of all evil.

提交回复
热议问题