Skip to content

Instantly share code, notes, and snippets.

@laacz
Created January 5, 2022 21:00
Show Gist options
  • Save laacz/a0198d21bd3ba482c7631998c3a583d7 to your computer and use it in GitHub Desktop.
Save laacz/a0198d21bd3ba482c7631998c3a583d7 to your computer and use it in GitHub Desktop.
Naive postgis MVT tileserver
<?php
require('../vendor/autoload.php');
$dotenv = Dotenv\Dotenv::createMutable(__DIR__ . '/../');
$dotenv->load();
const WORLD_MERCATOR_MAX = 20037508.3427892;
const WORLD_MERCATOR_MIN = -WORLD_MERCATOR_MAX;
const WORLD_MERCATOR_SIZE = WORLD_MERCATOR_MAX - WORLD_MERCATOR_MIN;
$uri = $_SERVER['REQUEST_URI'] ?? '';
if (preg_match('|/(?P<z>\d+)/(?P<x>\d+)/(?P<y>\d+)(\.pbf?)$|', $uri, $matches)) {
$tile = [
'x' => (int)$matches['x'],
'y' => (int)$matches['y'],
'z' => (int)$matches['z'],
];
// Sanity checks
if ($tile['x'] < 2 ** $tile['z'] && $tile['y'] < 2 ** $tile['z'] && $tile['x'] >= 0 && $tile['y'] >= 0) {
// Make tile envelope
$world_tile_size = 2 ** $tile['z'];
$tile_mercator_size = WORLD_MERCATOR_SIZE / $world_tile_size;
$envelope = [
'xmin' => WORLD_MERCATOR_MIN + $tile_mercator_size * $tile['x'],
'xmax' => WORLD_MERCATOR_MIN + $tile_mercator_size * ($tile['x'] + 1),
'ymin' => WORLD_MERCATOR_MAX - $tile_mercator_size * ($tile['y'] + 1),
'ymax' => WORLD_MERCATOR_MAX - $tile_mercator_size * $tile['y'],
];
$envelope['segsize'] = ($envelope['xmax'] - $envelope['xmin']) / 4;
// Build bounds SQL
$bounds_sql = <<<SQL
ST_Segmentize(ST_MakeEnvelope(
{$envelope['xmin']},
{$envelope['ymin']},
{$envelope['xmax']},
{$envelope['ymax']},
3857), {$envelope['segsize']})
SQL;
$tile_sql = <<<SQL
WITH bounds AS (SELECT {$bounds_sql} AS geom, {$bounds_sql}::box2d AS b2d),
mvtgeom AS (
SELECT ST_AsMVTGeom(ST_Transform(t.geom, 3857), bounds.b2d) AS geom,
objectcode,
parcelcode,
coalesce(
(select full_name from aw_eka e where st_contains(t.geom, e.geom) limit 1),
(select full_name from aw_eka e, kkparcel p where p.code = t.parcelcode and st_contains(p.geom, e.geom) limit 1),
'Neizdevās noteikt adresi'
) as address
FROM kkbuilding t, bounds
WHERE ST_Intersects(t.geom, ST_Transform(bounds.geom, 4326))
)
SELECT ST_AsMVT(mvtgeom.*) FROM mvtgeom
SQL;
$DB = new PDO($_ENV['DB_DSN'], $_ENV['DB_USER'], $_ENV['DB_PASSWORD']);
$data = $DB->query($tile_sql)->fetchColumn();
fpassthru($data);
} else {
http_response_code(400);
}
} else {
http_response_code(404);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment