I was asked by a customer today if it would be possible to create a Tableau viz that showed a set of locations (e.g. customers) on a map along with a user-defined circle to indicate a distance from a nominated point (e.g. a store).
Something like this? I replied…
Clearly it’s possible, but how do you do it?
The first step is to recognise that this is just an instance of plotting points and polygons on the same map – something I have blogged about previously. We can use the same techniques shown there – using custom SQL to get the point and polygon data into a single data source and then using an invisible mark (a 1x1px transparent PNG) to hide the circle on the points layer.
But how to create the data records for the circle? Again, we can leverage a technique previously explored – data densification. When creating our custom SQL all we have to do is append two records – one to be used as the start of the circle and one as the end. We can then use domain padding and densification to interpolate the values for the circle’s circumference.
Here is the full data set for the above visualisation – as you can see I am going to have 36 points around the outside of my circle (that should be enough to make it look smooth):
Identifier | Latitude | Longitude | Order | Type |
1 | Circle | |||
36 | Circle | |||
A | -37.7089 | 144.7861 | 1 | Point |
B | -37.7165 | 145.025 | 1 | Point |
C | -37.8294 | 145.0758 | 1 | Point |
D | -37.5936 | 145.0401 | 1 | Point |
E | -38.0179 | 145.1404 | 1 | Point |
From this we create our new Latitude and Longitude values using some simple high-school trigonometry:
//6.283185 is 2*PI (remember we are working in radians) //0.009 is an approx scaling factor for Km to deg Latitude if isNull(attr([Identifier])) then [Center Latitude] + (0.009*[Spread Distance]* SIN(6.283185*INDEX()/[Num Points])) else attr([Latitude]) end
//6.283185 is 2*PI (remember we are working in radians) //0.0117 is an approx scaling factor for Km to deg Longitude if isNull(attr([Identifier])) then [Center Longitude] + (0.0117*[Spread Distance]* COS(6.283185*INDEX()/[Num Points])) else attr([Longitude]) end
These calculations will densify when we create our final viz and use a Bin to pad out the Order field. Finally to make the workbook more flexible I set the spread distance, circle center lat/long and number of circle vertices as parameters.
You can download a copy of the workbook from here.
Enjoy!
You are too clever for your own good!! ☺
This is brilliant! What is the scaling factor for miles to degree latitude/longitude?
Hi jb,
The length of a degree changes as you move away from the equator, so it’s going to depend on where you want to draw your circle. Australia spans from -9° to -54° latitude so:
Latitude -9°
1° Latitude in Km 110.60
1° Latitude in Miles 68.72
Degrees per Mile 0.01455
1° Longitude in Km 109.96
1° Longitude in Miles 68.32
Degrees per Mile 0.01464
Latitude -54°
1° Latitude in Km 111.30
1° Latitude in Miles 69.16
Degrees per Mile 0.01446
1° Longitude in Km 65.56
1° Longitude in Miles 40.75
Degrees per Mile 0.02454
The solution I put together draws a circle so you might want to plug the different lat/lon scaling factors into the two calculations if you are drawing large circles in the south of Australia.
Here’s a useful calculator:
http://www.csgnetwork.com/degreelenllavcalc.html
Hope this helps.
Cheers,
Alan