POV-Ray : Newsgroups : povray.binaries.images : Helical SDF for Isosurfaces : Re: Helical SDF for Isosurfaces Server Time
4 Jan 2025 18:01:26 EST (-0500)
  Re: Helical SDF for Isosurfaces  
From: Chris R
Date: 27 Dec 2024 09:30:00
Message: <web.676eb94a4a98c6d6a40969eb5cc1b6e@news.povray.org>
"Tor Olav Kristensen" <tor### [at] TOBEREMOVEDgmailcom> wrote:
> Below are the results of some atan2-tests I just did.
>
> Some constants:
>
>   pi/2 = 1.570796326794897
>   pi   = 3.141592653589793
> 3*pi/2 = 4.712388980384690
> 2*pi   = 6.283185307179586
>
> tau = 2*pi
>
> Z = 1e-100
>
>
> Here the functions are given valid arguments:
>
> The results for atan2() are all in the closed interval [-pi, +pi]
>
> atan2(-0, -1) = -3.141592653589793
> atan2(-Z, -1) = -3.141592653589793
>
> atan2(-1, -Z) = -1.570796326794897
> atan2(-1, -0) = -1.570796326794897
> atan2(-1, +0) = -1.570796326794897
> atan2(-1, +Z) = -1.570796326794897
>
> atan2(-Z, +1) = -0
> atan2(-0, +1) = -0
>
> atan2(+0, +1) = +0
> atan2(+Z, +1) = +0
>
> atan2(+1, +Z) = +1.570796326794897
> atan2(+1, +0) = +1.570796326794897
> atan2(+1, -0) = +1.570796326794897
> atan2(+1, -Z) = +1.570796326794897
>
> atan2(+Z, -1) = +3.141592653589793
> atan2(+0, -1) = +3.141592653589793
>
>
> Atan2_Fn =
>     function(a, b) {
>         mod(atan2(a, b) + tau, tau)
>     }
>
> The results for Atan2_Fn() are all in the half-open interval [+0, +tau)
>
> Atan2_Fn(-Z, +1) = +0
> Atan2_Fn(-0, +1) = +0
> Atan2_Fn(+0, +1) = +0
> Atan2_Fn(+Z, +1) = +0
>
> Atan2_Fn(+1, +Z) = +1.570796326794897
> Atan2_Fn(+1, +0) = +1.570796326794897
> Atan2_Fn(+1, -0) = +1.570796326794897
> Atan2_Fn(+1, -Z) = +1.570796326794897
>
> Atan2_Fn(+Z, -1) = +3.141592653589793
> Atan2_Fn(+0, -1) = +3.141592653589793
> Atan2_Fn(-0, -1) = +3.141592653589793
> Atan2_Fn(-Z, -1) = +3.141592653589793
>
> Atan2_Fn(-1, -Z) = +4.712388980384690
> Atan2_Fn(-1, -0) = +4.712388980384690
> Atan2_Fn(-1, +0) = +4.712388980384690
> Atan2_Fn(-1, +Z) = +4.712388980384690
>
>
> n_atan2 =
>     function(a, b) {
>         atan2(a, b) + select(a, tau, 0)
>     }
>
> The results for n_atan2() should all be in the half-open interval [+0, +tau)
>
> n_atan2(-Z, +1) = +6.283185307179586  <--- NB
> n_atan2(-0, +1) = +0
> n_atan2(+0, +1) = +0
> n_atan2(+Z, +1) = +0
>
> n_atan2(+1, +Z) = +1.570796326794897
> n_atan2(+1, +0) = +1.570796326794897
> n_atan2(+1, -0) = +1.570796326794897
> n_atan2(+1, -Z) = +1.570796326794897
>
> n_atan2(+Z, -1) = +3.141592653589793
> n_atan2(+0, -1) = +3.141592653589793
> n_atan2(-0, -1) = -3.141592653589793  <--- NB !!!
> n_atan2(-Z, -1) = +3.141592653589793
>
> n_atan2(-1, -Z) = +4.712388980384690
> n_atan2(-1, -0) = +4.712388980384690
> n_atan2(-1, +0) = +4.712388980384690
> n_atan2(-1, +Z) = +4.712388980384690
>
>
> f_normalized_atan2 =
>     function(a, b) {
>         select(
>             a,
>             atan2(a, b) + tau,
>             select(b, pi, 0),
>             atan2(a, b)
>         )
>     }
>
> The results for f_normalized_atan2() are all in the half-open interval [+0,
> +tau)
>
> f_normalized_atan2(-Z, -1) = +3.141592653589793
> f_normalized_atan2(-0, -1) = +3.141592653589793
> f_normalized_atan2(+0, -1) = +3.141592653589793
> f_normalized_atan2(+Z, -1) = +3.141592653589793
>
> f_normalized_atan2(-Z, +1) = +6.283185307179586  <--- NB
> f_normalized_atan2(-0, +1) = +0
> f_normalized_atan2(+0, +1) = +0
> f_normalized_atan2(+Z, +1) = +0
>
> f_normalized_atan2(+1, -Z) = +1.570796326794897
> f_normalized_atan2(+1, -0) = +1.570796326794897
> f_normalized_atan2(+1, +0) = +1.570796326794897
> f_normalized_atan2(+1, +Z) = +1.570796326794897
>
> f_normalized_atan2(-1, -Z) = +4.712388980384690
> f_normalized_atan2(-1, -0) = +4.712388980384690
> f_normalized_atan2(-1, +0) = +4.712388980384690
> f_normalized_atan2(-1, +Z) = +4.712388980384690
>
>
> Here the functions are given invalid arguments:
>
> Atan2 =
>     function(a, b) {
>         atan2(a, b)
>     }
>
> Atan2(-0, -0) = -3.141592653589793
> Atan2(-0, +0) = -0
> Atan2(+0, +0) = +0
> Atan2(+0, -0) = +3.141592653589793
>
>
> Atan2_Fn =
>     function(a, b) {
>         mod(atan2(a, b) + tau, tau)
>     }
>
> Atan2_Fn(+0, +0) = +0
> Atan2_Fn(+0, -0) = +3.141592653589793
> Atan2_Fn(-0, -0) = +3.141592653589793
> Atan2_Fn(-0, +0) = +0
>
>
> n_atan2 =
>     function(a, b) {
>         atan2(a, b) + select(a, tau, 0)
>     }
>
> n_atan2(+0, +0) = +0
> n_atan2(+0, -0) = +pi
> n_atan2(-0, -0) = -pi  <--- NB !!!
> n_atan2(-0, +0) = +0
>
>
> f_normalized_atan2 =
>     function(a, b) {
>         select(
>             a,
>             atan2(a, b) + tau,
>             select(b, pi, 0),
>             atan2(a, b)
>         )
>     }
>
> f_normalized_atan2(+0, +0) = +0
> f_normalized_atan2(-0, +0) = +0
> f_normalized_atan2(-0, -0) = +0
> f_normalized_atan2(+0, -0) = +0
>
>
> When looking at the results from both the valid and invalid arguments, it seems
> to me that POV-Ray's built in atan2() gives the most consistent results,
> followed by Atan2_Fn().
>
> --
> Tor Olav
> http://subcube.com
> https://github.com/t-o-k

Nice analysis of the various options!

I have adopted your updated f_normalized_atan2, which I find works well with my
isosurfaces.  Others may have different expectations and use a different
implementation.

My question would be, (and I should look at the pov code at some point to
check), when an isosurface is being evaluated, are there cases where -0 is
supplied to the isosurface function?

-- Chris R


Post a reply to this message

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