Skip to content

Commit 3a19e4f

Browse files
author
Martin Journois
committed
Implement _get_self_bounds for GeoJson, Polyline...
1 parent d660a52 commit 3a19e4f

File tree

3 files changed

+71
-10
lines changed

3 files changed

+71
-10
lines changed

folium/features.py

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010

1111
from .utilities import (color_brewer, _parse_size, legend_scaler,
1212
_locations_mirror, _locations_tolist, image_to_url,
13-
text_type, binary_type)
13+
text_type, binary_type,
14+
none_min, none_max, iter_points,
15+
)
1416

1517
from .element import Element, Figure, JavascriptLink, CssLink, MacroElement
1618
from .map import Layer, Icon, Marker, Popup
@@ -280,7 +282,30 @@ def _get_self_bounds(self):
280282
"""Computes the bounds of the object itself (not including it's children)
281283
in the form [[lat_min, lon_min], [lat_max, lon_max]]
282284
"""
283-
raise NotImplementedError
285+
if not self.embed:
286+
raise ValueError('Cannot compute bounds of non-embedded GeoJSON.')
287+
288+
if 'features' not in self.data.keys():
289+
# Catch case when GeoJSON is just a single Feature or a geometry.
290+
if not (isinstance(self.data, dict) and 'geometry' in self.data.keys()):
291+
# Catch case when GeoJSON is just a geometry.
292+
self.data = {'type' : 'Feature', 'geometry' : self.data}
293+
self.data = {'type' : 'FeatureCollection', 'features' : [self.data]}
294+
295+
bounds = [[None,None],[None,None]]
296+
for feature in self.data['features']:
297+
for point in iter_points(feature.get('geometry',{}).get('coordinates',{})):
298+
bounds = [
299+
[
300+
none_min(bounds[0][0], point[1]),
301+
none_min(bounds[0][1], point[0]),
302+
],
303+
[
304+
none_max(bounds[1][0], point[1]),
305+
none_max(bounds[1][1], point[0]),
306+
],
307+
]
308+
return bounds
284309

285310
class TopoJson(MacroElement):
286311
def __init__(self, data, object_path):
@@ -584,7 +609,19 @@ def _get_self_bounds(self):
584609
"""Computes the bounds of the object itself (not including it's children)
585610
in the form [[lat_min, lon_min], [lat_max, lon_max]]
586611
"""
587-
raise NotImplementedError
612+
bounds = [[None,None],[None,None]]
613+
for point in iter_points(self.data):
614+
bounds = [
615+
[
616+
none_min(bounds[0][0], point[0]),
617+
none_min(bounds[0][1], point[1]),
618+
],
619+
[
620+
none_max(bounds[1][0], point[0]),
621+
none_max(bounds[1][1], point[1]),
622+
],
623+
]
624+
return bounds
588625

589626
class MultiPolyLine(MacroElement):
590627
def __init__(self, locations, color=None, weight=None,
@@ -636,7 +673,19 @@ def _get_self_bounds(self):
636673
"""Computes the bounds of the object itself (not including it's children)
637674
in the form [[lat_min, lon_min], [lat_max, lon_max]]
638675
"""
639-
raise NotImplementedError
676+
bounds = [[None,None],[None,None]]
677+
for point in iter_points(self.data):
678+
bounds = [
679+
[
680+
none_min(bounds[0][0], point[0]),
681+
none_min(bounds[0][1], point[1]),
682+
],
683+
[
684+
none_max(bounds[1][0], point[0]),
685+
none_max(bounds[1][1], point[1]),
686+
],
687+
]
688+
return bounds
640689

641690
class CustomIcon(Icon):
642691
def __init__(self, icon_image, icon_size=None, icon_anchor=None,

folium/map.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -167,12 +167,6 @@ def add_tile_layer(self, tiles='OpenStreetMap', name=None,
167167
detect_retina=detect_retina)
168168
self.add_children(tile_layer, name=tile_layer.tile_name)
169169

170-
def _get_self_bounds(self):
171-
"""Computes the bounds of the object itself (not including it's children)
172-
in the form [[lat_min, lon_min], [lat_max, lon_max]]
173-
"""
174-
return [[self.location[0],self.location[1]],[self.location[0],self.location[1]]]
175-
176170
class Layer(MacroElement):
177171
"""An abstract class for everything that is a Layer on the map.
178172
It will be used to define whether an object will be included in LayerControls.

folium/utilities.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,3 +444,21 @@ def none_max(x,y):
444444
return x
445445
else:
446446
return max(x,y)
447+
448+
def iter_points(x):
449+
"""Iterates over a list representing a feature, and returns a list of points,
450+
whatever the shape of the array (Point, MultiPolyline, etc).
451+
"""
452+
if isinstance(x,list):
453+
if len(x):
454+
if isinstance(x[0],list):
455+
out = []
456+
for y in x:
457+
out += iter_points(y)
458+
return out
459+
else:
460+
return [x]
461+
else:
462+
return []
463+
else:
464+
raise ValueError('List type expected {!r}'.format(x))

0 commit comments

Comments
 (0)