Sphere mesh from spherical coordinates

Metadata
aliases: []
shorthands: {}
created: 2022-02-26 18:07:01
modified: 2022-02-26 18:34:36

This is the standard way of generating a sphere mesh, using the spherical coordinate system with a constant radius:

This method results in quite a non-uniform distribution of vertices, the "density" of vertices diverges to at the poles of the sphere. This is shown by the following figure, which shows a sphere generated with this method. The color of the triangles shows the area of a given triangle (phi_res = 20, theta_res = 20).

The ratio of areas between the largest and smallest triangle on the mesh:

Steps

  1. Generate a uniform grid with and (so with inclusive ends on both sides)
  2. Map these pairs into Cartesian coordinates using the equations shown above (use a chosen value, for a unit sphere). Now we have our vertices.
  3. For the triangles, iterate through all the layers. All these layers will have vertices with the same values. Two neighboring vertices in the same layer and the same ones on the next layer form a quad. These can be just halved into two triangles We have all the triangles

Implementation in Python

This example uses the Separate arrays convention for storing triangle meshes.

The arguments of the function have the following meanings:

import numpy as np

def generate_sphere(r = 1.0, res_phi=10, res_theta=10):
    # Generate the inclusive uniform spacing of phi and theta
    phis = np.linspace(0, np.pi * 2.0, res_phi, True)
    thetas = np.linspace(0, np.pi, res_phi, True)

    # Arrays for the vertex coordinates
    x = []; y = []; z = []

    # Iterate through the (phi, theta) pairs and generate the vertices
    for phi in phis:
        for theta in thetas:
            cosphi = np.cos(phi)
            sinphi = np.sin(phi)
            costheta = np.cos(theta)
            sintheta = np.sin(theta)
            x.append(cosphi * sintheta * r)
            y.append(sinphi * sintheta * r)
            z.append(costheta)

    # Arrays for the triangle indices
    i = []; j = []; k = []

    for ti in range(res_phi - 1):
        for tt in range(res_theta - 1):
            # This lambda function gives the absolute index of a given
            # vertex in the vertex arrays
            pixd = lambda i1, i2 : i1 * (res_theta) + i2
            # The vertex indices for the corners of the quad
            idx = pixd(ti, tt)
            idx2 = pixd(ti, tt + 1)
            idx3 = pixd(ti + 1, tt)
            idx4 = pixd(ti + 1, tt + 1)
            # Add both triangles to the list
            i.append(idx)
            i.append(idx2)
            j.append(idx2)
            j.append(idx4)
            k.append(idx3)
            k.append(idx3)

    return x, y, z, i, j, k