From 7eb646e381337fcc9151d0c881b5b0dbe9ca4f14 Mon Sep 17 00:00:00 2001 From: Vijayan Balasubramanian Date: Mon, 9 Jan 2023 16:32:46 -0800 Subject: [PATCH] Update mapbounds logic (#175) if more than one copies are visible, use max bounds else wrap bounds. Signed-off-by: Vijayan Balasubramanian --- common/index.ts | 2 ++ public/model/layerRenderController.ts | 38 ++++++++++++++++++--------- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/common/index.ts b/common/index.ts index 94b49746..7d3939fe 100644 --- a/common/index.ts +++ b/common/index.ts @@ -43,6 +43,8 @@ export const LAYER_PANEL_HIDE_LAYER_ICON = 'eyeClosed'; export const MAX_LAYER_NAME_LIMIT = 35; export const MAP_LAYER_DEFAULT_NAME = 'Default map'; export const NEW_MAP_LAYER_DEFAULT_PREFIX = 'New layer'; +export const MIN_LONGITUDE = -180; +export const MAX_LONGITUDE = 180; // Starting position [lng, lat] and zoom export const MAP_INITIAL_STATE = { diff --git a/public/model/layerRenderController.ts b/public/model/layerRenderController.ts index 2f34cde3..98802cf4 100644 --- a/public/model/layerRenderController.ts +++ b/public/model/layerRenderController.ts @@ -3,9 +3,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { Map as Maplibre } from 'maplibre-gl'; +import { LngLatBounds, Map as Maplibre } from 'maplibre-gl'; import { DocumentLayerSpecification, MapLayerSpecification } from './mapLayerType'; -import { DASHBOARDS_MAPS_LAYER_TYPE } from '../../common'; +import { DASHBOARDS_MAPS_LAYER_TYPE, MAX_LONGITUDE, MIN_LONGITUDE } from '../../common'; import { buildOpenSearchQuery, Filter, @@ -22,16 +22,27 @@ interface MaplibreRef { current: Maplibre | null; } -// OpenSearch only accepts longitude in range [-180, 180] -// Maplibre could return value out of the range -function adjustLongitudeForSearch(lon: number) { - if (lon < -180) { - return -180; - } - if (lon > 180) { - return 180; +// calculate lng limits based on map bounds +// maps can render more than 1 copies of map at lower zoom level and displays +// one side from 1 copy and other side from other copy at higher zoom level if +// screen crosses internation dateline +function calculateBoundingBoxLngLimit(bounds: LngLatBounds) { + const boundsMinLng = bounds.getNorthWest().lng; + const boundsMaxLng = bounds.getSouthEast().lng; + // if bounds expands more than 360 then, consider complete globe is visible + if (boundsMaxLng - boundsMinLng >= MAX_LONGITUDE - MIN_LONGITUDE) { + return { + right: MAX_LONGITUDE, + left: MIN_LONGITUDE, + }; } - return lon; + // wrap bounds if only portion of globe is visible + // wrap() returns a new LngLat object whose longitude is + // wrapped to the range (-180, 180). + return { + right: bounds.getSouthEast().wrap().lng, + left: bounds.getNorthWest().wrap().lng, + }; } export const prepareDataLayerSource = ( @@ -112,13 +123,14 @@ export const handleDataLayerRender = ( maplibreRef.current ) { const mapBounds = maplibreRef.current.getBounds(); + const lngLimit = calculateBoundingBoxLngLimit(mapBounds); const filterBoundingBox = { bottom_right: { - lon: adjustLongitudeForSearch(mapBounds.getSouthEast().lng), + lon: lngLimit.right, lat: mapBounds.getSouthEast().lat, }, top_left: { - lon: adjustLongitudeForSearch(mapBounds.getNorthWest().lng), + lon: lngLimit.left, lat: mapBounds.getNorthWest().lat, }, };