Skip to content

Commit

Permalink
keep clustering if too many positions are on screen
Browse files Browse the repository at this point in the history
  • Loading branch information
satellitestudiodesign committed Sep 26, 2024
1 parent f13e3d4 commit 7d2ccc1
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 62 deletions.
1 change: 1 addition & 0 deletions libs/api-types/src/dataviews.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export type DataviewSublayerConfig = {

export type FourwingsGeolocation = 'country' | 'port' | 'default'

/** Used to define the max zoom level for each geolocation (all levels must be below 12) */
export type ClusterMaxZoomLevelConfig = Partial<Record<FourwingsGeolocation, number>>

export interface DataviewConfig<Type = DataviewType> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ const ICON_MAPPING: Record<FourwingsClusterEventType, any> = {

const CLUSTER_LAYER_ID = 'clusters'
const POINTS_LAYER_ID = 'points'
const MAX_INDIVIDUAL_POINTS = 1000

export class FourwingsClustersLayer extends CompositeLayer<
FourwingsClustersLayerProps & TileLayerProps
Expand Down Expand Up @@ -117,9 +118,9 @@ export class FourwingsClustersLayer extends CompositeLayer<
viewportLoaded: false,
clusterIndex: new Supercluster({
radius: 70,
maxZoom: Math.floor(this.props.clusterMaxZoomLevels?.default || MAX_ZOOM_TO_CLUSTER_POINTS),
maxZoom: 12,
reduce: (accumulated, props) => {
accumulated.count += props.count
return (accumulated.value += props.value)
},
}),
}
Expand Down Expand Up @@ -166,59 +167,49 @@ export class FourwingsClustersLayer extends CompositeLayer<

_onViewportLoad = (tiles: Tile2DHeader[]) => {
const { zoom } = this.context.viewport
if (this.clusterMode === 'positions') {
const points = tiles.flatMap((tile) => {
return tile.content
? tile.content.map((feature: any) =>
transformTileCoordsToWGS84(
feature,
tile.bbox as GeoBoundingBox,
this.context.viewport
)
)
: []
}) as FourwingsPointFeature[]
const data: FourwingsPointFeature[] = tiles.flatMap((tile) => {
return this.clusterMode === 'positions'
? (tile.content || []).map((feature: FourwingsPointFeature) =>
transformTileCoordsToWGS84(feature, tile.bbox as GeoBoundingBox, this.context.viewport)
)
: tile.content || []
})
if (this.clusterMode === 'positions' && data.length < MAX_INDIVIDUAL_POINTS) {
requestAnimationFrame(() => {
this.setState({
viewportLoaded: true,
points,
points: data,
clusters: undefined,
radiusScale: undefined,
} as FourwingsClustersTileLayerState)
})
} else {
const data = tiles.flatMap((tile) => {
return tile.content || []
}) as FourwingsPointFeature[]

this.state.clusterIndex.load(data)
const allClusters = this.state.clusterIndex.getClusters(
[-180, -85, 180, 85],
Math.round(zoom)
)
let clusters: FourwingsClusterFeature[] = []
let points: FourwingsPointFeature[] = []
if (allClusters.length) {
allClusters.forEach((f) => {
f.properties.count > 1
? clusters.push(f as FourwingsClusterFeature)
: points.push(f as FourwingsPointFeature)
})
}
})
return
}
this.state.clusterIndex.load(data)
const allClusters = this.state.clusterIndex.getClusters([-180, -85, 180, 85], Math.round(zoom))
let clusters: FourwingsClusterFeature[] = []
let points: FourwingsPointFeature[] = []

const counts = clusters.map((cluster) => cluster.properties.count)
const radiusScale = scaleSqrt()
.domain([1, counts.length ? max(counts) : 1])
.range([MIN_CLUSTER_RADIUS, MAX_CLUSTER_RADIUS])
requestAnimationFrame(() => {
this.setState({
viewportLoaded: true,
clusters,
points,
radiusScale,
} as FourwingsClustersTileLayerState)
if (allClusters.length) {
allClusters.forEach((f) => {
f.properties.value > 1
? clusters.push(f as FourwingsClusterFeature)
: points.push(f as FourwingsPointFeature)
})
}

const counts = clusters.map((cluster) => cluster.properties.value)
const radiusScale = scaleSqrt()
.domain([1, counts.length ? max(counts) : 1])
.range([MIN_CLUSTER_RADIUS, MAX_CLUSTER_RADIUS])
requestAnimationFrame(() => {
this.setState({
viewportLoaded: true,
clusters,
points,
radiusScale,
})
})
}

_fetchClusters = async (
Expand Down Expand Up @@ -326,25 +317,26 @@ export class FourwingsClustersLayer extends CompositeLayer<
}

_getRadius = (d: FourwingsClusterFeature) => {
return this.state.radiusScale?.(d.properties.count) || MIN_CLUSTER_RADIUS
return this.state.radiusScale?.(d.properties.value) || MIN_CLUSTER_RADIUS
}

_getClusterLabel = (d: FourwingsClusterFeature) => {
if (d.properties.count > 1000000) {
return `>${Math.floor(d.properties.count / 1000000)}M`
if (d.properties.value > 1000000) {
return `>${Math.floor(d.properties.value / 1000000)}M`
}
if (d.properties.count > 1000) {
return `>${Math.floor(d.properties.count / 1000)}k`
if (d.properties.value > 1000) {
return `>${Math.floor(d.properties.value / 1000)}k`
}
return d.properties.count.toString()
return d.properties.value.toString()
}

filterSubLayer({ layer }: FilterContext) {
if (this.clusterMode === 'positions') {
return !layer.id.includes(CLUSTER_LAYER_ID)
} else {
return true
}
return true
// if (this.clusterMode === 'positions') {
// return !layer.id.includes(CLUSTER_LAYER_ID)
// } else {
// return true
// }
}

renderLayers(): Layer<{}> | LayersList | null {
Expand Down Expand Up @@ -405,8 +397,8 @@ export class FourwingsClustersLayer extends CompositeLayer<
getAlignmentBaseline: 'center',
// extensions: [new CollisionFilterExtension()],
// collisionTestProps: { sizeScale: 1 },
// getCollisionPriority: (d: any) => parseInt(d.properties.count || 1),
collisionGroup: 'text',
// getCollisionPriority: (d: any) => parseInt(d.properties.value || 1),
// collisionGroup: 'text',
}),
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export type FourwingsClustersLayerProps = DeckLayerProps<{

export type FourwingsClusterProperties = {
id: string
count: number
value: number
col: number
row: number
tile: Tile2DHeader['index']
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export const getPoints = (
},
properties: {
// TODO:deck remove the round as won't be needed with real data
count: Math.round(offset + value * scale),
value: Math.round(offset + value * scale),
id: generateUniqueId(tile!.index.x, tile!.index.y, cellNum),
tile: tile?.index,
col,
Expand Down
2 changes: 1 addition & 1 deletion libs/deck-loaders/src/fourwings/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export type FourwingsPositionFeatureProperties = {

export type FourwingsPointFeatureProperties = {
id: number
count: number
value: number
[key: string]: any
}

Expand Down

0 comments on commit 7d2ccc1

Please sign in to comment.