淘先锋技术网

首页 1 2 3 4 5 6 7

Uniform Sampling on Sphere Surface

2023-6-15 16:10:37

When generating uniform spheres on a sphere surface in Unity, I found an interesting solution. This algorithm generates uniform points on the sphere surface by using golden angle.

在这里插入图片描述

The Unity code of generating spheres in C#:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SphereGen : MonoBehaviour
{
    private GameObject Spheres;
    void Start()
    {
        float scaling = 50;
        Vector3[] pts = PointsOnSphere(1000);
        List<GameObject> uspheres = new List<GameObject>();
        Spheres = new GameObject("Spheres");
        Spheres.transform.position = transform.position;
        int i = 0;
        foreach (Vector3 value in pts)
        {
            uspheres.Add(GameObject.CreatePrimitive(PrimitiveType.Sphere));
            uspheres[i].transform.SetParent(Spheres.transform);
            uspheres[i].transform.position = transform.position + value * scaling;// local position
            i++;
        }
    }


    Vector3[] PointsOnSphere(int n)
    {
        List<Vector3> upts = new List<Vector3>();
        float inc = Mathf.PI * (3 - Mathf.Sqrt(5));
        //float inc = Mathf.PI * (Mathf.Sqrt(5) - 1);//golden ratio
        float off = 2.0f / n;
        float x, y, z, r, phi = 0;

        for (var k = 0; k < n; k++)
        {
            y = k * off - 1 + (off / 2);
            r = Mathf.Sqrt(1 - y*y);
            phi = k * inc;
            x = Mathf.Cos(phi) * r;
            z = Mathf.Sin(phi) * r;

            upts.Add(new Vector3(x, y, z));
        }
        Vector3[] pts = upts.ToArray();
        return pts;
    }

    // Update is called once per frame
    void Update()
    {
        //If you change the position of center before running, 
        //the script will still keeps the inital position.
        //Therefore we need to update the current transform.  
        Spheres.transform.position = transform.position;
    }
}

The key point is in function PointsOnSphere(), where firstly calculate inc, which is the radian of golden angle:
i n c = π ( 3 − 5 ) \begin {align*} & inc = \pi(3-\sqrt5) \end {align*} inc=π(35 )
the variable offdivides the whole height of a sphere whose radius equals to 1 into n n n parts. The height of each point then can be calculated:
y = 2 k + 1 n − 1 \begin {align*} & y = \frac{2k+1}{n}-1 \end {align*} y=n2k+11

At each height, the related radius plane can be calculated, according to the triangle in the figure.
r = 1 − y 2 \begin {align*} & r = \sqrt{1-y^2} \end {align*} r=1y2

Then how to get the uniformly distributed x x x and y y y coordinates? The golden angle. This angle is used orderly, generated sequence of points at different heights, or at different angles if they are at the same plane. The angle difference is the golden angle. The generated grid is also called Fibonacci grid. As shown in this figure(source):

img

After that, the x x x and y y y coordinates can be calculated(in Unity using left-hand coordinates):
ϕ = k ∗ i n c x = r cos ⁡ ( ϕ ) z = r sin ⁡ ( ϕ ) \begin {align*} & \phi = k*inc\\ & x=r\cos(\phi)\\ & z=r\sin(\phi) \end {align*} ϕ=kincx=rcos(ϕ)z=rsin(ϕ)
The generated result in Unity:

在这里插入图片描述

I want to illustrate more about the transfer between golden angle and golden ration. Assume a round with radius equasl to 1. We know the golden ratio:
φ = 1 + 5 2 = 1.618 \begin {align*} & \varphi = \frac{1+\sqrt5}{2} = 1.618 \end {align*} φ=21+5 =1.618
Then for in the round, the part of the golden angle could be:
2 π ∗ 1 φ = − π ( 1 − 5 ) 2 \begin {align*} & 2\pi*\frac{1}{\varphi} = -\pi\frac{(1-\sqrt5)}{2} \end {align*} 2πφ1=π2(15 )
Also, the other part of the round can also be defined as golden angle:
2 π − 2 π 1 φ = 2 π ( 1 + 1 − 5 2 ) = π ( 3 − 5 ) \begin {align*} & 2\pi-2\pi\frac{1}{\varphi} = 2\pi(1+ \frac{1-\sqrt5}{2})=\pi(3-\sqrt5) \end {align*} 2π2πφ1=2π(1+215 )=π(35 )