Introduction: Scaling the Heights in 3D

As an avid sports competitor, triathlons, duathlons etc. I have spent a lot of time collecting data for all my sporting activities and like most people in this arena upload their data to Strava or other similar applications.

When not training or working I manage to make and create things.

Fairly recently I have become involved in 3D printing and whilst being an Engineer (Electronics/Coding); it felt more suitable to build a 3D printer rather than buying one. As I felt that I would get a better understanding of the inner workings of a printer and be able to troubleshoot problems much easier, additionally there is the satisfaction of completing a challenge.

I investigated a number of printers and decided on a HICTOP self-assembly, I built the printer and set about making a myriad of different objects with printing times from 20mins to 10hrs. Along the way there were pitfalls and disasters (setting a print going watching it progress with no issues for several hours, going the bed with the expectation of a completed print in the morning only to find a rats nest of filament due to a power surge or because it detached from the bed), all of which improved my knowledge..

A number of models have been created using BlockCAD and Cura.

But how does 3D printing and Sports data on STRAVA have a connection you may ask?

Well, whilst looking at a recent route I wondered what it would look like as a 3D model and what would be involved in the process.

How would I take a GPX file and turn it into a suitable file for the 3D printer?


1: GPX file - Downloaded directly from your GPS device or from your fitness application repository.

2: MS EXCEL including VBA - The application used to realise this project which would parse the GPX file and output a GCODE file

The following applications were used to debug the resulting GCODE file.

3: Ultimaker Cura slicer - Display the image with different viewing angles and also showing rapid moves which allowed me to see and optimise the print movement for areas not to be printed.

4: Pronterface - Similar visualisation to Cura but additionally, it listed the number of layers and an estimated print time.

5: Q'n'dirty would display the image with different viewing angles but would also show rapid moves similar to Prontaface. However, Q'n'dirty would highlight any commands it failed to resolve.


GPX - GPS Exchange Format -

GPS - Global Positioning System -

GCODE - Geometric Code -

STRAVA - an internet service for tracking human exercise which incorporates social network features.

XML - Extensible Markup Language, plain text file utilising tags.

Step 1: Parsing the GPX File

How would I take a GPX file and turn it into a suitable file for the 3D printer?

The first steps were to interrogate the GPX file contents, which was easily accomplished using a text editor, in this case I used Notepad.

Once passed the header information, the data consisted in this particular variant of a repeated sequence of data.

The main elements within this block of data being latitude (lat), longitude (lon) and elevation (ele) with additional data for date and time and heart rate.

Using VBA and Excel I constructed a parser that iterated through the file and extracting the data at the appropriate tags, I was then able to populate the cells with the data.

Additionally, using latitude and longitude I was able to calculate and include Speed, Slope and Watts.

Although, as far as this project is intended latitude, longitude and elevation were the primary focus.

Each block of data within the GPX file is used to populate rows 7 to the end of the file in this case row 6475.

A total of 6469 lines of data with a summary on rows 1 to 6.

I had now loaded the GPX data and added the appropriate information.

Graphical visualisation of the data was the next step to determine that this aligned with the reference map on STRAVA.

Step 2: Charting the Data

In charting the data I wanted to display this in 2 forms, 2D and 3D.

The 2D chart was simply longitude and latitude data plotted as an X/Y line chart and showed the outline of the route comparing this against the reference map showed no issues.

Next was to display this as a 3D map to enable comparison of the elevation data, with the addition of the data used to create the 2D chart, this was plotted as a 3D surface chart.

Both of these charts were plotted at run time directly from the data and negated additional manual steps.

I had now parsed the GPX data and columnated it in EXCEL with additional data, summaries and charts which aligned with the reference data.

The next stage was to convert this into GCODE although at this stage I had yet to investigate this process.

Step 3: 2D Numerical Visualisation

At this point it felt about time to add a user interface to easily change scaling factors for the 3 main GPS elements and set filament details rather than hardcoding these values.

The next stage was to create a 2D visualisation of this imported data on a worksheet where for each X/Y position in conjunction with it’s corresponding Z each column for that row would have an incremental value assigned up to the highest Z value in the dataset (ZDS). If the maximum Z for the row was less than the ZDS the cells from Z to ZDS would be filled with null values. This was repeated for each row of imported data.

This is visualised in the spreadsheet extract were the positive values are colour coded red showing a section of the route map profile. Each column represents a print slice with the red section the part of the slice which will actually be printed.

Because the maximum X, Y or Z can run into thousands of metres the data needs to be scaled to fit on the limited area of the print bed in millimetres.

This is accomplished using the following formula.

New Value = (Current value – Dataset Min)/Dataset Range * New Range + New Minimum.


Dataset Range = Dataset Max – Dataset Min

New Range = New Max – New Min

Suitable values being selected to produce a usable print and entered on the user interface.

However, although we have a numerical 2D representation this still need to be converted to GCODE.

Step 4: GCODE Creation

Zero experience of GCODE but undaunted I set about learning the requirements of the task in hand.

I found the following very useful.

In conjunction with information in the wiki I also had a ready supply of GCODE files from previous prints which I could inspect to see how the file was formatted.

For the main body of the GCODE mainly G0 (Rapid Move) and G1(Linear Move) instructions are used.

The format for each main line is:

G1 Xn Yn Zn En


E - The amount to extrude between the starting point and ending point and n is the value.

There are some other factors to take into out which impacts the E value in the GCODE, filament height, diameter & length extrusion width and Aroad-scaler. These options are included

The E value is cumulative for each move.

This instruction is used when printing is required.

For areas were printing is not required G0 is used in conjunction with the feed rate (F) either with or without co-ordinates.

G0 Fn were F is set to a higher feed-rate than that used when printing.

G0 F7200 X100 Y100

Would move to the specified co-ordinates at a feed-rate of 7200mm/min, the purpose being to move the extruder head rapidly from point to point and eliminate printing between those points.

Prior to printing at the required co-ordinates, the following type of command is issued to over-ride the previous feed-rate.

G0 F1500

However, a downside with the rapid move is strings between the points due to pressure in the print head continuing to force a small amount of molten plastic.

Applying retraction can be used to relieve the pressure in the print head to eliminate this.

The conversion process required taking the 2D visualisation data and beginning at column A iterating from row 1 to the last row and repeating this process for each column converting each data point to its GCODE equivalent.

Even with the GCODE complete for the GPS data there was still something missing.

I needed initialisation code at the beginning and reset code at the end.

Rather then generating these each time in the application I saved these into two separate sheets and pre-fixed and post fixed these to the generated GCODE with the result being saved in a file.

Once I had produced a GCODE file I could try sending this to the printer and see what happens.

Step 5: Testing the GCODE

Once I had produced a GCODE file I could try sending this to the printer and see what happens.

However, being a little more cautious at this stage I wanted to evaluate the file using a GCODE viewer/simulator to check for any issues.

In the course of this evaluation I tried 3, applications Cura, Pronterface & Q'n'dirty.

All could be used to load and visualise the data.

Cura - loaded the file but disabled any printer options.

Pronterface - when the file loaded filament, print duration time and layers were presented.

Q'n'dirty. - presented print time duration but was the only one to identify specific lines in the GCODE with issues, once these were resolved the image was displayed even though some warnings remained.

These warnings although for valid GCODES did not prevent the file being printed.

Step 6: Printing

Time to see whether the results of my efforts gave me what I intended.

I copied the file to the printer and initiated the print process.

After a few short minutes compared to some of my other prints, success.

I had finally produced a 3D model from a GPX file.

A little post processing to remove stringers was all that was required for the final model.

Maps Challenge

Participated in the
Maps Challenge