Skip to content

Commit

Permalink
[core] Fix get_bounds behavior in core (#2012)
Browse files Browse the repository at this point in the history
* [core] Fix get_bounds behavior in core.

Also:
- added alias for getBounds,
- fixed an issue where geemap crashed without a helpful message if the map hadn't been added to the screen, and
- added some unit tests.

The behavior was correct in geemap non-core.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Rename as_geo_json to as_geojson

* Rename as_geo_json to as_geojson

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Qiusheng Wu <giswqs@gmail.com>
  • Loading branch information
3 people committed Jun 14, 2024
1 parent 00b5bca commit c0fc89f
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 13 deletions.
25 changes: 23 additions & 2 deletions geemap/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -502,9 +502,29 @@ def set_zoom(self, value: int) -> None:
def get_center(self) -> Sequence:
return self.center

def get_bounds(self) -> Sequence:
def get_bounds(self, as_geojson: bool = False) -> Sequence:
"""Returns the bounds of the current map view.
Args:
as_geojson (bool, optional): If true, returns map bounds as
GeoJSON. Defaults to False.
Returns:
list|dict: A list in the format [west, south, east, north] in
degrees or a GeoJSON dictionary.
"""
bounds = self.bounds
return [bounds[0][0], bounds[0][1], bounds[1][0], bounds[1][1]]
if not bounds:
raise RuntimeError(
"Map bounds are undefined. Please display the " "map then try again."
)
# ipyleaflet returns bounds in the format [[south, west], [north, east]]
# https://ipyleaflet.readthedocs.io/en/latest/map_and_basemaps/map.html#ipyleaflet.Map.fit_bounds
coords = [bounds[0][1], bounds[0][0], bounds[1][1], bounds[1][0]]

if as_geojson:
return ee.Geometry.BBox(*coords).getInfo()
return coords

def get_scale(self) -> float:
# Reference:
Expand Down Expand Up @@ -901,3 +921,4 @@ def _on_layers_change(self, change) -> None:
addLayer = add_layer
centerObject = center_object
setCenter = set_center
getBounds = get_bounds
12 changes: 1 addition & 11 deletions geemap/geemap.py
Original file line number Diff line number Diff line change
Expand Up @@ -1137,17 +1137,7 @@ def get_bounds(self, asGeoJSON=False):
Returns:
list | dict: A list in the format [west, south, east, north] in degrees.
"""
bounds = self.bounds
coords = [bounds[0][1], bounds[0][0], bounds[1][1], bounds[1][0]]

if asGeoJSON:
return ee.Geometry.BBox(
bounds[0][1], bounds[0][0], bounds[1][1], bounds[1][0]
).getInfo()
else:
return coords

getBounds = get_bounds
return super().get_bounds(as_geo_json=asGeoJSON)

def add_cog_layer(
self,
Expand Down
6 changes: 6 additions & 0 deletions tests/fake_ee.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,12 @@ def getInfo(self, *_, **__):
"type": "Point",
"coordinates": [120, -70],
}
if self.type().value == "BBox":
return {
"geodesic": False,
"type": "Polygon",
"coordinates": [[0, 1], [1, 2], [0, 1]],
}
raise ValueError("Unexpected geometry type in test: ", self.type().value)

def __eq__(self, other: object):
Expand Down
17 changes: 17 additions & 0 deletions tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,23 @@ def test_center_object(self):
with self.assertRaisesRegex(ValueError, "Zoom must be an integer"):
self.core_map.center_object(ee.Geometry.Point(), "2")

@unittest.mock.patch.object(core.Map, "bounds")
def test_get_bounds(self, mock_bounds):
"""Tests that `get_bounds` returns the bounds of the map."""
mock_bounds.__get__ = Mock(return_value=[[1, 2], [3, 4]])
self.assertEqual(self.core_map.get_bounds(), [2, 1, 4, 3])
self.assertEqual(self.core_map.getBounds(), [2, 1, 4, 3])
expected_geo_json = {
"geodesic": False,
"type": "Polygon",
"coordinates": [[0, 1], [1, 2], [0, 1]],
}
self.assertEqual(self.core_map.get_bounds(as_geojson=True), expected_geo_json)

mock_bounds.__get__ = Mock(return_value=())
with self.assertRaisesRegex(RuntimeError, "Map bounds are undefined"):
self.core_map.get_bounds(as_geojson=True)

def test_add_basic_widget_by_name(self):
"""Tests that `add` adds widgets by name."""
self._clear_default_widgets()
Expand Down

0 comments on commit c0fc89f

Please sign in to comment.