Question

How can I calculate points around a sphere? I need this for my particles explosion. I don't want the particle's points to be all random. I need them in a spherical pattern. For 2d circle explosion I was using this:

float n=many;
float rad = 1;
for (int i = 0; i < n; i++)
{
        float fi = 2*PI*i/n;
        float x1 = rad*sin(fi + PI)+x ;
        float y1 = rad*cos(fi + PI)+y ;
        addparticlesmart(x,y,(x1-x),(y1-y), 0.01f),r,g,b,a,0.02f);
}
Was it helpful?

Solution

You have a few options.

Lat / Lon - Loop over latitude from -π/2 to + π/2 and longitude from 0 to 2π at whatever interval you like. Then convert from spherical to cartesian coordinates. While this is easy to code, it has the disadvantage that the points tend to cluster at the poles.

Tessellation - You can pick a regular polyhedron, preferably with triangular faces, (an icosahedron is my favorite for this purpose) and recursively find the bisector of each edge of each face. You then divide that face into four triangular faces, normalizing the bisector points so they lie on the surface of the sphere. Though the points are not quite uniformly distributed over the sphere (which can be seen if you don't use an icosahedron as the base polyhedron) it appears to be much more evenly distributed than the lat / lon approach. It has as a disadvantage, being somewhat more difficult to code. A more detailed description is available here.

Random points - I know you said you didn't like the idea of picking random points, but I'll include it here for completeness. There is a good treatment of it at Wolfram's site.

OTHER TIPS

Complete conversion from spherical to Cartesian coordinates:

Cartesian coordinates: (x,y,z)
Spherical coordinates: (r,φ,θ) with r∈[0,∞), φ∈[0,2π), θ∈[0,π]

Then:
x = r*cos(φ)*sin(θ)
y = r*sin(φ)*sin(θ)
z = r*cos(θ)

If you can use the new c++11 standard, it is easy to create gaussian distributed random numbers. Then you can use the fact that three 1-dimensional gaussian numbers makes one 3-dimensional gaussian coordinate, which is uniformly distributed on a sphere of constant radius (the radius is gaussian distributed). If you want the coordinates only on a specific radius you have to normalize your coordinates. Here's how you can do it:

#include <iostream>
#include <random>
#include <cmath>


using namespace std;

int main (int argC, char* argV[])
{
    //Create random generator
    mt19937 rnd;
    //Create Gaussian distribution
    normal_distribution<double> normDist ( 0.0, 1.0 );
    //Seed random generator
    rnd.seed(time(NULL));

    const double sphereRadius = 1;

    //Create 3 Gauss Random Numbers
    double rndArray[3];
    double rndSqrSum = 0;
    for ( uint i = 0; i < 3; i++ )
    {
        rndArray[i] = normDist( rnd );
        rndSqrSum += rndArray[i] * rndArray[i];
    }

    //Calculate Faktor to get a Sphere of radius sphereRadius
    double faktor = sphereRadius / sqrt( rndSqrSum ) ;

    //The random Coordinates then are:
    double x = rndArray[0]*faktor;
    double y = rndArray[1]*faktor;
    double z = rndArray[2]*faktor;

    cout << "Koordinates are: " << endl << "x: " << x << endl << "y: " << y << endl << "z: " << z << endl << "Radius is: " << sqrt(x*x+y*y+z*z) << endl;

}

For your application probably not needed but useful though, this method can be used for arbitrary dimensions, eg. 20 dimensional problems.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top