-
Notifications
You must be signed in to change notification settings - Fork 19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add support for preprocessed inline geojson layers #414
Changes from 13 commits
18f4eab
13c9d51
4ad7535
2672c33
929fc98
c2461f5
a050451
6809975
d2f4d43
3ae65c7
937fc29
40ba90a
8e77520
542e310
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,17 @@ | ||
from __future__ import division | ||
|
||
import itertools | ||
import json | ||
import os.path | ||
from collections import defaultdict | ||
from collections import namedtuple | ||
from cStringIO import StringIO | ||
from sys import getsizeof | ||
|
||
from shapely import geometry | ||
from shapely.geometry import GeometryCollection | ||
from shapely.geometry import MultiPolygon | ||
from shapely.geometry import shape | ||
from shapely.wkb import loads | ||
from zope.dottedname.resolve import resolve | ||
|
||
|
@@ -69,12 +74,13 @@ def _sizeof(val): | |
'log', | ||
]) | ||
|
||
|
||
# post-process all the layers simultaneously, which allows new | ||
# layers to be created from processing existing ones (e.g: for | ||
# computed centroids) or modifying layers based on the contents | ||
# of other layers (e.g: projecting attributes, deleting hidden | ||
# features, etc...) | ||
|
||
|
||
def _postprocess_data( | ||
feature_layers, post_process_data, nominal_zoom, unpadded_bounds, | ||
log_fn=None): | ||
|
@@ -112,7 +118,6 @@ def _log_fn(data): | |
# append it. | ||
if layer is not None: | ||
feature_layers.append(layer) | ||
|
||
return feature_layers | ||
|
||
|
||
|
@@ -146,7 +151,6 @@ def _cut_coord( | |
padded_bounds=padded_bounds, | ||
) | ||
cut_feature_layers.append(cut_feature_layer) | ||
|
||
return cut_feature_layers | ||
|
||
|
||
|
@@ -286,6 +290,12 @@ def process_coord_no_format( | |
# filter, and then transform each layer as necessary | ||
for feature_layer in feature_layers: | ||
layer_datum = feature_layer['layer_datum'] | ||
# inline layers are expected to be pre-processed | ||
layer_path = layer_datum.get('pre_processed_layer_path') | ||
if layer_path is not None: | ||
processed_feature_layers.append(feature_layer) | ||
continue | ||
|
||
layer_name = layer_datum['name'] | ||
geometry_types = layer_datum['geometry_types'] | ||
padded_bounds = feature_layer['padded_bounds'] | ||
|
@@ -512,6 +522,33 @@ def _calculate_scale(scale, coord, nominal_zoom): | |
return scale | ||
|
||
|
||
def _load_inline_layer(layer_path): | ||
# we can optionally load geojson layers from file all we need is a file path. we expect the coordinates to already | ||
# be in mercator projection and we only fill out the minimal structure of the feature tuple, ie there's no ID. if | ||
# the path is given and the file exists, we expect to be able to load the layer's features. so if the json is | ||
# malformed or shapely can't make sense of the geom then we'll raise | ||
features = [] | ||
|
||
# has to exist | ||
if not os.path.isfile(layer_path): | ||
return features | ||
|
||
# load the geojson into a shapely geometry collection | ||
with open(layer_path) as fh: | ||
fc = json.load(fh) | ||
# skip if this isnt pseudo mercator | ||
if fc['crs']['properties']['name'] != 'urn:ogc:def:crs:EPSG::3857': | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same concern, is there any log we can emit to tell whether it happens, otherwise it is hard to debug if it not working as expected? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. here we can log as it was clear the person meant to load it but screwed something up. maybe same for the file extension |
||
raise Exception('Pre-processed layers must be in pseudo mercator projection') | ||
gc = GeometryCollection([shape(feature['geometry']) for feature in fc['features']]) | ||
|
||
# add the features geometries with their properties in tuples | ||
for geom, feat in itertools.izip(gc.geoms, fc['features']): | ||
props = feat['properties'] | ||
features.append((geom, props, props.get('id'))) | ||
|
||
return features | ||
|
||
|
||
def format_coord( | ||
coord, nominal_zoom, max_zoom_with_changes, processed_feature_layers, formats, | ||
unpadded_bounds, cut_coords, buffer_cfg, extra_data, scale): | ||
|
@@ -645,7 +682,7 @@ def convert_source_data_to_feature_layers(rows, layer_data, unpadded_bounds, zoo | |
# expecting downstream in the process_coord function | ||
for layer_datum in layer_data: | ||
layer_name = layer_datum['name'] | ||
layer_props = row_props_by_layer[layer_name] | ||
layer_props = row_props_by_layer.get(layer_name) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any side-effect this might introduce? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i dont think so. if you scroll up just a bit you'll see that this object has props for every layer except this new landmarks layer. those are set to either a value or to |
||
if layer_props is not None: | ||
props = common_props.copy() | ||
props.update(layer_props) | ||
|
@@ -665,6 +702,13 @@ def convert_source_data_to_feature_layers(rows, layer_data, unpadded_bounds, zoo | |
|
||
features_by_layer[layer_name].append(query_props) | ||
|
||
# inline layers contain a path to their features inline in their datum | ||
for layer_datum in layer_data: | ||
layer_name = layer_datum['name'] | ||
layer_path = layer_datum.get('pre_processed_layer_path') | ||
if layer_path is not None: | ||
features_by_layer[layer_name].extend(_load_inline_layer(layer_path)) | ||
|
||
feature_layers = [] | ||
for layer_datum in layer_data: | ||
layer_name = layer_datum['name'] | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit, say
single child cood (here over XYZ placename)