UNPKG

@azure-rest/maps-render

Version:
65 lines 2.56 kB
// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. function clip(n, minValue, maxValue) { return Math.min(Math.max(n, minValue), maxValue); } const MIN_LATITUDE = -85.05112878; const MAX_LATITUDE = 85.05112878; const MIN_LONGITUDE = -180; const MAX_LONGITUDE = 180; /** * Calculates the XY tile coordinates that a coordinate falls into for a specific zoom level. * Reference: https://learn.microsoft.com/en-us/azure/azure-maps/zoom-levels-and-tile-grid?tabs=typescript#tile-math-source-code * * @example * ```ts snippet:ReadmeSampleRequestMapTiles * import { DefaultAzureCredential } from "@azure/identity"; * import MapsRender, { positionToTileXY } from "@azure-rest/maps-render"; * import { createWriteStream } from "node:fs"; * * const credential = new DefaultAzureCredential(); * const client = MapsRender(credential, "<maps-account-client-id>"); * * const zoom = 6; * // Use the helper function `positionToTileXY` to get the tile index from the coordinate. * const { x, y } = positionToTileXY([47.61559, -122.33817], 6, "256"); * const response = await client * .path("/map/tile") * .get({ * queryParameters: { * tilesetId: "microsoft.base.road", * zoom, * x, * y, * }, * }) * .asNodeStream(); * * // Handle the error. * if (!response.body) { * throw Error("No response body"); * } * * response.body.pipe(createWriteStream("tile.png")); * ``` * * @param position - Position coordinate in the format [latitude, longitude]. * @param zoom - Zoom level. * @param tileSize - The size of the tiles in the tile pyramid. * @returns Tile XY coordinates. */ export function positionToTileXY(position, zoom, tileSize) { const latitude = clip(position[0], MIN_LATITUDE, MAX_LATITUDE); const longitude = clip(position[1], MIN_LONGITUDE, MAX_LONGITUDE); const x = (longitude + 180) / 360; const sinLatitude = Math.sin((latitude * Math.PI) / 180); const y = 0.5 - Math.log((1 + sinLatitude) / (1 - sinLatitude)) / (4 * Math.PI); const tileSizeInNum = parseInt(tileSize); // tileSize needed in calculations as in rare cases the multiplying/rounding/dividing can make the difference of a pixel which can result in a completely different tile. const mapSize = Math.ceil(tileSizeInNum * Math.pow(2, zoom)); return { x: Math.floor(clip(x * mapSize + 0.5, 0, mapSize - 1) / tileSizeInNum), y: Math.floor(clip(y * mapSize + 0.5, 0, mapSize - 1) / tileSizeInNum), }; } //# sourceMappingURL=positionToTileXY.js.map