From fa0af463812fefd5cc46604ee3da6c3c991d8f07 Mon Sep 17 00:00:00 2001 From: Quincy Morgan <2046746+quincylvania@users.noreply.github.com> Date: Wed, 31 Jul 2024 12:00:28 -0400 Subject: [PATCH] Filter POIs to focus area --- js/index.js | 50 ++++++++++- js/mapController.js | 209 +++++++++++++++++++++++--------------------- 2 files changed, 159 insertions(+), 100 deletions(-) diff --git a/js/index.js b/js/index.js index 5285a79..90ca209 100644 --- a/js/index.js +++ b/js/index.js @@ -221,6 +221,52 @@ function isValidEntityInfo(entityInfo) { entityInfo?.id > 0; } +function compositeGeoJson(features) { + var coordinates = []; + features.forEach(function(feature) { + if (feature.geometry.type === 'Polygon') { + coordinates.push(feature.geometry.coordinates); + } else if (feature.geometry.type === 'MultiPolygon') { + coordinates = coordinates.concat(feature.geometry.coordinates); + } + }); + return { + type: "Feature", + geometry: { + type: "MultiPolygon", + coordinates: coordinates, + }, + properties: features.length ? features[0].properties : {} + }; +} + +var focusAreaGeoJson; + +function loadFocusAreaGeoJson() { + if (!focusedEntityInfo) { + focusAreaGeoJson = null; + return; + } + var id = omtId(focusedEntityInfo.id, focusedEntityInfo.type) + var results = map.querySourceFeatures('openmaptiles', { + filter: [ + "==", ["id"], id, + ], + sourceLayer: "park", + }); + if (!results.length) { + results = map.querySourceFeatures('openmaptiles', { + filter: [ + "all", + ["==", ["get", "subclass"], "park"], + ["==", ["id"], id], + ], + sourceLayer: "landcover", + }); + } + focusAreaGeoJson = compositeGeoJson(results); +} + function focusEntity(entityInfo) { if (!isValidEntityInfo(entityInfo)) entityInfo = null; @@ -237,7 +283,9 @@ function focusEntity(entityInfo) { focus: focusedEntityInfo ? type + "/" + entityId : null }); - updateMapForFocus(); + loadFocusAreaGeoJson(); + + updateTrailLayers(); document.getElementById("map-title").innerText = ''; diff --git a/js/mapController.js b/js/mapController.js index 2b8927c..7873643 100644 --- a/js/mapController.js +++ b/js/mapController.js @@ -605,11 +605,6 @@ function loadTrailLayers(name) { "text-halo-blur": 1, "text-halo-color": colors.labelHalo, }, - "filter": [ - "all", - ["has", "name"], - ["has", "ele_ft"], - ] }, 'clickable'); addTrailLayer({ "id": "trail-pois", @@ -985,32 +980,42 @@ function isSpecifiedExpressionForLens(lens, travelMode) { } function trailPoisFilter(travelMode) { - if (travelMode === 'all') return null; - var poiKeys = [travelMode]; - var poiKeysByTravelMode = { - "foot": ["hiking"], - "canoe": ["canoe", "portage"], - }; - if (poiKeysByTravelMode[travelMode]) poiKeys = poiKeysByTravelMode[travelMode]; - return [ + var filter = [ "all", [ - "none", - ['in', "leisure", "park", "nature_reserve"], - ['in', "boundary", "protected_area", "national_park"], + "!", + [ + "any", + ['in', ["get", "leisure"], ["literal", ["park", "nature_reserve"]]], + ['in', ["get", "boundary"], ["literal", ["protected_area", "national_park"]]], + ] ], - [ + ] + if (focusAreaGeoJson?.geometry?.coordinates?.length) { + filter.push(["within", focusAreaGeoJson]); + } + if (travelMode !== 'all') { + var poiKeys = [travelMode]; + var poiKeysByTravelMode = { + "foot": ["hiking"], + "canoe": ["canoe", "portage"], + }; + if (poiKeysByTravelMode[travelMode]) poiKeys = poiKeysByTravelMode[travelMode]; + filter.push([ 'any', [ - "none", - ["==", "highway", "trailhead"], - ["in", "information", "guidepost", "route_marker"], - ["==", "man_made", "cairn"], + "!", + [ + "any", + ["==", ["get", "highway"], "trailhead"], + ["in", ["get", "information"], ["literal", ["guidepost", "route_marker"]]], + ["==", ["get", "man_made"], "cairn"], + ] ], travelMode === 'canoe' ? [ "any", ...poiKeys.map(function(key) { - return ["==", key, "yes"]; + return ["==", ["get", key], "yes"]; }) ] : [ @@ -1018,13 +1023,14 @@ function trailPoisFilter(travelMode) { ...poiKeys.map(function(key) { return [ "any", - ["!has", key], - ["==", key, "yes"], + ["!", ["has", key]], + ["==", ["get", key], "yes"], ]; }) ] - ] - ]; + ]); + } + return filter; } function onewayArrowsFilter(travelMode) { @@ -1184,6 +1190,8 @@ function accessIsSpecifiedExpression(travelMode) { function updateTrailLayers() { toggleWaterTrailsIfNeeded(); + var focusedId = focusedEntityInfo?.id ? omtId(focusedEntityInfo.id, focusedEntityInfo.type) : null; + // ["!=", "true", "false"] always evalutes to true because "true" actually refers to the name of a // data attribute key, which is always undefined, while "false" is the string it's compared to. var allowedAccessExpression = ["!=", "true", "false"]; @@ -1343,9 +1351,83 @@ function updateTrailLayers() { "any", ["==", ["get", "waterway"], "waterfall"], ] : null) - .setFilter('trail-pois', trailPoisFilter(travelMode)); + .setFilter('trail-pois', trailPoisFilter(travelMode)) + .setFilter('major-trail-pois', [ + "all", + [ + "any", + ['in', ["get", "leisure"], ["literal", ["park", "nature_reserve"]]], + ['in', ["get", "boundary"], ["literal", ["protected_area", "national_park"]]] + ], + ["!=", ["get", "OSM_ID"], focusedEntityInfo ? focusedEntityInfo.id : null], + ...(focusAreaGeoJson?.geometry?.coordinates?.length ? + focusAreaFilter = [["within", focusAreaGeoJson]] : []), + ]) + .setFilter('peaks', [ + "all", + ["has", "name"], + ["has", "ele_ft"], + ...(focusAreaGeoJson?.geometry?.coordinates?.length ? + focusAreaFilter = [["within", focusAreaGeoJson]] : []), + ]); - updateMapForFocus(); + function setParksFilter(layer, filter) { + ['', '-landcover'].forEach(function(suffix) { + if (suffix === '-landcover') { + var origFilter = filter; + filter = [ + "all", + ["==", ["get", "subclass"], "park"], + ]; + if (origFilter) filter.push(origFilter); + } + map.setFilter(layer + suffix, filter); + }); + } + function setParksPaintProperty(layer, key, value) { + ['', '-landcover'].forEach(function(suffix) { + map.setPaintProperty(layer + suffix, key, value); + }); + } + function setParksLayoutProperty(layer, key, value) { + ['', '-landcover'].forEach(function(suffix) { + map.setLayoutProperty(layer + suffix, key, value); + }); + } + setParksFilter('park-fill', [ + "any", + ["==", ["id"], focusedId], + ["!", ["in", ["id"], ["literal", conservationDistrictOmtIds]]] + ]); + setParksFilter('park-outline', [ + "any", + [ + "all", + ["!=", ["id"], focusedId], + [">=", ["zoom"], 10], + ], + [">=", ["zoom"], 12], + ]); + setParksLayoutProperty('park-outline', "line-sort-key", [ + "case", + ["==", ["id"], focusedId], 2, + 1 + ]); + setParksLayoutProperty('park-fill', "fill-sort-key", [ + "case", + ["==", ["id"], focusedId], 2, + 1 + ]); + setParksPaintProperty('park-fill', "fill-color", [ + "case", + ["==", ["id"], focusedId], "#D8E8B7", + "#EFF5DC" + ]); + setParksPaintProperty('park-outline', "line-color", [ + "case", + ["==", ["id"], focusedId], "#738C40", + "#ACC47A" + ]); } function notNoAccessExpressions(mode) { @@ -1417,77 +1499,6 @@ function omtId(id, type) { return parseInt(id.toString() + codes[type]); } -function updateMapForFocus() { - var focusedId = focusedEntityInfo?.id ? omtId(focusedEntityInfo.id, focusedEntityInfo.type) : null; - - function setParksFilter(layer, filter) { - ['', '-landcover'].forEach(function(suffix) { - if (suffix === '-landcover') { - var origFilter = filter; - filter = [ - "all", - ["==", ["get", "subclass"], "park"], - ]; - if (origFilter) filter.push(origFilter); - } - map.setFilter(layer + suffix, filter); - }); - } - function setParksPaintProperty(layer, key, value) { - ['', '-landcover'].forEach(function(suffix) { - map.setPaintProperty(layer + suffix, key, value); - }); - } - function setParksLayoutProperty(layer, key, value) { - ['', '-landcover'].forEach(function(suffix) { - map.setLayoutProperty(layer + suffix, key, value); - }); - } - setParksFilter('park-fill', [ - "any", - ["==", ["id"], focusedId], - ["!", ["in", ["id"], ["literal", conservationDistrictOmtIds]]] - ]); - setParksFilter('park-outline', [ - "any", - [ - "all", - ["!=", ["id"], focusedId], - [">=", ["zoom"], 10], - ], - [">=", ["zoom"], 12], - ]); - setParksLayoutProperty('park-outline', "line-sort-key", [ - "case", - ["==", ["id"], focusedId], 2, - 1 - ]); - setParksLayoutProperty('park-fill', "fill-sort-key", [ - "case", - ["==", ["id"], focusedId], 2, - 1 - ]); - setParksPaintProperty('park-fill', "fill-color", [ - "case", - ["==", ["id"], focusedId], "#D8E8B7", - "#EFF5DC" - ]); - setParksPaintProperty('park-outline', "line-color", [ - "case", - ["==", ["id"], focusedId], "#738C40", - "#ACC47A" - ]); - map.setFilter('major-trail-pois', [ - "all", - [ - "any", - ['in', ["get", "leisure"], ["literal", ["park", "nature_reserve"]]], - ['in', ["get", "boundary"], ["literal", ["protected_area", "national_park"]]] - ], - ["!=", ["get", "OSM_ID"], focusedEntityInfo ? focusedEntityInfo.id : null] - ]); -} - function updateMapForSelection() { var id = selectedEntityInfo && selectedEntityInfo.id;