Commit 73533621 authored by Anne Blankert's avatar Anne Blankert

mvt include_nulls option, basic map legend

parent 3f99b45c
......@@ -6,8 +6,38 @@ const merc = new sm({
size: 256
})
function queryColumnsNotNull(queryColumns) {
if (queryColumns) {
function toBoolean(value) {
if (!value) {
return false;
}
if (typeof value === 'string'){
if (value.trim() === '') {
return false;
} else if (Number(value) === NaN) {
switch (value.toLowerCase().trim()) {
case 'no':
case 'false':
case 'n':
case 'f':
return false;
default:
return true;
}
} else {
return Number(value) !== 0;
}
}
if (Number(value)!== NaN) {
return Number(value) !== 0;
}
return true;
}
function queryColumnsNotNull(query) {
const queryColumns = query.columns;
const includeNulls = toBoolean(query.include_nulls);
if (!includeNulls && queryColumns) {
return ` and (${queryColumns.split(',').map(column=>`${column} is not null`).join(' or ')})`
}
return ''
......@@ -36,7 +66,7 @@ const sql = (params, query) => {
ST_MakeEnvelope(${bounds.join()}, 3857),
srid
) && ${query.geom_column}
${queryColumnsNotNull(query.columns)}
${queryColumnsNotNull(query)}
-- Optional Filter
${query.filter ? `AND ${query.filter}` : ''}
) r
......@@ -52,7 +82,7 @@ module.exports = function(app, pool, cache) {
return;
}
const cacheDir = `${req.params.datasource}/mvt/${req.params.z}/${req.params.x}/${req.params.y}`;
const key = ((req.query.geom_column?req.query.geom_column:'geom') + (req.query.columns?','+req.query.columns:''))
const key = ((req.query.geom_column?req.query.geom_column:'geom') + (req.query.columns?','+req.query.columns:'')) + (toBoolean(req.query.include_nulls)?'_includenulls':'')
.replace(/[\W]+/g, '_');
const mvt = await cache.getCachedFile(cacheDir, key);
......@@ -114,6 +144,11 @@ module.exports = function(app, pool, cache) {
* in: query
* required: false
* type: string
* - name: include_nulls
* description: 'optional parameter to include geometries where all attribute columns are null (default: false)'
* in: query
* required: false
* type: string
* responses:
* 200:
* description: vector tile
......
......@@ -4,12 +4,21 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Info</title>
<title>PGServer Info</title>
<style>
.medium {width: 300px; height: auto;}
#mapcontainer {
display: flex;
flex-wrap: wrap;
}
#map {display: inline-block; width: 500px; height: 500px; border: 1 px solid lightblue;}
#info {display: inline-block;}
#featurecontainer {
display: flex;
flex-direction: column;
justify-content: space-between;
}
#feaureinfo {display: inline-block;}
#attrinfo {
display: flex;
flex-wrap: wrap;
......@@ -72,6 +81,16 @@
})
}
function addLegendLine(color, label) {
const legend = document.querySelector('#legend');
const svg = `<svg width="30" height="15">
<rect width="30" height="15" style="fill:${color};fill-opacity:1;stroke-width:1;stroke:#444"></rect>
</svg>`
const legendLine = document.createElement('div');
legendLine.innerHTML = `<div><span>${svg}</span><span>${label}<span></div>`
legend.appendChild(legendLine);
}
function initMap()
{
const urlParams = new URLSearchParams(window.location.search);
......@@ -103,10 +122,6 @@
"type": "raster",
"source": "osmgray"
}
],
"filter": [
"has",
`${attrName}`
]
}
}
......@@ -157,19 +172,20 @@
"type": layerType,
"source": {
"type": "vector",
"tiles": [`${baseUrl}/${fullTableName}/mvt/{z}/{x}/{y}?geom_column=${geomColumn}&columns=${attrName}`],
"tiles": [`${baseUrl}/${fullTableName}/mvt/{z}/{x}/{y}?geom_column=${geomColumn}&columns=${attrName}&include_nulls=0`],
},
"source-layer": fullTableName,
"paint": paint,
"filter": ['has', attrName]
//"filter": ['has', attrName]
}
map.addLayer(layer);
addLegendLine('red', fullTableName);
document.querySelector("#layerjson").innerHTML = `<pre>${JSON.stringify(layer, null, 2)}</pre>`;
}
})
map.on('mousemove', function (e) {
var features = map.queryRenderedFeatures(e.point).map(function(feature){ return {layer: {id: feature.layer.id, type: feature.layer.type}, properties:(feature.properties)};});
document.getElementById('info').innerHTML = JSON.stringify(features.map(feature=>feature.properties), null, 2);
document.querySelector('#featureinfo').innerHTML = JSON.stringify(features.map(feature=>feature.properties), null, 2);
});
}
......@@ -292,8 +308,21 @@
<div class="dot"></div><div class="dot"></div><div class="dot"></div><div class="dot"></div>
</div>
</div>
<div id="mapcontainer">
<div id="map"></div>
<div id="info"></div>
<div id="featurecontainer">
<div id="legendcontainer">
<select id="numclasses" name="numclasses">
<option>1</option>
</select><label for="numclasses">number of classes</label><br>
<button>equal interval</button>
<button>quantile</button><br>
<input type="checkbox" id="hidenulls" name="hidenulls" checked><label for="hidenulls">Hide null values</label>
<div id="legend"></div>
</div>
<div id="featureinfo"></div>
</div>
</div>
<div id="layerjson"></div>
<div id="back"></div>
</body>
......
......@@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="pgserver.css">
<title>Welcome</title>
<title>PGServer UI</title>
</head>
<style>
......@@ -14,7 +14,7 @@
<h1>PGServer</h1>
Welcome to pgserver<br>
<a href="/info.html">Browse geo-data</a><br>
<a href="/api-docs">Swagger api docs</a><br>
<a href="/api-docs">API documentation (swagger)</a><br>
<a href="/upload.html">Upload files</a>
</body>
</html>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment