7
$\begingroup$

I was wondering if one could distribute points on a "cap" of a sphere, following a normal distribution of the points instead of a uniform distribution. This normal could be centered at the cap. Maybe one can use SpherePoints[]?

By "cap" I mean that we select only these points within a radius of some reference point. For instance, using the case for uniform points (from Carl Woll's answer here):

SeedRandom[1]
numberofPoints = 1000;
radiusofCap = .8;
ctr = RandomPoint[Sphere[]];
pts = RandomPoint[
   RegionIntersection[Ball[ctr, radiusofCap], Sphere[]], 
   numberofPoints];
Graphics3D[{Red, Point@pts, White, Opacity[.5], Sphere[]}]

We get:

enter image description here

How could we extend this so that the points are normal-distributed? A solution might be in the form:

myNormalCapPoints[sphereRadius_, capRadius_, numberofPoints_, std_] :=

Where we take the desired sphere and cap radius, then select a point on the sphere (randomly perhaps?), and generate the normal-distributed points around it with some standard deviation from the reference point.

Thanks!

Note/update 1: It would be like a 2D gaussian cloud of points on the surface of the sphere (at the "cap").

$\endgroup$
3
  • 2
    $\begingroup$ What do you mean by normal distribution on the sphere? What comes closest to this might be the spherical von Mises-Fisher distribution. $\endgroup$ Jul 10, 2020 at 23:36
  • $\begingroup$ Very interesting, I was not aware of this distribution but it seems that this is what I'd be looking for (I guess except for selecting points within the cap). However, the distribution seems a bit alien to me, I'll try to understand it better. Thanks for the reference! $\endgroup$ Jul 10, 2020 at 23:58
  • 1
    $\begingroup$ This answer contains an implementation of a von Mises-Fisher generator. $\endgroup$ Aug 5, 2020 at 14:52

1 Answer 1

8
$\begingroup$

Here I randomly rotate points away from the pole by a distance along the surface that is drawn from a truncated normal distribution. I hope this is close to what you need:

n = 1000;
capc = 0.4; (* Pi/2: cover hemisphere, Pi: cover the whole thing *)
dist = TruncatedDistribution[{-capc, capc}, NormalDistribution[0, 2]];
cvals = RandomVariate[dist, n];
dirs = Append[#, 0] & /@ RandomPoint[Circle[], n];
newpts = MapThread[RotationTransform[#1, #2][{0, 0, 1}] &, {cvals, dirs}];
Graphics3D[{Opacity[.5], Sphere[], Opacity[1], Point[newpts]}]

sphere cap normal distribution

$\endgroup$
5
  • $\begingroup$ .@flinty this is great! And a very simple way to have a "cap" from the truncated distribution. $\endgroup$ Jul 11, 2020 at 0:08
  • 1
    $\begingroup$ It should also work with other distributions and if you vary the standard deviation. If you want to move the cap to a different point other than {0,0,1} you should be able to rotate all the points after generating them first at {0,0,1} then applying a RotationTransform. Also if you increase the mean of the NormalDistribution from 0 to say 40, then you get a ring of points instead. $\endgroup$
    – flinty
    Jul 11, 2020 at 0:11
  • $\begingroup$ .@flinty, with the code as it is, it seems that varying the mean/std does not change the distribution of points. Do you know why? $\endgroup$ Jul 11, 2020 at 14:25
  • 1
    $\begingroup$ It does, you just have to increase the mean / stddev by quite a lot because of the truncation. Try replacing NormalDistribution[0, 2] with NormalDistribution[0, 0.1] and you'll see the difference. Same with NormalDistribution[80, 2] $\endgroup$
    – flinty
    Jul 11, 2020 at 14:27
  • $\begingroup$ Ohh, I see! I was setting things like NormalDistribution[0, 20000] with no perceptible change. But I see one has to decrease std instead (relative to the mean). I also see the ring effect you mention. Thanks! $\endgroup$ Jul 11, 2020 at 14:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.