qwc2
Version:
QGIS Web Client
66 lines • 7.98 kB
JavaScript
/**
* 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;