Implement simplify (using geopandas)
Add preserve_geometry option
This commit is contained in:
parent
e3ed311390
commit
c3caedea0e
6 changed files with 93 additions and 66 deletions
|
@ -7,7 +7,8 @@ import logging
|
|||
from typing import Annotated
|
||||
from asyncio import CancelledError
|
||||
|
||||
from fastapi import (Depends, FastAPI, HTTPException, Response, Header, WebSocket, WebSocketDisconnect,
|
||||
from fastapi import (Depends, FastAPI, HTTPException, Response, Header,
|
||||
WebSocket, WebSocketDisconnect,
|
||||
status, responses)
|
||||
|
||||
from gisaf.models.authentication import User
|
||||
|
@ -76,7 +77,8 @@ async def live_layer(store: str, websocket: WebSocket):
|
|||
async def get_geojson(store_name,
|
||||
user: User = Depends(get_current_active_user),
|
||||
If_None_Match: Annotated[str | None, Header()] = None,
|
||||
simplify: Annotated[float | None, Header()] = 50.0,
|
||||
simplify: Annotated[float | None, Header()] = None,
|
||||
preserveTopology: Annotated[bool|None, Header()] = None,
|
||||
):
|
||||
"""
|
||||
Some REST stores coded manually (route prefixed with "gj": geojson).
|
||||
|
@ -88,45 +90,45 @@ async def get_geojson(store_name,
|
|||
model = registry.stores.loc[store_name].model
|
||||
except KeyError:
|
||||
raise HTTPException(status.HTTP_404_NOT_FOUND)
|
||||
|
||||
if hasattr(model, 'viewable_role'):
|
||||
if not(user and user.can_view(model)):
|
||||
logger.info(f'{user.username if user else "Anonymous"} tried to access {model}')
|
||||
username = user.username if user else "Anonymous"
|
||||
logger.info(f'{username} tried to access {model}')
|
||||
raise HTTPException(status.HTTP_401_UNAUTHORIZED)
|
||||
|
||||
if await redis_store.has_channel(store_name):
|
||||
## Live layers
|
||||
data = await redis_store.get_layer_as_json(store_name)
|
||||
return Response(content=data.decode(),
|
||||
media_type="application/json")
|
||||
|
||||
# elif not model:
|
||||
# raise HTTPException(status.HTTP_404_NOT_FOUND)
|
||||
|
||||
if model.cache_enabled:
|
||||
ttag = await redis_store.get_ttag(store_name)
|
||||
if ttag and If_None_Match == ttag:
|
||||
return status.HTTP_304_NOT_MODIFIED
|
||||
|
||||
if hasattr(model, 'get_geojson'):
|
||||
geojson = await model.get_geojson(simplify_tolerance=simplify, registry=registry)
|
||||
geojson = await model.get_geojson(simplify_tolerance=simplify,
|
||||
preserve_topology=preserveTopology,
|
||||
registry=registry)
|
||||
## Store to redis for caching
|
||||
if use_cache:
|
||||
await redis_store.store_json(model, geojson)
|
||||
resp = geojson
|
||||
|
||||
elif model.can_get_features_as_df:
|
||||
## Get the GeoDataframe (gdf) with GeoPandas
|
||||
## get_popup and get_propertites get the gdf as argument and can use vectorised operations
|
||||
## get_popup and get_propertites get the gdf as argument
|
||||
## and can use vectorised operations
|
||||
try:
|
||||
gdf = await model.get_geo_df(cast=True, with_related=True, filter_columns=True)
|
||||
gdf = await model.get_gdf(cast=True, with_related=True,
|
||||
# filter_columns=True,
|
||||
preserve_topology=preserveTopology,
|
||||
simplify_tolerance=simplify)
|
||||
except CancelledError as err:
|
||||
logger.debug(f'Request for {store_name} cancelled while getting gdf')
|
||||
logger.debug(f'Getting {store_name} cancelled while getting gdf')
|
||||
raise err
|
||||
except Exception as err:
|
||||
logger.exception(err)
|
||||
raise err #status.HTTP_500_INTERNAL_SERVER_ERROR
|
||||
## The query of category defined models gets the status (not sure how and this could be skipped)
|
||||
raise HTTPException(status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
## The query of category defined models gets the status
|
||||
## (not sure how and this could be skipped)
|
||||
## Other models do not have: just add it manually from the model itself
|
||||
if 'status' not in gdf.columns:
|
||||
gdf['status'] = model.status
|
||||
|
@ -138,35 +140,38 @@ async def get_geojson(store_name,
|
|||
for property, values in properties.items():
|
||||
columns.append(property)
|
||||
gdf[property] = values
|
||||
geojson = gdf[columns].to_json(separators=(',', ':'), check_circular=False)
|
||||
geojson = gdf[columns].to_json(separators=(',', ':'),
|
||||
check_circular=False)
|
||||
## Store to redis for caching
|
||||
if use_cache:
|
||||
await redis_store.store_json(model, geojson)
|
||||
resp = geojson
|
||||
|
||||
else:
|
||||
logger.warn(f"{model} doesn't allow using dataframe for generating json!")
|
||||
attrs, features_kwargs = await model.get_features_attrs(simplify)
|
||||
## Using gino: allows OO model (get_info, etc)
|
||||
try:
|
||||
attrs['features'] = await model.get_features_in_bulk_gino(**features_kwargs)
|
||||
except Exception as err:
|
||||
logger.exception(err)
|
||||
raise status.HTTP_500_INTERNAL_SERVER_ERROR
|
||||
resp = attrs
|
||||
raise HTTPException(status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail='Gino is for: Gino Is No Option')
|
||||
# logger.warn(f"{model} doesn't allow using dataframe for generating json!")
|
||||
# attrs, features_kwargs = await model.get_features_attrs(simplify)
|
||||
# ## Using gino: allows OO model (get_info, etc)
|
||||
# try:
|
||||
# attrs['features'] = await model.get_features_in_bulk_gino(**features_kwargs)
|
||||
# except Exception as err:
|
||||
# logger.exception(err)
|
||||
# raise status.HTTP_500_INTERNAL_SERVER_ERROR
|
||||
# resp = attrs
|
||||
|
||||
headers = {}
|
||||
if model.cache_enabled and ttag:
|
||||
headers['ETag'] = ttag
|
||||
return Response(content=resp, media_type="application/json", headers=headers)
|
||||
return Response(content=resp,
|
||||
media_type="application/json", headers=headers)
|
||||
|
||||
|
||||
@api.get('/gj/{store_name}/popup/{id}')
|
||||
async def gj_popup(store_name: str, id: int):
|
||||
model = registry.geom.get(store_name)
|
||||
if not hasattr(model, 'get_popup_dynamic'):
|
||||
return ''
|
||||
obj = await model.get(id)
|
||||
## Escape characters for json
|
||||
popup_more = obj.get_popup_dynamic().replace('"', '\\"').replace('\n', '\\n')
|
||||
return {"text": popup_more}
|
||||
# @api.get('/gj/{store_name}/popup/{id}')
|
||||
# async def gj_popup(store_name: str, id: int):
|
||||
# model = registry.geom.get(store_name)
|
||||
# if not hasattr(model, 'get_popup_dynamic'):
|
||||
# return ''
|
||||
# obj = await model.get(id)
|
||||
# ## Escape characters for json
|
||||
# popup_more = obj.get_popup_dynamic().replace('"', '\\"').replace('\n', '\\n')
|
||||
# return {"text": popup_more}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue