qwc2 2025.10.9 → 2025.10.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (241) hide show
  1. package/actions/display.js +30 -1
  2. package/actions/editing.js +22 -1
  3. package/actions/layerinfo.js +13 -1
  4. package/actions/layers.js +213 -3
  5. package/actions/localConfig.js +58 -1
  6. package/actions/locale.js +21 -1
  7. package/actions/locate.js +26 -1
  8. package/actions/logging.js +10 -1
  9. package/actions/map.js +105 -2
  10. package/actions/measurement.js +12 -1
  11. package/actions/processNotifications.js +37 -1
  12. package/actions/redlining.js +18 -1
  13. package/actions/redliningPick.js +12 -1
  14. package/actions/search.js +12 -1
  15. package/actions/serviceinfo.js +12 -1
  16. package/actions/task.js +55 -3
  17. package/actions/theme.js +339 -19
  18. package/actions/windows.js +164 -5
  19. package/components/AppMenu.js +435 -3
  20. package/components/AttributeForm.js +928 -32
  21. package/components/AttributeTableWidget.js +1105 -13
  22. package/components/AutoEditForm.js +189 -3
  23. package/components/CoordinateDisplayer.js +78 -2
  24. package/components/EditComboField.js +190 -6
  25. package/components/EditUploadField.js +315 -3
  26. package/components/ExportSelection.js +203 -2
  27. package/components/FullscreenSwitcher.js +90 -3
  28. package/components/Icon.js +81 -2
  29. package/components/IdentifyViewer.js +1161 -6
  30. package/components/ImportLayer.js +718 -20
  31. package/components/LayerInfoWindow.js +145 -2
  32. package/components/LinkFeatureForm.js +246 -5
  33. package/components/MapButton.js +88 -2
  34. package/components/MapSelection.js +287 -8
  35. package/components/MessageBar.js +68 -2
  36. package/components/NumericInputWindow.js +359 -2
  37. package/components/PickFeature.js +266 -2
  38. package/components/PluginsContainer.js +227 -8
  39. package/components/PrintSelection.js +620 -49
  40. package/components/ProcessNotifications.js +104 -2
  41. package/components/QtDesignerForm.js +1137 -18
  42. package/components/ResizeableWindow.js +591 -8
  43. package/components/SearchBox.js +1307 -20
  44. package/components/ServiceInfoWindow.js +107 -2
  45. package/components/SideBar.js +204 -4
  46. package/components/StandardApp.js +381 -20
  47. package/components/Swipeable.js +15 -1
  48. package/components/TaskBar.js +85 -2
  49. package/components/ThemeLayersListWindow.js +216 -4
  50. package/components/ThemeList.js +381 -7
  51. package/components/Toolbar.js +106 -2
  52. package/components/WindowManager.js +178 -2
  53. package/components/map/OlLayer.js +257 -6
  54. package/components/map/OlMap.js +405 -5
  55. package/components/map/layers/BingLayer.js +31 -2
  56. package/components/map/layers/GoogleLayer.js +222 -19
  57. package/components/map/layers/GraticuleLayer.js +21 -1
  58. package/components/map/layers/ImageLayer.js +15 -1
  59. package/components/map/layers/MVTLayer.js +52 -2
  60. package/components/map/layers/OSMLayer.js +24 -2
  61. package/components/map/layers/OverlayLayer.js +55 -3
  62. package/components/map/layers/VectorLayer.js +173 -8
  63. package/components/map/layers/WFSLayer.js +220 -6
  64. package/components/map/layers/WMSLayer.js +180 -6
  65. package/components/map/layers/WMTSLayer.js +67 -3
  66. package/components/map/layers/XYZLayer.js +24 -2
  67. package/components/map/layers/index.js +28 -1
  68. package/components/map3d/EditDataset3D.js +190 -3
  69. package/components/map3d/HeightProfile3D.js +402 -3
  70. package/components/map3d/ImportObjects3D.js +162 -2
  71. package/components/map3d/Map3D.js +1304 -38
  72. package/components/map3d/MapControls3D.js +392 -7
  73. package/components/map3d/SearchField3D.js +183 -11
  74. package/components/map3d/View3DSwitcher.js +98 -2
  75. package/components/map3d/drawtool/CreateTool3D.js +174 -4
  76. package/components/map3d/drawtool/EditTool3D.js +590 -6
  77. package/components/map3d/drawtool/NumericInput3D.js +336 -4
  78. package/components/map3d/layers/GeoTIFFLayer3D.js +15 -1
  79. package/components/map3d/layers/VectorLayer3D.js +53 -2
  80. package/components/map3d/layers/WFSLayer3D.js +109 -3
  81. package/components/map3d/layers/WMSLayer3D.js +70 -2
  82. package/components/map3d/layers/WMTSLayer3D.js +27 -3
  83. package/components/map3d/layers/index.js +14 -1
  84. package/components/map3d/utils/FirstPersonControls3D.js +423 -16
  85. package/components/map3d/utils/MiscUtils3D.js +221 -13
  86. package/components/map3d/utils/OrbitControls3D.js +176 -5
  87. package/components/map3d/utils/Tiles3DStyle.js +238 -9
  88. package/components/share/ShareLink.js +54 -2
  89. package/components/share/ShareQRCode.js +62 -2
  90. package/components/share/ShareSocials.js +125 -3
  91. package/components/timeline/FixedTimeline.js +236 -5
  92. package/components/timeline/InfiniteTimeline.js +347 -8
  93. package/components/timeline/TimelineFeaturesSlider.js +439 -5
  94. package/components/widgets/AccordeonWidget.js +96 -2
  95. package/components/widgets/ButtonBar.js +124 -2
  96. package/components/widgets/ColorButton.js +201 -3
  97. package/components/widgets/ComboBox.js +166 -2
  98. package/components/widgets/CopyButton.js +110 -2
  99. package/components/widgets/DateTimeInput.js +100 -3
  100. package/components/widgets/EditableSelect.js +230 -3
  101. package/components/widgets/FileSelector.js +128 -4
  102. package/components/widgets/Input.js +124 -2
  103. package/components/widgets/InputContainer.js +96 -2
  104. package/components/widgets/LayerCatalogWidget.js +219 -3
  105. package/components/widgets/MenuButton.js +157 -1
  106. package/components/widgets/ModalDialog.js +64 -2
  107. package/components/widgets/NavBar.js +119 -2
  108. package/components/widgets/NumberInput.js +226 -4
  109. package/components/widgets/PopupMenu.js +72 -1
  110. package/components/widgets/Primitives.js +6 -1
  111. package/components/widgets/ReCaptchaWidget.js +55 -1
  112. package/components/widgets/SearchWidget.js +255 -2
  113. package/components/widgets/Spinner.js +44 -2
  114. package/components/widgets/SuggestionInput.js +77 -2
  115. package/components/widgets/TextInput.js +308 -2
  116. package/components/widgets/ToggleSwitch.js +85 -2
  117. package/components/widgets/VectorLayerPicker.js +85 -3
  118. package/libs/openlayers.js +225 -5
  119. package/package.json +1 -1
  120. package/plugins/API.js +358 -15
  121. package/plugins/AttributeTable.js +109 -3
  122. package/plugins/Authentication.js +130 -5
  123. package/plugins/BackgroundSwitcher.js +218 -4
  124. package/plugins/Bookmark.js +289 -3
  125. package/plugins/BottomBar.js +298 -4
  126. package/plugins/CookiePopup.js +67 -3
  127. package/plugins/Cyclomedia.js +442 -5
  128. package/plugins/Editing.js +497 -9
  129. package/plugins/FeatureForm.js +366 -4
  130. package/plugins/FeatureSearch.js +458 -3
  131. package/plugins/GeometryDigitizer.js +664 -7
  132. package/plugins/HeightProfile.js +763 -15
  133. package/plugins/Help.js +102 -3
  134. package/plugins/HomeButton.js +80 -3
  135. package/plugins/Identify.js +543 -5
  136. package/plugins/LayerCatalog.js +215 -4
  137. package/plugins/LayerTree.js +1194 -6
  138. package/plugins/LocateButton.js +94 -3
  139. package/plugins/Map.js +320 -16
  140. package/plugins/MapCompare.js +94 -3
  141. package/plugins/MapCopyright.js +127 -5
  142. package/plugins/MapExport.js +613 -20
  143. package/plugins/MapFilter.js +868 -12
  144. package/plugins/MapInfoTooltip.js +277 -3
  145. package/plugins/MapLegend.js +253 -4
  146. package/plugins/MapTip.js +290 -4
  147. package/plugins/Measure.js +220 -4
  148. package/plugins/NewsPopup.js +137 -3
  149. package/plugins/OverviewMap.js +167 -7
  150. package/plugins/Panoramax.js +340 -2
  151. package/plugins/Portal.js +199 -4
  152. package/plugins/Print.js +1231 -15
  153. package/plugins/Redlining.js +750 -6
  154. package/plugins/Reports.js +332 -3
  155. package/plugins/Routing.js +1278 -15
  156. package/plugins/ScratchDrawing.js +173 -5
  157. package/plugins/Settings.js +241 -4
  158. package/plugins/Share.js +198 -3
  159. package/plugins/StartupMarker.js +84 -4
  160. package/plugins/TaskButton.js +88 -3
  161. package/plugins/ThemeSwitcher.js +164 -4
  162. package/plugins/TimeManager.js +971 -10
  163. package/plugins/TopBar.js +300 -7
  164. package/plugins/TourGuide.js +213 -2
  165. package/plugins/ValueTool.js +419 -4
  166. package/plugins/View3D.js +519 -14
  167. package/plugins/ZoomButtons.js +165 -3
  168. package/plugins/map/EditingSupport.js +199 -7
  169. package/plugins/map/LocateSupport.js +260 -4
  170. package/plugins/map/MeasurementSupport.js +216 -8
  171. package/plugins/map/RedliningPickSupport.js +201 -7
  172. package/plugins/map/RedliningSupport.js +726 -17
  173. package/plugins/map/SnapInteraction.js +101 -1
  174. package/plugins/map/SnapSupport.js +210 -2
  175. package/plugins/map/SnappingSupport.js +356 -17
  176. package/plugins/map3d/BackgroundSwitcher3D.js +44 -3
  177. package/plugins/map3d/BottomBar3D.js +118 -3
  178. package/plugins/map3d/Compare3D.js +422 -8
  179. package/plugins/map3d/Draw3D.js +353 -6
  180. package/plugins/map3d/ExportObjects3D.js +393 -18
  181. package/plugins/map3d/HideObjects3D.js +313 -12
  182. package/plugins/map3d/Identify3D.js +283 -12
  183. package/plugins/map3d/LayerTree3D.js +323 -3
  184. package/plugins/map3d/MapCopyright3D.js +128 -5
  185. package/plugins/map3d/MapExport3D.js +590 -10
  186. package/plugins/map3d/MapLight3D.js +553 -6
  187. package/plugins/map3d/Measure3D.js +571 -20
  188. package/plugins/map3d/OverviewMap3D.js +169 -3
  189. package/plugins/map3d/Settings3D.js +73 -3
  190. package/plugins/map3d/TopBar3D.js +207 -9
  191. package/plugins/redlining/RedliningBufferSupport.js +206 -3
  192. package/reducers/display.js +34 -2
  193. package/reducers/editing.js +68 -3
  194. package/reducers/index.js +9 -1
  195. package/reducers/layerinfo.js +26 -2
  196. package/reducers/layers.js +456 -9
  197. package/reducers/localConfig.js +122 -2
  198. package/reducers/locale.js +38 -2
  199. package/reducers/locate.js +40 -2
  200. package/reducers/map.js +176 -5
  201. package/reducers/measurement.js +42 -2
  202. package/reducers/processNotifications.js +49 -2
  203. package/reducers/redlining.js +50 -2
  204. package/reducers/redliningPick.js +27 -2
  205. package/reducers/search.js +20 -1
  206. package/reducers/serviceinfo.js +25 -2
  207. package/reducers/task.js +45 -2
  208. package/reducers/theme.js +51 -2
  209. package/reducers/windows.js +203 -2
  210. package/scripts/dist.sh +1 -1
  211. package/scripts/gen-plugin-docs.js +152 -2
  212. package/scripts/makeIconkit.js +85 -6
  213. package/scripts/themesConfig.js +742 -40
  214. package/scripts/updateTranslations.js +251 -10
  215. package/selectors/searchproviders.js +44 -2
  216. package/stores/StandardStore.js +42 -2
  217. package/utils/ConfigUtils.js +84 -3
  218. package/utils/CoordinatesUtils.js +234 -23
  219. package/utils/DxfUtils.js +237 -11
  220. package/utils/EditingInterface.js +421 -87
  221. package/utils/EditingUtils.js +357 -13
  222. package/utils/ElevationInterface.js +83 -22
  223. package/utils/FeatureStyles.js +429 -5
  224. package/utils/IdentifyUtils.js +443 -7
  225. package/utils/ImageEditor.js +79 -9
  226. package/utils/LayerUtils.js +1516 -50
  227. package/utils/LocaleUtils.js +117 -7
  228. package/utils/MapUtils.js +241 -59
  229. package/utils/MeasureUtils.js +323 -2
  230. package/utils/MiscUtils.js +189 -11
  231. package/utils/PermaLinkUtils.js +429 -6
  232. package/utils/PluginStore.js +27 -1
  233. package/utils/ResourceRegistry.js +15 -1
  234. package/utils/RoutingInterface.js +307 -7
  235. package/utils/SearchProviders.js +722 -19
  236. package/utils/ServiceLayerUtils.js +669 -14
  237. package/utils/Signal.js +32 -2
  238. package/utils/ThemeUtils.js +341 -7
  239. package/utils/VectorLayerUtils.js +589 -15
  240. package/utils/expr_grammar/grammar.js +2239 -2
  241. package/utils/expr_grammar/test.js +65 -3
@@ -5,10 +5,120 @@
5
5
  *
6
6
  * This source code is licensed under the BSD-style license found in the
7
7
  * LICENSE file in the root directory of this source tree.
8
- */import axios from"axios";import deepmerge from"deepmerge";import StandardApp from"../components/StandardApp";import ConfigUtils from"./ConfigUtils";var themeTranslationCache={};var LocaleUtils={loadLocale:function loadLocale(lang,fallbackLangData){return new Promise(function(resolve){var loadLang=null;var availableLanguages=process.env.AvailableLanguages;if(availableLanguages.indexOf(lang)!==-1){// Exact match: lang-REGION
9
- loadLang=lang}else if(availableLanguages.indexOf(lang.slice(0,2))!==-1){// Exact match: lang
10
- loadLang=lang.slice(0,2)}else{// Try match lang-<OTHER_REGION>
11
- loadLang=availableLanguages.find(function(lc){return lc.slice(0,2)===lang.slice(0,2)})}var config={headers:{"Content-Type":"application/json"},data:{}};var translationsPath=ConfigUtils.getTranslationsPath();var resolveLang=function resolveLang(locale,messages){if(ConfigUtils.getConfigProp("loadTranslationOverrides")){axios.get(translationsPath+"/"+locale+"_overrides.json",config).then(function(response){var overrideMessages=response.data.messages;resolve({locale:locale,messages:deepmerge(messages,overrideMessages)})})["catch"](function(){resolve({locale:locale,messages:messages})})}else{resolve({locale:locale,messages:messages})}};if(!loadLang){// eslint-disable-next-line
12
- console.warn("No suitable translations available for "+lang+", defaulting to "+fallbackLangData.locale);resolveLang(fallbackLangData.locale,fallbackLangData.messages)}else{axios.get(translationsPath+"/"+loadLang+".json",config).then(function(response){resolveLang(loadLang,response.data.messages)})["catch"](function(){// eslint-disable-next-line
13
- console.warn("Failed to load translations for "+loadLang+", defaulting to "+fallbackLangData.locale);resolveLang(fallbackLangData.locale,fallbackLangData.messages)})}})},tr:function tr(key){var state=StandardApp.store.getState();var text=key in state.locale.messages?state.locale.messages[key]||state.locale.fallbackMessages[key]||key:key;var args=Array.prototype.slice.call(arguments,1);if(args.length>0){return text.replace(/{(\d+)}/g,function(match,number){return typeof args[number]!=="undefined"?args[number]:match})}else{return text}},// Just a stub to make updateTranslations pick up the msgId
14
- trmsg:function trmsg(key){return key},trWithFallback:function trWithFallback(key,fallback){var state=StandardApp.store.getState();return state.locale.messages[key]||fallback},lang:function lang(){var state=StandardApp.store.getState();return state.locale.current},toLocaleFixed:function toLocaleFixed(number,decimals){if(ConfigUtils.getConfigProp("localeAwareNumbers")){return number.toLocaleString(LocaleUtils.lang(),{minimumFractionDigits:decimals,maximumFractionDigits:decimals})}else{return number.toFixed(decimals)}},loadThemeTranslations:function loadThemeTranslations(serviceUrl){return new Promise(function(resolve){if(serviceUrl in themeTranslationCache){resolve(themeTranslationCache[serviceUrl])}else{axios.get(serviceUrl+"?SERVICE=GetTranslations&LANG="+LocaleUtils.lang()).then(function(response){themeTranslationCache[serviceUrl]=response.data;resolve(response.data)})["catch"](function(e){resolve({})})}})}};export default LocaleUtils;
8
+ */
9
+
10
+ import axios from 'axios';
11
+ import deepmerge from 'deepmerge';
12
+ import StandardApp from '../components/StandardApp';
13
+ import ConfigUtils from './ConfigUtils';
14
+ var themeTranslationCache = {};
15
+ var LocaleUtils = {
16
+ loadLocale: function loadLocale(lang, fallbackLangData) {
17
+ return new Promise(function (resolve) {
18
+ var loadLang = null;
19
+ var availableLanguages = process.env.AvailableLanguages;
20
+ if (availableLanguages.indexOf(lang) !== -1) {
21
+ // Exact match: lang-REGION
22
+ loadLang = lang;
23
+ } else if (availableLanguages.indexOf(lang.slice(0, 2)) !== -1) {
24
+ // Exact match: lang
25
+ loadLang = lang.slice(0, 2);
26
+ } else {
27
+ // Try match lang-<OTHER_REGION>
28
+ loadLang = availableLanguages.find(function (lc) {
29
+ return lc.slice(0, 2) === lang.slice(0, 2);
30
+ });
31
+ }
32
+ var config = {
33
+ headers: {
34
+ 'Content-Type': 'application/json'
35
+ },
36
+ data: {}
37
+ };
38
+ var translationsPath = ConfigUtils.getTranslationsPath();
39
+ var resolveLang = function resolveLang(locale, messages) {
40
+ if (ConfigUtils.getConfigProp("loadTranslationOverrides")) {
41
+ axios.get(translationsPath + '/' + locale + '_overrides.json', config).then(function (response) {
42
+ var overrideMessages = response.data.messages;
43
+ resolve({
44
+ locale: locale,
45
+ messages: deepmerge(messages, overrideMessages)
46
+ });
47
+ })["catch"](function () {
48
+ resolve({
49
+ locale: locale,
50
+ messages: messages
51
+ });
52
+ });
53
+ } else {
54
+ resolve({
55
+ locale: locale,
56
+ messages: messages
57
+ });
58
+ }
59
+ };
60
+ if (!loadLang) {
61
+ // eslint-disable-next-line
62
+ console.warn("No suitable translations available for " + lang + ", defaulting to " + fallbackLangData.locale);
63
+ resolveLang(fallbackLangData.locale, fallbackLangData.messages);
64
+ } else {
65
+ axios.get(translationsPath + '/' + loadLang + '.json', config).then(function (response) {
66
+ resolveLang(loadLang, response.data.messages);
67
+ })["catch"](function () {
68
+ // eslint-disable-next-line
69
+ console.warn("Failed to load translations for " + loadLang + ", defaulting to " + fallbackLangData.locale);
70
+ resolveLang(fallbackLangData.locale, fallbackLangData.messages);
71
+ });
72
+ }
73
+ });
74
+ },
75
+ tr: function tr(key) {
76
+ var state = StandardApp.store.getState();
77
+ var text = key in state.locale.messages ? state.locale.messages[key] || state.locale.fallbackMessages[key] || key : key;
78
+ var args = Array.prototype.slice.call(arguments, 1);
79
+ if (args.length > 0) {
80
+ return text.replace(/{(\d+)}/g, function (match, number) {
81
+ return typeof args[number] !== 'undefined' ? args[number] : match;
82
+ });
83
+ } else {
84
+ return text;
85
+ }
86
+ },
87
+ // Just a stub to make updateTranslations pick up the msgId
88
+ trmsg: function trmsg(key) {
89
+ return key;
90
+ },
91
+ trWithFallback: function trWithFallback(key, fallback) {
92
+ var state = StandardApp.store.getState();
93
+ return state.locale.messages[key] || fallback;
94
+ },
95
+ lang: function lang() {
96
+ var state = StandardApp.store.getState();
97
+ return state.locale.current;
98
+ },
99
+ toLocaleFixed: function toLocaleFixed(number, decimals) {
100
+ if (ConfigUtils.getConfigProp("localeAwareNumbers")) {
101
+ return number.toLocaleString(LocaleUtils.lang(), {
102
+ minimumFractionDigits: decimals,
103
+ maximumFractionDigits: decimals
104
+ });
105
+ } else {
106
+ return number.toFixed(decimals);
107
+ }
108
+ },
109
+ loadThemeTranslations: function loadThemeTranslations(serviceUrl) {
110
+ return new Promise(function (resolve) {
111
+ if (serviceUrl in themeTranslationCache) {
112
+ resolve(themeTranslationCache[serviceUrl]);
113
+ } else {
114
+ axios.get(serviceUrl + "?SERVICE=GetTranslations&LANG=" + LocaleUtils.lang()).then(function (response) {
115
+ themeTranslationCache[serviceUrl] = response.data;
116
+ resolve(response.data);
117
+ })["catch"](function (e) {
118
+ resolve({});
119
+ });
120
+ }
121
+ });
122
+ }
123
+ };
124
+ export default LocaleUtils;
package/utils/MapUtils.js CHANGED
@@ -5,62 +5,244 @@
5
5
  *
6
6
  * This source code is licensed under the BSD-style license found in the
7
7
  * LICENSE file in the root directory of this source tree.
8
- */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]},/**
9
- * @param dpi {number} dot per inch resolution
10
- * @return {number} dot per meter resolution
11
- */dpi2dpm:function dpi2dpm(dpi){return(dpi||DEFAULT_SCREEN_DPI)*(100/2.54)},/**
12
- * @param dpi {number} screen resolution in dots per inch.
13
- * @param projection {string} map projection.
14
- * @return {number} dots per map unit.
15
- */dpi2dpu:function dpi2dpu(dpi,projection){var units=CoordinatesUtils.getUnits(projection);return METERS_PER_UNIT[units]*MapUtils.dpi2dpm(dpi)},/**
16
- * Get a list of scales for each zoom level of the Google Mercator.
17
- * @param minZoom {number} min zoom level.
18
- * @param maxZoom {number} max zoom level.
19
- * @return {array} a list of scale for each zoom level in the given interval.
20
- */getGoogleMercatorScales:function getGoogleMercatorScales(minZoom,maxZoom){var dpi=arguments.length>2&&arguments[2]!==undefined?arguments[2]:DEFAULT_SCREEN_DPI;// Google mercator params
21
- 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},/**
22
- * @param scales {array} list of scales.
23
- * @param projection {string} map projection.
24
- * @param dpi {number} screen resolution in dots per inch.
25
- * @return {array} a list of resolutions corresponding to the given scales, projection and dpi.
26
- */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},/**
27
- * Calculates the best fitting zoom level for the given extent.
28
- *
29
- * @param extent {Array} [minx, miny, maxx, maxy]
30
- * @param resolutions {Array} The list of available map resolutions
31
- * @param mapSize {Object} current size of the map.
32
- * @param minZoom {number} min zoom level.
33
- * @param maxZoom {number} max zoom level.
34
- * @param dpi {number} screen resolution in dot per inch.
35
- * @return {Number} the zoom level fitting th extent
36
- */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))}},/**
37
- * Calculates the extent for the provided center and zoom level
38
- * @param center {Array} [x, y]
39
- * @param zoom {number} The zoom level
40
- * @param resolutions {Array} The list of map resolutions
41
- * @param mapSize {Object} The current size of the map
42
- */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]},/**
43
- * Transform width and height specified in meters to the units of the specified projection
44
- *
45
- * @param projection {string} projection.
46
- * @param center {Array} Center of extent in EPSG:4326 coordinates.
47
- * @param width {number} Width in meters.
48
- * @param height {number} Height in meters.
49
- */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
50
- 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}},/**
51
- * Compute the scale or resolution matching a (possibly fractional) zoom level.
52
- *
53
- * @param list {Array} List of scales or resolutions.
54
- * @param zoomLevel (number) Zoom level (integer or fractional).
55
- * @return Scale of resolution matching zoomLevel
56
- */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},/**
57
- * Compute the (possibly fractional) zoom level matching the specified scale or resolution.
58
- *
59
- * @param list {Array} List of scales or resolutions.
60
- * @param value (number) Scale or resolution.
61
- * @return Zoom level matching the specified scale or resolution.
62
- */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}},/**
63
- * Convert degrees to radians
64
- * @param degrees {number}
65
- * @return {number} in radians
66
- */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;
8
+ */
9
+
10
+ import isEmpty from 'lodash.isempty';
11
+ import ConfigUtils from './ConfigUtils';
12
+ import CoordinatesUtils from './CoordinatesUtils';
13
+ import { UrlParams } from './PermaLinkUtils';
14
+ var DEFAULT_SCREEN_DPI = 96;
15
+ var METERS_PER_UNIT = {
16
+ 'm': 1,
17
+ 'degrees': 111194.87428468118,
18
+ 'ft': 0.3048,
19
+ 'us-ft': 1200 / 3937
20
+ };
21
+ var hooks = {};
22
+ var MapUtils = {
23
+ GET_PIXEL_FROM_COORDINATES_HOOK: 'GET_PIXEL_FROM_COORDINATES_HOOK',
24
+ GET_COORDINATES_FROM_PIXEL_HOOK: 'GET_COORDINATES_FROM_PIXEL_HOOK',
25
+ GET_SNAPPED_COORDINATES_FROM_PIXEL_HOOK: 'GET_SNAPPED_COORDINATES_FROM_PIXEL_HOOK',
26
+ GET_NATIVE_LAYER: 'GET_NATIVE_LAYER',
27
+ ADD_POINTER_MOVE_LISTENER: 'ADD_POINTER_MOVE_LISTENER',
28
+ REMOVE_POINTER_MOVE_LISTENER: 'REMOVE_POINTER_MOVE_LISTENER',
29
+ GET_MAP: 'GET_MAP',
30
+ registerHook: function registerHook(name, hook) {
31
+ hooks[name] = hook;
32
+ },
33
+ getHook: function getHook(name) {
34
+ return hooks[name];
35
+ },
36
+ /**
37
+ * @param dpi {number} dot per inch resolution
38
+ * @return {number} dot per meter resolution
39
+ */
40
+ dpi2dpm: function dpi2dpm(dpi) {
41
+ return (dpi || DEFAULT_SCREEN_DPI) * (100 / 2.54);
42
+ },
43
+ /**
44
+ * @param dpi {number} screen resolution in dots per inch.
45
+ * @param projection {string} map projection.
46
+ * @return {number} dots per map unit.
47
+ */
48
+ dpi2dpu: function dpi2dpu(dpi, projection) {
49
+ var units = CoordinatesUtils.getUnits(projection);
50
+ return METERS_PER_UNIT[units] * MapUtils.dpi2dpm(dpi);
51
+ },
52
+ /**
53
+ * Get a list of scales for each zoom level of the Google Mercator.
54
+ * @param minZoom {number} min zoom level.
55
+ * @param maxZoom {number} max zoom level.
56
+ * @return {array} a list of scale for each zoom level in the given interval.
57
+ */
58
+ getGoogleMercatorScales: function getGoogleMercatorScales(minZoom, maxZoom) {
59
+ var dpi = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : DEFAULT_SCREEN_DPI;
60
+ // Google mercator params
61
+ var RADIUS = 6378137;
62
+ var TILE_WIDTH = 256;
63
+ var ZOOM_FACTOR = 2;
64
+ var retval = [];
65
+ for (var l = minZoom; l <= maxZoom; l++) {
66
+ retval.push(2 * Math.PI * RADIUS / (TILE_WIDTH * Math.pow(ZOOM_FACTOR, l) / MapUtils.dpi2dpm(dpi)));
67
+ }
68
+ return retval;
69
+ },
70
+ /**
71
+ * @param scales {array} list of scales.
72
+ * @param projection {string} map projection.
73
+ * @param dpi {number} screen resolution in dots per inch.
74
+ * @return {array} a list of resolutions corresponding to the given scales, projection and dpi.
75
+ */
76
+ getResolutionsForScales: function getResolutionsForScales(scales, projection) {
77
+ var dpi = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : DEFAULT_SCREEN_DPI;
78
+ var dpu = MapUtils.dpi2dpu(dpi, projection);
79
+ var resolutions = scales.map(function (scale) {
80
+ return scale / dpu;
81
+ });
82
+ return resolutions;
83
+ },
84
+ /**
85
+ * Calculates the best fitting zoom level for the given extent.
86
+ *
87
+ * @param extent {Array} [minx, miny, maxx, maxy]
88
+ * @param resolutions {Array} The list of available map resolutions
89
+ * @param mapSize {Object} current size of the map.
90
+ * @param minZoom {number} min zoom level.
91
+ * @param maxZoom {number} max zoom level.
92
+ * @param dpi {number} screen resolution in dot per inch.
93
+ * @return {Number} the zoom level fitting th extent
94
+ */
95
+ getZoomForExtent: function getZoomForExtent(extent, resolutions, mapSize, minZoom, maxZoom) {
96
+ var wExtent = extent[2] - extent[0];
97
+ var hExtent = extent[3] - extent[1];
98
+ var xResolution = Math.abs(wExtent / mapSize.width);
99
+ var yResolution = Math.abs(hExtent / mapSize.height);
100
+ var extentResolution = Math.max(xResolution, yResolution);
101
+ var zoom = this.computeZoom(resolutions, extentResolution);
102
+ if (ConfigUtils.getConfigProp("allowFractionalZoom") === true) {
103
+ return Math.max(minZoom, Math.min(zoom, maxZoom));
104
+ } else {
105
+ return Math.max(minZoom, Math.min(Math.round(zoom), maxZoom));
106
+ }
107
+ },
108
+ /**
109
+ * Calculates the extent for the provided center and zoom level
110
+ * @param center {Array} [x, y]
111
+ * @param zoom {number} The zoom level
112
+ * @param resolutions {Array} The list of map resolutions
113
+ * @param mapSize {Object} The current size of the map
114
+ */
115
+ getExtentForCenterAndZoom: function getExtentForCenterAndZoom(center, zoom, resolutions, mapSize) {
116
+ if (ConfigUtils.getConfigProp("allowFractionalZoom") !== true) {
117
+ zoom = Math.round(zoom);
118
+ }
119
+ var width = this.computeForZoom(resolutions, zoom) * mapSize.width;
120
+ var height = this.computeForZoom(resolutions, zoom) * mapSize.height;
121
+ return [center[0] - 0.5 * width, center[1] - 0.5 * height, center[0] + 0.5 * width, center[1] + 0.5 * height];
122
+ },
123
+ /**
124
+ * Transform width and height specified in meters to the units of the specified projection
125
+ *
126
+ * @param projection {string} projection.
127
+ * @param center {Array} Center of extent in EPSG:4326 coordinates.
128
+ * @param width {number} Width in meters.
129
+ * @param height {number} Height in meters.
130
+ */
131
+ transformExtent: function transformExtent(projection, center, width, height) {
132
+ var units = CoordinatesUtils.getUnits(projection);
133
+ if (units === 'ft') {
134
+ return {
135
+ width: width / METERS_PER_UNIT.ft,
136
+ height: height / METERS_PER_UNIT.ft
137
+ };
138
+ } else if (units === 'us-ft') {
139
+ return {
140
+ width: width / METERS_PER_UNIT['us-ft'],
141
+ height: height / METERS_PER_UNIT['us-ft']
142
+ };
143
+ } else if (units === 'degrees') {
144
+ // https://en.wikipedia.org/wiki/Geographic_coordinate_system#Length_of_a_degree
145
+ var phi = center[1] / 180 * Math.PI;
146
+ var latPerM = 111132.92 - 559.82 * Math.cos(2 * phi) + 1.175 * Math.cos(4 * phi) - 0.0023 * Math.cos(6 * phi);
147
+ var lonPerM = 111412.84 * Math.cos(phi) - 93.5 * Math.cos(3 * phi) + 0.118 * Math.cos(5 * phi);
148
+ return {
149
+ width: width / lonPerM,
150
+ height: height / latPerM
151
+ };
152
+ }
153
+ return {
154
+ width: width,
155
+ height: height
156
+ };
157
+ },
158
+ /**
159
+ * Compute the scale or resolution matching a (possibly fractional) zoom level.
160
+ *
161
+ * @param list {Array} List of scales or resolutions.
162
+ * @param zoomLevel (number) Zoom level (integer or fractional).
163
+ * @return Scale of resolution matching zoomLevel
164
+ */
165
+ computeForZoom: function computeForZoom(list, zoomLevel) {
166
+ if (ConfigUtils.getConfigProp("allowFractionalZoom") !== true) {
167
+ return list[Math.min(list.length - 1, Math.round(zoomLevel))];
168
+ }
169
+ zoomLevel = Math.max(zoomLevel, 0);
170
+ var upper = Math.ceil(zoomLevel);
171
+ var lower = Math.floor(zoomLevel);
172
+ if (upper >= list.length) {
173
+ return list[list.length - 1];
174
+ }
175
+ var frac = zoomLevel - lower;
176
+ return list[lower] * (1 - frac) + list[upper] * frac;
177
+ },
178
+ /**
179
+ * Compute the (possibly fractional) zoom level matching the specified scale or resolution.
180
+ *
181
+ * @param list {Array} List of scales or resolutions.
182
+ * @param value (number) Scale or resolution.
183
+ * @return Zoom level matching the specified scale or resolution.
184
+ */
185
+ computeZoom: function computeZoom(list, value) {
186
+ if (ConfigUtils.getConfigProp("allowFractionalZoom") === true) {
187
+ var index = 0;
188
+ for (var i = 1; i < list.length - 1; ++i) {
189
+ if (value <= list[i]) {
190
+ index = i;
191
+ }
192
+ }
193
+ return index + (value - list[index]) / (list[index + 1] - list[index]);
194
+ } else {
195
+ var closestVal = Math.abs(value - list[0]);
196
+ var closestIdx = 0;
197
+ for (var _i = 1; _i < list.length; ++_i) {
198
+ var currVal = Math.abs(value - list[_i]);
199
+ if (currVal < closestVal) {
200
+ closestVal = currVal;
201
+ closestIdx = _i;
202
+ }
203
+ }
204
+ return closestIdx;
205
+ }
206
+ },
207
+ /**
208
+ * Convert degrees to radians
209
+ * @param degrees {number}
210
+ * @return {number} in radians
211
+ */
212
+ degreesToRadians: function degreesToRadians(degrees) {
213
+ var pi = Math.PI;
214
+ return degrees * (pi / 180);
215
+ },
216
+ updateMapUrlParams: function updateMapUrlParams(state) {
217
+ var newParams = {};
218
+ var positionFormat = ConfigUtils.getConfigProp("urlPositionFormat");
219
+ var positionCrs = ConfigUtils.getConfigProp("urlPositionCrs") || state.projection;
220
+ var prec = CoordinatesUtils.getPrecision(positionCrs);
221
+ if (positionFormat === "centerAndZoom") {
222
+ var center = CoordinatesUtils.reproject(state.center, state.projection, positionCrs);
223
+ var scale = Math.round(MapUtils.computeForZoom(state.scales, state.zoom));
224
+ Object.assign(newParams, {
225
+ c: center.map(function (x) {
226
+ return x.toFixed(prec);
227
+ }).join(","),
228
+ s: scale
229
+ });
230
+ } else {
231
+ var bounds = CoordinatesUtils.reprojectBbox(state.bbox.bounds, state.projection, positionCrs);
232
+ Object.assign(newParams, {
233
+ e: bounds.map(function (x) {
234
+ return x.toFixed(prec);
235
+ }).join(",")
236
+ });
237
+ }
238
+ if (positionCrs !== state.projection) {
239
+ Object.assign(newParams, {
240
+ crs: positionCrs
241
+ });
242
+ }
243
+ if (!isEmpty(newParams)) {
244
+ UrlParams.updateParams(newParams);
245
+ }
246
+ }
247
+ };
248
+ export default MapUtils;