I have a bunch of GPX tracks generated by iSmoothRun, a GPS tracker for the iPhone that tries to correct for location error by using the accelerometer as a pedometer. The tracks it produces are pretty lumpy too, so I’m trying to use ST_Simplify afterwards to clean them up.
ST_Simplify takes as a second parameter the “tolerance”, how much to smooth. This parameter is not well documented but it seems to be measured in the units of the geometry you are simplifying. For my walking tracks 0.00005 seems to be about right. If that were degrees, that’d correspond to about 15 – 20′ in San Francisco.
Here’s a quicky chart of the average percentage difference between the original track length and the simplified track length, for different tolerances.
0.00001 0.1% 0.00003 0.7% 0.00005 1.8% 0.00007 2.8% 0.0001 4.4% 0.001 19.9%
0.00005 seems to be a reasonable compromise. It produces tracks with about 1/3 the number of points as the original. Below is a picture of the original track and the simplified drawn on top of it, to show the geometry change.
I wish I understood SRIDs more intuitively, I feel like I’m bashing about. Half my data is WGS84 and half is Google Mercator, and then below I’m using SRID 2163 to do the distance calculation. That’s a bit of cargo cult coding, I think it’s NAD83 which is close enough to WGS84 to get away with.
-- Create a simplified view of an ogr2ogr imported track create or replace view simple_tracks as select ogc_fid, ST_Simplify(wkb_geometry,0.0001) as wkb_geometry, name from tracks; -- Display the difference between original and simplified select miles-smiles as difference, round((miles-smiles)/miles*100) as pctlength, round(spoints*100/points) as pctpoints, * from (select tracks.name, ST_Length(ST_Transform(simple_tracks.wkb_geometry, 2163)) /1609 as smiles, ST_Length(ST_Transform(tracks.wkb_geometry, 2163)) /1609 as miles, ST_NPoints(simple_tracks.wkb_geometry) as spoints, ST_NPoints(tracks.wkb_geometry) as points from simple_tracks inner join tracks on simple_tracks.name = tracks.name order by name) as m; -- Calculate just the average difference select avg((miles-smiles)/miles*100) from (select tracks.name, ST_Length(ST_Transform(simple_tracks.wkb_geometry, 2163)) /1609 as smiles, ST_Length(ST_Transform(tracks.wkb_geometry, 2163)) /1609 as miles from simple_tracks inner join tracks on simple_tracks.name = tracks.name order by name) as m where miles > 1;