UNPKG

qwc2

Version:
66 lines 7.98 kB
/** * Copyright 2015-2016 GeoSolutions Sas * Copyright 2016-2024 Sourcepole AG * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. */import isEmpty from"lodash.isempty";import ConfigUtils from"./ConfigUtils";import CoordinatesUtils from"./CoordinatesUtils";import{UrlParams}from"./PermaLinkUtils";var DEFAULT_SCREEN_DPI=96;var METERS_PER_UNIT={"m":1,"degrees":111194.87428468118,"ft":0.3048,"us-ft":1200/3937};var hooks={};var MapUtils={GET_PIXEL_FROM_COORDINATES_HOOK:"GET_PIXEL_FROM_COORDINATES_HOOK",GET_COORDINATES_FROM_PIXEL_HOOK:"GET_COORDINATES_FROM_PIXEL_HOOK",GET_SNAPPED_COORDINATES_FROM_PIXEL_HOOK:"GET_SNAPPED_COORDINATES_FROM_PIXEL_HOOK",GET_NATIVE_LAYER:"GET_NATIVE_LAYER",ADD_POINTER_MOVE_LISTENER:"ADD_POINTER_MOVE_LISTENER",REMOVE_POINTER_MOVE_LISTENER:"REMOVE_POINTER_MOVE_LISTENER",GET_MAP:"GET_MAP",registerHook:function registerHook(name,hook){hooks[name]=hook},getHook:function getHook(name){return hooks[name]},/** * @param dpi {number} dot per inch resolution * @return {number} dot per meter resolution */dpi2dpm:function dpi2dpm(dpi){return(dpi||DEFAULT_SCREEN_DPI)*(100/2.54)},/** * @param dpi {number} screen resolution in dots per inch. * @param projection {string} map projection. * @return {number} dots per map unit. */dpi2dpu:function dpi2dpu(dpi,projection){var units=CoordinatesUtils.getUnits(projection);return METERS_PER_UNIT[units]*MapUtils.dpi2dpm(dpi)},/** * Get a list of scales for each zoom level of the Google Mercator. * @param minZoom {number} min zoom level. * @param maxZoom {number} max zoom level. * @return {array} a list of scale for each zoom level in the given interval. */getGoogleMercatorScales:function getGoogleMercatorScales(minZoom,maxZoom){var dpi=arguments.length>2&&arguments[2]!==undefined?arguments[2]:DEFAULT_SCREEN_DPI;// Google mercator params var RADIUS=6378137;var TILE_WIDTH=256;var ZOOM_FACTOR=2;var retval=[];for(var l=minZoom;l<=maxZoom;l++){retval.push(2*Math.PI*RADIUS/(TILE_WIDTH*Math.pow(ZOOM_FACTOR,l)/MapUtils.dpi2dpm(dpi)))}return retval},/** * @param scales {array} list of scales. * @param projection {string} map projection. * @param dpi {number} screen resolution in dots per inch. * @return {array} a list of resolutions corresponding to the given scales, projection and dpi. */getResolutionsForScales:function getResolutionsForScales(scales,projection){var dpi=arguments.length>2&&arguments[2]!==undefined?arguments[2]:DEFAULT_SCREEN_DPI;var dpu=MapUtils.dpi2dpu(dpi,projection);var resolutions=scales.map(function(scale){return scale/dpu});return resolutions},/** * Calculates the best fitting zoom level for the given extent. * * @param extent {Array} [minx, miny, maxx, maxy] * @param resolutions {Array} The list of available map resolutions * @param mapSize {Object} current size of the map. * @param minZoom {number} min zoom level. * @param maxZoom {number} max zoom level. * @param dpi {number} screen resolution in dot per inch. * @return {Number} the zoom level fitting th extent */getZoomForExtent:function getZoomForExtent(extent,resolutions,mapSize,minZoom,maxZoom){var wExtent=extent[2]-extent[0];var hExtent=extent[3]-extent[1];var xResolution=Math.abs(wExtent/mapSize.width);var yResolution=Math.abs(hExtent/mapSize.height);var extentResolution=Math.max(xResolution,yResolution);var zoom=this.computeZoom(resolutions,extentResolution);if(ConfigUtils.getConfigProp("allowFractionalZoom")===true){return Math.max(minZoom,Math.min(zoom,maxZoom))}else{return Math.max(minZoom,Math.min(Math.round(zoom),maxZoom))}},/** * Calculates the extent for the provided center and zoom level * @param center {Array} [x, y] * @param zoom {number} The zoom level * @param resolutions {Array} The list of map resolutions * @param mapSize {Object} The current size of the map */getExtentForCenterAndZoom:function getExtentForCenterAndZoom(center,zoom,resolutions,mapSize){if(ConfigUtils.getConfigProp("allowFractionalZoom")!==true){zoom=Math.round(zoom)}var width=this.computeForZoom(resolutions,zoom)*mapSize.width;var height=this.computeForZoom(resolutions,zoom)*mapSize.height;return[center[0]-0.5*width,center[1]-0.5*height,center[0]+0.5*width,center[1]+0.5*height]},/** * Transform width and height specified in meters to the units of the specified projection * * @param projection {string} projection. * @param center {Array} Center of extent in EPSG:4326 coordinates. * @param width {number} Width in meters. * @param height {number} Height in meters. */transformExtent:function transformExtent(projection,center,width,height){var units=CoordinatesUtils.getUnits(projection);if(units==="ft"){return{width:width/METERS_PER_UNIT.ft,height:height/METERS_PER_UNIT.ft}}else if(units==="us-ft"){return{width:width/METERS_PER_UNIT["us-ft"],height:height/METERS_PER_UNIT["us-ft"]}}else if(units==="degrees"){// https://en.wikipedia.org/wiki/Geographic_coordinate_system#Length_of_a_degree var phi=center[1]/180*Math.PI;var latPerM=111132.92-559.82*Math.cos(2*phi)+1.175*Math.cos(4*phi)-0.0023*Math.cos(6*phi);var lonPerM=111412.84*Math.cos(phi)-93.5*Math.cos(3*phi)+0.118*Math.cos(5*phi);return{width:width/lonPerM,height:height/latPerM}}return{width:width,height:height}},/** * Compute the scale or resolution matching a (possibly fractional) zoom level. * * @param list {Array} List of scales or resolutions. * @param zoomLevel (number) Zoom level (integer or fractional). * @return Scale of resolution matching zoomLevel */computeForZoom:function computeForZoom(list,zoomLevel){if(ConfigUtils.getConfigProp("allowFractionalZoom")!==true){return list[Math.min(list.length-1,Math.round(zoomLevel))]}zoomLevel=Math.max(zoomLevel,0);var upper=Math.ceil(zoomLevel);var lower=Math.floor(zoomLevel);if(upper>=list.length){return list[list.length-1]}var frac=zoomLevel-lower;return list[lower]*(1-frac)+list[upper]*frac},/** * Compute the (possibly fractional) zoom level matching the specified scale or resolution. * * @param list {Array} List of scales or resolutions. * @param value (number) Scale or resolution. * @return Zoom level matching the specified scale or resolution. */computeZoom:function computeZoom(list,value){if(ConfigUtils.getConfigProp("allowFractionalZoom")===true){var index=0;for(var i=1;i<list.length-1;++i){if(value<=list[i]){index=i}}return index+(value-list[index])/(list[index+1]-list[index])}else{var closestVal=Math.abs(value-list[0]);var closestIdx=0;for(var _i=1;_i<list.length;++_i){var currVal=Math.abs(value-list[_i]);if(currVal<closestVal){closestVal=currVal;closestIdx=_i}}return closestIdx}},/** * Convert degrees to radians * @param degrees {number} * @return {number} in radians */degreesToRadians:function degreesToRadians(degrees){var pi=Math.PI;return degrees*(pi/180)},updateMapUrlParams:function updateMapUrlParams(state){var newParams={};var positionFormat=ConfigUtils.getConfigProp("urlPositionFormat");var positionCrs=ConfigUtils.getConfigProp("urlPositionCrs")||state.projection;var prec=CoordinatesUtils.getPrecision(positionCrs);if(positionFormat==="centerAndZoom"){var center=CoordinatesUtils.reproject(state.center,state.projection,positionCrs);var scale=Math.round(MapUtils.computeForZoom(state.scales,state.zoom));Object.assign(newParams,{c:center.map(function(x){return x.toFixed(prec)}).join(","),s:scale})}else{var bounds=CoordinatesUtils.reprojectBbox(state.bbox.bounds,state.projection,positionCrs);Object.assign(newParams,{e:bounds.map(function(x){return x.toFixed(prec)}).join(",")})}if(positionCrs!==state.projection){Object.assign(newParams,{crs:positionCrs})}if(!isEmpty(newParams)){UrlParams.updateParams(newParams)}}};export default MapUtils;