In this post I’ll revive work I did during my PhD to generate 3D points that are equally spaced on the unit sphere. Such equidistant points are useful for many operations over the sphere as well as to properly tesselate it. The method is based on a spiral walk of the spherical surface in angular increments equal to the golden angle. The golden angle is related to the golden ratio.

Two quantities are in the golden ratio, , if their ratio is the same as the ratio of their sum to the larger of the two quantities. which is approximately 1.6180339887… The golden angle is the angle subtended by the small arc which is approximately 2.3999632297… radians or 137.5077640500… degrees.

The ratios between consecutive Fibonacci numbers approach the golden ratio. Also, an alternative for expressing the Fibonacci sequence is . #mindblown 🤯. The spiral walk discussed here is therefore often referred to as a spherical Fibonacci lattice or a Fibonacci spiral sphere.

The method presented here I originally implemented for a paper on Numerical Verification of Bidirectional Reflectance Distribution Functions for Physical Plausibility. A pre-print of the paper is available from ResearchGate and via my Google Scholar page. The paper also discusses an alternative method based on subdivision of a 20-sided regular icosahedron.

The Fibonacci Spiral Disc

The Fibonacci spiral is a way of stepping around a circle to generate angular positions with limited repeated structure in the sequence. The step size is equal to the golden angle. Due to the properties of the golden angle, if one were to create a histogram of angles generated by this methods then the angle bins will always be approximately equally filled.

Using Vogal’s method, one can combine this property with an increasing radius to distribute points on a 2D disc. Even distribution of points over different radii of the disc is ensured by having for the index of the point being generated and inversely proportional to the overall density of the points. Due to the relationship between the radius and the point’s index, the disc’s surface area correctly grows in proportion to the number of points.

Putting this together, is the range and angle cylindrical polar coordinate of point for .

Shown above is a spiral disc with 500 points for (left) and (right). A characteristic of this method is that there seems to be a space in the centre for another point.

The C++ code to generate the points on the disc is:

std::vector<Vec2> fibonacci_spiral_disc(const int num_points, const double k) {
    std::vector<Vec2> vectors;
    vectors.reserve(num_points);

    const double gr=(sqrt(5.0) + 1.0) / 2.0;  // golden ratio = 1.6180339887498948482
    const double ga=(2.0 - gr) * (2.0*M_PI);  // golden angle = 2.39996322972865332

    for (size_t i=1; i <= num_points; ++i) {
        const double r = sqrt(i) * k;
        const double theta = ga * i;

        const double x = cos(theta) * r;
        const double y = sin(theta) * r;

        vectors.emplace_back(x, y);
    }
    
    return vectors;
}

The Fibonacci Spiral Sphere

One can use a similar spiral method to also distribute points on a sphere. To evenly distribute the points, proportionally more turns are allocated to larger circles on the sphere. If the spiral starts at a sphere’s pole then the radius and circumference of the spiral at any point is proportional to for in . The density of the turns of the spiral is therefore also proportional to and the continuous distribution function (CDF) of the turns proportional to .

Given this CDF, the point index of a latitude can be calculated with for the total number of points required. Then taking the inverse gives, .

Wrapping this up, , is the latitude & longitude spherical polar coordinate of point for in . Notice that the longitude component of the coordinate is the same as for the disc, but the disc’s radius component has been adapted to a latitude component for the sphere of points.

Shown above is a tessellated Fibonacci spiral sphere with 162 points (on the left) and its geometric dual (on the right). The geometric dual shows the shapes of the spaces around each of the equidistant points. Note that the points are generated in latitude order. To tesselate the sphere one still needs to apply a Delaunay or similar triangulation algorithm.

The C++ code to generate the points on the sphere is:

std::vector<Vec3> fibonacci_spiral_sphere(const int num_points) {
    std::vector<Vec3> vectors;
    vectors.reserve(num_points);
    
    const double gr=(sqrt(5.0) + 1.0) / 2.0;  // golden ratio = 1.6180339887498948482
    const double ga=(2.0 - gr) * (2.0*M_PI);  // golden angle = 2.39996322972865332

    for (size_t i=1; i <= num_points; ++i) {
        const double lat = asin(-1.0 + 2.0 * double(i) / (num_points+1));
        const double lon = ga * i;

        const double x = cos(lon)*cos(lat);
        const double y = sin(lon)*cos(lat);
        const double z = sin(lat);

        vectors.emplace_back(x, y, z);
    }
    
    return vectors;
}

Summary

The Fibonacci lattice/spiral is a simple and efficient method for generating equidistant points on the unit sphere. The golden angle is approximately 2.400 radians or 137.5 degrees. Therefore, each turn of the spiral walk adds two or three points to the sphere. To tesselate the sphere one still needs to apply a Delaunay or similar triangulation algorithm.

Full source for generating the equidistant points is available in my Bits-O-Cpp GitHub repo.