"""Map related commands."""
import time
import gws
import gws.common.action
import gws.common.layer
import gws.config
import gws.gis.cache
import gws.gis.feature
import gws.gis.render
import gws.gis.renderview
import gws.tools.json2
import gws.tools.misc
import gws.tools.net
import gws.tools.units as units
import gws.web.error
import gws.types as t
[docs]class RenderBoxParams(t.Params):
bbox: t.Extent
width: int
height: int
layerUid: str
crs: t.Optional[t.Crs]
dpi: t.Optional[int]
layers: t.Optional[t.List[str]]
[docs]class RenderXyzParams(t.Params):
layerUid: str
x: int
y: int
z: int
[docs]class RenderLegendParams(t.Params):
layerUid: str
[docs]class DescribeLayerParams(t.Params):
layerUid: str
[docs]class DescribeLayerResponse(t.Params):
description: str
[docs]class GetFeaturesParams(t.Params):
bbox: t.Optional[t.Extent]
layerUid: str
crs: t.Optional[t.Crs]
resolution: t.Optional[float]
limit: int = 0
[docs]class GetFeaturesResponse(t.Response):
features: t.List[t.FeatureProps]
[docs]class Config(t.WithTypeAndAccess):
"""Map rendering action"""
pass
[docs]class Object(gws.common.action.Object):
[docs] def api_render_box(self, req: t.IRequest, p: RenderBoxParams) -> t.HttpResponse:
"""Render a part of the map inside a bounding box"""
layer = req.require_layer(p.layerUid)
img = None
extra_params = {}
if p.layers:
extra_params['layers'] = p.layers
rv = gws.gis.renderview.from_bbox(
crs=p.crs or layer.map.crs,
bbox=p.bbox,
out_size=(p.width, p.height),
out_size_unit='px',
dpi=p.dpi or units.OGC_SCREEN_PPI,
rotation=0
)
ts = time.time()
try:
img = layer.render_box(rv, extra_params)
except:
gws.log.exception()
gws.log.debug('RENDER_PROFILE: %s - %s - %.2f' % (p.layerUid, repr(rv), time.time() - ts))
return t.HttpResponse(mime='image/png', content=img or gws.tools.misc.Pixels.png8)
[docs] def api_render_xyz(self, req: t.IRequest, p: RenderXyzParams) -> t.HttpResponse:
"""Render an XYZ tile"""
layer = req.require_layer(p.layerUid)
img = None
ts = time.time()
try:
img = layer.render_xyz(p.x, p.y, p.z)
except:
gws.log.exception()
gws.log.debug('RENDER_PROFILE: %s - %s %s %s - %.2f' % (p.layerUid, p.x, p.y, p.z, time.time() - ts))
# for public tiled layers, write tiles to the web cache
# so they will be subsequently served directly by nginx
if img and layer.is_public and layer.has_cache:
gws.gis.cache.store_in_web_cache(layer, p.x, p.y, p.z, img)
return t.HttpResponse(mime='image/png', content=img or gws.tools.misc.Pixels.png8)
[docs] def api_render_legend(self, req: t.IRequest, p: RenderLegendParams) -> t.HttpResponse:
"""Render a legend for a layer"""
path = self._legend_path(req, p)
content = gws.read_file_b(path) if path else gws.tools.misc.Pixels.png8
return t.HttpResponse(mime='image/png', content=content)
[docs] def http_get_legend(self, req: t.IRequest, p: RenderLegendParams) -> t.Response:
path = self._legend_path(req, p)
if path:
return t.FileResponse(mime='image/png', path=path)
return t.HttpResponse(mime='image/png', content=gws.tools.misc.Pixels.png8)
def _legend_path(self, req: t.IRequest, p: RenderLegendParams):
layer = req.require_layer(p.layerUid)
if layer.has_legend:
try:
return layer.render_legend()
except:
gws.log.exception()
[docs] def api_describe_layer(self, req: t.IRequest, p: DescribeLayerParams) -> DescribeLayerResponse:
layer = req.require_layer(p.layerUid)
return DescribeLayerResponse(description=layer.description)
[docs] def api_get_features(self, req: t.IRequest, p: GetFeaturesParams) -> GetFeaturesResponse:
"""Get a list of features in a bounding box"""
layer = req.require_layer(p.layerUid)
bounds = t.Bounds(
crs=p.crs or layer.map.crs,
extent=p.get('bbox') or layer.map.extent
)
found = layer.get_features(bounds, p.get('limit'))
for f in found:
f.transform_to(bounds.crs)
f.apply_templates(keys=['label'])
return GetFeaturesResponse(features=[f.props for f in found])
[docs] def http_get_box(self, req: t.IRequest, p: RenderBoxParams) -> t.HttpResponse:
return self.api_render_box(req, p)
[docs] def http_get_xyz(self, req: t.IRequest, p: RenderXyzParams) -> t.HttpResponse:
return self.api_render_xyz(req, p)
[docs] def http_get_features(self, req: t.IRequest, p: GetFeaturesParams) -> t.HttpResponse:
res = self.api_get_features(req, p)
return t.HttpResponse(mime='application/json', content=gws.tools.json2.to_string(res))