POV-Ray : Newsgroups : povray.general : Proposed VAngle alternative AngleBetweenVectors. (Attn: Tor Olav) : Re: Proposed VAngle alternative AngleBetweenVectors. (Attn: Tor Olav) Server Time
29 Nov 2022 12:25:16 EST (-0500)
  Re: Proposed VAngle alternative AngleBetweenVectors. (Attn: Tor Olav)  
From: William F Pokorny
Date: 13 May 2021 15:35:27
Message: <609d7f7f$1@news.povray.org>
On 5/11/21 4:50 AM, William F Pokorny wrote:
> OK. Been running both approaches within the c++ 'vectors.h' framework of 
> POV-Ray. Initial idea is both forms could be in one inbuilt function and 
> therefore "munction" too.
> 
> // Original macro approach:
> 
> #macro VAngle(V1, V2)
>      acos(max(-1,min(1,vdot(vnormalize(V1),vnormalize(V2)))))
> #end
> 
> 
> // Tor Olav's proposal for better accuracy:
> #macro AngleBetweenVectors(v1, v2)
> 
>      #local v1n = vnormalize(v1);
>      #local v2n = vnormalize(v2);
> 
>      (2*atan2(vlength(v1n - v2n), vlength(v1n + v2n)))
> 
> #end // macro AngleBetweenVectors
> 
...
> 
> I have still a few other tests in mind(1), but busy for a couple days - 
> starting now.
> 
> (1) - Different optimizations, etc.
...

All more complicated than expected and I'm not normally concise, but 
I'll try...

I now have an inbuilt f_vangle() which supports both the old and Tor 
Olav's method - and where both are faster when used within VAngle making 
it now a "munction." I'll post more about f_vangle later in povray 
unofficial patches.

---
Using more targeted random vectors near the noisy parts:

Largest diff 2 ver    0.00000003650005986  ~ 1e-7
Max dot prod sum     +1.00000000000000067  (3x DBL_EPSILON)
Min dot prod sum     -1.00000000000000067
Min abs dot prod sum  0.00000000000000000

---
With the results above, one might ask how did we not have domain errors 
on the -1 side with all those acos(dot(... based macros we have?

Ans: It turns out the parser version of acos tests the inputs, clamps if 
need be and issues a warning on each bad-domain call. This means any 
math.inc clamping is really there to suppress the warning messages.

Why not a parse error over a warning is a good question - given warnings 
can be ignored. It would be better for the user to learn and correct code.

---
The raw acos result and so the vm version of acos returns nan (not a 
number) for bad inputs. Peripherally related compiler optimizations 
related to the -ffastmath optimizations cause internal routines like
POV_ISINF, POV_ISNAN (std::isnan and the like too) to always return 
false. And, POV_ISFINITE and IsFinite() to always return true. These are 
not much used, but this caught me up as I was trying to use them to pick 
up domain errors initially.

---
Related to this VAngle look we have in math.inc a macro called 
VCos_Angle which I believe should be clamped and it now is in my version.

// Cosine of angle between V1 and V2
// #macro VCos_Angle(V1, V2) vdot(vnormalize(V1), vnormalize(V2)) #end
    // +14% over million calls to clamp, but we should clamp.
    #macro VCos_Angle(V1, V2)
        max(-1,min(1,vdot(vnormalize(V1),vnormalize(V2))))
    #end

---
By experiment only it looks like the old method gives us about 7 
significant digits, Tor Olav's 12 significant digits. This is at 
extremes, however.

---
I ran both approaches posted at top against over a million random vector 
calls to measure the performance impact of the more accurate method.

One million calls to VAngle

9.65user 5.52system 0:15.70elapsed  <-- Original acos(dot..)macro.
10.01user 5.24system 0:15.79elapsed     with both min and max clip.
9.69user 5.35system 0:15.58elapsed
9.69user 5.36system 0:15.58elapsed
   "9.65 9.69 9.69"

One million calls to AngleBetweenVectors

11.21user 5.31system 0:17.05elapsed
11.35user 5.26system 0:17.14elapsed
11.57user 5.48system 0:17.57elapsed
11.43user 5.45system 0:17.42elapsed
   "11.21 11.35 11.43"                 29.03 -> 33.99 ---> +17.09%

Expect similar performance differences in any v3.8 based branch.

Bill P.


Post a reply to this message

Copyright 2003-2021 Persistence of Vision Raytracer Pty. Ltd.