Refactor data maps and add building outlines (#630)
* Add subtle border for age layer buildings * Simplify map data queries * Fix typo in updated construction layer query * Enable data tile caching switch for development * Enable turning tile cache off * Use render time variables for highlight tiles * Create building numbers map layer * Create database view for simpler map queries * Decrease min zoom for numbers layer * Add building outlines to all map layers * Adjust building numbers style and zoom level * Revert "Create database view for simpler map queries" This reverts commit e3c342cb7393f491c838df5654c2316a9dab08e1 which cannot be implemented before upgrading Postgres to min v11
This commit is contained in:
parent
2927b04b54
commit
1ff3b38c4a
@ -8,13 +8,6 @@
|
||||
<MaxScaleDenominator>17000</MaxScaleDenominator>
|
||||
<MinScaleDenominator>0</MinScaleDenominator>
|
||||
</Rule>
|
||||
<Rule>
|
||||
<TextSymbolizer face-name="DejaVu Sans Condensed Bold" fill="#000000">
|
||||
[location_number]
|
||||
</TextSymbolizer>
|
||||
<MaxScaleDenominator>5000</MaxScaleDenominator>
|
||||
<MinScaleDenominator>0</MinScaleDenominator>
|
||||
</Rule>
|
||||
</Style>
|
||||
<Style name="base_night">
|
||||
<Rule>
|
||||
@ -25,17 +18,25 @@
|
||||
<MaxScaleDenominator>17000</MaxScaleDenominator>
|
||||
<MinScaleDenominator>0</MinScaleDenominator>
|
||||
</Rule>
|
||||
</Style>
|
||||
<Style name="number_labels">
|
||||
<Rule>
|
||||
<TextSymbolizer face-name="DejaVu Sans Condensed Bold" fill="#ffffff">
|
||||
<TextSymbolizer
|
||||
face-name="DejaVu Sans Condensed Bold"
|
||||
fill="#eee"
|
||||
size="21"
|
||||
halo-radius="1"
|
||||
halo-fill="#333"
|
||||
>
|
||||
[location_number]
|
||||
</TextSymbolizer>
|
||||
<MaxScaleDenominator>5000</MaxScaleDenominator>
|
||||
<MaxScaleDenominator>2132</MaxScaleDenominator>
|
||||
<MinScaleDenominator>0</MinScaleDenominator>
|
||||
</Rule>
|
||||
</Style>
|
||||
<Style name="highlight">
|
||||
<Rule>
|
||||
<Filter>[base_layer] = 'location' or [base_layer] = 'conservation_area'</Filter>
|
||||
<Filter>@base_data_layer = 'location' or @base_data_layer = 'conservation_area'</Filter>
|
||||
<LineSymbolizer stroke="#ff0000aa" stroke-width="4.5" />
|
||||
<LineSymbolizer stroke="#ff0000ff" stroke-width="2.5" />
|
||||
</Rule>
|
||||
@ -66,6 +67,17 @@
|
||||
<Filter>[location_info_count] > 0 and [location_info_count] < 2</Filter>
|
||||
<PolygonSymbolizer fill="#bae4bc" />
|
||||
</Rule>
|
||||
|
||||
<Rule>
|
||||
<MaxScaleDenominator>17061</MaxScaleDenominator>
|
||||
<MinScaleDenominator>4264</MinScaleDenominator>
|
||||
<LineSymbolizer stroke="#888" stroke-width="1.0"/>
|
||||
</Rule>
|
||||
<Rule>
|
||||
<MaxScaleDenominator>4264</MaxScaleDenominator>
|
||||
<MinScaleDenominator>0</MinScaleDenominator>
|
||||
<LineSymbolizer stroke="#888" stroke-width="3.0"/>
|
||||
</Rule>
|
||||
</Style>
|
||||
<Style name="size_storeys">
|
||||
<Rule>
|
||||
@ -88,6 +100,17 @@
|
||||
<Filter>[size_storeys] >= 1 and [size_storeys] < 6</Filter>
|
||||
<PolygonSymbolizer fill="#800026" />
|
||||
</Rule>
|
||||
|
||||
<Rule>
|
||||
<MaxScaleDenominator>17061</MaxScaleDenominator>
|
||||
<MinScaleDenominator>4264</MinScaleDenominator>
|
||||
<LineSymbolizer stroke="#ccc" stroke-width="1.0"/>
|
||||
</Rule>
|
||||
<Rule>
|
||||
<MaxScaleDenominator>4264</MaxScaleDenominator>
|
||||
<MinScaleDenominator>0</MinScaleDenominator>
|
||||
<LineSymbolizer stroke="#ccc" stroke-width="3.0"/>
|
||||
</Rule>
|
||||
</Style>
|
||||
<Style name="size_height">
|
||||
<Rule>
|
||||
@ -122,6 +145,17 @@
|
||||
<Filter>[size_height] >= 152</Filter>
|
||||
<PolygonSymbolizer fill="#980043" />
|
||||
</Rule>
|
||||
|
||||
<Rule>
|
||||
<MaxScaleDenominator>17061</MaxScaleDenominator>
|
||||
<MinScaleDenominator>4264</MinScaleDenominator>
|
||||
<LineSymbolizer stroke="#ccc" stroke-width="1.0"/>
|
||||
</Rule>
|
||||
<Rule>
|
||||
<MaxScaleDenominator>4264</MaxScaleDenominator>
|
||||
<MinScaleDenominator>0</MinScaleDenominator>
|
||||
<LineSymbolizer stroke="#ccc" stroke-width="3.0"/>
|
||||
</Rule>
|
||||
</Style>
|
||||
<Style name="construction_core_material">
|
||||
<Rule>
|
||||
@ -156,6 +190,17 @@
|
||||
<Filter>[construction_core_material] = "Other Man-Made Material"</Filter>
|
||||
<PolygonSymbolizer fill="#c48a85" />
|
||||
</Rule>
|
||||
|
||||
<Rule>
|
||||
<MaxScaleDenominator>17061</MaxScaleDenominator>
|
||||
<MinScaleDenominator>4264</MinScaleDenominator>
|
||||
<LineSymbolizer stroke="#888" stroke-width="1.0"/>
|
||||
</Rule>
|
||||
<Rule>
|
||||
<MaxScaleDenominator>4264</MaxScaleDenominator>
|
||||
<MinScaleDenominator>0</MinScaleDenominator>
|
||||
<LineSymbolizer stroke="#888" stroke-width="3.0"/>
|
||||
</Rule>
|
||||
</Style>
|
||||
<Style name="date_year">
|
||||
<Rule>
|
||||
@ -218,6 +263,17 @@
|
||||
<Filter>[date_year] < 1700</Filter>
|
||||
<PolygonSymbolizer fill="#d0c291" />
|
||||
</Rule>
|
||||
|
||||
<Rule>
|
||||
<MaxScaleDenominator>8530</MaxScaleDenominator>
|
||||
<MinScaleDenominator>4264</MinScaleDenominator>
|
||||
<LineSymbolizer stroke="#888" stroke-width="1.0"/>
|
||||
</Rule>
|
||||
<Rule>
|
||||
<MaxScaleDenominator>4264</MaxScaleDenominator>
|
||||
<MinScaleDenominator>0</MinScaleDenominator>
|
||||
<LineSymbolizer stroke="#888" stroke-width="3.0"/>
|
||||
</Rule>
|
||||
</Style>
|
||||
<Style name="conservation_area">
|
||||
<Rule>
|
||||
@ -246,6 +302,19 @@
|
||||
<PolygonSymbolizer fill="#858ed4"/>
|
||||
</Rule>
|
||||
|
||||
<Rule>
|
||||
<Filter>[listing_type] != "None" or [planning_in_conservation_area] = true</Filter>
|
||||
<MaxScaleDenominator>17061</MaxScaleDenominator>
|
||||
<MinScaleDenominator>4264</MinScaleDenominator>
|
||||
<LineSymbolizer stroke="#888" stroke-width="1.0"/>
|
||||
</Rule>
|
||||
<Rule>
|
||||
<Filter>[listing_type] != "None" or [planning_in_conservation_area] = true</Filter>
|
||||
<MaxScaleDenominator>4264</MaxScaleDenominator>
|
||||
<MinScaleDenominator>0</MinScaleDenominator>
|
||||
<LineSymbolizer stroke="#888" stroke-width="3.0"/>
|
||||
</Rule>
|
||||
|
||||
<!-- Conservation area outline -->
|
||||
<Rule>
|
||||
<Filter>[listing_type] != "None" and [planning_in_conservation_area] = true</Filter>
|
||||
@ -295,6 +364,17 @@
|
||||
<Filter>[sust_dec] = G</Filter>
|
||||
<PolygonSymbolizer fill="#e31d23" />
|
||||
</Rule>
|
||||
|
||||
<Rule>
|
||||
<MaxScaleDenominator>17061</MaxScaleDenominator>
|
||||
<MinScaleDenominator>4264</MinScaleDenominator>
|
||||
<LineSymbolizer stroke="#888" stroke-width="1.0"/>
|
||||
</Rule>
|
||||
<Rule>
|
||||
<MaxScaleDenominator>4264</MaxScaleDenominator>
|
||||
<MinScaleDenominator>0</MinScaleDenominator>
|
||||
<LineSymbolizer stroke="#888" stroke-width="3.0"/>
|
||||
</Rule>
|
||||
</Style>
|
||||
<Style name="building_attachment_form">
|
||||
<Rule>
|
||||
@ -313,6 +393,17 @@
|
||||
<Filter>[building_attachment_form] = "Mid-Terrace"</Filter>
|
||||
<PolygonSymbolizer fill="#226291" />
|
||||
</Rule>
|
||||
|
||||
<Rule>
|
||||
<MaxScaleDenominator>17061</MaxScaleDenominator>
|
||||
<MinScaleDenominator>4264</MinScaleDenominator>
|
||||
<LineSymbolizer stroke="#888" stroke-width="0.8"/>
|
||||
</Rule>
|
||||
<Rule>
|
||||
<MaxScaleDenominator>4264</MaxScaleDenominator>
|
||||
<MinScaleDenominator>0</MinScaleDenominator>
|
||||
<LineSymbolizer stroke="#888" stroke-width="2.0"/>
|
||||
</Rule>
|
||||
</Style>
|
||||
<Style name="likes">
|
||||
<Rule>
|
||||
@ -343,6 +434,17 @@
|
||||
<Filter>[likes] = 1</Filter>
|
||||
<PolygonSymbolizer fill="#ffe8a9" />
|
||||
</Rule>
|
||||
|
||||
<Rule>
|
||||
<MaxScaleDenominator>17061</MaxScaleDenominator>
|
||||
<MinScaleDenominator>4264</MinScaleDenominator>
|
||||
<LineSymbolizer stroke="#888" stroke-width="1.0"/>
|
||||
</Rule>
|
||||
<Rule>
|
||||
<MaxScaleDenominator>4264</MaxScaleDenominator>
|
||||
<MinScaleDenominator>0</MinScaleDenominator>
|
||||
<LineSymbolizer stroke="#888" stroke-width="3.0"/>
|
||||
</Rule>
|
||||
</Style>
|
||||
<Style name="landuse">
|
||||
<Rule>
|
||||
@ -393,5 +495,16 @@
|
||||
<Filter>[current_landuse_order] = "Mixed Use"</Filter>
|
||||
<PolygonSymbolizer fill="#e5050d" />
|
||||
</Rule>
|
||||
|
||||
<Rule>
|
||||
<MaxScaleDenominator>8530</MaxScaleDenominator>
|
||||
<MinScaleDenominator>4264</MinScaleDenominator>
|
||||
<LineSymbolizer stroke="#888" stroke-width="0.8"/>
|
||||
</Rule>
|
||||
<Rule>
|
||||
<MaxScaleDenominator>4264</MaxScaleDenominator>
|
||||
<MinScaleDenominator>0</MinScaleDenominator>
|
||||
<LineSymbolizer stroke="#888" stroke-width="3.0"/>
|
||||
</Rule>
|
||||
</Style>
|
||||
</Map>
|
||||
|
@ -155,13 +155,21 @@ class ColouringMap extends Component<ColouringMapProps, ColouringMapState> {
|
||||
const highlightLayer = this.props.building != undefined ?
|
||||
<TileLayer
|
||||
key={this.props.building.building_id}
|
||||
url={`/tiles/highlight/{z}/{x}/{y}{r}.png?highlight=${this.props.building.geometry_id}&base=${tileset}`}
|
||||
url={`/tiles/highlight/{z}/{x}/{y}{r}.png?highlight=${this.props.building.building_id}&base=${tileset}`}
|
||||
minZoom={13}
|
||||
maxZoom={19}
|
||||
zIndex={100}
|
||||
/>
|
||||
: null;
|
||||
|
||||
const numbersLayer = <TileLayer
|
||||
key={this.state.theme}
|
||||
url={`/tiles/number_labels/{z}/{x}/{y}{r}.png?rev=${rev}`}
|
||||
zIndex={200}
|
||||
minZoom={17}
|
||||
maxZoom={19}
|
||||
/>
|
||||
|
||||
const isEdit = ['edit', 'multi-edit'].includes(this.props.mode);
|
||||
|
||||
return (
|
||||
@ -182,6 +190,7 @@ class ColouringMap extends Component<ColouringMapProps, ColouringMapState> {
|
||||
{ boundaryLayer }
|
||||
{ dataLayer }
|
||||
{ highlightLayer }
|
||||
{ numbersLayer }
|
||||
<ZoomControl position="topright" />
|
||||
<AttributionControl prefix=""/>
|
||||
</Map>
|
||||
|
@ -59,6 +59,11 @@ export function decBigInt(bigStr: string): string {
|
||||
return bigStr == undefined ? bigStr : String(BigInt(bigStr) - BigInt(1));
|
||||
}
|
||||
|
||||
export function parseBooleanExact(val: string) {
|
||||
if(val === 'true') return true;
|
||||
if(val === 'false') return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
export function pickFields(obj: any, fieldWhitelist: Set<string>) {
|
||||
const subObject = {};
|
||||
@ -68,4 +73,4 @@ export function pickFields(obj: any, fieldWhitelist: Set<string>) {
|
||||
}
|
||||
}
|
||||
return subObject;
|
||||
}
|
||||
}
|
||||
|
@ -2,211 +2,198 @@ import { strictParseInt } from "../parse";
|
||||
|
||||
import { DataConfig } from "./types";
|
||||
|
||||
const BUILDING_LAYER_DEFINITIONS = {
|
||||
base_light: `(
|
||||
const LAYER_QUERIES = {
|
||||
base_light: `
|
||||
SELECT
|
||||
b.location_number as location_number,
|
||||
g.geometry_geom
|
||||
geometry_id
|
||||
FROM
|
||||
geometries as g,
|
||||
buildings as b
|
||||
WHERE
|
||||
g.geometry_id = b.geometry_id
|
||||
) as outline`,
|
||||
base_night: `(
|
||||
buildings`,
|
||||
base_night: `
|
||||
SELECT
|
||||
b.location_number as location_number,
|
||||
g.geometry_geom
|
||||
geometry_id
|
||||
FROM
|
||||
geometries as g,
|
||||
buildings as b
|
||||
WHERE
|
||||
g.geometry_id = b.geometry_id
|
||||
) as outline`,
|
||||
date_year: `(
|
||||
buildings`,
|
||||
number_labels:`
|
||||
SELECT
|
||||
b.date_year as date_year,
|
||||
g.geometry_geom
|
||||
geometry_id,
|
||||
location_number
|
||||
FROM
|
||||
geometries as g,
|
||||
buildings as b
|
||||
WHERE
|
||||
g.geometry_id = b.geometry_id
|
||||
) as date_year`,
|
||||
size_storeys: `(
|
||||
buildings`,
|
||||
highlight: `
|
||||
SELECT
|
||||
geometry_id
|
||||
FROM
|
||||
buildings
|
||||
WHERE building_id = !@highlight!`,
|
||||
date_year: `
|
||||
SELECT
|
||||
geometry_id,
|
||||
date_year
|
||||
FROM
|
||||
buildings
|
||||
WHERE date_year IS NOT NULL`,
|
||||
size_storeys: `
|
||||
SELECT
|
||||
geometry_id,
|
||||
(
|
||||
coalesce(b.size_storeys_attic, 0) +
|
||||
coalesce(b.size_storeys_core, 0)
|
||||
) as size_storeys,
|
||||
g.geometry_geom
|
||||
coalesce(size_storeys_attic, 0) +
|
||||
coalesce(size_storeys_core, 0)
|
||||
) AS size_storeys
|
||||
FROM
|
||||
geometries as g,
|
||||
buildings as b
|
||||
buildings
|
||||
WHERE
|
||||
g.geometry_id = b.geometry_id
|
||||
) as size_stories`,
|
||||
size_height: `(
|
||||
size_storeys_attic IS NOT NULL OR size_storeys_core IS NOT NULL`,
|
||||
size_height: `
|
||||
SELECT
|
||||
b.size_height_apex as size_height,
|
||||
g.geometry_geom
|
||||
geometry_id,
|
||||
size_height_apex AS size_height
|
||||
FROM
|
||||
geometries as g,
|
||||
buildings as b
|
||||
WHERE g.geometry_id = b.geometry_id
|
||||
) as size_height`,
|
||||
construction_core_material: `(
|
||||
buildings
|
||||
WHERE
|
||||
size_height_apex IS NOT NULL`,
|
||||
construction_core_material: `
|
||||
SELECT
|
||||
b.construction_core_material::text as construction_core_material,
|
||||
g.geometry_geom
|
||||
geometry_id,
|
||||
construction_core_material::text AS construction_core_material
|
||||
FROM
|
||||
geometries as g,
|
||||
buildings as b
|
||||
WHERE g.geometry_id = b.geometry_id
|
||||
) as construction_core_material`,
|
||||
location: `(
|
||||
buildings
|
||||
WHERE
|
||||
construction_core_material IS NOT NULL`,
|
||||
location: `
|
||||
SELECT
|
||||
geometry_id,
|
||||
(
|
||||
case when b.location_name is null then 0 else 1 end +
|
||||
case when b.location_number is null then 0 else 1 end +
|
||||
case when b.location_street is null then 0 else 1 end +
|
||||
case when b.location_line_two is null then 0 else 1 end +
|
||||
case when b.location_town is null then 0 else 1 end +
|
||||
case when b.location_postcode is null then 0 else 1 end +
|
||||
case when b.location_latitude is null then 0 else 1 end +
|
||||
case when b.location_longitude is null then 0 else 1 end +
|
||||
case when b.ref_toid is null then 0 else 1 end +
|
||||
case when b.ref_osm_id is null then 0 else 1 end
|
||||
) as location_info_count,
|
||||
g.geometry_geom
|
||||
case when location_name IS NULL then 0 else 1 end +
|
||||
case when location_number IS NULL then 0 else 1 end +
|
||||
case when location_street IS NULL then 0 else 1 end +
|
||||
case when location_line_two IS NULL then 0 else 1 end +
|
||||
case when location_town IS NULL then 0 else 1 end +
|
||||
case when location_postcode IS NULL then 0 else 1 end +
|
||||
case when location_latitude IS NULL then 0 else 1 end +
|
||||
case when location_longitude IS NULL then 0 else 1 end +
|
||||
case when ref_toid IS NULL then 0 else 1 end +
|
||||
case when ref_osm_id IS NULL then 0 else 1 end
|
||||
) AS location_info_count
|
||||
FROM
|
||||
geometries as g,
|
||||
buildings as b
|
||||
WHERE
|
||||
g.geometry_id = b.geometry_id
|
||||
) as location`,
|
||||
likes: `(
|
||||
buildings`,
|
||||
likes: `
|
||||
SELECT
|
||||
g.geometry_geom,
|
||||
b.likes_total as likes
|
||||
geometry_id,
|
||||
likes_total AS likes
|
||||
FROM
|
||||
geometries as g,
|
||||
buildings as b
|
||||
buildings
|
||||
WHERE
|
||||
g.geometry_id = b.geometry_id
|
||||
AND b.likes_total > 0
|
||||
) as likes`,
|
||||
planning_combined: `(
|
||||
likes_total > 0`,
|
||||
planning_combined: `
|
||||
SELECT
|
||||
g.geometry_geom,
|
||||
geometry_id,
|
||||
(
|
||||
CASE
|
||||
WHEN b.planning_list_cat = 'Listed Building' and b.planning_list_grade = 'I' THEN 'Grade I Listed'
|
||||
WHEN b.planning_list_cat = 'Listed Building' and b.planning_list_grade = 'II*' THEN 'Grade II* Listed'
|
||||
WHEN b.planning_list_cat = 'Listed Building' and b.planning_list_grade = 'II' THEN 'Grade II Listed'
|
||||
WHEN b.planning_in_local_list THEN 'Locally Listed'
|
||||
WHEN planning_list_cat = 'Listed Building' and planning_list_grade = 'I' THEN 'Grade I Listed'
|
||||
WHEN planning_list_cat = 'Listed Building' and planning_list_grade = 'II*' THEN 'Grade II* Listed'
|
||||
WHEN planning_list_cat = 'Listed Building' and planning_list_grade = 'II' THEN 'Grade II Listed'
|
||||
WHEN planning_in_local_list THEN 'Locally Listed'
|
||||
ELSE 'None'
|
||||
END
|
||||
) as listing_type,
|
||||
b.planning_in_conservation_area
|
||||
FROM geometries as g
|
||||
JOIN buildings as b
|
||||
ON g.geometry_id = b.geometry_id
|
||||
) AS listing_type,
|
||||
planning_in_conservation_area
|
||||
FROM buildings
|
||||
WHERE
|
||||
b.planning_in_conservation_area
|
||||
OR b.planning_in_local_list
|
||||
OR b.planning_list_cat is not null
|
||||
) as planning_combined`,
|
||||
conservation_area: `(
|
||||
planning_in_conservation_area
|
||||
OR planning_in_local_list
|
||||
OR planning_list_cat IS NOT NULL`,
|
||||
conservation_area: `
|
||||
SELECT
|
||||
g.geometry_geom
|
||||
geometry_id
|
||||
FROM
|
||||
geometries as g,
|
||||
buildings as b
|
||||
buildings
|
||||
WHERE
|
||||
g.geometry_id = b.geometry_id
|
||||
AND b.planning_in_conservation_area = true
|
||||
) as conservation_area`,
|
||||
sust_dec: `(
|
||||
planning_in_conservation_area = true`,
|
||||
sust_dec: `
|
||||
SELECT
|
||||
b.sust_dec::text as sust_dec,
|
||||
g.geometry_geom
|
||||
geometry_id,
|
||||
sust_dec::text AS sust_dec
|
||||
FROM
|
||||
geometries as g,
|
||||
buildings as b
|
||||
buildings
|
||||
WHERE
|
||||
g.geometry_id = b.geometry_id
|
||||
) as sust_dec`,
|
||||
building_attachment_form: `(
|
||||
sust_dec IS NOT NULL`,
|
||||
building_attachment_form: `
|
||||
SELECT
|
||||
b.building_attachment_form::text as building_attachment_form,
|
||||
g.geometry_geom
|
||||
geometry_id,
|
||||
building_attachment_form::text AS building_attachment_form
|
||||
FROM
|
||||
geometries as g,
|
||||
buildings as b
|
||||
buildings
|
||||
WHERE
|
||||
g.geometry_id = b.geometry_id
|
||||
) as building_attachment_form`,
|
||||
landuse: `(
|
||||
building_attachment_form IS NOT NULL`,
|
||||
landuse: `
|
||||
SELECT
|
||||
b.current_landuse_order,
|
||||
g.geometry_geom
|
||||
FROM geometries as g
|
||||
JOIN buildings as b
|
||||
ON g.geometry_id = b.geometry_id
|
||||
) as current_landuse_order`,
|
||||
geometry_id,
|
||||
current_landuse_order
|
||||
FROM
|
||||
buildings
|
||||
WHERE
|
||||
current_landuse_order IS NOT NULL`,
|
||||
};
|
||||
|
||||
const GEOMETRY_FIELD = 'geometry_geom';
|
||||
|
||||
function getBuildingLayerNames() {
|
||||
return Object.keys(BUILDING_LAYER_DEFINITIONS);
|
||||
return Object.keys(LAYER_QUERIES);
|
||||
}
|
||||
|
||||
function getAllLayerNames() {
|
||||
return ['highlight', ...getBuildingLayerNames()];
|
||||
}
|
||||
|
||||
function getBuildingsDataConfig(tileset: string, dataParams: any): DataConfig {
|
||||
const table = BUILDING_LAYER_DEFINITIONS[tileset];
|
||||
function getDataConfig(tileset: string): DataConfig {
|
||||
const table = LAYER_QUERIES[tileset];
|
||||
|
||||
if(table == undefined) {
|
||||
throw new Error('Invalid tileset requested');
|
||||
}
|
||||
|
||||
const query = `(
|
||||
SELECT
|
||||
d.*,
|
||||
g.geometry_geom
|
||||
FROM (
|
||||
${table}
|
||||
) AS d
|
||||
JOIN
|
||||
geometries AS g
|
||||
ON d.geometry_id = g.geometry_id
|
||||
) AS data
|
||||
`;
|
||||
|
||||
return {
|
||||
geometry_field: GEOMETRY_FIELD,
|
||||
table: table
|
||||
table: query
|
||||
};
|
||||
}
|
||||
|
||||
function getHighlightDataConfig(tileset: string, dataParams: any): DataConfig {
|
||||
let { highlight, base } = dataParams;
|
||||
function getLayerVariables(tileset: string, dataParams: any): object {
|
||||
if(tileset == 'highlight') {
|
||||
let { highlight, base } = dataParams;
|
||||
|
||||
highlight = strictParseInt(highlight);
|
||||
base = base || 'default';
|
||||
highlight = strictParseInt(highlight);
|
||||
base = base || 'default';
|
||||
|
||||
if(isNaN(highlight) || base.match(/^\w+$/) == undefined) {
|
||||
throw new Error('Bad parameters for highlight layer');
|
||||
if(isNaN(highlight) || base.match(/^\w+$/) == undefined) {
|
||||
throw new Error('Bad parameters for highlight layer');
|
||||
}
|
||||
|
||||
return {
|
||||
highlight,
|
||||
base_data_layer: base
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
geometry_field: GEOMETRY_FIELD,
|
||||
table: `(
|
||||
SELECT
|
||||
g.geometry_geom,
|
||||
'${base}' as base_layer
|
||||
FROM
|
||||
geometries as g
|
||||
WHERE
|
||||
g.geometry_id = ${highlight}
|
||||
) as highlight`
|
||||
};
|
||||
return {};
|
||||
}
|
||||
|
||||
export {
|
||||
getBuildingLayerNames,
|
||||
getAllLayerNames,
|
||||
getBuildingsDataConfig,
|
||||
getHighlightDataConfig
|
||||
getDataConfig,
|
||||
getLayerVariables
|
||||
};
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { getAllLayerNames, getBuildingLayerNames, getBuildingsDataConfig, getHighlightDataConfig } from "./dataDefinition";
|
||||
import { parseBooleanExact } from '../helpers';
|
||||
import { getAllLayerNames, getBuildingLayerNames, getDataConfig, getLayerVariables } from "./dataDefinition";
|
||||
import { createBlankTile } from "./renderers/createBlankTile";
|
||||
import { getTileWithCaching } from "./renderers/getTileWithCaching";
|
||||
import { renderDataSourceTile } from "./renderers/renderDataSourceTile";
|
||||
@ -24,6 +25,23 @@ const STITCH_THRESHOLD = 12;
|
||||
*/
|
||||
const EXTENT_BBOX: BoundingBox = [-61149.622628, 6667754.851372, 28128.826409, 6744803.375884];
|
||||
|
||||
const allLayersCacheSwitch = parseBooleanExact(process.env.CACHE_TILES) ?? true;
|
||||
const dataLayersCacheSwitch = parseBooleanExact(process.env.CACHE_DATA_TILES) ?? true;
|
||||
let shouldCacheFn: (t: TileParams) => boolean;
|
||||
|
||||
if(!allLayersCacheSwitch) {
|
||||
shouldCacheFn = t => false;
|
||||
} else if(!dataLayersCacheSwitch) {
|
||||
// cache age data and base building outlines for more zoom levels than other layers
|
||||
shouldCacheFn = ({ tileset, z }: TileParams) =>
|
||||
(tileset === 'date_year' && z <= 16) ||
|
||||
(['base_light', 'base_night'].includes(tileset) && z <= 17) ||
|
||||
z <= 13;
|
||||
} else {
|
||||
shouldCacheFn = ({ tileset, z }: TileParams) =>
|
||||
['base_light', 'base_night'].includes(tileset) && z <= 17;
|
||||
}
|
||||
|
||||
const tileCache = new TileCache(
|
||||
process.env.TILECACHE_PATH,
|
||||
{
|
||||
@ -32,18 +50,13 @@ const tileCache = new TileCache(
|
||||
maxZoom: 19,
|
||||
scales: [1, 2]
|
||||
},
|
||||
|
||||
// cache age data and base building outlines for more zoom levels than other layers
|
||||
({ tileset, z }: TileParams) => (tileset === 'date_year' && z <= 16) ||
|
||||
((tileset === 'base_light' || tileset === 'base_night') && z <= 17) ||
|
||||
z <= 13,
|
||||
shouldCacheFn,
|
||||
|
||||
// don't clear base_light and base_night on bounding box cache clear
|
||||
(tileset: string) => tileset !== 'base_light' && tileset !== 'base_night'
|
||||
);
|
||||
|
||||
const renderBuildingTile = (t: TileParams, d: any) => renderDataSourceTile(t, d, getBuildingsDataConfig);
|
||||
const renderHighlightTile = (t: TileParams, d: any) => renderDataSourceTile(t, d, getHighlightDataConfig);
|
||||
const renderBuildingTile = (t: TileParams, d: any) => renderDataSourceTile(t, d, getDataConfig, getLayerVariables);
|
||||
|
||||
function cacheOrCreateBuildingTile(tileParams: TileParams, dataParams: any): Promise<Tile> {
|
||||
return getTileWithCaching(tileParams, dataParams, tileCache, stitchOrRenderBuildingTile);
|
||||
@ -64,7 +77,7 @@ function renderTile(tileParams: TileParams, dataParams: any): Promise<Tile> {
|
||||
}
|
||||
|
||||
if (tileParams.tileset === 'highlight') {
|
||||
return renderHighlightTile(tileParams, dataParams);
|
||||
return renderBuildingTile(tileParams, dataParams);
|
||||
}
|
||||
|
||||
return cacheOrCreateBuildingTile(tileParams, dataParams);
|
||||
|
@ -2,7 +2,7 @@ import mapnik from "mapnik";
|
||||
import path from 'path';
|
||||
import { promisify } from "util";
|
||||
|
||||
import { TableDefinitionFunction, Tile, TileParams } from "../types";
|
||||
import { TableDefinitionFunction, VariablesFunction, Tile, TileParams } from "../types";
|
||||
import { getBbox, TILE_SIZE } from "../util";
|
||||
|
||||
|
||||
@ -29,7 +29,12 @@ if (mapnik.register_default_input_plugins) {
|
||||
mapnik.register_default_fonts();
|
||||
|
||||
|
||||
async function renderDataSourceTile({ tileset, z, x, y, scale }: TileParams, dataParams: any, getTableDefinitionFn: TableDefinitionFunction): Promise<Tile> {
|
||||
async function renderDataSourceTile(
|
||||
{ tileset, z, x, y, scale }: TileParams,
|
||||
dataParams: any,
|
||||
getTableDefinitionFn: TableDefinitionFunction,
|
||||
getVariablesFn: VariablesFunction
|
||||
): Promise<Tile> {
|
||||
const bbox = getBbox(z, x, y);
|
||||
|
||||
const tileSize = TILE_SIZE * scale;
|
||||
@ -37,9 +42,11 @@ async function renderDataSourceTile({ tileset, z, x, y, scale }: TileParams, dat
|
||||
map.bufferSize = TILE_BUFFER_SIZE;
|
||||
const layer = new mapnik.Layer('tile', PROJ4_STRING);
|
||||
|
||||
const dataSourceConfig = getTableDefinitionFn(tileset, dataParams);
|
||||
const dataSourceConfig = getTableDefinitionFn(tileset);
|
||||
const dataSourceVariables = getVariablesFn(tileset, dataParams);
|
||||
|
||||
const conf = Object.assign(dataSourceConfig, DATASOURCE_CONFIG);
|
||||
const vars = Object.assign(dataSourceVariables, { zoom: z});
|
||||
|
||||
const postgis = new mapnik.Datasource(conf);
|
||||
layer.datasource = postgis;
|
||||
@ -52,7 +59,7 @@ async function renderDataSourceTile({ tileset, z, x, y, scale }: TileParams, dat
|
||||
map.add_layer(layer);
|
||||
const im = new mapnik.Image(map.width, map.height);
|
||||
map.extent = bbox;
|
||||
const rendered = await promisify(map.render.bind(map))(im, {});
|
||||
const rendered = await promisify(map.render.bind(map))(im, { variables: vars});
|
||||
|
||||
return await promisify(rendered.encode.bind(rendered))('png');
|
||||
}
|
||||
|
@ -38,7 +38,8 @@ interface DataConfig {
|
||||
geometry_field: string;
|
||||
}
|
||||
|
||||
type TableDefinitionFunction = (tileset: string, dataParams: any) => DataConfig;
|
||||
type TableDefinitionFunction = (tileset: string) => DataConfig;
|
||||
type VariablesFunction = (tileset: string, dataParams: any) => object;
|
||||
|
||||
type Tile = Image | Sharp;
|
||||
type RendererFunction = (tileParams: TileParams, dataParams: any) => Promise<Tile>;
|
||||
@ -54,5 +55,6 @@ export {
|
||||
Tile,
|
||||
RendererFunction,
|
||||
DataConfig,
|
||||
TableDefinitionFunction
|
||||
TableDefinitionFunction,
|
||||
VariablesFunction
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user