From 05612bdf44c9af6b331e6e18fa0252c2c0cb4254 Mon Sep 17 00:00:00 2001 From: Tariq Soliman Date: Mon, 18 Dec 2023 16:52:29 -0800 Subject: [PATCH] #473 MeasureTool and IdentifierTool Layer Vars (#476) * #473 Layer Specific IdentifierTool vars 1 * #473 MeasureTool and IdentifierTool Layer Vars --- config/js/config.js | 24 ++ docs/pages/Configure/Layers/Tile/Tile.md | 23 +- src/essence/Ancillary/CursorInfo.js | 9 +- src/essence/Basics/Layers_/Layers_.js | 14 +- .../Tools/Identifier/IdentifierTool.js | 263 ++++++++++-------- src/essence/Tools/Measure/MeasureTool.js | 45 ++- 6 files changed, 247 insertions(+), 131 deletions(-) diff --git a/config/js/config.js b/config/js/config.js index ae1c5531..6b00aea7 100644 --- a/config/js/config.js +++ b/config/js/config.js @@ -2813,6 +2813,30 @@ function layerPopulateVariable(modalId, layerType) { "value_in_response_to_replace_with.use.dot.notation.to.traverse.objects", }, }; + currentLayerVars.tools = currentLayerVars.tools + ? currentLayerVars.tools + : { + measure: { + layerDems: [ + { + name: "(str) example", + url: "(str) path_to_data/data.tif (required)", + }, + ], + }, + identifier: { + data: [ + { + url: "(str) path_to_data/data.tif (required)", + bands: "(int) how many bands to query from", + sigfigs: "(int) how many digits after the decimal", + unit: "(str) whatever string unit", + timeFormat: + "(str) for injecting '{starttime}' and '{endtime}' in url. See syntax in https://d3js.org/d3-time-format#locale_format", + }, + ], + }, + }; } else if (layerType == "data") { currentLayerVars = currentLayerVars.shader ? { shader: currentLayerVars.shader } diff --git a/docs/pages/Configure/Layers/Tile/Tile.md b/docs/pages/Configure/Layers/Tile/Tile.md index 4ce50733..4ed4ee55 100644 --- a/docs/pages/Configure/Layers/Tile/Tile.md +++ b/docs/pages/Configure/Layers/Tile/Tile.md @@ -114,7 +114,28 @@ Example: return: "value_in_response_to_replace_with.use.dot.notation.to.traverse.objects", }, - } + }, + "tools": { + "measure": { + "layerDems": [ + { + "name": "(str) example", + "url": "(str) path_to_data/data.tif (required)" + } + ] + }, + "identifier": { + "data": [ + { + "url": "(str) path_to_data/data.tif (required)", + "bands": "(int) how many bands to query from", + "sigfigs": "(int) how many digits after the decimal", + "unit": "(str) whatever string unit", + "timeFormat": "(str) for injecting '{starttime}' and '{endtime}' in url. See syntax in https://d3js.org/d3-time-format#locale_format" + } + ] + } + } } ``` diff --git a/src/essence/Ancillary/CursorInfo.js b/src/essence/Ancillary/CursorInfo.js index c611d796..794bd400 100644 --- a/src/essence/Ancillary/CursorInfo.js +++ b/src/essence/Ancillary/CursorInfo.js @@ -57,7 +57,8 @@ var CursorInfo = { forceColor, forceFontColor, asHTML, - withBorder + withBorder, + withoutPadding ) { if (position) { CursorInfo.forcedPos = true @@ -65,6 +66,12 @@ var CursorInfo = { .style('left', position.x + 'px') .style('top', Math.max(40, position.y) + 'px') } + if (withoutPadding) { + CursorInfo.cursorInfoDiv.style('padding', 0) + } else { + CursorInfo.cursorInfoDiv.style('padding', '5px 9px 4px 9px') + } + $('#cursorInfo').stop() CursorInfo.cursorInfoDiv.style('display', 'block').style('opacity', 1) CursorInfo.cursorInfoDiv diff --git a/src/essence/Basics/Layers_/Layers_.js b/src/essence/Basics/Layers_/Layers_.js index 76f8e987..2d58c4f6 100644 --- a/src/essence/Basics/Layers_/Layers_.js +++ b/src/essence/Basics/Layers_/Layers_.js @@ -1782,16 +1782,26 @@ const L_ = { } return false }, - getToolVars: function (toolName, showWarnings) { + getToolVars: function (toolName, withVarsFromLayers, showWarnings) { + let vars = {} for (var i = 0; i < L_.tools.length; i++) { if ( L_.tools[i].hasOwnProperty('name') && L_.tools[i].name.toLowerCase() == toolName && L_.tools[i].hasOwnProperty('variables') ) { - return L_.tools[i].variables + vars = L_.tools[i].variables } } + if (withVarsFromLayers) { + vars.__layers = {} + L_.layers.dataFlat.forEach((d) => { + if (d.name != null && d?.variables?.tools?.[toolName] != null) { + vars.__layers[d.name] = d.variables.tools[toolName] + } + }) + } + if (Object.keys(vars).length > 0) return vars if (showWarnings) console.warn( `WARNING: Tried to get ${toolName} Tool's config variables and failed.` diff --git a/src/essence/Tools/Identifier/IdentifierTool.js b/src/essence/Tools/Identifier/IdentifierTool.js index 27a86c33..4254a173 100644 --- a/src/essence/Tools/Identifier/IdentifierTool.js +++ b/src/essence/Tools/Identifier/IdentifierTool.js @@ -31,12 +31,26 @@ var IdentifierTool = { this.MMWebGISInterface = new interfaceWithMMWebGIS() //Get tool variables - this.varsRaw = L_.getToolVars('identifier') - this.vars = {} + this.varsRaw = L_.getToolVars('identifier', true) + this.vars = { + data: {}, + } Object.keys(this.varsRaw).forEach((layerName) => { - this.vars[L_.asLayerUUID(layerName)] = this.varsRaw[layerName] + if (layerName != '__layers') + this.vars.data[L_.asLayerUUID(layerName)] = { + data: [this.varsRaw[layerName]], + } }) + if (this.varsRaw.__layers) { + Object.keys(this.varsRaw.__layers).forEach((layerName) => { + const layer = this.varsRaw.__layers[layerName] + if (layer.data) { + this.vars.data[layerName] = layer + } + }) + } + //Probably always 256 this.tileImageWidth = 256 //x y and zoom of mousedover tile @@ -57,9 +71,9 @@ var IdentifierTool = { this.MMWebGISInterface.separateFromMMWebGIS() }, fillURLParameters: function (url, layerUUID) { - if (IdentifierTool.vars[layerUUID]) { + if (IdentifierTool.vars.data[layerUUID]) { const layerTimeFormat = d3.utcFormat( - IdentifierTool.vars[layerUUID].timeFormat + IdentifierTool.vars.data[layerUUID].timeFormat ) let filledURL = url @@ -120,28 +134,9 @@ var IdentifierTool = { Globe_.litho.zoom, ]) }, - idValueMap: function (e) { - IdentifierTool.idPixel( - e, - [e.latlng.lng, e.latlng.lat, Map_.map.getZoom()], - true - ) - }, - idValueGlobe: function (e) { - if (Globe_.litho.mouse) - IdentifierTool.idPixel( - e, - [ - Globe_.litho.mouse.lng, - Globe_.litho.mouse.lat, - Globe_.litho.zoom, - ], - true - ) - }, //lnglatzoom is [lng,lat,zoom] //if trueValue is true, query the data layer for the value, else us the legend if possible - idPixel: function (e, lnglatzoom, trueValue) { + idPixel: function (e, lnglatzoom, trueValue, selfish) { trueValue = trueValue || false clearTimeout(IdentifierTool.mousemoveTimeout) @@ -258,105 +253,128 @@ var IdentifierTool = { ) } //Oh IdentifierTool is the same as X != undefined - if (pxRGBA) { - if ( - trueValue && - IdentifierTool.vars[IdentifierTool.activeLayerNames[i]] - ) { - queryDataValue( - IdentifierTool.vars[IdentifierTool.activeLayerNames[i]] - .url, - lnglatzoom[0], - lnglatzoom[1], - IdentifierTool.vars[IdentifierTool.activeLayerNames[i]] - .bands, - IdentifierTool.activeLayerNames[i], - (function (pxRGBA, i) { - return function (value) { - var htmlValues = '' - var cnt = 0 - for (var v in value) { - var unit = - IdentifierTool.vars[ - IdentifierTool.activeLayerNames[i] - ].unit || '' - if ( - IdentifierTool.vars[ - IdentifierTool.activeLayerNames[i] - ].units && - IdentifierTool.vars[ - IdentifierTool.activeLayerNames[i] - ].units.constructor === Array && - IdentifierTool.vars[ - IdentifierTool.activeLayerNames[i] - ].units[cnt] - ) { - unit = - IdentifierTool.vars[ + if ( + IdentifierTool.vars.data[IdentifierTool.activeLayerNames[i]] + ?.data + ) { + const data = + IdentifierTool.vars.data[IdentifierTool.activeLayerNames[i]] + for (let j = 0; j < data.data.length; j++) { + const d = data.data[j] + + if (pxRGBA) { + if (trueValue) { + queryDataValue( + d.url, + lnglatzoom[0], + lnglatzoom[1], + d.bands, + IdentifierTool.activeLayerNames[i], + (function (pxRGBA, i, j) { + return function (value) { + const d2 = + IdentifierTool.vars.data[ IdentifierTool.activeLayerNames[ i ] - ].units[cnt] + ].data[j] + var htmlValues = '' + // first empty it + $( + `#identifierToolIdPixelCursorInfo_${i}_${j}` + ).html( + [ + '
', + '
', + '
 
', + '
', + ].join('') + ) + var cnt = 0 + for (var v in value) { + var unit = d2.unit || '' + if ( + d2.units && + d2.units.constructor === + Array && + d2.units[cnt] + ) { + unit = d2.units[cnt] + } + var valueParsed = + parseValue( + value[v][1], + d2.sigfigs + ) + + '' + + unit + + htmlValues += + '
' + + value[v][0] + + '
' + + valueParsed + + '
' + cnt++ + } + $( + `#identifierToolIdPixelCursorInfo_${i}_${j}` + ).html(htmlValues) } - var valueParsed = - parseValue( - value[v][1], - IdentifierTool.vars[ - IdentifierTool.activeLayerNames[ - i - ] - ].sigfigs - ) + - '' + - unit - htmlValues += - '
' + - value[v][0] + - '
' + - valueParsed + - '
' - cnt++ - } - $('#identifierToolIdPixelCursorInfo_' + i).html( - htmlValues + })(pxRGBA, i, j) + ) + } else { + if ( + L_.layers.data[ + IdentifierTool.activeLayerNames[i] + ]?._legend + ) { + value = bestMatchInLegend( + pxRGBA, + L_.layers.data[ + IdentifierTool.activeLayerNames[i] + ]._legend ) } - })(pxRGBA, i) - ) - } else { - if ( - L_.layers.data[IdentifierTool.activeLayerNames[i]] - ?._legend - ) { - value = bestMatchInLegend( - pxRGBA, - L_.layers.data[IdentifierTool.activeLayerNames[i]] - ._legend - ) + } + colorString = + 'rgba(' + + pxRGBA.r + + ',' + + pxRGBA.g + + ',' + + pxRGBA.b + + ',' + + pxRGBA.a / 255 + + ')' } + + // prettier-ignore + liEls.push( + [`
  • `, + `
    `, + `
    `, + `
    `, + d.name || + L_.layers.data[ + IdentifierTool.activeLayerNames[i] + ].display_name, + `
    `, + `
    `, + `
    `, + + (trueValue || value == null || value == '') ? [ + '
    ', + '
    ', + '
     
    ', + '
    '].join('') : value, + + `
    `, + '
  • ', + ].join('') + ) } - colorString = - 'rgba(' + - pxRGBA.r + - ',' + - pxRGBA.g + - ',' + - pxRGBA.b + - ',' + - pxRGBA.a / 255 + - ')' } - liEls[i] = - "
  • " + - L_.layers.data[IdentifierTool.activeLayerNames[i]] - .display_name + - "
    " + - value + - '
  • ' } CursorInfo.update( htmlInfoString + liEls.join('') + '', @@ -365,17 +383,19 @@ var IdentifierTool = { null, null, null, + true, + null, true ) - if (!trueValue) { + if (!trueValue && !selfish) { IdentifierTool.mousemoveTimeout = setTimeout(function () { - IdentifierTool.idPixel(e, lnglatzoom, true) + IdentifierTool.idPixel(e, lnglatzoom, true, true) }, 150) } function parseValue(v, sigfigs) { - var ed = 4 + var ed = 10 if (typeof v === 'string') { return v } @@ -393,8 +413,9 @@ var IdentifierTool = { if (sigfigs != undefined) v = v.toFixed(sigfigs) } v = parseFloat(v) - if (sigfigs != undefined) ed = sigfigs - if (decPlacesAfter >= ed) v = v.toExponential(ed) + if (decPlacesAfter >= ed) { + v = v.toExponential(ed) + } return parseFloat(v) } } @@ -498,7 +519,7 @@ function queryDataValue(url, lng, lat, numBands, layerUUID, callback) { bands: '[[1,' + numBands + ']]', path: dataPath, }, - function (data) { + (data) => { //Convert python's Nones to nulls data = data.replace(/none/gi, 'null') if (data.length > 2) { diff --git a/src/essence/Tools/Measure/MeasureTool.js b/src/essence/Tools/Measure/MeasureTool.js index 36627330..7c52c8d7 100644 --- a/src/essence/Tools/Measure/MeasureTool.js +++ b/src/essence/Tools/Measure/MeasureTool.js @@ -620,7 +620,27 @@ let MeasureTool = { steps = 100 //Get tool variables - this.vars = L_.getToolVars('measure') + this.vars = L_.getToolVars('measure', true) + this.vars.layerDems = this.vars.layerDems || {} + + const standardLayerDems = {} + Object.keys(this.vars.layerDems).forEach((layerName) => { + standardLayerDems[L_.asLayerUUID(layerName)] = [ + this.vars.layerDems[layerName], + ] + }) + this.vars.layerDems = standardLayerDems + + if (this.vars.__layers) { + Object.keys(this.vars.__layers).forEach((layerName) => { + const layer = this.vars.__layers[layerName] + if (layer.layerDems) { + this.vars.layerDems[layerName] = ( + this.vars.layerDems[layerName] || [] + ).concat(layer.layerDems) + } + }) + } if ( this.vars.defaultMode && @@ -698,14 +718,27 @@ let MeasureTool = { dems.push({ name: 'Main', path: MeasureTool.vars.dem }) if (MeasureTool.vars.layerDems) for (let name in MeasureTool.vars.layerDems) { - if (!onlyShowDemIfLayerOn || L_.layers.on[name]) - dems.push({ - name: name, - path: MeasureTool.vars.layerDems[name], - }) + MeasureTool.vars.layerDems[name].forEach((item) => { + if (!onlyShowDemIfLayerOn || L_.layers.on[name]) { + if (typeof item === 'string') { + dems.push({ + name: L_.layers.data[name]?.display_name, + path: item, + }) + } else { + dems.push({ + name: + item.name || + L_.layers.data[name]?.display_name, + path: item.url, + }) + } + } + }) } if (dems.length === 0) dems.push({ name: 'Misconfigured', path: 'none' }) + return dems }, clickMap: function (e) {