William F Pokorny <ano### [at] anonymousorg> wrote:
> In creating some testing for include file macros I came across code for
> the two VAngle* macros (and two similar rotation related macros):
> #macro VAngle(V1, V2)
> acos(min(1, vdot(vnormalize(V1), vnormalize(V2))))
> The min(1,..) is obviously trying to protect acos from domain errors.
> Why only the clamp to the positive side? Aren't we as exposed to <-1.0?
> Often enough in code - including POV_Ray's own - I've seen code clamping
> to a [-1..1] range after a dot product into acos() for acos domain
> I cannot come up with reasoning to clamp only the positive side. Anyone
> else? If valid to do, we might be able to slightly streamline some
> internal code.
Perhaps the one that made that macro experienced a problem with at value from
the dot product being slightly higher than one so he inserted that min()
function to deal with it, without thinking through the problem thoroughly.
You are right there should also be a max() function there to discard values
Anyway the way that macro calculates the angle is not the best numerically.
I would rather suggest something like this:
#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 not tested this macro yet, but the angle() function in my scikit-vectors
Python library seems to work ok. It works in is similar way as the macro above.
"Computing Cross-Products and Rotations in 2- and 3-Dimensional Euclidian
My opinion is that several of the other math related macros in the include files
need some rework.
Post a reply to this message