Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve 4wings rendering #2591

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions apps/fishing-map/features/workspace/common/MapLegend.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import { LegendType, MapLegend, Tooltip, UILegend } from '@globalfishingwatch/ui
import { DataviewCategory } from '@globalfishingwatch/api-types'
import { UrlDataviewInstance } from '@globalfishingwatch/dataviews-client'
import { useGetDeckLayerLegend } from '@globalfishingwatch/deck-layer-composer'
import { ColorRange, deckToRgbaColor } from '@globalfishingwatch/deck-layers'
import { useTimeCompareTimeDescription } from 'features/reports/reports-timecomparison.hooks'
import {
selectActivityMergedDataviewId,
selectDetectionsMergedDataviewId,
Expand All @@ -33,15 +31,13 @@ const MapLegendWrapper = ({ dataview }: { dataview: UrlDataviewInstance }) => {
const legendSublayerIndex = deckLegend?.sublayers.findIndex(
(sublayer) => sublayer.id === dataview.id
)
if (legendSublayerIndex < 0 || (isBivariate && legendSublayerIndex !== 0)) {
if (legendSublayerIndex < 0 || (isBivariate && legendSublayerIndex !== 0) || !deckLegend.ranges) {
return null
}

const colors = isBivariate
? (deckLegend.ranges as string[])
: (deckLegend.ranges?.[legendSublayerIndex] as ColorRange)?.map((color) => {
return Array.isArray(color) ? deckToRgbaColor(color) : color.toString()
})
: (deckLegend.ranges[legendSublayerIndex] as string[])
const uiLegend: UILegend = {
id: deckLegend.id,
type: isBivariate ? LegendType.Bivariate : LegendType.ColorRampDiscrete,
Expand Down
14 changes: 8 additions & 6 deletions libs/deck-layer-composer/src/hooks/deck-layers-legends.hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {
FourwingsLayer,
FourwingsComparisonMode,
FourwingsPickingObject,
getBivariateRampLegend,
ColorRampId,
} from '@globalfishingwatch/deck-layers'
import { GRID_AREA_BY_ZOOM_LEVEL, HEATMAP_DEFAULT_MAX_ZOOM } from '../config'
import { DeckLegend, LegendType } from '../types'
Expand All @@ -19,10 +21,6 @@ export const deckLayersLegendsAtom = atom<DeckLegend[]>((get) => {
const interaction = deckLayerHoverFeatures?.features?.find((i) => i.layer?.id === layer.id)

const { domain, range } = layer.instance.getColorScale() || {}
if (!domain || !range) {
// TODO: handle when the layer does not have a color scale because the state is not ready after an update
}

let label = layer.instance.props.sublayers?.[0]?.unit || ''
if (label === 'hours') {
const gridZoom = Math.round(
Expand All @@ -34,7 +32,6 @@ export const deckLayersLegendsAtom = atom<DeckLegend[]>((get) => {
const gridAreaFormatted = gridArea ? `${gridArea}${isSquareKm ? 'km' : 'm'}` : ''
label = `hours / ${gridAreaFormatted}²`
}

return {
id: layer.id,
type:
Expand All @@ -43,7 +40,12 @@ export const deckLayersLegendsAtom = atom<DeckLegend[]>((get) => {
: LegendType.ColorRampDiscrete,
sublayers: layer.instance.props.sublayers,
domain,
ranges: range,
ranges:
layer.instance.props.comparisonMode === FourwingsComparisonMode.Bivariate
? getBivariateRampLegend(
layer.instance.props.sublayers.map((sublayer) => sublayer.colorRamp as ColorRampId)
)
: range,
currentValues: (interaction?.object as FourwingsPickingObject)?.sublayers?.map(
(s: any) => s.value
)!,
Expand Down
94 changes: 62 additions & 32 deletions libs/deck-layers/src/layers/fourwings/FourwingsHeatmapLayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@ import { Color, CompositeLayer, LayersList, PickingInfo } from '@deck.gl/core'
import { PathLayer, SolidPolygonLayer, TextLayer } from '@deck.gl/layers'
import { GeoBoundingBox } from '@deck.gl/geo-layers'
import { PathStyleExtension } from '@deck.gl/extensions'
import { screen } from 'color-blend'
import { FourwingsFeature, getTimeRangeKey } from '@globalfishingwatch/deck-loaders'
import { COLOR_HIGHLIGHT_LINE, LayerGroup, getLayerGroupOffset, rgbaToDeckColor } from '../../utils'
import {
EMPTY_CELL_COLOR,
aggregateCell,
getBivariateValue,
getIntervalFrames,
} from './fourwings.utils'
COLOR_HIGHLIGHT_LINE,
LayerGroup,
getLayerGroupOffset,
rgbaStringToComponents,
rgbaStringToObject,
rgbaToDeckColor,
} from '../../utils'
import { EMPTY_CELL_COLOR, aggregateCell, getIntervalFrames } from './fourwings.utils'
import {
FourwingsComparisonMode,
FourwingsHeatmapLayerProps,
Expand Down Expand Up @@ -69,6 +72,7 @@ export class FourwingsHeatmapLayer extends CompositeLayer<FourwingsHeatmapLayerP
availableIntervals,
aggregationOperation,
tilesCache,
scales,
} = this.props
if (!data || !colorDomain || !colorRanges || !tilesCache) {
return []
Expand All @@ -82,7 +86,7 @@ export class FourwingsHeatmapLayer extends CompositeLayer<FourwingsHeatmapLayerP

const timeRangeKey = getTimeRangeKey(startFrame, endFrame)

const getFillColor = (feature: FourwingsFeature, { target }: { target: Color }) => {
const getCompareFillColor = (feature: FourwingsFeature, { target }: { target: Color }) => {
if (!colorDomain || !colorRanges) {
target = EMPTY_CELL_COLOR
return target
Expand All @@ -98,35 +102,58 @@ export class FourwingsHeatmapLayer extends CompositeLayer<FourwingsHeatmapLayerP
})
let chosenValueIndex = 0
let chosenValue: number | undefined
if (comparisonMode === FourwingsComparisonMode.Compare) {
aggregatedCellValues.forEach((value, index) => {
if (value && (!chosenValue || value > chosenValue)) {
chosenValue = value
chosenValueIndex = index
}
aggregatedCellValues.forEach((value, index) => {
if (value && (!chosenValue || value > chosenValue)) {
chosenValue = value
chosenValueIndex = index
}
})
if (!chosenValue) {
target = EMPTY_CELL_COLOR
return target
}
if (scales[chosenValueIndex]) {
const color = scales[chosenValueIndex](chosenValue)
target = color ? (rgbaStringToComponents(color) as Color) : EMPTY_CELL_COLOR
return target
}
const colorIndex = (colorDomain as number[]).findIndex((d, i) =>
(chosenValue as number) <= d || i === colorRanges[0].length - 1 ? i : 0
)
target = rgbaStringToComponents(colorRanges[chosenValueIndex][colorIndex]) as Color
return target
}

const getBivariateFillColor = (feature: FourwingsFeature, { target }: { target: Color }) => {
if (!colorDomain || !colorRanges) {
target = EMPTY_CELL_COLOR
return target
}
const aggregatedCellValues =
feature.properties.initialValues[timeRangeKey] ||
aggregateCell({
cellValues: feature.properties.values,
startFrame,
endFrame,
aggregationOperation,
cellStartOffsets: feature.properties.startOffsets,
})
// if (scale) {
// return rgbaStringToComponents(scale(chosenValue)) as Color
// }
const colorIndex = (colorDomain as number[]).findIndex((d, i) =>
(chosenValue as number) <= d || i === colorRanges[0].length - 1 ? i : 0
let chosenValue: number | undefined
if (scales.length) {
const colors = scales.map((s, i) =>
aggregatedCellValues[i] ? s(aggregatedCellValues[i]) : undefined
)
if (!chosenValue) {
target = EMPTY_CELL_COLOR
return target
}
return colorRanges[chosenValueIndex][colorIndex] as Color
} else if (comparisonMode === FourwingsComparisonMode.Bivariate) {
chosenValue = getBivariateValue(aggregatedCellValues, colorDomain as number[][])
if (!chosenValue) {
target = EMPTY_CELL_COLOR
return target
}
return rgbaToDeckColor(colorRanges[chosenValue] as unknown as string)
} else {
const color = screen(rgbaStringToObject(colors[0]), rgbaStringToObject(colors[1]))
target = color ? [color.r, color.g, color.b, color.a * 255] : EMPTY_CELL_COLOR
return target
}
// chosenValue = getBivariateValue(aggregatedCellValues, colorDomain as number[][])
if (!chosenValue) {
target = EMPTY_CELL_COLOR
return target
}
target = rgbaToDeckColor(colorRanges[chosenValue] as unknown as string)
return target
}

this.layers = [
Expand All @@ -136,7 +163,10 @@ export class FourwingsHeatmapLayer extends CompositeLayer<FourwingsHeatmapLayerP
id: `fourwings-tile`,
pickable: true,
getPickingInfo: this.getPickingInfo,
getFillColor,
getFillColor:
comparisonMode === FourwingsComparisonMode.Compare
? getCompareFillColor
: getBivariateFillColor,
getPolygon: (d: FourwingsFeature) => d.geometry.coordinates[0],
getPolygonOffset: (params: any) => getLayerGroupOffset(LayerGroup.Heatmap, params),
updateTriggers: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ import {
MAX_RAMP_VALUES_PER_TILE,
} from './fourwings.config'
import {
ColorRange,
FourwingsHeatmapTileLayerProps,
FourwingsTileLayerState,
FourwingsAggregationOperation,
Expand Down Expand Up @@ -83,11 +82,8 @@ export class FourwingsHeatmapStaticLayer extends CompositeLayer<
}

_getColorRanges = () => {
return this.props.sublayers.map(
({ colorRamp }) =>
HEATMAP_COLOR_RAMPS[colorRamp as ColorRampsIds].map((c) =>
rgbaStringToComponents(c)
) as ColorRange
return this.props.sublayers.map(({ colorRamp }) =>
HEATMAP_COLOR_RAMPS[colorRamp as ColorRampsIds].map((c) => rgbaStringToComponents(c))
)
}

Expand Down Expand Up @@ -187,7 +183,7 @@ export class FourwingsHeatmapStaticLayer extends CompositeLayer<
renderLayers(): Layer<{}> | LayersList {
const { tilesUrl, sublayers, resolution, minVisibleValue, maxVisibleValue, maxZoom } =
this.props
const { colorDomain, colorRanges, scale } = this.state as FourwingsTileLayerState
const { colorDomain, colorRanges, scales } = this.state as FourwingsTileLayerState
const params = {
datasets: sublayers.flatMap((sublayer) => sublayer.datasets),
format: 'MVT',
Expand All @@ -207,7 +203,7 @@ export class FourwingsHeatmapStaticLayer extends CompositeLayer<
getPolygonOffset: (params) => getLayerGroupOffset(LayerGroup.HeatmapStatic, params),
getFillColor: this.getFillColor,
updateTriggers: {
getFillColor: [colorDomain, colorRanges, scale, minVisibleValue, maxVisibleValue],
getFillColor: [colorDomain, colorRanges, scales, minVisibleValue, maxVisibleValue],
},
}),
]
Expand Down
Loading
Loading