|
10 | 10 |
|
11 | 11 | from .utilities import (color_brewer, _parse_size, legend_scaler,
|
12 | 12 | _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 | + ) |
14 | 16 |
|
15 | 17 | from .element import Element, Figure, JavascriptLink, CssLink, MacroElement
|
16 | 18 | from .map import Layer, Icon, Marker, Popup
|
@@ -280,7 +282,30 @@ def _get_self_bounds(self):
|
280 | 282 | """Computes the bounds of the object itself (not including it's children)
|
281 | 283 | in the form [[lat_min, lon_min], [lat_max, lon_max]]
|
282 | 284 | """
|
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 |
284 | 309 |
|
285 | 310 | class TopoJson(MacroElement):
|
286 | 311 | def __init__(self, data, object_path):
|
@@ -584,7 +609,19 @@ def _get_self_bounds(self):
|
584 | 609 | """Computes the bounds of the object itself (not including it's children)
|
585 | 610 | in the form [[lat_min, lon_min], [lat_max, lon_max]]
|
586 | 611 | """
|
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 |
588 | 625 |
|
589 | 626 | class MultiPolyLine(MacroElement):
|
590 | 627 | def __init__(self, locations, color=None, weight=None,
|
@@ -636,7 +673,19 @@ def _get_self_bounds(self):
|
636 | 673 | """Computes the bounds of the object itself (not including it's children)
|
637 | 674 | in the form [[lat_min, lon_min], [lat_max, lon_max]]
|
638 | 675 | """
|
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 |
640 | 689 |
|
641 | 690 | class CustomIcon(Icon):
|
642 | 691 | def __init__(self, icon_image, icon_size=None, icon_anchor=None,
|
|
0 commit comments