WebMapServiceImageryProvider.js 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768
  1. import defaultValue from "../Core/defaultValue.js";
  2. import defined from "../Core/defined.js";
  3. import DeveloperError from "../Core/DeveloperError.js";
  4. import GeographicTilingScheme from "../Core/GeographicTilingScheme.js";
  5. import Resource from "../Core/Resource.js";
  6. import WebMercatorProjection from "../Core/WebMercatorProjection.js";
  7. import GetFeatureInfoFormat from "./GetFeatureInfoFormat.js";
  8. import TimeDynamicImagery from "./TimeDynamicImagery.js";
  9. import UrlTemplateImageryProvider from "./UrlTemplateImageryProvider.js";
  10. /**
  11. * EPSG codes known to include reverse axis orders, but are not within 4000-5000.
  12. *
  13. * @type {number[]}
  14. */
  15. const includesReverseAxis = [
  16. 3034, // ETRS89-extended / LCC Europe
  17. 3035, // ETRS89-extended / LAEA Europe
  18. 3042, // ETRS89 / UTM zone 30N (N-E)
  19. 3043, // ETRS89 / UTM zone 31N (N-E)
  20. 3044, // ETRS89 / UTM zone 32N (N-E)
  21. ];
  22. /**
  23. * EPSG codes known to not include reverse axis orders, and are within 4000-5000.
  24. *
  25. * @type {number[]}
  26. */
  27. const excludesReverseAxis = [
  28. 4471, // Mayotte
  29. 4559, // French Antilles
  30. ];
  31. /**
  32. * @typedef {Object} WebMapServiceImageryProvider.ConstructorOptions
  33. *
  34. * Initialization options for the WebMapServiceImageryProvider constructor
  35. *
  36. * @property {Resource|String} url The URL of the WMS service. The URL supports the same keywords as the {@link UrlTemplateImageryProvider}.
  37. * @property {String} layers The layers to include, separated by commas.
  38. * @property {Object} [parameters=WebMapServiceImageryProvider.DefaultParameters] Additional parameters to pass to the WMS server in the GetMap URL.
  39. * @property {Object} [getFeatureInfoParameters=WebMapServiceImageryProvider.GetFeatureInfoDefaultParameters] Additional parameters to pass to the WMS server in the GetFeatureInfo URL.
  40. * @property {Boolean} [enablePickFeatures=true] If true, {@link WebMapServiceImageryProvider#pickFeatures} will invoke
  41. * the GetFeatureInfo operation on the WMS server and return the features included in the response. If false,
  42. * {@link WebMapServiceImageryProvider#pickFeatures} will immediately return undefined (indicating no pickable features)
  43. * without communicating with the server. Set this property to false if you know your WMS server does not support
  44. * GetFeatureInfo or if you don't want this provider's features to be pickable. Note that this can be dynamically
  45. * overridden by modifying the WebMapServiceImageryProvider#enablePickFeatures property.
  46. * @property {GetFeatureInfoFormat[]} [getFeatureInfoFormats=WebMapServiceImageryProvider.DefaultGetFeatureInfoFormats] The formats
  47. * in which to try WMS GetFeatureInfo requests.
  48. * @property {Rectangle} [rectangle=Rectangle.MAX_VALUE] The rectangle of the layer.
  49. * @property {TilingScheme} [tilingScheme=new GeographicTilingScheme()] The tiling scheme to use to divide the world into tiles.
  50. * @property {Ellipsoid} [ellipsoid] The ellipsoid. If the tilingScheme is specified,
  51. * this parameter is ignored and the tiling scheme's ellipsoid is used instead. If neither
  52. * parameter is specified, the WGS84 ellipsoid is used.
  53. * @property {Number} [tileWidth=256] The width of each tile in pixels.
  54. * @property {Number} [tileHeight=256] The height of each tile in pixels.
  55. * @property {Number} [minimumLevel=0] The minimum level-of-detail supported by the imagery provider. Take care when
  56. * specifying this that the number of tiles at the minimum level is small, such as four or less. A larger number is
  57. * likely to result in rendering problems.
  58. * @property {Number} [maximumLevel] The maximum level-of-detail supported by the imagery provider, or undefined if there is no limit.
  59. * If not specified, there is no limit.
  60. * @property {String} [crs] CRS specification, for use with WMS specification >= 1.3.0.
  61. * @property {String} [srs] SRS specification, for use with WMS specification 1.1.0 or 1.1.1
  62. * @property {Credit|String} [credit] A credit for the data source, which is displayed on the canvas.
  63. * @property {String|String[]} [subdomains='abc'] The subdomains to use for the <code>{s}</code> placeholder in the URL template.
  64. * If this parameter is a single string, each character in the string is a subdomain. If it is
  65. * an array, each element in the array is a subdomain.
  66. * @property {Clock} [clock] A Clock instance that is used when determining the value for the time dimension. Required when `times` is specified.
  67. * @property {TimeIntervalCollection} [times] TimeIntervalCollection with its data property being an object containing time dynamic dimension and their values.
  68. * @property {Resource|String} [getFeatureInfoUrl] The getFeatureInfo URL of the WMS service. If the property is not defined then we use the property value of url.
  69. */
  70. /**
  71. * Provides tiled imagery hosted by a Web Map Service (WMS) server.
  72. *
  73. * @alias WebMapServiceImageryProvider
  74. * @constructor
  75. *
  76. * @param {WebMapServiceImageryProvider.ConstructorOptions} options Object describing initialization options
  77. *
  78. * @see ArcGisMapServerImageryProvider
  79. * @see BingMapsImageryProvider
  80. * @see GoogleEarthEnterpriseMapsProvider
  81. * @see OpenStreetMapImageryProvider
  82. * @see SingleTileImageryProvider
  83. * @see TileMapServiceImageryProvider
  84. * @see WebMapTileServiceImageryProvider
  85. * @see UrlTemplateImageryProvider
  86. *
  87. * @see {@link http://resources.esri.com/help/9.3/arcgisserver/apis/rest/|ArcGIS Server REST API}
  88. * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}
  89. *
  90. * @example
  91. * const provider = new Cesium.WebMapServiceImageryProvider({
  92. * url : 'https://sampleserver1.arcgisonline.com/ArcGIS/services/Specialty/ESRI_StatesCitiesRivers_USA/MapServer/WMSServer',
  93. * layers : '0',
  94. * proxy: new Cesium.DefaultProxy('/proxy/')
  95. * });
  96. *
  97. * viewer.imageryLayers.addImageryProvider(provider);
  98. */
  99. function WebMapServiceImageryProvider(options) {
  100. options = defaultValue(options, defaultValue.EMPTY_OBJECT);
  101. //>>includeStart('debug', pragmas.debug);
  102. if (!defined(options.url)) {
  103. throw new DeveloperError("options.url is required.");
  104. }
  105. if (!defined(options.layers)) {
  106. throw new DeveloperError("options.layers is required.");
  107. }
  108. //>>includeEnd('debug');
  109. if (defined(options.times) && !defined(options.clock)) {
  110. throw new DeveloperError(
  111. "options.times was specified, so options.clock is required."
  112. );
  113. }
  114. /**
  115. * The default alpha blending value of this provider, with 0.0 representing fully transparent and
  116. * 1.0 representing fully opaque.
  117. *
  118. * @type {Number|undefined}
  119. * @default undefined
  120. */
  121. this.defaultAlpha = undefined;
  122. /**
  123. * The default alpha blending value on the night side of the globe of this provider, with 0.0 representing fully transparent and
  124. * 1.0 representing fully opaque.
  125. *
  126. * @type {Number|undefined}
  127. * @default undefined
  128. */
  129. this.defaultNightAlpha = undefined;
  130. /**
  131. * The default alpha blending value on the day side of the globe of this provider, with 0.0 representing fully transparent and
  132. * 1.0 representing fully opaque.
  133. *
  134. * @type {Number|undefined}
  135. * @default undefined
  136. */
  137. this.defaultDayAlpha = undefined;
  138. /**
  139. * The default brightness of this provider. 1.0 uses the unmodified imagery color. Less than 1.0
  140. * makes the imagery darker while greater than 1.0 makes it brighter.
  141. *
  142. * @type {Number|undefined}
  143. * @default undefined
  144. */
  145. this.defaultBrightness = undefined;
  146. /**
  147. * The default contrast of this provider. 1.0 uses the unmodified imagery color. Less than 1.0 reduces
  148. * the contrast while greater than 1.0 increases it.
  149. *
  150. * @type {Number|undefined}
  151. * @default undefined
  152. */
  153. this.defaultContrast = undefined;
  154. /**
  155. * The default hue of this provider in radians. 0.0 uses the unmodified imagery color.
  156. *
  157. * @type {Number|undefined}
  158. * @default undefined
  159. */
  160. this.defaultHue = undefined;
  161. /**
  162. * The default saturation of this provider. 1.0 uses the unmodified imagery color. Less than 1.0 reduces the
  163. * saturation while greater than 1.0 increases it.
  164. *
  165. * @type {Number|undefined}
  166. * @default undefined
  167. */
  168. this.defaultSaturation = undefined;
  169. /**
  170. * The default gamma correction to apply to this provider. 1.0 uses the unmodified imagery color.
  171. *
  172. * @type {Number|undefined}
  173. * @default undefined
  174. */
  175. this.defaultGamma = undefined;
  176. /**
  177. * The default texture minification filter to apply to this provider.
  178. *
  179. * @type {TextureMinificationFilter}
  180. * @default undefined
  181. */
  182. this.defaultMinificationFilter = undefined;
  183. /**
  184. * The default texture magnification filter to apply to this provider.
  185. *
  186. * @type {TextureMagnificationFilter}
  187. * @default undefined
  188. */
  189. this.defaultMagnificationFilter = undefined;
  190. this._getFeatureInfoUrl = defaultValue(
  191. options.getFeatureInfoUrl,
  192. options.url
  193. );
  194. const resource = Resource.createIfNeeded(options.url);
  195. const pickFeatureResource = Resource.createIfNeeded(this._getFeatureInfoUrl);
  196. resource.setQueryParameters(
  197. WebMapServiceImageryProvider.DefaultParameters,
  198. true
  199. );
  200. pickFeatureResource.setQueryParameters(
  201. WebMapServiceImageryProvider.GetFeatureInfoDefaultParameters,
  202. true
  203. );
  204. if (defined(options.parameters)) {
  205. resource.setQueryParameters(objectToLowercase(options.parameters));
  206. }
  207. if (defined(options.getFeatureInfoParameters)) {
  208. pickFeatureResource.setQueryParameters(
  209. objectToLowercase(options.getFeatureInfoParameters)
  210. );
  211. }
  212. const that = this;
  213. this._reload = undefined;
  214. if (defined(options.times)) {
  215. this._timeDynamicImagery = new TimeDynamicImagery({
  216. clock: options.clock,
  217. times: options.times,
  218. requestImageFunction: function (x, y, level, request, interval) {
  219. return requestImage(that, x, y, level, request, interval);
  220. },
  221. reloadFunction: function () {
  222. if (defined(that._reload)) {
  223. that._reload();
  224. }
  225. },
  226. });
  227. }
  228. const parameters = {};
  229. parameters.layers = options.layers;
  230. parameters.bbox =
  231. "{westProjected},{southProjected},{eastProjected},{northProjected}";
  232. parameters.width = "{width}";
  233. parameters.height = "{height}";
  234. // Use SRS or CRS based on the WMS version.
  235. if (parseFloat(resource.queryParameters.version) >= 1.3) {
  236. // Use CRS with 1.3.0 and going forward.
  237. // For GeographicTilingScheme, use CRS:84 vice EPSG:4326 to specify lon, lat (x, y) ordering for
  238. // bbox requests.
  239. parameters.crs = defaultValue(
  240. options.crs,
  241. options.tilingScheme &&
  242. options.tilingScheme.projection instanceof WebMercatorProjection
  243. ? "EPSG:3857"
  244. : "CRS:84"
  245. );
  246. // The axis order in previous versions of the WMS specifications was to always use easting (x or lon ) and northing (y or
  247. // lat). WMS 1.3.0 specifies that, depending on the particular CRS, the x axis may or may not be oriented West-to-East,
  248. // and the y axis may or may not be oriented South-to-North. The WMS portrayal operation shall account for axis order.
  249. // This affects some of the EPSG codes that were commonly used such as ESPG:4326. The current implementation
  250. // makes sure that coordinates passed to the server (as part of the GetMap BBOX parameter) as well as those advertised
  251. // in the capabilities document reflect the inverse axe orders for EPSG codes between 4000 and 5000.
  252. // - Taken from Section 9.1.3 of https://download.osgeo.org/mapserver/docs/MapServer-56.pdf
  253. const parts = parameters.crs.split(":");
  254. if (parts[0] === "EPSG" && parts.length === 2) {
  255. const code = Number(parts[1]);
  256. if (
  257. (code >= 4000 && code < 5000 && !excludesReverseAxis.includes(code)) ||
  258. includesReverseAxis.includes(code)
  259. ) {
  260. parameters.bbox =
  261. "{southProjected},{westProjected},{northProjected},{eastProjected}";
  262. }
  263. }
  264. } else {
  265. // SRS for WMS 1.1.0 or 1.1.1.
  266. parameters.srs = defaultValue(
  267. options.srs,
  268. options.tilingScheme &&
  269. options.tilingScheme.projection instanceof WebMercatorProjection
  270. ? "EPSG:3857"
  271. : "EPSG:4326"
  272. );
  273. }
  274. resource.setQueryParameters(parameters, true);
  275. pickFeatureResource.setQueryParameters(parameters, true);
  276. const pickFeatureParams = {
  277. query_layers: options.layers,
  278. info_format: "{format}",
  279. };
  280. // use correct pixel coordinate identifier based on version
  281. if (parseFloat(pickFeatureResource.queryParameters.version) >= 1.3) {
  282. pickFeatureParams.i = "{i}";
  283. pickFeatureParams.j = "{j}";
  284. } else {
  285. pickFeatureParams.x = "{i}";
  286. pickFeatureParams.y = "{j}";
  287. }
  288. pickFeatureResource.setQueryParameters(pickFeatureParams, true);
  289. this._resource = resource;
  290. this._pickFeaturesResource = pickFeatureResource;
  291. this._layers = options.layers;
  292. // Let UrlTemplateImageryProvider do the actual URL building.
  293. this._tileProvider = new UrlTemplateImageryProvider({
  294. url: resource,
  295. pickFeaturesUrl: pickFeatureResource,
  296. tilingScheme: defaultValue(
  297. options.tilingScheme,
  298. new GeographicTilingScheme({ ellipsoid: options.ellipsoid })
  299. ),
  300. rectangle: options.rectangle,
  301. tileWidth: options.tileWidth,
  302. tileHeight: options.tileHeight,
  303. minimumLevel: options.minimumLevel,
  304. maximumLevel: options.maximumLevel,
  305. subdomains: options.subdomains,
  306. tileDiscardPolicy: options.tileDiscardPolicy,
  307. credit: options.credit,
  308. getFeatureInfoFormats: defaultValue(
  309. options.getFeatureInfoFormats,
  310. WebMapServiceImageryProvider.DefaultGetFeatureInfoFormats
  311. ),
  312. enablePickFeatures: options.enablePickFeatures,
  313. });
  314. }
  315. function requestImage(imageryProvider, col, row, level, request, interval) {
  316. const dynamicIntervalData = defined(interval) ? interval.data : undefined;
  317. const tileProvider = imageryProvider._tileProvider;
  318. if (defined(dynamicIntervalData)) {
  319. // We set the query parameters within the tile provider, because it is managing the query.
  320. tileProvider._resource.setQueryParameters(dynamicIntervalData);
  321. }
  322. return tileProvider.requestImage(col, row, level, request);
  323. }
  324. function pickFeatures(
  325. imageryProvider,
  326. x,
  327. y,
  328. level,
  329. longitude,
  330. latitude,
  331. interval
  332. ) {
  333. const dynamicIntervalData = defined(interval) ? interval.data : undefined;
  334. const tileProvider = imageryProvider._tileProvider;
  335. if (defined(dynamicIntervalData)) {
  336. // We set the query parameters within the tile provider, because it is managing the query.
  337. tileProvider._pickFeaturesResource.setQueryParameters(dynamicIntervalData);
  338. }
  339. return tileProvider.pickFeatures(x, y, level, longitude, latitude);
  340. }
  341. Object.defineProperties(WebMapServiceImageryProvider.prototype, {
  342. /**
  343. * Gets the URL of the WMS server.
  344. * @memberof WebMapServiceImageryProvider.prototype
  345. * @type {String}
  346. * @readonly
  347. */
  348. url: {
  349. get: function () {
  350. return this._resource._url;
  351. },
  352. },
  353. /**
  354. * Gets the proxy used by this provider.
  355. * @memberof WebMapServiceImageryProvider.prototype
  356. * @type {Proxy}
  357. * @readonly
  358. */
  359. proxy: {
  360. get: function () {
  361. return this._resource.proxy;
  362. },
  363. },
  364. /**
  365. * Gets the names of the WMS layers, separated by commas.
  366. * @memberof WebMapServiceImageryProvider.prototype
  367. * @type {String}
  368. * @readonly
  369. */
  370. layers: {
  371. get: function () {
  372. return this._layers;
  373. },
  374. },
  375. /**
  376. * Gets the width of each tile, in pixels. This function should
  377. * not be called before {@link WebMapServiceImageryProvider#ready} returns true.
  378. * @memberof WebMapServiceImageryProvider.prototype
  379. * @type {Number}
  380. * @readonly
  381. */
  382. tileWidth: {
  383. get: function () {
  384. return this._tileProvider.tileWidth;
  385. },
  386. },
  387. /**
  388. * Gets the height of each tile, in pixels. This function should
  389. * not be called before {@link WebMapServiceImageryProvider#ready} returns true.
  390. * @memberof WebMapServiceImageryProvider.prototype
  391. * @type {Number}
  392. * @readonly
  393. */
  394. tileHeight: {
  395. get: function () {
  396. return this._tileProvider.tileHeight;
  397. },
  398. },
  399. /**
  400. * Gets the maximum level-of-detail that can be requested. This function should
  401. * not be called before {@link WebMapServiceImageryProvider#ready} returns true.
  402. * @memberof WebMapServiceImageryProvider.prototype
  403. * @type {Number|undefined}
  404. * @readonly
  405. */
  406. maximumLevel: {
  407. get: function () {
  408. return this._tileProvider.maximumLevel;
  409. },
  410. },
  411. /**
  412. * Gets the minimum level-of-detail that can be requested. This function should
  413. * not be called before {@link WebMapServiceImageryProvider#ready} returns true.
  414. * @memberof WebMapServiceImageryProvider.prototype
  415. * @type {Number}
  416. * @readonly
  417. */
  418. minimumLevel: {
  419. get: function () {
  420. return this._tileProvider.minimumLevel;
  421. },
  422. },
  423. /**
  424. * Gets the tiling scheme used by this provider. This function should
  425. * not be called before {@link WebMapServiceImageryProvider#ready} returns true.
  426. * @memberof WebMapServiceImageryProvider.prototype
  427. * @type {TilingScheme}
  428. * @readonly
  429. */
  430. tilingScheme: {
  431. get: function () {
  432. return this._tileProvider.tilingScheme;
  433. },
  434. },
  435. /**
  436. * Gets the rectangle, in radians, of the imagery provided by this instance. This function should
  437. * not be called before {@link WebMapServiceImageryProvider#ready} returns true.
  438. * @memberof WebMapServiceImageryProvider.prototype
  439. * @type {Rectangle}
  440. * @readonly
  441. */
  442. rectangle: {
  443. get: function () {
  444. return this._tileProvider.rectangle;
  445. },
  446. },
  447. /**
  448. * Gets the tile discard policy. If not undefined, the discard policy is responsible
  449. * for filtering out "missing" tiles via its shouldDiscardImage function. If this function
  450. * returns undefined, no tiles are filtered. This function should
  451. * not be called before {@link WebMapServiceImageryProvider#ready} returns true.
  452. * @memberof WebMapServiceImageryProvider.prototype
  453. * @type {TileDiscardPolicy}
  454. * @readonly
  455. */
  456. tileDiscardPolicy: {
  457. get: function () {
  458. return this._tileProvider.tileDiscardPolicy;
  459. },
  460. },
  461. /**
  462. * Gets an event that is raised when the imagery provider encounters an asynchronous error. By subscribing
  463. * to the event, you will be notified of the error and can potentially recover from it. Event listeners
  464. * are passed an instance of {@link TileProviderError}.
  465. * @memberof WebMapServiceImageryProvider.prototype
  466. * @type {Event}
  467. * @readonly
  468. */
  469. errorEvent: {
  470. get: function () {
  471. return this._tileProvider.errorEvent;
  472. },
  473. },
  474. /**
  475. * Gets a value indicating whether or not the provider is ready for use.
  476. * @memberof WebMapServiceImageryProvider.prototype
  477. * @type {Boolean}
  478. * @readonly
  479. */
  480. ready: {
  481. get: function () {
  482. return this._tileProvider.ready;
  483. },
  484. },
  485. /**
  486. * Gets a promise that resolves to true when the provider is ready for use.
  487. * @memberof WebMapServiceImageryProvider.prototype
  488. * @type {Promise.<Boolean>}
  489. * @readonly
  490. */
  491. readyPromise: {
  492. get: function () {
  493. return this._tileProvider.readyPromise;
  494. },
  495. },
  496. /**
  497. * Gets the credit to display when this imagery provider is active. Typically this is used to credit
  498. * the source of the imagery. This function should not be called before {@link WebMapServiceImageryProvider#ready} returns true.
  499. * @memberof WebMapServiceImageryProvider.prototype
  500. * @type {Credit}
  501. * @readonly
  502. */
  503. credit: {
  504. get: function () {
  505. return this._tileProvider.credit;
  506. },
  507. },
  508. /**
  509. * Gets a value indicating whether or not the images provided by this imagery provider
  510. * include an alpha channel. If this property is false, an alpha channel, if present, will
  511. * be ignored. If this property is true, any images without an alpha channel will be treated
  512. * as if their alpha is 1.0 everywhere. When this property is false, memory usage
  513. * and texture upload time are reduced.
  514. * @memberof WebMapServiceImageryProvider.prototype
  515. * @type {Boolean}
  516. * @readonly
  517. */
  518. hasAlphaChannel: {
  519. get: function () {
  520. return this._tileProvider.hasAlphaChannel;
  521. },
  522. },
  523. /**
  524. * Gets or sets a value indicating whether feature picking is enabled. If true, {@link WebMapServiceImageryProvider#pickFeatures} will
  525. * invoke the <code>GetFeatureInfo</code> service on the WMS server and attempt to interpret the features included in the response. If false,
  526. * {@link WebMapServiceImageryProvider#pickFeatures} will immediately return undefined (indicating no pickable
  527. * features) without communicating with the server. Set this property to false if you know your data
  528. * source does not support picking features or if you don't want this provider's features to be pickable.
  529. * @memberof WebMapServiceImageryProvider.prototype
  530. * @type {Boolean}
  531. * @default true
  532. */
  533. enablePickFeatures: {
  534. get: function () {
  535. return this._tileProvider.enablePickFeatures;
  536. },
  537. set: function (enablePickFeatures) {
  538. this._tileProvider.enablePickFeatures = enablePickFeatures;
  539. },
  540. },
  541. /**
  542. * Gets or sets a clock that is used to get keep the time used for time dynamic parameters.
  543. * @memberof WebMapServiceImageryProvider.prototype
  544. * @type {Clock}
  545. */
  546. clock: {
  547. get: function () {
  548. return this._timeDynamicImagery.clock;
  549. },
  550. set: function (value) {
  551. this._timeDynamicImagery.clock = value;
  552. },
  553. },
  554. /**
  555. * Gets or sets a time interval collection that is used to get time dynamic parameters. The data of each
  556. * TimeInterval is an object containing the keys and values of the properties that are used during
  557. * tile requests.
  558. * @memberof WebMapServiceImageryProvider.prototype
  559. * @type {TimeIntervalCollection}
  560. */
  561. times: {
  562. get: function () {
  563. return this._timeDynamicImagery.times;
  564. },
  565. set: function (value) {
  566. this._timeDynamicImagery.times = value;
  567. },
  568. },
  569. /**
  570. * Gets the getFeatureInfo URL of the WMS server.
  571. * @memberof WebMapServiceImageryProvider.prototype
  572. * @type {Resource|String}
  573. * @readonly
  574. */
  575. getFeatureInfoUrl: {
  576. get: function () {
  577. return this._getFeatureInfoUrl;
  578. },
  579. },
  580. });
  581. /**
  582. * Gets the credits to be displayed when a given tile is displayed.
  583. *
  584. * @param {Number} x The tile X coordinate.
  585. * @param {Number} y The tile Y coordinate.
  586. * @param {Number} level The tile level;
  587. * @returns {Credit[]} The credits to be displayed when the tile is displayed.
  588. *
  589. * @exception {DeveloperError} <code>getTileCredits</code> must not be called before the imagery provider is ready.
  590. */
  591. WebMapServiceImageryProvider.prototype.getTileCredits = function (x, y, level) {
  592. return this._tileProvider.getTileCredits(x, y, level);
  593. };
  594. /**
  595. * Requests the image for a given tile. This function should
  596. * not be called before {@link WebMapServiceImageryProvider#ready} returns true.
  597. *
  598. * @param {Number} x The tile X coordinate.
  599. * @param {Number} y The tile Y coordinate.
  600. * @param {Number} level The tile level.
  601. * @param {Request} [request] The request object. Intended for internal use only.
  602. * @returns {Promise.<ImageryTypes>|undefined} A promise for the image that will resolve when the image is available, or
  603. * undefined if there are too many active requests to the server, and the request should be retried later.
  604. *
  605. * @exception {DeveloperError} <code>requestImage</code> must not be called before the imagery provider is ready.
  606. */
  607. WebMapServiceImageryProvider.prototype.requestImage = function (
  608. x,
  609. y,
  610. level,
  611. request
  612. ) {
  613. let result;
  614. const timeDynamicImagery = this._timeDynamicImagery;
  615. let currentInterval;
  616. // Try and load from cache
  617. if (defined(timeDynamicImagery)) {
  618. currentInterval = timeDynamicImagery.currentInterval;
  619. result = timeDynamicImagery.getFromCache(x, y, level, request);
  620. }
  621. // Couldn't load from cache
  622. if (!defined(result)) {
  623. result = requestImage(this, x, y, level, request, currentInterval);
  624. }
  625. // If we are approaching an interval, preload this tile in the next interval
  626. if (defined(result) && defined(timeDynamicImagery)) {
  627. timeDynamicImagery.checkApproachingInterval(x, y, level, request);
  628. }
  629. return result;
  630. };
  631. /**
  632. * Asynchronously determines what features, if any, are located at a given longitude and latitude within
  633. * a tile. This function should not be called before {@link ImageryProvider#ready} returns true.
  634. *
  635. * @param {Number} x The tile X coordinate.
  636. * @param {Number} y The tile Y coordinate.
  637. * @param {Number} level The tile level.
  638. * @param {Number} longitude The longitude at which to pick features.
  639. * @param {Number} latitude The latitude at which to pick features.
  640. * @return {Promise.<ImageryLayerFeatureInfo[]>|undefined} A promise for the picked features that will resolve when the asynchronous
  641. * picking completes. The resolved value is an array of {@link ImageryLayerFeatureInfo}
  642. * instances. The array may be empty if no features are found at the given location.
  643. *
  644. * @exception {DeveloperError} <code>pickFeatures</code> must not be called before the imagery provider is ready.
  645. */
  646. WebMapServiceImageryProvider.prototype.pickFeatures = function (
  647. x,
  648. y,
  649. level,
  650. longitude,
  651. latitude
  652. ) {
  653. const timeDynamicImagery = this._timeDynamicImagery;
  654. const currentInterval = defined(timeDynamicImagery)
  655. ? timeDynamicImagery.currentInterval
  656. : undefined;
  657. return pickFeatures(this, x, y, level, longitude, latitude, currentInterval);
  658. };
  659. /**
  660. * The default parameters to include in the WMS URL to obtain images. The values are as follows:
  661. * service=WMS
  662. * version=1.1.1
  663. * request=GetMap
  664. * styles=
  665. * format=image/jpeg
  666. *
  667. * @constant
  668. * @type {Object}
  669. */
  670. WebMapServiceImageryProvider.DefaultParameters = Object.freeze({
  671. service: "WMS",
  672. version: "1.1.1",
  673. request: "GetMap",
  674. styles: "",
  675. format: "image/jpeg",
  676. });
  677. /**
  678. * The default parameters to include in the WMS URL to get feature information. The values are as follows:
  679. * service=WMS
  680. * version=1.1.1
  681. * request=GetFeatureInfo
  682. *
  683. * @constant
  684. * @type {Object}
  685. */
  686. WebMapServiceImageryProvider.GetFeatureInfoDefaultParameters = Object.freeze({
  687. service: "WMS",
  688. version: "1.1.1",
  689. request: "GetFeatureInfo",
  690. });
  691. WebMapServiceImageryProvider.DefaultGetFeatureInfoFormats = Object.freeze([
  692. Object.freeze(new GetFeatureInfoFormat("json", "application/json")),
  693. Object.freeze(new GetFeatureInfoFormat("xml", "text/xml")),
  694. Object.freeze(new GetFeatureInfoFormat("text", "text/html")),
  695. ]);
  696. function objectToLowercase(obj) {
  697. const result = {};
  698. for (const key in obj) {
  699. if (obj.hasOwnProperty(key)) {
  700. result[key.toLowerCase()] = obj[key];
  701. }
  702. }
  703. return result;
  704. }
  705. export default WebMapServiceImageryProvider;