From f9cd1292a0c387f6a357e8d5b8ae106c61e26382 Mon Sep 17 00:00:00 2001 From: Tor-Einar Skog <tor-einar.skog@nibio.no> Date: Tue, 5 Sep 2023 15:06:05 +0200 Subject: [PATCH] Check that selected point is covered by forecast source --- ipmd/static/ipmd/js/ipmdlib.js | 64 ++++++++++++++------ ipmd/templates/ipmd/saddlegallmidgeform.html | 22 +++++-- 2 files changed, 64 insertions(+), 22 deletions(-) diff --git a/ipmd/static/ipmd/js/ipmdlib.js b/ipmd/static/ipmd/js/ipmdlib.js index 791bc4fe..c270c275 100644 --- a/ipmd/static/ipmd/js/ipmdlib.js +++ b/ipmd/static/ipmd/js/ipmdlib.js @@ -20,6 +20,7 @@ /** * Dependencies: * momentJS + * turf v6 */ const ipmdDSSApiURL = "https://platform.ipmdecisions.net/api/dss/"; @@ -190,6 +191,26 @@ function getPragmaticWeatherParameterList(requestedParameters, availableParamete } +async function isPointCoveredByDatasource(coordinate, datasource) +{ + // If the geoJson is {"type":"Sphere"}, return true + if(datasource.spatial.geoJSON != null && JSON.parse(datasource.spatial.geoJSON).type.toLowerCase() == "sphere") + { + return true; + } + let geoJson = await getDatasourceFeatures(JSON.parse(datasource.spatial.geoJSON), datasource.spatial.countries); + console.info(geoJson); + let retVal = false; + for(let i=0; i<geoJson.features.length;i++) + { + if(turf.booleanPointInPolygon(coordinate, geoJson.features[i])) + { + retVal = true; + } + } + return retVal; +} + /** * Displays the weather data in a table * @param {Object} weatherData the weatherData in IPM Decisions format @@ -439,25 +460,14 @@ async function initDataSourceMap(containerId, geoJson, countryCodeList, featureC let features = new ol.Collection(); let format = new ol.format.GeoJSON(); - let drawnFeatures = undefined; - - // If we have geoJson available, we display that - if (geoJson != null && geoJson.features.length > 0) { - drawnFeatures = format.readFeatures(geoJson, { - dataProjection: 'EPSG:4326', - featureProjection: map.getView().getProjection().getCode() - }); - - } - // If not, we have to get geoJson mapped to the countries - else if (countryCodeList != undefined && countryCodeList != null && countryCodeList.length > 0) { - let countryBoundaries = await getCountryBoundaries(countryCodeList); - //console.info(countryBoundaries); - drawnFeatures = await format.readFeatures(countryBoundaries, { + + let drawnFeatures = await format.readFeatures( + await getDatasourceFeatures(geoJson, countryCodeList), + { dataProjection: 'EPSG:4326', featureProjection: map.getView().getProjection().getCode() - }); - } + } + ); let featureOverlay = undefined; @@ -513,6 +523,22 @@ async function initDataSourceMap(containerId, geoJson, countryCodeList, featureC }); } +/** + * Get "complete" spatial info from weather datasource, using either provided GeoJson or + * inferred from list of countries + * @param {JSON} geoJson + * @param {Array} countryCodeList + * @returns {Json} GeoJson + */ +async function getDatasourceFeatures(geoJson, countryCodeList) +{ + // If we have geoJson available, we display that + if (geoJson != null && geoJson.features !== undefined && geoJson.features.length > 0) { + return geoJson; + } + return await getCountryBoundaries(countryCodeList); +} + const styleUnselected = new ol.style.Style({ fill: new ol.style.Fill({ color: 'rgba(173, 173, 173, 0.5)' @@ -580,6 +606,10 @@ function getDecimalDegrees(map, coordinate) async function getCountryBoundaries(countryCodeList) { + if(countryCodeList == undefined || countryCodeList == null) + { + return {}; + } const response = await fetch(ipmdWeatherApiURL + "rest/country/" + countryCodeList.join(",")); return await response.json(); } diff --git a/ipmd/templates/ipmd/saddlegallmidgeform.html b/ipmd/templates/ipmd/saddlegallmidgeform.html index 33f20917..8252456c 100644 --- a/ipmd/templates/ipmd/saddlegallmidgeform.html +++ b/ipmd/templates/ipmd/saddlegallmidgeform.html @@ -84,6 +84,7 @@ {% block customJS %} <script src="https://cdn.jsdelivr.net/npm/@json-editor/json-editor@latest/dist/jsoneditor.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> +<script src='https://unpkg.com/@turf/turf@6/turf.min.js'></script> <script type="text/javascript" src="{% static "js/3rdparty/moment.min.js" %}"></script> <script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment"></script> <script type="text/javascript" src="{% static "js/3rdparty/ol-debug.js" %}"></script> @@ -203,7 +204,6 @@ function handleHistoricDatasourceMapClicked(id, coordinate) { - //console.info("Map clicked, station=" + id +", coordinate=" + coordinate + ". TODO: select station and/or populate lat/lon fields"); // id != null => station. Pull station coordinates from source list to avoid inacurracies in user's map click coordinate if(id !== null) @@ -234,7 +234,7 @@ } } - function handleForecastSourceSelected(forecastSourceSelectList) + async function handleForecastSourceSelected(forecastSourceSelectList) { currentForecastWeatherDatasource = getWeatherDatasource( weatherDatasources, @@ -248,10 +248,12 @@ return; } + let geoJson = JSON.parse(currentForecastWeatherDatasource.spatial.geoJSON); + // Display map initDataSourceMap( "forecastDatasourceMap", - JSON.parse(currentForecastWeatherDatasource.spatial.geoJSON), + geoJson, currentForecastWeatherDatasource.spatial.countries, function(){} // We don't do nothing, right? ); @@ -259,6 +261,10 @@ let sourceInfo = document.getElementById("forecastSourceInfo"); sourceInfo.innerHTML = currentForecastWeatherDatasource.description; sourceInfoPanel.style.display="block"; + // Does the forecast data source cover the point in question? + console.info("In geoJson? " + await isPointCoveredByDatasource(getLatLon(), currentForecastWeatherDatasource)); + + } function handleWeatherStationSelected(weatherStationSelectList) @@ -275,6 +281,11 @@ document.getElementById("latitude").value = coordinate[1]; } + function getLatLon() + { + return [document.getElementById("longitude").value, document.getElementById("latitude").value]; + } + async function submitData(){ //console.info("submitData!"); let inputData = editor.getValue(); @@ -321,10 +332,11 @@ } else { + coordinate = getLatLon(); weatherData = await getLocationWeatherData( getWeatherDatasourceEndpoint(currentWeatherDatasource), - document.getElementById("longitude").value, - document.getElementById("latitude").value, + coordinate[0], + coordinate[1], getPragmaticWeatherParameterList( function (){ let parameterList = [] -- GitLab