Generate n uniform points from a center vector between r and 2r in a ball

42 Views Asked by At

I have a center vector (x,y,z).

I want to generate N random points that lies outside the border of a sphere with radius r and center x,z,y and inside a sphere with radius 2*r and center x,y,z.

I have implemented this via the following

    function generatePointFromCenter(center, radiusStart, radiusEnd) {
        var d, x, y, z;
        var scaleThreshold = radiusStart/radiusEnd;

        do {
            x = Math.random() * 2.0 - 1.0;
            y = Math.random() * 2.0 - 1.0;
            z = Math.random() * 2.0 - 1.0;
            d = x * x + y * y + z * z;
        } while (d > 1.0 || d < scaleThreshold);

        return new THREE.Vector3(x, y, z).multiplyScalar(radiusEnd)
    }

Needless to say, this approach is very slow if the scaleThreshhold is close to 1.0, because the while loop has to be run so many times.

Is there a faster way to generate the points?

It should look like this: enter image description here

UPDATE: The following code seems to do the trick. I'm not sure if I should use the cubic root to prevent cluttering but it seems to work. From another example " Curves are modeled by trigonometric functions, which have distinct curved areas which vary differently with respect to the input. In a later method, we tackle this problem by using the cubic root"

  var u = Math.random();
  var v = Math.random();
  var theta = u * 2.0 * Math.PI;
  var phi = Math.acos(2.0 * v - 1.0);
  var number = Math.random() * (radiusEnd - radiusStart) + radiusStart; 
  var r = number;
  var sinTheta = Math.sin(theta);
  var cosTheta = Math.cos(theta);
  var sinPhi = Math.sin(phi);
  var cosPhi = Math.cos(phi);
  var x = r * sinPhi * cosTheta;
  var y = r * sinPhi * sinTheta;
  var z = r * cosPhi;

  return new THREE.Vector3(x, y, z);
1

There are 1 best solutions below

1
On BEST ANSWER

The easiest way would be to use spherical coordinates: Let $\tilde{r}$ be a random value in $[r,2r]$, and $\theta \in [0,\pi]$, $\psi \in [0,2\pi)$, and then convert back to Cartesian coordinates.