jazzband / geojson

Python bindings and utilities for GeoJSON
https://pypi.python.org/pypi/geojson/
BSD 3-Clause "New" or "Revised" License
905 stars 120 forks source link

Add option to allow specifying floating point precision on geojson.dump/geojson.dumps #84

Closed frewsxcv closed 5 years ago

frewsxcv commented 7 years ago

Just received an email with this request:

I would like to suggest that you provide a means to specify the precision of floats that the module outputs, perhaps a format string as an argument to dump()/dumps().

A typical coordinate coming from geojson looks like: [-74.4995503571598, 39.42247551734061]. That's 14 decimal places in the fraction, far, far more than I'll ever need considering that 8 places gives 1.1mm precision. I would like to reduce the file size by limiting the precision to a sensible value.

frewsxcv commented 7 years ago

From what I can tell, there's no way to do this via json.dumps, so I'm not entirely sure how one would go about this.

sgillies commented 7 years ago

@frewsxcv json.dumps will not write excess places of precision for rounded floats:

>>> import json
>>> import math
>>> json.dumps(round(math.pi, 2))
'3.14'

In my Fiona project, I'm doing this in Cython: https://github.com/Toblerity/Fiona/blob/master/fiona/_transform.pyx#L151-L180. It could be ported?

frewsxcv commented 7 years ago

round returns a String, which might not be what the user wants? I'll think about it.

sgillies commented 7 years ago

No, round() returns a float. json.dumps() returns a string.

frewsxcv commented 7 years ago

You're right, not sure what I was thinking. sips coffee

That looks like a good solution then.

emiliom commented 6 years ago

Has this feature been implemented? I assume not, but checking just in case. Thanks.

frewsxcv commented 6 years ago

It hasn't been implemented yet, but if someone had time to implement it, I'd gladly review+merge it

dharasty commented 6 years ago

This can be accomplished with the current API via this:

def round5(c): return round(c, 5)
rounded_coords_geom = geojson.GeoJSON.to_instance(geojson.utils.map_coords(round5, geometry))

Then use rounded_coords_geom in dumps().

Quick tip: rounding lng-lat to 5 decimal places is pretty close to 1 meter precision. (This varies by latitude, but not a bad estimate.)

rayrrr commented 5 years ago

Looking at the Decimal Degrees precision chart, 7 decimal places is the "practical limit of commercial surveying" and 8 is related to "specialized surveying (e.g. tectonic plate mapping)." So, let's go with 8 decimal places as the default; customization can be implemented separately/in parallel.

rayrrr commented 5 years ago

I did some more research on the WGS84 Geodetic Datum (the one to which GeoJSON is specifically bound) and it turns out that, according to the U.S. National Geospatial-Intelligence Agency (PDF link) the accuracy of WGS84 is in the 1 meter range. That puts us in the 5-6 decimal place default range. So we'll go with 6 places instead of 8 as the default.