Skip to content

Commit

Permalink
use ujson if available, and optimize bbox function
Browse files Browse the repository at this point in the history
new version of coordstring_bbox function is approx 2x as fast with a
string of 1000 random 2D coordinates

Note: removes NumpyAwareJSONEncoder, meaning that numpy >= 1.9 is
required if inputs have coordinates stored in numpy arrays
  • Loading branch information
njwilson23 committed Feb 15, 2017
1 parent b61b808 commit f4c6232
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 24 deletions.
13 changes: 10 additions & 3 deletions picogeojson/bbox.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-

def geom_bbox(geom):
if type(geom).__name__ == "Point":
Expand Down Expand Up @@ -45,10 +46,16 @@ def feature_collection_bbox(coll):
return bbx

def coordstring_bbox(coordinates):
""" Given a string of coodinates, return the bounds as a *2×N* length list,
where *N* is the number of dimensions (at least two).
The bounding list is structured `xmin, ymin[, ...], xmax, ymax[, ...]`.
"""
ndim = len(coordinates[0])
bbx = [0 for _ in range(2*ndim)]
for dim in range(ndim):
bbx[dim] = min(crds[dim] for crds in coordinates)
bbx[dim+ndim] = max(crds[dim] for crds in coordinates)
components = [[a[i] for a in coordinates] for i in range(ndim)]
for i, comp in enumerate(components):
bbx[i] = min(comp)
bbx[i+ndim] = max(comp)
return bbx

28 changes: 7 additions & 21 deletions picogeojson/geojson.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@
- `Serializer` validates and converts named tuples to GeoJSON strings.
"""

import json
try:
import ujson as json
except ImportError:
import json

from .types import (Point, LineString, Polygon,
MultiPoint, MultiLineString, MultiPolygon,
GeometryCollection, Feature, FeatureCollection)
Expand All @@ -25,23 +29,6 @@
DEFAULTCRS = {"type": "name",
"properties": {"name": "urn:ogc:def:crs:OGC:1.3:CRS84"}}

class NumpyAwareJSONEncoder(json.JSONEncoder):
""" Numpy-specific numbers prior to 1.9 don't inherit from Python numeric
ABCs. This class is a hack to coerce numpy values into Python types for
JSON serialization. """

def default(self, o):
if not hasattr(o, "dtype") or (hasattr(o, "__len__") and (len(o) != 1)):
return json.JSONEncoder.default(self, o)
elif o.dtype in ("int8", "int16", "int32", "int64"):
return int(o)
elif o.dtype in ("float16", "float32", "float64", "float128"):
return float(o)
elif o.dtype in ("complex64", "complex128", "complex256"):
return complex(o)
else:
raise TypeError("not a recognized type")

class Deserializer(object):

def __init__(self, defaultcrs=DEFAULTCRS):
Expand Down Expand Up @@ -165,9 +152,8 @@ def __init__(self, antimeridian_cutting=True, enforce_poly_winding=True, write_b
self.write_bbox = write_bbox
return

def __call__(self, geom, indent=None):
return json.dumps(self.geojson_asdict(geom), indent=indent,
cls=NumpyAwareJSONEncoder)
def __call__(self, geom, indent=0):
return json.dumps(self.geojson_asdict(geom), indent=indent)

def geojson_asdict(self, geom, parent_crs=None):
if isinstance(geom, Feature):
Expand Down

0 comments on commit f4c6232

Please sign in to comment.