POV-Ray : Newsgroups : povray.general : Why only a +1 clamp with VAngle, VAngleD macros in math.inc? : Re: Why only a +1 clamp with VAngle, VAngleD macros in math.inc? Server Time
23 Apr 2024 13:40:24 EDT (-0400)
  Re: Why only a +1 clamp with VAngle, VAngleD macros in math.inc?  
From: William F Pokorny
Date: 7 May 2021 07:13:18
Message: <609520ce$1@news.povray.org>
On 5/6/21 10:58 AM, Tor Olav Kristensen wrote:
> 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))))
>> #end
>>
>> 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
>> concerns.
>>
>> 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
> below -1.
> 

Thanks. What I suspected too, but I don't have near your expertise.

> 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
> 

Interesting, thanks. I'll play with it. There will be four sqrt calls 
with this vs two so I expect it's a slower approach.

Reminds me I captured fast approximation atan2 code I was thinking of 
making an inbuilt function, but I've not gotten to it...

And that thought reminds me of my plans to turn many macros into 
"munctions"(1) calling new faster, inbuilt functions. Done only a tiny 
bit of that so far.

(1) - Yes, thinking about creating a munctions.inc file breaking out 
what are really macro wrappers to functions into that file to make clear 
what they are. Maybe all as M_ prefixed so my current F_dents() would 
become M_dents(). Angle perhaps then M_Angle.

> 
> 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.
> 
> https://github.com/t-o-k/scikit-vectors/blob/master/skvectors/cartesian_vectors.py
> 
> 

> "Computing Cross-Products and Rotations in 2- and 3-Dimensional Euclidian
> Spaces"
> https://people.eecs.berkeley.edu/~wkahan/MathH110/Cross.pdf
> 
> My opinion is that several of the other math related macros in the include files
> need some rework.
> 

I'd consider alternatives for my branch if you want to offer details. 
Suppose I could compare to forms in skvectors?

Something I've done too with the inbuilt function changes is allow 
alternative calculations for the same thing. Compiled such conditionals 
not that expensive. Most frequently single float options where those are 
much faster, but different methods too. For one thing, the alternatives 
I can bang against each other as a way to test!

Bill P.


Post a reply to this message

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