Adding Arrowheads in a Route

Capture.JPG
Click link to view dashboard

Tableau is easy to use for many visualizations, but one feature which posed a challenge to me was adding arrows to show the direction of a route in map. However, once one understand the workings of how some trigonometry and Tableau works (and its limitations), it is quite easy to replicate.

First, I downloaded my runkeeper data around a park. It has the latitude (Y) and longitude (X) coordinates and the sequence of coordinates (track_seg_point_id). Representing in Tableau, the path will show this:

Capture.JPG

Now let’s build the arrowheads.

1. Calculate the angle of travel for each row

The formula for calculating angle between two XY coordinates in Excel is =INT(DEGREES(ATAN2((A2-A3),(B2-B3)))).

Breaking it down:

A2 = longitude of the previous row
A3 = longitude of current row
B2 = latitude of previous row
B3 = latitude of current row
ATAN2 = formula to derive angle in radians
DEGREES = convert radian to degrees
INT = convert degree in decimals to an integer

A side note, for SQL it would be this below. Note that latitude & longitude are swapped for atan2 function compared to Excel.

select latitude, longitude, path_sequence,
degrees(atan2(latitude - lag(latitude) over(order by path_sequence),
	      longitude - lag(longitude) over(order by path_sequence)))
              as angle
from table_nm

Use this formula to create a new column called angle and apply to all rows.

Now add angles in the same column from -180 to 180 (including 0), leaving all other values in other fields as null.

Capture.JPG

2. Get an Arrowhead Picture and rotate it 360 times

Note: this step is optional. You can just extract my custom shapes from my twbx file and dump it in your Tableau shapes folder using this handy extractor tool.

Now go google for an arrowhead picture that suits your taste and purpose. It should be in png format with transparency. The arrowhead should be pointing directly to the east.

Then, create a folder call ‘arrowheads’ in your ..\Documents\My Tableau Repository\Shapes folder, and put it in there. Now, rotate the arrowhead so that it has the angles -180 to 180, including 0. I used a python script below to do the rotation.

from PIL import Image

img = Image.open(r'C:\Users\...\Documents\My Tableau Repository\Shapes\Arrowhead\000.png')

# rotate arrows anticlockwise
for angle in range(1,180):
newangle = angle
img.rotate(newangle).save('C:\Users\...\Documents\My Tableau Repository\Shapes\Arrowhead\{}.png'.format(str(angle).zfill(3)))

# rotate arrows clockwise
for angle in range(1,180):
newangle = 180-angle
img.rotate(newangle).save(r'C:\Users\...\Documents\My Tableau Repository\Shapes\Arrowhead\000 -{}.png'.format(str(angle).zfill(3)))

A key note is to label the arrowhead images so that they arrange according to how Tableau arranges it at Marks > Shape. Notice at it starts from NULL (note that the first row is always null as there are no coordinates before the first sequence to calculate an angle, and then from -180 to 0 to 180. It is because of this limitation (of not being able to match values to shape image names) that the extra -180 to 180 values have to be added to the Excel angle column so that all possible angles are covered.

Capture1.JPG
How Tableau arranges values

3. Plot the Arrowheads in Tableau

Now to add the arrowheads. First create another map by ctrl + drag the X or Y column.

At the marks panel, change the mark type dropdown to Shape
> drag the Angle column into the Shape mark
> Click on the Shape mark > Select Shape Palette
> arrowhead (the folder you created earlier, if not present, click Reload Shapes and try again)
> Assign Palette.

Capture.JPG

Now, merge both maps together by clicking the dropdown button at the AVG(Y) and select Dual Axis. Add the Angle column to the Color marks and change all angles to red. The result is as seen below.

Capture

Of course, we don’t need so many arrows. So I created a new column and only retain certain angles at fixed intervals. Now it looks much nicer!

Capture1

Leave a comment