From 9f8e01f51331a8b3913fd5cc59d94eeaa70bbf79 Mon Sep 17 00:00:00 2001 From: Charles Richardson Date: Fri, 20 Dec 2024 13:16:40 -0500 Subject: [PATCH 1/6] docs: elevation control in MapViewState --- modules/core/src/views/map-view.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/core/src/views/map-view.ts b/modules/core/src/views/map-view.ts index 4d80ef73cc3..201b14cc877 100644 --- a/modules/core/src/views/map-view.ts +++ b/modules/core/src/views/map-view.ts @@ -27,8 +27,8 @@ export type MapViewState = { minPitch?: number; /** Max pitch, default `60` */ maxPitch?: number; - /** Viewport center offsets from lng, lat in meters */ - position?: number[]; + /** Viewport center offsets from lng, lat, and elevation in meters */ + position?: [number, number, number]; } & CommonViewState; export type MapViewProps = { From e6b304d31e7d88c19946b65e93ed898e20ee8b3d Mon Sep 17 00:00:00 2001 From: Charles Richardson Date: Sat, 21 Dec 2024 16:11:33 -0500 Subject: [PATCH 2/6] Add MapViewState change documentation --- docs/upgrade-guide.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/upgrade-guide.md b/docs/upgrade-guide.md index 3ef720e4aa8..c24f310b9b3 100644 --- a/docs/upgrade-guide.md +++ b/docs/upgrade-guide.md @@ -32,6 +32,10 @@ Breaking changes: - `PointLight.attenuation` was previously ignored. To retain old behavior, use the default (`[1, 0, 0]`). +### MapViewState + +- The `position` property changed from `number[]` to `[number, number, number]` (lat, lng, elevation). + ## Upgrading to v9.0 **Before you upgrade: known issues** From 33dde585154ca09247fa79fe7a109fa78c3dff3b Mon Sep 17 00:00:00 2001 From: charlieforward9 Date: Mon, 6 Jan 2025 16:14:03 -0500 Subject: [PATCH 3/6] fix: strictly include elevation in position type and docs --- docs/api-reference/core/globe-viewport.md | 2 +- .../core/src/shaderlib/project/project-functions.ts | 4 ++-- modules/core/src/viewports/first-person-viewport.ts | 2 +- modules/core/src/viewports/viewport.ts | 10 +++++----- modules/core/src/viewports/web-mercator-viewport.ts | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/api-reference/core/globe-viewport.md b/docs/api-reference/core/globe-viewport.md index 69f29e1f4ec..0678bffee3d 100644 --- a/docs/api-reference/core/globe-viewport.md +++ b/docs/api-reference/core/globe-viewport.md @@ -64,7 +64,7 @@ Projects world coordinates to pixel coordinates on screen. Parameters: -* `coordinates` (number[]) - `[longitude, latitude, altitude]`. `altitude` is in meters and default to `0` if not supplied. +* `coordinates` ([number, number, number]) - `[longitude, latitude, altitude]`. `altitude` is in meters and default to `0` if not supplied. * `opts` (object) + `topLeft` (boolean, optional) - Whether projected coords are top left. Default to `true`. diff --git a/modules/core/src/shaderlib/project/project-functions.ts b/modules/core/src/shaderlib/project/project-functions.ts index bc66d1498c1..86362dc8258 100644 --- a/modules/core/src/shaderlib/project/project-functions.ts +++ b/modules/core/src/shaderlib/project/project-functions.ts @@ -81,7 +81,7 @@ function normalizeParameters(opts: { /** Get the common space position from world coordinates in the given coordinate system */ export function getWorldPosition( - position: number[], + position: [number, number, number], { viewport, modelMatrix, @@ -134,7 +134,7 @@ export function getWorldPosition( * a reference coordinate system */ export function projectPosition( - position: number[], + position: [number, number, number], params: { /** The current viewport */ viewport: Viewport; diff --git a/modules/core/src/viewports/first-person-viewport.ts b/modules/core/src/viewports/first-person-viewport.ts index 41d709ac2d5..a60a71f76ef 100644 --- a/modules/core/src/viewports/first-person-viewport.ts +++ b/modules/core/src/viewports/first-person-viewport.ts @@ -21,7 +21,7 @@ export type FirstPersonViewportOptions = { longitude?: number; /** Latitude of the camera, in the geospatial case. */ latitude?: number; - /** Meter offsets of the camera from the lng-lat anchor point. Default `[0, 0, 0]`. */ + /** Meter offsets of the camera from the lng-lat-elevation anchor point. Default `[0, 0, 0]`. */ position?: [number, number, number]; /** Bearing (heading) of the camera in degrees. Default `0` (north). */ bearing?: number; diff --git a/modules/core/src/viewports/viewport.ts b/modules/core/src/viewports/viewport.ts index 05597627ce3..7d9777b9450 100644 --- a/modules/core/src/viewports/viewport.ts +++ b/modules/core/src/viewports/viewport.ts @@ -45,8 +45,8 @@ export type ViewportOptions = { longitude?: number; /** Latitude in degrees (geospatial only) */ latitude?: number; - /** Viewport center in world space. If geospatial, refers to meter offsets from lng, lat */ - position?: number[]; + /** Viewport center in world space. If geospatial, refers to meter offsets from lng, lat, elevation */ + position?: [number, number, number]; /** Zoom level */ zoom?: number; /** Padding around the viewport, in pixels. */ @@ -76,7 +76,7 @@ const DEGREES_TO_RADIANS = Math.PI / 180; const IDENTITY = createMat4(); -const ZERO_VECTOR = [0, 0, 0]; +const ZERO_VECTOR: [number, number, number] = [0, 0, 0]; const DEFAULT_DISTANCE_SCALES: DistanceScales = { unitsPerMeter: [1, 1, 1], @@ -138,7 +138,7 @@ export default class Viewport { isGeospatial: boolean; zoom: number; focalDistance: number; - position: number[]; + position: [number, number, number]; modelMatrix: number[] | null; /** Derived parameters */ @@ -149,7 +149,7 @@ export default class Viewport { distanceScales: DistanceScales; /** scale factors between world space and common space */ scale!: number; /** scale factor, equals 2^zoom */ center!: number[]; /** viewport center in common space */ - cameraPosition!: number[]; /** Camera position in common space */ + cameraPosition!: [number, number, number]; /** Camera position in common space */ projectionMatrix!: number[]; viewMatrix!: number[]; viewMatrixUncentered!: number[]; diff --git a/modules/core/src/viewports/web-mercator-viewport.ts b/modules/core/src/viewports/web-mercator-viewport.ts index 55dc1c360f7..453894859e2 100644 --- a/modules/core/src/viewports/web-mercator-viewport.ts +++ b/modules/core/src/viewports/web-mercator-viewport.ts @@ -44,8 +44,8 @@ export type WebMercatorViewportOptions = { altitude?: number; /** Camera fovy in degrees. If provided, overrides `altitude` */ fovy?: number; - /** Viewport center in world space. If geospatial, refers to meter offsets from lng, lat */ - position?: number[]; + /** Viewport center in world space. If geospatial, refers to meter offsets from lng, lat, elevation */ + position?: [number, number, number]; /** Zoom level */ zoom?: number; /** Padding around the viewport, in pixels. */ From 9d8647abefe8771d1ce733c428732333e5560b88 Mon Sep 17 00:00:00 2001 From: Charles Richardson Date: Mon, 6 Jan 2025 16:56:30 -0500 Subject: [PATCH 4/6] docs: ViewportOptions position type change --- docs/upgrade-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/upgrade-guide.md b/docs/upgrade-guide.md index 28c4f8619a0..d57e5827214 100644 --- a/docs/upgrade-guide.md +++ b/docs/upgrade-guide.md @@ -32,7 +32,7 @@ Breaking changes: - `PointLight.attenuation` was previously ignored. To retain old behavior, use the default (`[1, 0, 0]`). -### MapViewState +### MapViewState / ViewportOptions - The `position` property changed from `number[]` to `[number, number, number]` (lat, lng, elevation). From 5c144634787f49d3f12793a4dc37fca008615107 Mon Sep 17 00:00:00 2001 From: charlieforward9 Date: Wed, 8 Jan 2025 13:58:13 -0500 Subject: [PATCH 5/6] fix: enforce 3D coordinates across dependent modules --- .../src/contour-layer/contour-layer.ts | 9 ++- .../src/grid-layer/grid-layer.ts | 9 ++- .../src/heatmap-layer/heatmap-layer.ts | 17 +++--- .../src/hexagon-layer/hexagon-layer.ts | 9 ++- .../screen-grid-layer/screen-grid-layer.ts | 2 +- modules/core/src/lib/layer.ts | 8 +-- modules/core/src/lib/picking/pick-info.ts | 4 +- modules/core/src/lib/view-manager.ts | 12 ++-- .../shaderlib/project/project-functions.ts | 2 +- .../src/transitions/linear-interpolator.ts | 6 +- modules/core/src/viewports/globe-viewport.ts | 30 +++++----- modules/core/src/viewports/orbit-viewport.ts | 2 +- .../src/viewports/orthographic-viewport.ts | 12 ++-- modules/core/src/viewports/viewport.ts | 57 ++++++++++--------- .../src/viewports/web-mercator-viewport.ts | 10 ++-- .../extensions/src/brushing/shader-module.ts | 7 +-- .../extensions/src/terrain/terrain-cover.ts | 12 +++- .../extensions/src/utils/projection-utils.ts | 16 ++++-- .../src/h3-layers/h3-hexagon-layer.ts | 2 +- .../src/tile-3d-layer/tile-3d-layer.ts | 2 +- .../src/tileset-2d/tile-2d-traversal.ts | 12 ++-- modules/geo-layers/src/tileset-2d/utils.ts | 12 ++-- modules/google-maps/src/utils.ts | 2 +- .../solid-polygon-layer.ts | 7 ++- 24 files changed, 149 insertions(+), 112 deletions(-) diff --git a/modules/aggregation-layers/src/contour-layer/contour-layer.ts b/modules/aggregation-layers/src/contour-layer/contour-layer.ts index ded0d2acd82..9952ca64068 100644 --- a/modules/aggregation-layers/src/contour-layer/contour-layer.ts +++ b/modules/aggregation-layers/src/contour-layer/contour-layer.ts @@ -143,7 +143,7 @@ export default class GridLayer extends getValue: ({positions}: {positions: number[]}, index: number, opts: BinOptions) => { const viewport = this.state.aggregatorViewport; // project to common space - const p = viewport.projectPosition(positions); + const p = viewport.projectPosition([positions[0], positions[1], positions[2] || 0]); const {cellSizeCommon, cellOriginCommon} = opts; return [ Math.floor((p[0] - cellOriginCommon[0]) / cellSizeCommon[0]), @@ -241,7 +241,10 @@ export default class GridLayer extends let viewport = this.context.viewport; if (bounds && Number.isFinite(bounds[0][0])) { - let centroid = [(bounds[0][0] + bounds[1][0]) / 2, (bounds[0][1] + bounds[1][1]) / 2]; + let centroid: [number, number] = [ + (bounds[0][0] + bounds[1][0]) / 2, + (bounds[0][1] + bounds[1][1]) / 2 + ]; const {cellSize, gridOrigin} = this.props; const {unitsPerMeter} = viewport.getDistanceScales(centroid); cellSizeCommon[0] = unitsPerMeter[0] * cellSize; @@ -272,7 +275,7 @@ export default class GridLayer extends binIdRange = getBinIdRange({ dataBounds: bounds, getBinId: (p: number[]) => { - const positionCommon = viewport.projectFlat(p); + const positionCommon = viewport.projectFlat([p[0], p[1]]); return [ Math.floor((positionCommon[0] - cellOriginCommon[0]) / cellSizeCommon[0]), Math.floor((positionCommon[1] - cellOriginCommon[1]) / cellSizeCommon[1]) diff --git a/modules/aggregation-layers/src/grid-layer/grid-layer.ts b/modules/aggregation-layers/src/grid-layer/grid-layer.ts index f0b82e8028b..ed37da97358 100644 --- a/modules/aggregation-layers/src/grid-layer/grid-layer.ts +++ b/modules/aggregation-layers/src/grid-layer/grid-layer.ts @@ -313,7 +313,7 @@ export default class GridLayer extends } const viewport = this.state.aggregatorViewport; // project to common space - const p = viewport.projectPosition(positions); + const p = viewport.projectPosition([positions[0], positions[1], positions[2] || 0]); const {cellSizeCommon, cellOriginCommon} = opts; return [ Math.floor((p[0] - cellOriginCommon[0]) / cellSizeCommon[0]), @@ -446,7 +446,10 @@ export default class GridLayer extends let viewport = this.context.viewport; if (bounds && Number.isFinite(bounds[0][0])) { - let centroid = [(bounds[0][0] + bounds[1][0]) / 2, (bounds[0][1] + bounds[1][1]) / 2]; + let centroid: [number, number] = [ + (bounds[0][0] + bounds[1][0]) / 2, + (bounds[0][1] + bounds[1][1]) / 2 + ]; const {cellSize} = this.props; const {unitsPerMeter} = viewport.getDistanceScales(centroid); cellSizeCommon[0] = unitsPerMeter[0] * cellSize; @@ -475,7 +478,7 @@ export default class GridLayer extends binIdRange = getBinIdRange({ dataBounds: bounds, getBinId: (p: number[]) => { - const positionCommon = viewport.projectFlat(p); + const positionCommon = viewport.projectFlat([p[0], p[1]]); return [ Math.floor((positionCommon[0] - cellOriginCommon[0]) / cellSizeCommon[0]), Math.floor((positionCommon[1] - cellOriginCommon[1]) / cellSizeCommon[1]) diff --git a/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts b/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts index a1ad95b8d53..bbed01c8d9c 100644 --- a/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts +++ b/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts @@ -492,10 +492,10 @@ export default class HeatmapLayer< // Unproject all 4 corners of the current screen coordinates into world coordinates (lng/lat) // Takes care of viewport has non zero bearing/pitch (i.e axis not aligned with world coordiante system) const viewportCorners = [ - viewport.unproject([0, 0]), - viewport.unproject([viewport.width, 0]), - viewport.unproject([0, viewport.height]), - viewport.unproject([viewport.width, viewport.height]) + viewport.unproject([0, 0, 0]), + viewport.unproject([viewport.width, 0, 0]), + viewport.unproject([0, viewport.height, 0]), + viewport.unproject([viewport.width, viewport.height, 0]) ].map(p => p.map(Math.fround)); // #1: get world bounds for current viewport extends @@ -546,7 +546,10 @@ export default class HeatmapLayer< triPositionBuffer!.write(packVertices(viewportCorners, 3)); const textureBounds = viewportCorners.map(p => - getTextureCoordinates(viewport.projectPosition(p), normalizedCommonBounds!) + getTextureCoordinates( + viewport.projectPosition([p[0], p[1], p[2] || 0]), + normalizedCommonBounds! + ) ); triTexCoordBuffer!.write(packVertices(textureBounds, 2)); } @@ -691,8 +694,8 @@ export default class HeatmapLayer< _commonToWorldBounds(commonBounds) { const [xMin, yMin, xMax, yMax] = commonBounds; const {viewport} = this.context; - const bottomLeftWorld = viewport.unprojectPosition([xMin, yMin]); - const topRightWorld = viewport.unprojectPosition([xMax, yMax]); + const bottomLeftWorld = viewport.unprojectPosition([xMin, yMin, 0]); + const topRightWorld = viewport.unprojectPosition([xMax, yMax, 0]); return bottomLeftWorld.slice(0, 2).concat(topRightWorld.slice(0, 2)); } diff --git a/modules/aggregation-layers/src/hexagon-layer/hexagon-layer.ts b/modules/aggregation-layers/src/hexagon-layer/hexagon-layer.ts index 0be249804d7..f4bcbee31db 100644 --- a/modules/aggregation-layers/src/hexagon-layer/hexagon-layer.ts +++ b/modules/aggregation-layers/src/hexagon-layer/hexagon-layer.ts @@ -317,7 +317,7 @@ export default class HexagonLayer< } const viewport = this.state.aggregatorViewport; // project to common space - const p = viewport.projectPosition(positions); + const p = viewport.projectPosition([positions[0], positions[1], positions[2] || 0]); const {radiusCommon, hexOriginCommon} = opts; return pointToHexbin( [p[0] - hexOriginCommon[0], p[1] - hexOriginCommon[1]], @@ -451,7 +451,10 @@ export default class HexagonLayer< let viewport = this.context.viewport; if (bounds && Number.isFinite(bounds[0][0])) { - let centroid = [(bounds[0][0] + bounds[1][0]) / 2, (bounds[0][1] + bounds[1][1]) / 2]; + let centroid: [number, number] = [ + (bounds[0][0] + bounds[1][0]) / 2, + (bounds[0][1] + bounds[1][1]) / 2 + ]; const {radius} = this.props; const {unitsPerMeter} = viewport.getDistanceScales(centroid); radiusCommon = unitsPerMeter[0] * radius; @@ -474,7 +477,7 @@ export default class HexagonLayer< binIdRange = getBinIdRange({ dataBounds: bounds, getBinId: (p: number[]) => { - const positionCommon = viewport.projectFlat(p); + const positionCommon = viewport.projectFlat([p[0], p[1]]); positionCommon[0] -= hexOriginCommon[0]; positionCommon[1] -= hexOriginCommon[1]; return pointToHexbin(positionCommon, radiusCommon); diff --git a/modules/aggregation-layers/src/screen-grid-layer/screen-grid-layer.ts b/modules/aggregation-layers/src/screen-grid-layer/screen-grid-layer.ts index 0be80371606..4f2c3edd55f 100644 --- a/modules/aggregation-layers/src/screen-grid-layer/screen-grid-layer.ts +++ b/modules/aggregation-layers/src/screen-grid-layer/screen-grid-layer.ts @@ -138,7 +138,7 @@ export default class ScreenGridLayer< sources: ['positions'], getValue: ({positions}: {positions: number[]}, index: number, opts: BinOptions) => { const viewport = this.context.viewport; - const p = viewport.project(positions); + const p = viewport.project([positions[0], positions[1], positions[2] || 0]); const cellSizePixels: number = opts.cellSizePixels; if (p[0] < 0 || p[0] >= viewport.width || p[1] < 0 || p[1] >= viewport.height) { // Not on screen diff --git a/modules/core/src/lib/layer.ts b/modules/core/src/lib/layer.ts index 04e16aa177b..31730d50f48 100644 --- a/modules/core/src/lib/layer.ts +++ b/modules/core/src/lib/layer.ts @@ -219,7 +219,7 @@ export default abstract class Layer extends Component< // Public API for users /** Projects a point with current view state from the current layer's coordinate system to screen */ - project(xyz: number[]): number[] { + project(xyz: [number, number, number]): [number, number, number] { assert(this.internalState); const viewport = this.internalState.viewport || this.context.viewport; @@ -230,12 +230,12 @@ export default abstract class Layer extends Component< coordinateSystem: this.props.coordinateSystem }); const [x, y, z] = worldToPixels(worldPosition, viewport.pixelProjectionMatrix); - return xyz.length === 2 ? [x, y] : [x, y, z]; + return [x, y, z]; } /** Unprojects a screen pixel to the current view's default coordinate system Note: this does not reverse `project`. */ - unproject(xy: number[]): number[] { + unproject(xy: [number, number, number]): [number, number, number] { assert(this.internalState); const viewport = this.internalState.viewport || this.context.viewport; return viewport.unproject(xy); @@ -243,7 +243,7 @@ export default abstract class Layer extends Component< /** Projects a point with current view state from the current layer's coordinate system to the world space */ projectPosition( - xyz: number[], + xyz: [number, number, number], params?: { /** The viewport to use */ viewport?: Viewport; diff --git a/modules/core/src/lib/picking/pick-info.ts b/modules/core/src/lib/picking/pick-info.ts index 4a1d36bb379..ae13a02f2f1 100644 --- a/modules/core/src/lib/picking/pick-info.ts +++ b/modules/core/src/lib/picking/pick-info.ts @@ -53,9 +53,9 @@ export function getEmptyPickingInfo({ // Find the viewport that contain the picked pixel pickedViewport = getViewportFromCoordinates(pickInfo?.pickedViewports || viewports, {x, y}); } - let coordinate: number[] | undefined; + let coordinate: [number, number, number] | undefined; if (pickedViewport) { - const point = [x - pickedViewport.x, y - pickedViewport.y]; + const point: [number, number, number] = [x - pickedViewport.x, y - pickedViewport.y, 0]; if (z !== undefined) { point[2] = z; } diff --git a/modules/core/src/lib/view-manager.ts b/modules/core/src/lib/view-manager.ts index 8d68f61aebd..d53771a7f76 100644 --- a/modules/core/src/lib/view-manager.ts +++ b/modules/core/src/lib/view-manager.ts @@ -20,14 +20,14 @@ type ViewStateOf = ViewT extends View ? ViewStateT : ne type OneOfViews = ViewsT extends null ? MapView : ViewsT extends View[] - ? ViewsT[number] - : ViewsT; + ? ViewsT[number] + : ViewsT; export type AnyViewStateOf = ViewStateOf>; export type ViewStateMap = ViewsT extends null ? MapViewState : ViewsT extends View - ? ViewStateOf - : {[viewId: string]: AnyViewStateOf}; + ? ViewStateOf + : {[viewId: string]: AnyViewStateOf}; /** This is a very lose type of all "acceptable" viewState * It's not good for type hinting but matches what may exist internally @@ -195,13 +195,13 @@ export default class ViewManager { * @param {Object} opts.topLeft=true - Whether origin is top left * @return {Array|null} - [lng, lat, Z] or [X, Y, Z] */ - unproject(xyz: number[], opts?: {topLeft?: boolean}): number[] | null { + unproject(xyz: [number, number, number], opts?: {topLeft?: boolean}): number[] | null { const viewports = this.getViewports(); const pixel = {x: xyz[0], y: xyz[1]}; for (let i = viewports.length - 1; i >= 0; --i) { const viewport = viewports[i]; if (viewport.containsPixel(pixel)) { - const p = xyz.slice(); + const p = xyz.slice() as [number, number, number]; p[0] -= viewport.x; p[1] -= viewport.y; return viewport.unproject(p, opts); diff --git a/modules/core/src/shaderlib/project/project-functions.ts b/modules/core/src/shaderlib/project/project-functions.ts index 86362dc8258..8936ce04a4e 100644 --- a/modules/core/src/shaderlib/project/project-functions.ts +++ b/modules/core/src/shaderlib/project/project-functions.ts @@ -17,7 +17,7 @@ import type {CoordinateSystem} from '../../lib/constants'; import type Viewport from '../../viewports/viewport'; import type {NumericArray} from '../../types/types'; -const DEFAULT_COORDINATE_ORIGIN = [0, 0, 0]; +const DEFAULT_COORDINATE_ORIGIN: [number, number, number] = [0, 0, 0]; // In project.glsl, offset modes calculate z differently from LNG_LAT mode. // offset modes apply the y adjustment (unitsPerMeter2) when projecting z diff --git a/modules/core/src/transitions/linear-interpolator.ts b/modules/core/src/transitions/linear-interpolator.ts index b064b9a743b..84477c9e0b3 100644 --- a/modules/core/src/transitions/linear-interpolator.ts +++ b/modules/core/src/transitions/linear-interpolator.ts @@ -11,7 +11,7 @@ const DEFAULT_PROPS = ['longitude', 'latitude', 'zoom', 'bearing', 'pitch']; const DEFAULT_REQUIRED_PROPS = ['longitude', 'latitude', 'zoom']; type PropsWithAnchor = { - around?: number[]; + around?: [number, number, number]; aroundPosition?: number[]; [key: string]: any; }; @@ -21,7 +21,7 @@ type PropsWithAnchor = { */ export default class LinearInterpolator extends TransitionInterpolator { opts: { - around?: number[]; + around?: [number, number, number]; makeViewport?: (props: Record) => Viewport; }; @@ -42,7 +42,7 @@ export default class LinearInterpolator extends TransitionInterpolator { extract?: string[]; required?: string[]; }; - around?: number[]; + around?: [number, number, number]; makeViewport?: (props: Record) => Viewport; } = {} ) { diff --git a/modules/core/src/viewports/globe-viewport.ts b/modules/core/src/viewports/globe-viewport.ts index 1d7657dd7e5..1fa011d1502 100644 --- a/modules/core/src/viewports/globe-viewport.ts +++ b/modules/core/src/viewports/globe-viewport.ts @@ -47,7 +47,7 @@ export type GlobeViewportOptions = { /** Camera altitude relative to the viewport height, used to control the FOV. Default `1.5` */ altitude?: number; /* Meter offsets of the viewport center from lng, lat */ - position?: number[]; + position?: [number, number, number]; /** Zoom level */ zoom?: number; /** Use orthographic projection */ @@ -138,10 +138,10 @@ export default class GlobeViewport extends Viewport { getBounds(options: {z?: number} = {}): [number, number, number, number] { const unprojectOption = {targetZ: options.z || 0}; - const left = this.unproject([0, this.height / 2], unprojectOption); - const top = this.unproject([this.width / 2, 0], unprojectOption); - const right = this.unproject([this.width, this.height / 2], unprojectOption); - const bottom = this.unproject([this.width / 2, this.height], unprojectOption); + const left = this.unproject([0, this.height / 2, 0], unprojectOption); + const top = this.unproject([this.width / 2, 0, 0], unprojectOption); + const right = this.unproject([this.width, this.height / 2, 0], unprojectOption); + const bottom = this.unproject([this.width / 2, this.height, 0], unprojectOption); if (right[0] < this.longitude) right[0] += 360; if (left[0] > this.longitude) left[0] -= 360; @@ -155,9 +155,9 @@ export default class GlobeViewport extends Viewport { } unproject( - xyz: number[], + xyz: [number, number, number], {topLeft = true, targetZ}: {topLeft?: boolean; targetZ?: number} = {} - ): number[] { + ): [number, number, number] { const [x, y, z] = xyz; const y2 = topLeft ? y : this.height - y; @@ -190,10 +190,10 @@ export default class GlobeViewport extends Viewport { if (Number.isFinite(z)) { return [X, Y, Z]; } - return Number.isFinite(targetZ) ? [X, Y, targetZ as number] : [X, Y]; + return Number.isFinite(targetZ) ? [X, Y, targetZ as number] : [X, Y, 0]; } - projectPosition(xyz: number[]): [number, number, number] { + projectPosition(xyz: [number, number, number]): [number, number, number] { const [lng, lat, Z = 0] = xyz; const lambda = lng * DEGREES_TO_RADIANS; const phi = lat * DEGREES_TO_RADIANS; @@ -203,7 +203,7 @@ export default class GlobeViewport extends Viewport { return [Math.sin(lambda) * cosPhi * D, -Math.cos(lambda) * cosPhi * D, Math.sin(phi) * D]; } - unprojectPosition(xyz: number[]): [number, number, number] { + unprojectPosition(xyz: [number, number, number]): [number, number, number] { const [x, y, z] = xyz; const D = vec3.len(xyz); const phi = Math.asin(z / D); @@ -215,15 +215,15 @@ export default class GlobeViewport extends Viewport { return [lng, lat, Z]; } - projectFlat(xyz: number[]): [number, number] { - return xyz as [number, number]; + projectFlat(xy: [number, number]): [number, number] { + return xy; } - unprojectFlat(xyz: number[]): [number, number] { - return xyz as [number, number]; + unprojectFlat(xy: [number, number]): [number, number] { + return xy; } - panByPosition(coords: number[], pixel: number[]): GlobeViewportOptions { + panByPosition(coords: number[], pixel: [number, number, number]): GlobeViewportOptions { const fromPosition = this.unproject(pixel); return { longitude: coords[0] - fromPosition[0] + this.longitude, diff --git a/modules/core/src/viewports/orbit-viewport.ts b/modules/core/src/viewports/orbit-viewport.ts index 333f6afaaf4..3c8c159b32d 100644 --- a/modules/core/src/viewports/orbit-viewport.ts +++ b/modules/core/src/viewports/orbit-viewport.ts @@ -136,7 +136,7 @@ export default class OrbitViewport extends Viewport { return [X, Y, Z]; } - panByPosition(coords: number[], pixel: number[]): OrbitViewportOptions { + panByPosition(coords: [number, number, number], pixel: number[]): OrbitViewportOptions { const p0 = this.project(coords); const nextCenter = [ this.width / 2 + p0[0] - pixel[0], diff --git a/modules/core/src/viewports/orthographic-viewport.ts b/modules/core/src/viewports/orthographic-viewport.ts index c97635c339a..96c008fe2fc 100644 --- a/modules/core/src/viewports/orthographic-viewport.ts +++ b/modules/core/src/viewports/orthographic-viewport.ts @@ -60,7 +60,7 @@ export type OrthographicViewportOptions = { /** Viewport height in pixels */ height?: number; /** The world position at the center of the viewport. Default `[0, 0, 0]`. */ - target?: [number, number, number] | [number, number]; + target?: [number, number, number]; /** The zoom level of the viewport. `zoom: 0` maps one unit distance to one pixel on screen, and increasing `zoom` by `1` scales the same object to twice as large. * To apply independent zoom levels to the X and Y axes, supply an array `[zoomX, zoomY]`. Default `0`. */ zoom?: number | [number, number]; @@ -121,24 +121,24 @@ export default class OrthographicViewport extends Viewport { }); } - projectFlat([X, Y]: number[]): [number, number] { + projectFlat([X, Y]: [number, number]): [number, number] { const {unitsPerMeter} = this.distanceScales; return [X * unitsPerMeter[0], Y * unitsPerMeter[1]]; } - unprojectFlat([x, y]: number[]): [number, number] { + unprojectFlat([x, y]: [number, number]): [number, number] { const {metersPerUnit} = this.distanceScales; return [x * metersPerUnit[0], y * metersPerUnit[1]]; } /* Needed by LinearInterpolator */ - panByPosition(coords: number[], pixel: number[]): OrthographicViewportOptions { + panByPosition(coords: [number, number], pixel: number[]): OrthographicViewportOptions { const fromLocation = pixelsToWorld(pixel, this.pixelUnprojectionMatrix); const toLocation = this.projectFlat(coords); const translate = vec2.add([], toLocation, vec2.negate([], fromLocation)); const newCenter = vec2.add([], this.center, translate); - - return {target: this.unprojectFlat(newCenter)}; + const target = this.unprojectFlat(newCenter); + return {target: [target[0], target[1], 0]}; } } diff --git a/modules/core/src/viewports/viewport.ts b/modules/core/src/viewports/viewport.ts index 7d9777b9450..f60725f6536 100644 --- a/modules/core/src/viewports/viewport.ts +++ b/modules/core/src/viewports/viewport.ts @@ -148,7 +148,7 @@ export default class Viewport { distanceScales: DistanceScales; /** scale factors between world space and common space */ scale!: number; /** scale factor, equals 2^zoom */ - center!: number[]; /** viewport center in common space */ + center!: [number, number, number]; /** viewport center in common space */ cameraPosition!: [number, number, number]; /** Camera position in common space */ projectionMatrix!: number[]; viewMatrix!: number[]; @@ -234,22 +234,21 @@ export default class Viewport { /** * Projects xyz (possibly latitude and longitude) to pixel coordinates in window * using viewport projection parameters - * - [longitude, latitude] to [x, y] * - [longitude, latitude, Z] => [x, y, z] * Note: By default, returns top-left coordinates for canvas/SVG type render * - * @param {Array} lngLatZ - [lng, lat] or [lng, lat, Z] + * @param {Array} xyz - [lng, lat, Z] * @param {Object} opts - options * @param {Object} opts.topLeft=true - Whether projected coords are top left * @return {Array} - [x, y] or [x, y, z] in top left coords */ - project(xyz: number[], {topLeft = true}: {topLeft?: boolean} = {}): number[] { + project(xyz: [number, number, number], {topLeft = true}: {topLeft?: boolean} = {}): number[] { const worldPosition = this.projectPosition(xyz); const coord = worldToPixels(worldPosition, this.pixelProjectionMatrix); const [x, y] = coord; const y2 = topLeft ? y : this.height - y; - return xyz.length === 2 ? [x, y2] : [x, y2, coord[2]]; + return [x, y2, coord[2]]; } /** @@ -263,33 +262,37 @@ export default class Viewport { * @return {Array|null} - [lng, lat, Z] or [X, Y, Z] */ unproject( - xyz: number[], + xyz: [number, number, number], {topLeft = true, targetZ}: {topLeft?: boolean; targetZ?: number} = {} - ): number[] { + ): [number, number, number] { const [x, y, z] = xyz; const y2 = topLeft ? y : this.height - y; const targetZWorld = targetZ && targetZ * this.distanceScales.unitsPerMeter[2]; - const coord = pixelsToWorld([x, y2, z], this.pixelUnprojectionMatrix, targetZWorld); + const coord = pixelsToWorld([x, y2, z], this.pixelUnprojectionMatrix, targetZWorld) as [ + number, + number, + number + ]; const [X, Y, Z] = this.unprojectPosition(coord); if (Number.isFinite(z)) { return [X, Y, Z]; } - return Number.isFinite(targetZ) ? [X, Y, targetZ as number] : [X, Y]; + return [X, Y, targetZ as number]; } // NON_LINEAR PROJECTION HOOKS // Used for web meractor projection - projectPosition(xyz: number[]): [number, number, number] { - const [X, Y] = this.projectFlat(xyz); + projectPosition(xyz: [number, number, number]): [number, number, number] { + const [X, Y] = this.projectFlat([xyz[0], xyz[1]]); const Z = (xyz[2] || 0) * this.distanceScales.unitsPerMeter[2]; return [X, Y, Z]; } - unprojectPosition(xyz: number[]): [number, number, number] { - const [X, Y] = this.unprojectFlat(xyz); + unprojectPosition(xyz: [number, number, number]): [number, number, number] { + const [X, Y] = this.unprojectFlat([xyz[0], xyz[1]]); const Z = (xyz[2] || 0) * this.distanceScales.metersPerUnit[2]; return [X, Y, Z]; } @@ -303,16 +306,16 @@ export default class Viewport { * Specifies a point on the sphere to project onto the map. * @return {Array} [x,y] coordinates. */ - projectFlat(xyz: number[]): [number, number] { + projectFlat(xy: [number, number]): [number, number] { if (this.isGeospatial) { // Shader clamps latitude to +-89.9, see /shaderlib/project/project.glsl.js // lngLatToWorld([0, -89.9])[1] = -317.9934163758329 // lngLatToWorld([0, 89.9])[1] = 829.9934163758271 - const result = lngLatToWorld(xyz); + const result = lngLatToWorld(xy); result[1] = clamp(result[1], -318, 830); - return result; + return [result[0], result[1]]; } - return xyz as [number, number]; + return xy; } /** @@ -323,11 +326,11 @@ export default class Viewport { * Has toArray method if you need a GeoJSON Array. * Per cartographic tradition, lat and lon are specified as degrees. */ - unprojectFlat(xyz: number[]): [number, number] { + unprojectFlat(xy: [number, number]): [number, number] { if (this.isGeospatial) { - return worldToLngLat(xyz); + return worldToLngLat(xy); } - return xyz as [number, number]; + return xy; } /** @@ -337,10 +340,10 @@ export default class Viewport { getBounds(options: {z?: number} = {}): [number, number, number, number] { const unprojectOption = {targetZ: options.z || 0}; - const topLeft = this.unproject([0, 0], unprojectOption); - const topRight = this.unproject([this.width, 0], unprojectOption); - const bottomLeft = this.unproject([0, this.height], unprojectOption); - const bottomRight = this.unproject([this.width, this.height], unprojectOption); + const topLeft = this.unproject([0, 0, 0], unprojectOption); + const topRight = this.unproject([this.width, 0, 0], unprojectOption); + const bottomLeft = this.unproject([0, this.height, 0], unprojectOption); + const bottomRight = this.unproject([this.width, this.height, 0], unprojectOption); return [ Math.min(topLeft[0], topRight[0], bottomLeft[0], bottomRight[0]), @@ -431,10 +434,10 @@ export default class Viewport { this.scale = scale; const {position, modelMatrix} = opts; - let meterOffset: number[] = ZERO_VECTOR; + let meterOffset: [number, number, number] = ZERO_VECTOR; if (position) { meterOffset = modelMatrix - ? (new Matrix4(modelMatrix).transformAsVector(position, []) as number[]) + ? (new Matrix4(modelMatrix).transformAsVector(position, []) as [number, number, number]) : position; } @@ -445,7 +448,7 @@ export default class Viewport { this.center = new Vector3(meterOffset) // Convert to pixels in current zoom .scale(this.distanceScales.unitsPerMeter) - .add(center); + .toArray() as [number, number, number]; } else { this.center = this.projectPosition(meterOffset); } diff --git a/modules/core/src/viewports/web-mercator-viewport.ts b/modules/core/src/viewports/web-mercator-viewport.ts index 453894859e2..45ec9b7f328 100644 --- a/modules/core/src/viewports/web-mercator-viewport.ts +++ b/modules/core/src/viewports/web-mercator-viewport.ts @@ -236,22 +236,22 @@ export default class WebMercatorViewport extends Viewport { return this._subViewports; } - projectPosition(xyz: number[]): [number, number, number] { + projectPosition(xyz: [number, number, number]): [number, number, number] { if (this._pseudoMeters) { // Backward compatibility return super.projectPosition(xyz); } - const [X, Y] = this.projectFlat(xyz); + const [X, Y] = this.projectFlat([xyz[0], xyz[1]]); const Z = (xyz[2] || 0) * unitsPerMeter(xyz[1]); return [X, Y, Z]; } - unprojectPosition(xyz: number[]): [number, number, number] { + unprojectPosition(xyz: [number, number, number]): [number, number, number] { if (this._pseudoMeters) { // Backward compatibility return super.unprojectPosition(xyz); } - const [X, Y] = this.unprojectFlat(xyz); + const [X, Y] = this.unprojectFlat([xyz[0], xyz[1]]); const Z = (xyz[2] || 0) / unitsPerMeter(Y); return [X, Y, Z]; } @@ -270,7 +270,7 @@ export default class WebMercatorViewport extends Viewport { return addMetersToLngLat(lngLatZ, xyz); } - panByPosition(coords: number[], pixel: number[]): WebMercatorViewportOptions { + panByPosition(coords: [number, number], pixel: number[]): WebMercatorViewportOptions { const fromLocation = pixelsToWorld(pixel, this.pixelUnprojectionMatrix); const toLocation = this.projectFlat(coords); diff --git a/modules/extensions/src/brushing/shader-module.ts b/modules/extensions/src/brushing/shader-module.ts index d2a487090e8..263d7143ceb 100644 --- a/modules/extensions/src/brushing/shader-module.ts +++ b/modules/extensions/src/brushing/shader-module.ts @@ -129,10 +129,9 @@ export default { radius: brushingRadius, target: TARGET[brushingTarget] || 0, mousePos: mousePosition - ? (viewport.unproject([mousePosition.x - viewport.x, mousePosition.y - viewport.y]) as [ - number, - number - ]) + ? (viewport + .unproject([mousePosition.x - viewport.x, mousePosition.y - viewport.y, 0]) + .slice(0, 2) as [number, number]) : [0, 0] }; }, diff --git a/modules/extensions/src/terrain/terrain-cover.ts b/modules/extensions/src/terrain/terrain-cover.ts index cb39fedfb28..ef27c620047 100644 --- a/modules/extensions/src/terrain/terrain-cover.ts +++ b/modules/extensions/src/terrain/terrain-cover.ts @@ -117,8 +117,16 @@ export class TerrainCover { shouldRedraw = true; this.targetBounds = this.tile.boundingBox; - const bottomLeftCommon = viewport.projectPosition(this.targetBounds[0]); - const topRightCommon = viewport.projectPosition(this.targetBounds[1]); + const bottomLeftCommon = viewport.projectPosition([ + this.targetBounds[0][0], + this.targetBounds[0][1], + this.targetBounds[0][2] || 0 + ]); + const topRightCommon = viewport.projectPosition([ + this.targetBounds[1][0], + this.targetBounds[1][1], + this.targetBounds[1][2] || 0 + ]); this.targetBoundsCommon = [ bottomLeftCommon[0], bottomLeftCommon[1], diff --git a/modules/extensions/src/utils/projection-utils.ts b/modules/extensions/src/utils/projection-utils.ts index 3d8b491ddb5..6ed485bf4dc 100644 --- a/modules/extensions/src/utils/projection-utils.ts +++ b/modules/extensions/src/utils/projection-utils.ts @@ -23,8 +23,14 @@ export function joinLayerBounds( for (const layer of layers) { const layerBounds = layer.getBounds(); if (layerBounds) { - const bottomLeftCommon = layer.projectPosition(layerBounds[0], {viewport, autoOffset: false}); - const topRightCommon = layer.projectPosition(layerBounds[1], {viewport, autoOffset: false}); + const bottomLeftCommon = layer.projectPosition([layerBounds[0][0], layerBounds[0][1], 0], { + viewport, + autoOffset: false + }); + const topRightCommon = layer.projectPosition([layerBounds[1][0], layerBounds[1][1], 0], { + viewport, + autoOffset: false + }); bounds[0] = Math.min(bounds[0], bottomLeftCommon[0]); bounds[1] = Math.min(bounds[1], bottomLeftCommon[1]); @@ -135,8 +141,10 @@ export function getViewportBounds(viewport: Viewport, zRange?: [number, number]) } // Viewport bounds in cartesian coordinates - const viewportBottomLeftCommon = viewport.projectPosition(viewportBoundsWorld.slice(0, 2)); - const viewportTopRightCommon = viewport.projectPosition(viewportBoundsWorld.slice(2, 4)); + const bottomLeft = viewportBoundsWorld.slice(0, 2); + const topRight = viewportBoundsWorld.slice(2, 4); + const viewportBottomLeftCommon = viewport.projectPosition([bottomLeft[0], bottomLeft[1], 0]); + const viewportTopRightCommon = viewport.projectPosition([topRight[0], topRight[1], 0]); return [ viewportBottomLeftCommon[0], viewportBottomLeftCommon[1], diff --git a/modules/geo-layers/src/h3-layers/h3-hexagon-layer.ts b/modules/geo-layers/src/h3-layers/h3-hexagon-layer.ts index 20220c174f1..d720c4d7031 100644 --- a/modules/geo-layers/src/h3-layers/h3-hexagon-layer.ts +++ b/modules/geo-layers/src/h3-layers/h3-hexagon-layer.ts @@ -211,7 +211,7 @@ export default class H3HexagonLayer< const [centerX, centerY] = viewport.projectFlat([centerLng, centerLat]); vertices = vertices.map(p => { - const worldPosition = viewport.projectFlat(p); + const worldPosition = viewport.projectFlat([p[0], p[1]]); return [ (worldPosition[0] - centerX) / unitsPerMeter[0], (worldPosition[1] - centerY) / unitsPerMeter[1] diff --git a/modules/geo-layers/src/tile-3d-layer/tile-3d-layer.ts b/modules/geo-layers/src/tile-3d-layer/tile-3d-layer.ts index 1710e20e09e..f1df582580c 100644 --- a/modules/geo-layers/src/tile-3d-layer/tile-3d-layer.ts +++ b/modules/geo-layers/src/tile-3d-layer/tile-3d-layer.ts @@ -241,7 +241,7 @@ export default class Tile3DLayer exten return; } - // eslint-disable-next-line @typescript-eslint/no-floating-promises + //@ts-expect-error Type 'Vector3' is not assignable to type '[number, number, number]' tileset3d.selectTiles(Object.values(viewports)).then(frameNumber => { const tilesetChanged = this.state.frameNumber !== frameNumber; if (tilesetChanged) { diff --git a/modules/geo-layers/src/tileset-2d/tile-2d-traversal.ts b/modules/geo-layers/src/tileset-2d/tile-2d-traversal.ts index ab3dba4ef55..2d1bde9185d 100644 --- a/modules/geo-layers/src/tileset-2d/tile-2d-traversal.ts +++ b/modules/geo-layers/src/tileset-2d/tile-2d-traversal.ts @@ -70,7 +70,7 @@ class OSMNode { // eslint-disable-next-line complexity update(params: { viewport: Viewport; - project: ((xyz: number[]) => number[]) | null; + project: ((xyz: [number, number, number]) => [number, number, number]) | null; cullingVolume: CullingVolume; elevationBounds: ZRange; minZ: number; @@ -144,7 +144,7 @@ class OSMNode { getBoundingVolume( zRange: ZRange, worldOffset: number, - project: ((xyz: number[]) => number[]) | null + project: ((xyz: [number, number, number]) => [number, number, number]) | null ) { if (project) { // Custom projection @@ -155,7 +155,11 @@ class OSMNode { // Convert from tile-relative coordinates to common space const refPointPositions: number[][] = []; for (const p of refPoints) { - const lngLat: number[] = osmTile2lngLat(this.x + p[0], this.y + p[1], this.z); + const lngLat: [number, number, number] = osmTile2lngLat( + this.x + p[0], + this.y + p[1], + this.z + ); lngLat[2] = zRange[0]; refPointPositions.push(project(lngLat)); @@ -190,7 +194,7 @@ export function getOSMTileIndices( zRange: ZRange | null, bounds?: Bounds ): TileIndex[] { - const project: ((xyz: number[]) => number[]) | null = + const project: ((xyz: [number, number, number]) => [number, number, number]) | null = viewport instanceof _GlobeViewport && viewport.resolution ? // eslint-disable-next-line @typescript-eslint/unbound-method viewport.projectPosition diff --git a/modules/geo-layers/src/tileset-2d/utils.ts b/modules/geo-layers/src/tileset-2d/utils.ts index 4de85da8edd..303e841b864 100644 --- a/modules/geo-layers/src/tileset-2d/utils.ts +++ b/modules/geo-layers/src/tileset-2d/utils.ts @@ -165,10 +165,10 @@ function getCullBoundsInViewport( const unprojectOption = {targetZ: z}; - const topLeft = viewport.unproject([x, y], unprojectOption); - const topRight = viewport.unproject([x + width, y], unprojectOption); - const bottomLeft = viewport.unproject([x, y + height], unprojectOption); - const bottomRight = viewport.unproject([x + width, y + height], unprojectOption); + const topLeft = viewport.unproject([x, y, 0], unprojectOption); + const topRight = viewport.unproject([x + width, y, 0], unprojectOption); + const bottomLeft = viewport.unproject([x, y + height, 0], unprojectOption); + const bottomRight = viewport.unproject([x + width, y + height, 0], unprojectOption); return [ Math.min(topLeft[0], topRight[0], bottomLeft[0], bottomRight[0]), @@ -204,12 +204,12 @@ function getScale(z: number, tileSize: number): number { } // https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Lon..2Flat._to_tile_numbers_2 -export function osmTile2lngLat(x: number, y: number, z: number): [number, number] { +export function osmTile2lngLat(x: number, y: number, z: number): [number, number, number] { const scale = getScale(z, TILE_SIZE); const lng = (x / scale) * 360 - 180; const n = Math.PI - (2 * Math.PI * y) / scale; const lat = (180 / Math.PI) * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n))); - return [lng, lat]; + return [lng, lat, 0]; } function tile2XY(x: number, y: number, z: number, tileSize: number): [number, number] { diff --git a/modules/google-maps/src/utils.ts b/modules/google-maps/src/utils.ts index 34e4911719c..605c0e581d1 100644 --- a/modules/google-maps/src/utils.ts +++ b/modules/google-maps/src/utils.ts @@ -282,7 +282,7 @@ function getEventPixel(event, deck: Deck): {x: number; y: number} { } // event.pixel may not exist when clicking on a POI // https://developers.google.com/maps/documentation/javascript/reference/map#MouseEvent - const point = deck.getViewports()[0].project([event.latLng.lng(), event.latLng.lat()]); + const point = deck.getViewports()[0].project([event.latLng.lng(), event.latLng.lat(), 0]); return { x: point[0], y: point[1] diff --git a/modules/layers/src/solid-polygon-layer/solid-polygon-layer.ts b/modules/layers/src/solid-polygon-layer/solid-polygon-layer.ts index 675a90c6383..704741d48cd 100644 --- a/modules/layers/src/solid-polygon-layer/solid-polygon-layer.ts +++ b/modules/layers/src/solid-polygon-layer/solid-polygon-layer.ts @@ -160,13 +160,16 @@ export default class SolidPolygonLayer coordinateSystem = COORDINATE_SYSTEM.LNGLAT; } - let preproject: ((xy: number[]) => number[]) | undefined; + let preproject: ((xyz: [number, number, number]) => number[]) | undefined; if (coordinateSystem === COORDINATE_SYSTEM.LNGLAT) { if (_full3d) { preproject = viewport.projectPosition.bind(viewport); } else { - preproject = viewport.projectFlat.bind(viewport); + preproject = (xyz: [number, number, number]) => { + const [x, y] = viewport.projectFlat([xyz[0], xyz[1]]); + return [x, y, 0]; + }; } } From a8117e5a7ac5ac0214d913c339ff570e37af3f86 Mon Sep 17 00:00:00 2001 From: charlieforward9 Date: Wed, 8 Jan 2025 14:01:34 -0500 Subject: [PATCH 6/6] fix: coordinate ordering --- docs/upgrade-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/upgrade-guide.md b/docs/upgrade-guide.md index d57e5827214..78d95fe8031 100644 --- a/docs/upgrade-guide.md +++ b/docs/upgrade-guide.md @@ -34,7 +34,7 @@ Breaking changes: ### MapViewState / ViewportOptions -- The `position` property changed from `number[]` to `[number, number, number]` (lat, lng, elevation). +- The `position` property changed from `number[]` to `[number, number, number]` (lng, lat, elevation). ## Upgrading to v9.0