diff --git a/python/grass/jupyter/interactivemap.py b/python/grass/jupyter/interactivemap.py index 16917d22716..92537084a8b 100644 --- a/python/grass/jupyter/interactivemap.py +++ b/python/grass/jupyter/interactivemap.py @@ -165,6 +165,16 @@ def __init__( folium documentation: https://python-visualization.github.io/folium/modules.html + Raster and vector data are always reprojected to Pseudo-Mercator. + With use_region=True or saved_region=myregion, the region extent + is reprojected and the number of rows and columns of that region + is kept the same. This region is then used for reprojection. + By default, use_region is False, which results in the + reprojection of the entire raster in its native resolution. + The reprojected resolution is estimated with r.proj. + Vector data are always reprojected without any clipping, + i.e., region options don't do anything. + :param int height: height in pixels of figure (default 400) :param int width: width in pixels of figure (default 400) :param str tiles: map tileset to use diff --git a/python/grass/jupyter/region.py b/python/grass/jupyter/region.py index 495b3581abe..298d95bc23a 100644 --- a/python/grass/jupyter/region.py +++ b/python/grass/jupyter/region.py @@ -17,6 +17,7 @@ from .utils import ( get_map_name_from_d_command, + estimate_resolution, set_target_region, get_rendering_size, ) @@ -39,16 +40,19 @@ def __init__(self, use_region, saved_region, src_env, tgt_env): self._saved_region = saved_region self._src_env = src_env self._tgt_env = tgt_env + self._resolution = None # [SW, NE]: inverted to easily expand based on data, see _set_bbox self._bbox = [[90, 180], [-90, -180]] if self._use_region: - # tgt region already set + # tgt region already set, set resolution + self._resolution = self._get_psmerc_region_resolution() self._set_bbox(self._src_env) if self._saved_region: self._src_env["GRASS_REGION"] = gs.region_env( region=self._saved_region, env=self._src_env ) set_target_region(src_env=self._src_env, tgt_env=self._tgt_env) + self._resolution = self._get_psmerc_region_resolution() self._set_bbox(self._src_env) @property @@ -56,6 +60,16 @@ def bbox(self): """Bbox property for accessing maximum bounding box of all rendered layers.""" return self._bbox + @property + def resolution(self): + """Resolution to be used for reprojection.""" + return self._resolution + + def _get_psmerc_region_resolution(self): + """Get region resolution (average ns and ew) of psmerc mapset""" + reg = gs.region(env=self._tgt_env) + return (reg["nsres"] + reg["ewres"]) / 2 + def set_region_from_raster(self, raster): """Sets computational region for rendering. @@ -71,8 +85,19 @@ def set_region_from_raster(self, raster): if self._use_region or self._saved_region: # target region and bbox already set return + # set target location region extent self._src_env["GRASS_REGION"] = gs.region_env(raster=raster, env=self._src_env) set_target_region(src_env=self._src_env, tgt_env=self._tgt_env) + # set resolution based on r.proj estimate + env_info = gs.gisenv(env=self._src_env) + name, mapset = raster.split("@") + self._resolution = estimate_resolution( + raster=name, + mapset=mapset, + location=env_info["LOCATION_NAME"], + dbase=env_info["GISDBASE"], + env=self._tgt_env, + ) self._set_bbox(self._src_env) def set_bbox_vector(self, vector): diff --git a/python/grass/jupyter/reprojection_renderer.py b/python/grass/jupyter/reprojection_renderer.py index 1610799d27a..fbf6e30bd1d 100644 --- a/python/grass/jupyter/reprojection_renderer.py +++ b/python/grass/jupyter/reprojection_renderer.py @@ -21,7 +21,6 @@ import grass.script as gs from .map import Map from .utils import ( - estimate_resolution, get_location_proj_string, get_region, reproject_region, @@ -99,13 +98,6 @@ def render_raster(self, name): self._region_manager.set_region_from_raster(full_name) # Reproject raster into WGS84/epsg3857 location env_info = gs.gisenv(env=self._src_env) - resolution = estimate_resolution( - raster=name, - mapset=mapset, - location=env_info["LOCATION_NAME"], - dbase=env_info["GISDBASE"], - env=self._psmerc_env, - ) tgt_name = full_name.replace("@", "_") gs.run_command( "r.proj", @@ -114,15 +106,15 @@ def render_raster(self, name): mapset=mapset, location=env_info["LOCATION_NAME"], dbase=env_info["GISDBASE"], - resolution=resolution, + resolution=self._region_manager.resolution, env=self._psmerc_env, ) # Write raster to png file with Map - region_info = gs.region(env=self._src_env) + raster_info = gs.raster_info(tgt_name, env=self._psmerc_env) filename = os.path.join(self._tmp_dir.name, f"{tgt_name}.png") img = Map( - width=region_info["cols"], - height=region_info["rows"], + width=int(raster_info["cols"]), + height=int(raster_info["rows"]), env=self._psmerc_env, filename=filename, use_region=True, diff --git a/python/grass/jupyter/utils.py b/python/grass/jupyter/utils.py index f4fa48f8957..b8cf8660738 100644 --- a/python/grass/jupyter/utils.py +++ b/python/grass/jupyter/utils.py @@ -131,7 +131,10 @@ def setup_location(name, path, epsg, src_env): def set_target_region(src_env, tgt_env): - """Set target region based on source region""" + """Set target region based on source region. + + Number of rows and columns is preserved. + """ region = get_region(env=src_env) from_proj = get_location_proj_string(src_env) to_proj = get_location_proj_string(env=tgt_env) @@ -143,6 +146,8 @@ def set_target_region(src_env, tgt_env): s=new_region["south"], e=new_region["east"], w=new_region["west"], + rows=new_region["rows"], + cols=new_region["cols"], env=tgt_env, )