diff --git a/src/components/side-panel/layer-panel/layer-configurator.js b/src/components/side-panel/layer-panel/layer-configurator.js index a677a9c95d..240a54a8a8 100644 --- a/src/components/side-panel/layer-panel/layer-configurator.js +++ b/src/components/side-panel/layer-panel/layer-configurator.js @@ -541,6 +541,14 @@ export default function LayerConfiguratorFactory( /> + + {/* elevation scale */} + + + ); } diff --git a/src/deckgl-layers/line-layer/line-layer.js b/src/deckgl-layers/line-layer/line-layer.js index 00285dcd01..54a9d7cc76 100644 --- a/src/deckgl-layers/line-layer/line-layer.js +++ b/src/deckgl-layers/line-layer/line-layer.js @@ -44,16 +44,64 @@ function addInstanceColorShader(vs) { ); } +function addElevationScale(vs) { + let elevationVs = editShader( + vs, + 'line elevation scale 1 vs', + 'uniform float widthMaxPixels;', + `uniform float widthMaxPixels; + uniform float elevationScale;` + ); + + elevationVs = editShader( + elevationVs, + 'line elevation scale 2 vs', + `geometry.worldPosition = instanceSourcePositions; + geometry.worldPositionAlt = instanceTargetPositions;`, + `vec3 sourcePosAdjusted = instanceSourcePositions; + vec3 targetPosAdjusted = instanceTargetPositions; + sourcePosAdjusted.z *= elevationScale; + targetPosAdjusted.z *= elevationScale; + + geometry.worldPosition = sourcePosAdjusted; + geometry.worldPositionAlt = sourcePosAdjusted;` + ); + + elevationVs = editShader( + elevationVs, + 'line elevation scale 3 vs', + 'vec4 source = project_position_to_clipspace(instanceSourcePositions, instanceSourcePositions64Low, vec3(0.), source_commonspace);', + 'vec4 source = project_position_to_clipspace(sourcePosAdjusted, instanceSourcePositions64Low, vec3(0.), source_commonspace);' + ); + + elevationVs = editShader( + elevationVs, + 'line elevation scale 4 vs', + 'vec4 target = project_position_to_clipspace(instanceTargetPositions, instanceTargetPositions64Low, vec3(0.), target_commonspace);', + 'vec4 target = project_position_to_clipspace(targetPosAdjusted, instanceTargetPositions64Low, vec3(0.), target_commonspace);' + ); + + return elevationVs; +} + export default class EnhancedLineLayer extends LineLayer { getShaders() { const shaders = super.getShaders(); + let vs = addInstanceColorShader(shaders.vs); + vs = addElevationScale(vs); + return { ...shaders, - vs: addInstanceColorShader(shaders.vs) + vs }; } + draw({uniforms}) { + const {elevationScale} = this.props; + super.draw({uniforms: {...uniforms, elevationScale}}); + } + initializeState() { super.initializeState(); const {attributeManager} = this.state; diff --git a/src/layers/line-layer/line-layer.js b/src/layers/line-layer/line-layer.js index 92f48d2bbc..561f4002b2 100644 --- a/src/layers/line-layer/line-layer.js +++ b/src/layers/line-layer/line-layer.js @@ -20,11 +20,52 @@ import {BrushingExtension} from '@deck.gl/extensions'; +import {LAYER_VIS_CONFIGS} from 'layers/layer-factory'; import LineLayerIcon from './line-layer-icon'; import ArcLayer from '../arc-layer/arc-layer'; import EnhancedLineLayer from 'deckgl-layers/line-layer/line-layer'; +export const linePosAccessor = ({lat0, lng0, lat1, lng1, alt0, alt1}) => d => [ + d.data[lng0.fieldIdx], + d.data[lat0.fieldIdx], + alt0?.fieldIdx > -1 ? d.data[alt0.fieldIdx] : 0, + d.data[lng1.fieldIdx], + d.data[lat1.fieldIdx], + alt1?.fieldIdx > -1 ? d.data[alt1.fieldIdx] : 0 +]; + +export const lineRequiredColumns = ['lat0', 'lng0', 'lat1', 'lng1']; +export const lineOptionalColumns = ['alt0', 'alt1']; + +export const lineColumnLabels = { + lat0: 'arc.lat0', + lng0: 'arc.lng0', + lat1: 'arc.lat1', + lng1: 'arc.lng1', + alt0: 'line.alt0', + alt1: 'line.alt1' +}; + +export const lineVisConfigs = { + opacity: 'opacity', + thickness: 'thickness', + colorRange: 'colorRange', + sizeRange: 'strokeWidthRange', + targetColor: 'targetColor', + elevationScale: { + ...LAYER_VIS_CONFIGS.elevationScale, + defaultValue: 1 + } +}; + export default class LineLayer extends ArcLayer { + constructor(props) { + super(props); + + this.registerVisConfig(lineVisConfigs); + this.getPositionAccessor = () => linePosAccessor(this.config.columns); + } + get type() { return 'line'; } @@ -33,6 +74,18 @@ export default class LineLayer extends ArcLayer { return LineLayerIcon; } + get requiredLayerColumns() { + return lineRequiredColumns; + } + + get optionalColumns() { + return lineOptionalColumns; + } + + get columnLabels() { + return lineColumnLabels; + } + get visualChannels() { const visualChannels = super.visualChannels; return { @@ -50,12 +103,14 @@ export default class LineLayer extends ArcLayer { } const props = {}; - // connect the first two point layer with arc + // connect the first two point layer with line props.columns = { lat0: fieldPairs[0].pair.lat, lng0: fieldPairs[0].pair.lng, + alt0: {value: null, fieldIdx: -1, optional: true}, lat1: fieldPairs[1].pair.lat, - lng1: fieldPairs[1].pair.lng + lng1: fieldPairs[1].pair.lng, + alt1: {value: null, fieldIdx: -1, optional: true} }; props.label = `${fieldPairs[0].defaultName} -> ${fieldPairs[1].defaultName} line`; @@ -66,7 +121,8 @@ export default class LineLayer extends ArcLayer { const {data, gpuFilter, objectHovered, interactionConfig} = opts; const layerProps = { - widthScale: this.config.visConfig.thickness + widthScale: this.config.visConfig.thickness, + elevationScale: this.config.visConfig.elevationScale }; const updateTriggers = { diff --git a/src/localization/ca.js b/src/localization/ca.js index cb99e18a0f..cf8fca9eb7 100644 --- a/src/localization/ca.js +++ b/src/localization/ca.js @@ -409,6 +409,10 @@ export default { lat1: 'lat destinació', lng1: 'lng destinació' }, + line: { + alt0: 'alçada origen', + alt1: 'alçada destinació' + }, grid: { worldUnitSize: 'Mida de malla (km)' }, diff --git a/src/localization/en.js b/src/localization/en.js index 0200c2ea33..a3e83c10f4 100644 --- a/src/localization/en.js +++ b/src/localization/en.js @@ -414,6 +414,10 @@ export default { lat1: 'target lat', lng1: 'target lng' }, + line: { + alt0: 'source altitude', + alt1: 'target altitude' + }, grid: { worldUnitSize: 'Grid Size (km)' }, diff --git a/src/localization/es.js b/src/localization/es.js index 919660e49d..ae1e91d990 100644 --- a/src/localization/es.js +++ b/src/localization/es.js @@ -410,6 +410,10 @@ export default { lat1: 'lat destino', lng1: 'lng destino' }, + line: { + alt0: 'altura origen', + alt1: 'altura destino' + }, grid: { worldUnitSize: 'Tamaño de la malla (km)' }, diff --git a/src/localization/fi.js b/src/localization/fi.js index 61d16b84ee..6c323449ba 100644 --- a/src/localization/fi.js +++ b/src/localization/fi.js @@ -400,6 +400,10 @@ export default { lat1: 'kohteen lat', lng1: 'kohteen lng' }, + line: { + alt0: 'lähteen korkeus', + alt1: 'kohde korkeus' + }, grid: { worldUnitSize: 'Ruutujen koko (km)' }, diff --git a/src/localization/pt.js b/src/localization/pt.js index c7b96f9088..98af9c2ee4 100644 --- a/src/localization/pt.js +++ b/src/localization/pt.js @@ -401,6 +401,10 @@ export default { lat1: 'destino lat', lng1: 'destino lng' }, + line: { + alt0: 'origem altitude', + alt1: 'destino altitude' + }, grid: { worldUnitSize: 'Tamanho da Grade (km)' }, diff --git a/test/node/reducers/vis-state-test.js b/test/node/reducers/vis-state-test.js index ef964eb25f..c689474482 100644 --- a/test/node/reducers/vis-state-test.js +++ b/test/node/reducers/vis-state-test.js @@ -1254,7 +1254,17 @@ test('#visStateReducer -> UPDATE_VIS_DATA.2 -> to empty state', t => { lat0: {fieldIdx: 0, value: 'start_point_lat'}, lng0: {fieldIdx: 1, value: 'start_point_lng'}, lat1: {fieldIdx: 2, value: 'end_point_lat'}, - lng1: {fieldIdx: 3, value: 'end_point_lng'} + lng1: {fieldIdx: 3, value: 'end_point_lng'}, + alt0: { + value: null, + fieldIdx: -1, + optional: true + }, + alt1: { + value: null, + fieldIdx: -1, + optional: true + } } }); diff --git a/test/node/utils/layer-utils-test.js b/test/node/utils/layer-utils-test.js index 828128b40a..986fb78240 100644 --- a/test/node/utils/layer-utils-test.js +++ b/test/node/utils/layer-utils-test.js @@ -235,6 +235,16 @@ test('layerUtils -> findDefaultLayer.1', t => { lng1: { value: 'two_two.lng', fieldIdx: 2 + }, + alt0: { + value: null, + fieldIdx: -1, + optional: true + }, + alt1: { + value: null, + fieldIdx: -1, + optional: true } } }) @@ -464,6 +474,16 @@ test('layerUtils -> findDefaultLayer.4', t => { lng1: { value: 'dropoff_lng', fieldIdx: 3 + }, + alt0: { + value: null, + fieldIdx: -1, + optional: true + }, + alt1: { + value: null, + fieldIdx: -1, + optional: true } } })