Pints in the sun uses a bunch of tech that I wanted to try out and learn more about. It addresses the very real problem of finding a pub that will be sunny in the evening, and not overshadowed by adjacent buildings.

What it does

Using building outline data from Open Streetmap, the locality around a pub (located via Four Square) is rendered in 3D with three.js (map projection conversion couresty of the D3 library) and onto it. A directional light is projected onto it from the part of the sky where the sun would be at certain times of year/day. It turns out that the position of the sun can be calculated with a Solar Almanac Calculation, helpfully implemented in JS by SunCalc Alt text

Maths

The solar positional calculation provides an Altitude (in radians) and an Azimuth (also in radians). Converting this into a useful lightsource position for threejs presented a pretty major challenge. After many confused sketches, I managed to workout how to triangulate these two angles (a spherical coordinate system) into X, Y and Z for the 3D rendering. Alt text Alt text

Data

Using Open Streetmap for the mapping part (I fancied a change from Google Maps) my attention was drawn to a clever API called Overpass. It delivers (amongst a lot of other stuff) building outline data for a certain radius around a point. The lat/lng nodes in the GeoJSON returned is converted into the localised 3D coordinate system, using the magical map projection feature of D3.

Architecture

…Of the app, not the buildings

Many of the challenges of rendering 3D buildings has been addressed by the much more clever project Vizi Cities. As well as 3D, there are many learnings to be taken in terms of application architecture. One such design pattern that I made used of was loosely coupling components such as the map, the renderer and the clock, via a Mediator. In this way different parts of the app can publish and subscribe to events, generated or consumed by others. For example when the user drags the slider to change time time of day, both the clock display and the 3D renderer subscribe to events, and manifest their reaction within their own responsibilities.

Whilst all this, as a solution, is inferior to simply going down the boozer and making observations it's been a fun way of trying out some very clever libraries.