Tuesday, 7 July 2015

python - Rounding all coordinates in shapely?


Following on from How can I add points to a LineString in shapely?, I'm hitting a problem where floating point representations mean objects aren't precisely where I expect them be after they are moved using affinity.translate.


This would be fixed if there was a way of rounding all the coordinates to the nearest cm (or other insignificantly-small value).



Does this exist?




For what it's worth, I'm doing all my intersection and union operations first before the translation and that seems to be working.



Answer



Shapely and GEOS cannot reduce precision (floating-point precision problem) but you can use other functions as numpy.round() or round(),with the GeoJSON format.


For polygons


from shapely.geometry import shape, mapping
import numpy as np
# one polygon
print poly.wkt

POLYGON ((101.2200527190607 -114.6493019170767, 146.6225142079163 -114.4488495484725, 185.0301801801801 -114.2792792792793, 184.6581081081081 -217.7153153153153, 14.99324324324321 -218.4594594594595, 16.4815315315315 -115.0234234234234, 101.2200527190607 -114.6493019170767))
# convert to GeoJSON format
geojson = mapping(poly)
print geojson
{'type': 'Polygon', 'coordinates': (((101.2200527190607, -114.6493019170767), (146.6225142079163, -114.4488495484725), (185.0301801801801, -114.2792792792793), (184.6581081081081, -217.7153153153153), (14.99324324324321, -218.4594594594595), (16.4815315315315, -115.0234234234234), (101.2200527190607, -114.6493019170767)),)}
geosjson['coordinates'] = np.round(np.array(geosjon['coordinates']),2)
print geosjson
{'type': 'Polygon', 'coordinates': array([[[ 101.22, -114.65],
[ 146.62, -114.45],
[ 185.03, -114.28],

[ 184.66, -217.72],
[ 14.99, -218.46],
[ 16.48, -115.02],
[ 101.22, -114.65]]])}
print shape(geosjson)
POLYGON ((101.22 -114.65, 146.62 -114.45, 185.03 -114.28, 184.66 -217.72, 14.99 -218.46, 16.48 -115.02, 101.22 -114.65))

If you don't want to use Numpy, you can adapt the function def _set_precision(coords, precision) of the geosjson-precision module


 def set_precision(coords, precision):
result = []

try:
return round(coords, int(precision))
except TypeError:
for coord in coords:
result.append(_set_precision(coord, precision))
return result
geojson = mapping(poly)
geosjson['coordinates']= set_precision(geosjson['coordinates'], 2)
print geosjson
{'type': 'Polygon', 'coordinates': [[[101.22, -114.65], [146.62, -114.45], [185.03, -114.28], [184.66, -217.72], [14.99, -218.46], [16.48, -115.02], [101.22, -114.65]]]}

print shape(geosjson)
POLYGON ((101.22 -114.65, 146.62 -114.45, 185.03 -114.28, 184.66 -217.72, 14.99 -218.46, 16.48 -115.02, 101.22 -114.65))

No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...