# How to distribute points on a Sphere[] cap from a normal distribution?

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;
ctr = RandomPoint[Sphere[]];
pts = RandomPoint[
numberofPoints];
Graphics3D[{Red, Point@pts, White, Opacity[.5], Sphere[]}]


We get:

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").

• What do you mean by normal distribution on the sphere? What comes closest to this might be the spherical von Mises-Fisher distribution. Jul 10, 2020 at 23:36
• 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! Jul 10, 2020 at 23:58
• This answer contains an implementation of a von Mises-Fisher generator. Aug 5, 2020 at 14:52

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]}]


• .@flinty this is great! And a very simple way to have a "cap" from the truncated distribution. Jul 11, 2020 at 0:08
• 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. Jul 11, 2020 at 0:11
• .@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? Jul 11, 2020 at 14:25
• 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] Jul 11, 2020 at 14:27
• 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! Jul 11, 2020 at 14:29