(back to main)
How do you sample random points in a spherical cap? How do you randomly pick a direction inside a 3D cone, whose tip is at the origin? How do you get randomly latitude–longitude pairs that are within some distance of a given latitude and longitude? These are all one and the same question!
Sampling points on a unit sphere (in three dimensions, centered at the origin with radius 1) is a little tricky: anyone who tried to do this by drawing uniformly random latitudes between ±90° and longitudes between ±180° can be forgiven for it, but this is the wrong way to do it. A glance at the visualizations by MathWorld, D3.js–guru Jason Davies, or Chris Wellons shows that this bunches points near the poles:
Luckily there are many right ways to sample points from the unit sphere (MathWorld has your back). However, Pedro77 needed something a little different when asking their question on StackOverflow: they needed random points on a unit sphere that lay inside a cone, with tip at the origin and oriented in a particular direction, towards some (latitude, longitude) pair on the sphere. They were generating random points on the entire sphere and discarding points that failed to meet this criterion, and wanted to know if there was a better way. Rejection sampling is perfectly correct, but can be inefficient for small angles, when it has to throw away most samples.
I tried intuiting a mathematical solution for a few minutes in vain, then sought to find the name of this cone–sphere intersection—maybe knowing what it’s called would aid searching. Google quickly sent me to Mathworld’s “Spherical Cap” entry. A picture is worth a thousand words:
Knowing what to search for, in this case, meant all the world. Between Jim Belk and joriki’s fine answers on—where else—Math.StackExchange (StackOverflow’s sister site for mathematicians), the problem reduced to converting mathematical pseudocode to Matlab code. My answer as well as my personal Matlab toolkit (GitHub), contains that public-domain Matlab code.
I wanted you, kind reader, to visualize spherical caps just as you are, since you are likely reading these words on a programmable device in a programmable browser, so I wound up making the
The interactive 3D scatter plot above, courtesy of plotly.js, shows random samples from three spherical caps:
- the 30° spherical cap at the North Pole in blue,
- the 30° spherical cap pointing towards the middle of the first octant, pointing at [1, 1, 1], in orange, and
- the 110° spherical cap, which looks like a Dymaxion dome, at the South Pole, in green.
It was very pleasant to use bl.ocks for the first time. It was unpleasant but educational to write an ES2015 module with Rollup and Babel—ClojureScript and the Google Closure Compiler shielded me from all that, so I felt like a real 2016 Web Developer: