What is the meaning of the math expression in the periodic table example?

As topic

Here is the periodic table example :

line 298,299

const phi = Math.acos( - 1 + ( 2 * i ) / l );
const theta = Math.sqrt( l * Math.PI ) * phi;

Above is a segment code of periodic table. It can calculate the phi and theta to create a set of spiral elements on the surface of sphere. It just looks like uniformed distribution. But I have no idea why this expression Math.sqrt( l * Math.PI ) * phi can turn out such beautiful spiral distribution?

I thought it was fabonacci sphere, but it’s not. So What is the source or paper this expression based on?

If we look at a little bigger portion of the code:

for ( let i = 0, l = objects.length; i < l; i ++ ) {

	const phi = Math.acos( - 1 + ( 2 * i ) / l );
	const theta = Math.sqrt( l * Math.PI ) * phi;


we can see, that “l” is the total number of objects, which I counted from the “table” display to be something close to 118. Hold that number.

In the loop,i goes from 0 to 117, hence phi goes from

( -1 + (2 * 0) / 118 ) ==> -1
( -1 + ( 2 * 118 ) / 118 ) ==> -1 + 2 = +1

As we are taking the Math.acos from those values, we are talking about angles which linearly increase from -90° to +90°. That’s the (geographic) latitude in spherical coordinates.

Looking at theta:
The term Math.sqrt( l * Math.PI ) is constant during the whole loop. And equates to

Math.sqrt( 118 * Math.PI ) = 19.25.

Remembering that a full revolution takes 2 * Math.PI, that gives us approx. 9.6 full revolutions of the spherical spiral. The 9.6 revolutions are evenly distributed along the longitude values, because the total number is multiplied by the linearly increasing phi.



Even though some of you liked this little break-down (thanks, guys!) , my explanation was a little quick and dirty, that’s why I would like to add the following refinements:

The Math.acos() of the value range [ -1 … +1 ] (as seen above) of course covers the angle range [ 180° … 0° ] , counting angles ccw from positive x-axis, instead of [ -90° … +90° ], as I falsely claimed. (The picture of going from south pole to north pole and phi representing the geographic latitude was just too tempting to resist.)

But then looking at how the “current” spiral radius sinPhiRadius is computed in the vector3() method

setFromSphericalCoords( radius, phi, theta ) {

	const sinPhiRadius = Math.sin( phi ) * radius;

	this.x = sinPhiRadius * Math.sin( theta );
	this.y = Math.cos( phi ) * radius;
	this.z = sinPhiRadius * Math.cos( theta );

	return this;


I realised, that the author of the Vector3().setFromSphericalCoords( radius, phi, theta ) set up a little “trap” or two, which sort of obfuscates what the code is actually doing. Let me explain:
This is how sinPhiRadius is computed:

And this is how that computed sinPhiRadius is used in computing this.x, this.y and this.z:

Note, how the author of the spiral sphere demo implicitly uses the symmetry which lies in computing sinPhiRadius with phi increasing CCW from 0° => 180° vs. phi going CW from 180° => 0°, both of which yield the same sinPhiRadius!

Also note, how the author of the setFromSphericalCoords() method implicitly computes the sinPhiRadius in a vertical fashion, while using it horizontally.

Both authors may do so with impunity, because a sphere has perfect symmetry with respect to any plane passing through its center.


Is there any article about spiral formula algorithm for reference?