By on .

When we set out to build Dark Sky, our plan was to focus exclusively on precipitation for the next hour. It’s what we do differently, and it’s what we do well: we wanted to leave the longer-term prediction to other apps. Our users have asked us repeatedly for more, though: it’s frustrating to have to use multiple apps just to get a single picture of the day.[1]

Really, we find it flattering that our users want to spend more time in Dark Sky. So, you may have noticed that version 1.2 (from last week) included the current temperature, and Dark Sky 1.3 (out today!) includes 24-hour forecasts of both precipitation and temperature. We’ve talked previously about how Dark Sky finds the precipitation down to your exact location; we thought we’d shed a little light on how we do the same for the temperature.

In addition to its approximately 150 radar stations, the National Weather Service also operates about 1500 ground stations that take more traditional readings, including temperature, dew point, wind speed, and so on; additionally, they provide hour-by-hour forecasts of this data over the next day. All of this information is publicly available just like the radar data is. It’s really easy for us to know the temperature at those specific places around the country simply by downloading it from the government’s servers and looking up the temperature at the desired time. As an example, here are the ground stations and their temperatures for upstate New York:

The temperatures at various ground stations around the Northeast.

But what about everywhere in between those stations? Well, temperature is a very low-resolution phenomenon: it doesn’t change very much even over moderate distances. One approach (and, in fact, the first one we tried) is to simply find the nearest station to a given location and use its temperature. This works pretty well most of the time, but starts to fall apart if the nearest station is on top of a mountain, or far away: we could be off by several degrees. A couple degrees doesn’t sound like much, but trust me: we get complaints over even minor issues!

A better solution (and the one we now use[2]) is to average the temperatures of nearby stations; but which stations do we pick? The technique that we settled on is one that has been successfully applied to similar scenarios in computer graphics, called triangulation[3]: we just “connect the dots” between stations until we’ve covered the entire country in triangles; then, to figure out which stations to average, we find which triangle the desired location is in, and take a weighted average of the three stations that form that triangle.[4]

The ground stations with triangles drawn between them.

That’s really all there is to it! For sake of comparison, below is the “nearest station” version side by side with the “averaged” version. You can see how much more smoothly temperatures blend over distances:

A heatmap overlaid on the ground stations using both the nearest neighbor algorithm and triangulation interpolation.

  1. We really like using Apple’s iPhone weather widget alongside Dark Sky, but we found out later that it isn’t available on the iPad — and since one of our developers only uses an iPad, we knew we had to do something about it! 

  2. We find that doing these kinds of predictions on our servers, rather than in the app itself, is preferable because we can continually improve accuracy without having to send out an app update. 

  3. The exact method we use is called Delaunay triangulation: it tries to form triangles that are as close to equilateral as possible. This ensures that the stations that form the vertices of the triangle are as close (on average) to any point within the triangle as possible. Our JavaScript implementation of Delaunay triangulation is open source. 

  4. The fastest way to check whether a point is within a triangle is to find that point’s barycentric coordinates; this has the beneficial side effect of also giving us the weighting coefficients for each vertex for free.