Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions services/tileserver/macrostrat/tileserver/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,10 @@ async def shutdown_event():

app.include_router(fossils_router, tags=["PBDB"], prefix="/pbdb")

from .measurements import router as measurements_router

app.include_router(measurements_router, tags=["Measurements"], prefix="/measurements")

from .integrations import router as integrations_router

app.include_router(integrations_router, tags=["Integrations"], prefix="/integrations")
Expand Down
116 changes: 116 additions & 0 deletions services/tileserver/macrostrat/tileserver/measurements/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
from pathlib import Path

from buildpg import render
from fastapi import APIRouter, Request, Response
from timvt.resources.enums import MimeTypes

router = APIRouter()

__here__ = Path(__file__).parent


@router.get("/tile/{z}/{x}/{y}")
async def tile_query(
request: Request,
z: int,
x: int,
y: int,
):
"""Get a tile from the tileserver."""
pool = request.app.state.pool

where = ""

params = {
"z": z,
"x": x,
"y": y,
}

if "type" in request.query_params:
type_vals = request.query_params["type"].split(",")
type_vals = [v.strip() for v in type_vals if v.strip()]
where += " AND type = ANY(:type_vals)"
params["type_vals"] = type_vals

if "cluster" in request.query_params:
cluster_val = request.query_params["cluster"]
cluster = cluster_val.lower() not in ("false", "0", "no")

else:
cluster = True

clusterSQL = """
,

mvt_features AS (
SELECT id,
ST_SnapToGrid(geom, 256, 256) AS cluster_geom,
geom
FROM points
),
grouped_features AS (
SELECT
tile_utils.cluster_expansion_zoom(ST_Collect(geom), :z) AS expansion_zoom,
count(*) AS n,
st_centroid(ST_Collect(geom)) AS geom,
CASE
WHEN count(*) < 2 THEN string_agg(f.id::text, ',')
ELSE null
END AS id
FROM mvt_features f
GROUP BY cluster_geom
)
SELECT ST_AsMVT(row) AS mvt
FROM (SELECT * FROM grouped_features) AS row;
"""

unclusteredSQL = """
SELECT ST_AsMVT(
points.*,
'default',
4096,
'geom'
) AS mvt
FROM points
"""

if cluster:
ending = clusterSQL
else:
ending = unclusteredSQL

query = f"""
WITH
tile AS (
SELECT ST_TileEnvelope(:z, :x, :y) AS envelope,
tile_layers.geographic_envelope(:x, :y, :z, 0.01) AS envelope_4326
),
points AS (
SELECT
id,
type,
tile_layers.tile_geom(
ST_Intersection(geometry, envelope_4326),
envelope
) AS geom
FROM macrostrat_api.measurements_with_type
JOIN tile ON true
WHERE
lat IS NOT NULL AND lng IS NOT NULL
AND ST_Intersects(
ST_SetSRID(ST_MakePoint(lng, lat), 4326),
envelope_4326
)
{where}
)
{ending}
"""

q, p = render(query, **params)
q = q.replace("textarray", "text[]")

async with pool.acquire() as con:
data = await con.fetchval(q, *p)

return Response(data, media_type=MimeTypes.pbf.value)