0
votes

I'm trying to simulate radiation emitting from a point source. To do this, given the coordinates of a source and the desired length of emitted rays, I randomly generate a direction vector in spherical coordinates, convert it to cartesian, and return the correct end point. However, when I run this, and visualize the resulting point cloud (consisting of all the randomly generated end points) in Blender, I see that it's more densely populated at the "poles" of the sphere. I'd like the points to be uniformly distributed along the sphere. How can I achieve this?

enter image description here

The random generation function:

def getRadiationEmissionLineSeg(p, t):
    if(p.size == 4):
        #polar angle spans [0, pi] from +Z axis to -Z axis
        #azimuthal angle spans [0, 2*pi] orthogonal to the zenith (in the XY plane)
        theta = math.pi * random.random()
        phi = 2 * math.pi * random.random()

        #use r = 1 to get a unit direction vector
        v = sphericalToCartesian(1, theta, phi)

        #parametric vector form: vec = p + tv
        #p = point that lies on vector (origin point in case of a ray)
        #t = parameter (-inf, inf) for lines, [0, inf) for rays
        #v = direction vector (must be normalized)
        return p + t * v

The spherical coordinates -> cartesian conversion function:

def sphericalToCartesian(r, theta, phi):

    x = r * math.sin(theta) * math.cos(phi)
    y = r * math.sin(theta) * math.sin(phi)
    z = r * math.cos(theta)

    return npy.array([x, y, z, 0])
1
Did you look at the (accumulated randomly generated) data itself to determine if it is randomly distributed? Have you tested your functions with known inputs and are satisfied that they work?wwii
Wouldn't the point cloud picture I posted qualify as me looking at the data and determining that it is not in fact being distributed properly? All functions involved were tested thoroughlysdighe
See stackoverflow.com/a/33977530/2166798, then scale the length of the resulting vectors to the desired length. Generating normals generalizes to multiple dimensions, while the trig approaches get hairy very quickly.pjs
Was this a math/geometry question or a programming question?wwii

1 Answers

3
votes

When you transform points by spherical coordinates and angle theta approaches pi, the circle which is an image of [0,2pi]x{theta} gets smaller and smaller. Since theta is uniformly distributed, there will be more points near poles. It could be seen on image of grid.

sphere

If you want to generate uniformly distributed points on sphere, you can use the fact that if you cut a sphere with two parallel planes, the area of the strip of spherical surface between the planes depends only on the distance between the planes. Hence, you can get a uniform distribution on the sphere using two uniformly distributed random variables:

  • z coordinate between -r and r,
  • an angle theta between [0, 2pi) corresponding to a longitude.

Then you can easily calculate x and y coordiantes.

Example code:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

r = 1
n = 1000

z = np.random.random(n)*2*r - r
phi = np.random.random(n)*2*np.pi

x = np.sqrt(1 - z**2)*np.cos(phi)
y = np.sqrt(1 - z**2)*np.sin(phi)

fig = plt.figure(figsize=(8, 8))
ax = plt.axes(projection='3d')
ax.scatter(x, y, z)
plt.show()

Results for n=100,250,1000:

Results