Create atan2 function in programmable filter

I’m trying to create a programmable filter that does something similar to the atan2 function in many languages, accounting for the periodicity of the arctan function. Unfortunately, I’m struggling to understand the way that precedence and NaN interact here.

There are a variety of formulations for this function, and many are discussed here: atan2 - Wikipedia. I have had consistent trouble with the use of conditionals (e.g. where(cond, x, y)), so I’m attempting to use the version based on the sgn function:

.

I’ve attached a state file based on the Wavelet source. atan2.pvsm (405.4 KB)

There is an inherent singularity in the atan2 function at the origin, though I would expect this form to evaluate to zero there. Instead, I seem to compute NaN in a couple of places. It seems likely that this is because python evaluates 0*NaN as NaN, but the results I’m getting don’t seem entirely consistent with that, either. I would have expected to see NaN everywhere on the x-axis, in that case.

Can anyone help me figure out what’s going on here?

@patchett2002 @cory.quammen

Your function seems to behaving exactly like you expect. Like you said, there is a singularity at the origin. That is just the nature of arctan. There simply is no angle for a vector of length 0, so a NaN value there makes sense. It’s not angle 0, which would be pointing along the x axis. It’s not pointing in that direction. It’s not pointing in any direction.

As for why you see NaN in places other than the origin, that has to do with how the rendering system fills polygons. When the rendering fills a polygon, it interpolates the scalars between the points. But how do you interpolate from a finite value to NaN? You can’t. When you compute the simple expression for linear interpolation with a NaN value, you end up with NaN everywhere in the polygon, which if you think about it makes sense. The reason why you see an asymmetry is because internally the rendering system divides polygons into triangles.

If you set the representation to Point Gaussian, you will see that only those points on the origin are really the ones with NaN values.

Okay, that all makes sense. I’ll have to figure out some way to plug the hole for my analysis.