智慧水务管理系统 - 精河县供水工程综合管理平台

UrlTemplateImageryProvider.js 36KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989
  1. import Cartesian2 from "../Core/Cartesian2.js";
  2. import Cartesian3 from "../Core/Cartesian3.js";
  3. import Cartographic from "../Core/Cartographic.js";
  4. import Check from "../Core/Check.js";
  5. import combine from "../Core/combine.js";
  6. import Credit from "../Core/Credit.js";
  7. import Frozen from "../Core/Frozen.js";
  8. import defined from "../Core/defined.js";
  9. import Event from "../Core/Event.js";
  10. import GeographicProjection from "../Core/GeographicProjection.js";
  11. import CesiumMath from "../Core/Math.js";
  12. import Rectangle from "../Core/Rectangle.js";
  13. import Resource from "../Core/Resource.js";
  14. import WebMercatorTilingScheme from "../Core/WebMercatorTilingScheme.js";
  15. import ImageryProvider from "./ImageryProvider.js";
  16. const templateRegex = /{[^}]+}/g;
  17. const tags = {
  18. x: xTag,
  19. y: yTag,
  20. z: zTag,
  21. s: sTag,
  22. reverseX: reverseXTag,
  23. reverseY: reverseYTag,
  24. reverseZ: reverseZTag,
  25. westDegrees: westDegreesTag,
  26. southDegrees: southDegreesTag,
  27. eastDegrees: eastDegreesTag,
  28. northDegrees: northDegreesTag,
  29. westProjected: westProjectedTag,
  30. southProjected: southProjectedTag,
  31. eastProjected: eastProjectedTag,
  32. northProjected: northProjectedTag,
  33. width: widthTag,
  34. height: heightTag,
  35. };
  36. const pickFeaturesTags = combine(tags, {
  37. i: iTag,
  38. j: jTag,
  39. reverseI: reverseITag,
  40. reverseJ: reverseJTag,
  41. longitudeDegrees: longitudeDegreesTag,
  42. latitudeDegrees: latitudeDegreesTag,
  43. longitudeProjected: longitudeProjectedTag,
  44. latitudeProjected: latitudeProjectedTag,
  45. format: formatTag,
  46. });
  47. /**
  48. * @typedef {object} UrlTemplateImageryProvider.ConstructorOptions
  49. *
  50. * Initialization options for the UrlTemplateImageryProvider constructor
  51. *
  52. * @property {Resource|string} url The URL template to use to request tiles. It has the following keywords:
  53. * <ul>
  54. * <li><code>{z}</code>: The level of the tile in the tiling scheme. Level zero is the root of the quadtree pyramid.</li>
  55. * <li><code>{x}</code>: The tile X coordinate in the tiling scheme, where 0 is the Westernmost tile.</li>
  56. * <li><code>{y}</code>: The tile Y coordinate in the tiling scheme, where 0 is the Northernmost tile.</li>
  57. * <li><code>{s}</code>: One of the available subdomains, used to overcome browser limits on the number of simultaneous requests per host.</li>
  58. * <li><code>{reverseX}</code>: The tile X coordinate in the tiling scheme, where 0 is the Easternmost tile.</li>
  59. * <li><code>{reverseY}</code>: The tile Y coordinate in the tiling scheme, where 0 is the Southernmost tile.</li>
  60. * <li><code>{reverseZ}</code>: The level of the tile in the tiling scheme, where level zero is the maximum level of the quadtree pyramid. In order to use reverseZ, maximumLevel must be defined.</li>
  61. * <li><code>{westDegrees}</code>: The Western edge of the tile in geodetic degrees.</li>
  62. * <li><code>{southDegrees}</code>: The Southern edge of the tile in geodetic degrees.</li>
  63. * <li><code>{eastDegrees}</code>: The Eastern edge of the tile in geodetic degrees.</li>
  64. * <li><code>{northDegrees}</code>: The Northern edge of the tile in geodetic degrees.</li>
  65. * <li><code>{westProjected}</code>: The Western edge of the tile in projected coordinates of the tiling scheme.</li>
  66. * <li><code>{southProjected}</code>: The Southern edge of the tile in projected coordinates of the tiling scheme.</li>
  67. * <li><code>{eastProjected}</code>: The Eastern edge of the tile in projected coordinates of the tiling scheme.</li>
  68. * <li><code>{northProjected}</code>: The Northern edge of the tile in projected coordinates of the tiling scheme.</li>
  69. * <li><code>{width}</code>: The width of each tile in pixels.</li>
  70. * <li><code>{height}</code>: The height of each tile in pixels.</li>
  71. * </ul>
  72. * @property {Resource|string} [pickFeaturesUrl] The URL template to use to pick features. If this property is not specified,
  73. * {@link UrlTemplateImageryProvider#pickFeatures} will immediately returned undefined, indicating no
  74. * features picked. The URL template supports all of the keywords supported by the <code>url</code>
  75. * parameter, plus the following:
  76. * <ul>
  77. * <li><code>{i}</code>: The pixel column (horizontal coordinate) of the picked position, where the Westernmost pixel is 0.</li>
  78. * <li><code>{j}</code>: The pixel row (vertical coordinate) of the picked position, where the Northernmost pixel is 0.</li>
  79. * <li><code>{reverseI}</code>: The pixel column (horizontal coordinate) of the picked position, where the Easternmost pixel is 0.</li>
  80. * <li><code>{reverseJ}</code>: The pixel row (vertical coordinate) of the picked position, where the Southernmost pixel is 0.</li>
  81. * <li><code>{longitudeDegrees}</code>: The longitude of the picked position in degrees.</li>
  82. * <li><code>{latitudeDegrees}</code>: The latitude of the picked position in degrees.</li>
  83. * <li><code>{longitudeProjected}</code>: The longitude of the picked position in the projected coordinates of the tiling scheme.</li>
  84. * <li><code>{latitudeProjected}</code>: The latitude of the picked position in the projected coordinates of the tiling scheme.</li>
  85. * <li><code>{format}</code>: The format in which to get feature information, as specified in the {@link GetFeatureInfoFormat}.</li>
  86. * </ul>
  87. * @property {object} [urlSchemeZeroPadding] Gets the URL scheme zero padding for each tile coordinate. The format is '000' where
  88. * each coordinate will be padded on the left with zeros to match the width of the passed string of zeros. e.g. Setting:
  89. * urlSchemeZeroPadding : { '{x}' : '0000'}
  90. * will cause an 'x' value of 12 to return the string '0012' for {x} in the generated URL.
  91. * It the passed object has the following keywords:
  92. * <ul>
  93. * <li> <code>{z}</code>: The zero padding for the level of the tile in the tiling scheme.</li>
  94. * <li> <code>{x}</code>: The zero padding for the tile X coordinate in the tiling scheme.</li>
  95. * <li> <code>{y}</code>: The zero padding for the the tile Y coordinate in the tiling scheme.</li>
  96. * <li> <code>{reverseX}</code>: The zero padding for the tile reverseX coordinate in the tiling scheme.</li>
  97. * <li> <code>{reverseY}</code>: The zero padding for the tile reverseY coordinate in the tiling scheme.</li>
  98. * <li> <code>{reverseZ}</code>: The zero padding for the reverseZ coordinate of the tile in the tiling scheme.</li>
  99. * </ul>
  100. * @property {string|string[]} [subdomains='abc'] The subdomains to use for the <code>{s}</code> placeholder in the URL template.
  101. * If this parameter is a single string, each character in the string is a subdomain. If it is
  102. * an array, each element in the array is a subdomain.
  103. * @property {Credit|string} [credit=''] A credit for the data source, which is displayed on the canvas.
  104. * @property {number} [minimumLevel=0] The minimum level-of-detail supported by the imagery provider. Take care when specifying
  105. * this that the number of tiles at the minimum level is small, such as four or less. A larger number is likely
  106. * to result in rendering problems.
  107. * @property {number} [maximumLevel] The maximum level-of-detail supported by the imagery provider, or undefined if there is no limit.
  108. * @property {Rectangle} [rectangle=Rectangle.MAX_VALUE] The rectangle, in radians, covered by the image.
  109. * @property {TilingScheme} [tilingScheme=WebMercatorTilingScheme] The tiling scheme specifying how the ellipsoidal
  110. * surface is broken into tiles. If this parameter is not provided, a {@link WebMercatorTilingScheme}
  111. * is used.
  112. * @property {Ellipsoid} [ellipsoid] The ellipsoid. If the tilingScheme is specified,
  113. * this parameter is ignored and the tiling scheme's ellipsoid is used instead. If neither
  114. * parameter is specified, the WGS84 ellipsoid is used.
  115. * @property {number} [tileWidth=256] Pixel width of image tiles.
  116. * @property {number} [tileHeight=256] Pixel height of image tiles.
  117. * @property {boolean} [hasAlphaChannel=true] true if the images provided by this imagery provider
  118. * include an alpha channel; otherwise, false. If this property is false, an alpha channel, if
  119. * present, will be ignored. If this property is true, any images without an alpha channel will
  120. * be treated as if their alpha is 1.0 everywhere. When this property is false, memory usage
  121. * and texture upload time are potentially reduced.
  122. * @property {GetFeatureInfoFormat[]} [getFeatureInfoFormats] The formats in which to get feature information at a
  123. * specific location when {@link UrlTemplateImageryProvider#pickFeatures} is invoked. If this
  124. * parameter is not specified, feature picking is disabled.
  125. * @property {boolean} [enablePickFeatures=true] If true, {@link UrlTemplateImageryProvider#pickFeatures} will
  126. * request the <code>pickFeaturesUrl</code> and attempt to interpret the features included in the response. If false,
  127. * {@link UrlTemplateImageryProvider#pickFeatures} will immediately return undefined (indicating no pickable
  128. * features) without communicating with the server. Set this property to false if you know your data
  129. * source does not support picking features or if you don't want this provider's features to be pickable. Note
  130. * that this can be dynamically overridden by modifying the {@link UriTemplateImageryProvider#enablePickFeatures}
  131. * property.
  132. * @property {TileDiscardPolicy} [tileDiscardPolicy] A policy for discarding tile images according to some criteria
  133. * @property {object} [customTags] Allow to replace custom keywords in the URL template. The object must have strings as keys and functions as values.
  134. */
  135. /**
  136. * Provides imagery by requesting tiles using a specified URL template.
  137. *
  138. * @alias UrlTemplateImageryProvider
  139. * @constructor
  140. *
  141. * @param {UrlTemplateImageryProvider.ConstructorOptions} options Object describing initialization options
  142. *
  143. * @example
  144. * // Access Natural Earth II imagery, which uses a TMS tiling scheme and Geographic (EPSG:4326) project
  145. * const tms = new Cesium.UrlTemplateImageryProvider({
  146. * url : Cesium.buildModuleUrl('Assets/Textures/NaturalEarthII') + '/{z}/{x}/{reverseY}.jpg',
  147. * tilingScheme : new Cesium.GeographicTilingScheme(),
  148. * maximumLevel : 5
  149. * });
  150. * // Access the CartoDB Positron basemap, which uses an OpenStreetMap-like tiling scheme.
  151. * const positron = new Cesium.UrlTemplateImageryProvider({
  152. * url : 'http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png',
  153. * credit : 'Map tiles by CartoDB, under CC BY 3.0. Data by OpenStreetMap, under ODbL.'
  154. * });
  155. * // Access a Web Map Service (WMS) server.
  156. * const wms = new Cesium.UrlTemplateImageryProvider({
  157. * url : 'https://services.ga.gov.au/gis/services/NM_Hydrology_and_Marine_Points/MapServer/WMSServer?' +
  158. * 'tiled=true&transparent=true&format=image%2Fpng&exceptions=application%2Fvnd.ogc.se_xml&' +
  159. * 'styles=&service=WMS&version=1.3.0&request=GetMap&' +
  160. * 'layers=Bores&crs=EPSG%3A3857&' +
  161. * 'bbox={westProjected}%2C{southProjected}%2C{eastProjected}%2C{northProjected}&' +
  162. * 'width=256&height=256',
  163. * rectangle : Cesium.Rectangle.fromDegrees(95.0, -55.0, 170.0, -1.0) // From GetCapabilities EX_GeographicBoundingBox
  164. * });
  165. * // Using custom tags in your template url.
  166. * const custom = new Cesium.UrlTemplateImageryProvider({
  167. * url : 'https://yoururl/{Time}/{z}/{y}/{x}.png',
  168. * customTags : {
  169. * Time: function(imageryProvider, x, y, level) {
  170. * return '20171231'
  171. * }
  172. * }
  173. * });
  174. *
  175. * @see ArcGisMapServerImageryProvider
  176. * @see BingMapsImageryProvider
  177. * @see GoogleEarthEnterpriseMapsProvider
  178. * @see OpenStreetMapImageryProvider
  179. * @see SingleTileImageryProvider
  180. * @see TileMapServiceImageryProvider
  181. * @see WebMapServiceImageryProvider
  182. * @see WebMapTileServiceImageryProvider
  183. */
  184. function UrlTemplateImageryProvider(options) {
  185. options = options ?? Frozen.EMPTY_OBJECT;
  186. this._errorEvent = new Event();
  187. //>>includeStart('debug', pragmas.debug);
  188. Check.defined("options.url", options.url);
  189. //>>includeEnd('debug');
  190. const resource = Resource.createIfNeeded(options.url);
  191. const pickFeaturesResource = Resource.createIfNeeded(options.pickFeaturesUrl);
  192. this._resource = resource;
  193. this._urlSchemeZeroPadding = options.urlSchemeZeroPadding;
  194. this._getFeatureInfoFormats = options.getFeatureInfoFormats;
  195. this._pickFeaturesResource = pickFeaturesResource;
  196. let subdomains = options.subdomains;
  197. if (Array.isArray(subdomains)) {
  198. subdomains = subdomains.slice();
  199. } else if (defined(subdomains) && subdomains.length > 0) {
  200. subdomains = subdomains.split("");
  201. } else {
  202. subdomains = ["a", "b", "c"];
  203. }
  204. this._subdomains = subdomains;
  205. this._tileWidth = options.tileWidth ?? 256;
  206. this._tileHeight = options.tileHeight ?? 256;
  207. this._minimumLevel = options.minimumLevel ?? 0;
  208. this._maximumLevel = options.maximumLevel;
  209. this._tilingScheme =
  210. options.tilingScheme ??
  211. new WebMercatorTilingScheme({ ellipsoid: options.ellipsoid });
  212. this._rectangle = options.rectangle ?? this._tilingScheme.rectangle;
  213. this._rectangle = Rectangle.intersection(
  214. this._rectangle,
  215. this._tilingScheme.rectangle,
  216. );
  217. this._tileDiscardPolicy = options.tileDiscardPolicy;
  218. let credit = options.credit;
  219. if (typeof credit === "string") {
  220. credit = new Credit(credit);
  221. }
  222. this._credit = credit;
  223. this._hasAlphaChannel = options.hasAlphaChannel ?? true;
  224. const customTags = options.customTags;
  225. const allTags = combine(tags, customTags);
  226. const allPickFeaturesTags = combine(pickFeaturesTags, customTags);
  227. this._tags = allTags;
  228. this._pickFeaturesTags = allPickFeaturesTags;
  229. this._defaultAlpha = undefined;
  230. this._defaultNightAlpha = undefined;
  231. this._defaultDayAlpha = undefined;
  232. this._defaultBrightness = undefined;
  233. this._defaultContrast = undefined;
  234. this._defaultHue = undefined;
  235. this._defaultSaturation = undefined;
  236. this._defaultGamma = undefined;
  237. this._defaultMinificationFilter = undefined;
  238. this._defaultMagnificationFilter = undefined;
  239. /**
  240. * Gets or sets a value indicating whether feature picking is enabled. If true, {@link UrlTemplateImageryProvider#pickFeatures} will
  241. * request the <code>options.pickFeaturesUrl</code> and attempt to interpret the features included in the response. If false,
  242. * {@link UrlTemplateImageryProvider#pickFeatures} will immediately return undefined (indicating no pickable
  243. * features) without communicating with the server. Set this property to false if you know your data
  244. * source does not support picking features or if you don't want this provider's features to be pickable.
  245. * @type {boolean}
  246. * @default true
  247. */
  248. this.enablePickFeatures = options.enablePickFeatures ?? true;
  249. }
  250. Object.defineProperties(UrlTemplateImageryProvider.prototype, {
  251. /**
  252. * Gets the URL template to use to request tiles. It has the following keywords:
  253. * <ul>
  254. * <li> <code>{z}</code>: The level of the tile in the tiling scheme. Level zero is the root of the quadtree pyramid.</li>
  255. * <li> <code>{x}</code>: The tile X coordinate in the tiling scheme, where 0 is the Westernmost tile.</li>
  256. * <li> <code>{y}</code>: The tile Y coordinate in the tiling scheme, where 0 is the Northernmost tile.</li>
  257. * <li> <code>{s}</code>: One of the available subdomains, used to overcome browser limits on the number of simultaneous requests per host.</li>
  258. * <li> <code>{reverseX}</code>: The tile X coordinate in the tiling scheme, where 0 is the Easternmost tile.</li>
  259. * <li> <code>{reverseY}</code>: The tile Y coordinate in the tiling scheme, where 0 is the Southernmost tile.</li>
  260. * <li> <code>{reverseZ}</code>: The level of the tile in the tiling scheme, where level zero is the maximum level of the quadtree pyramid. In order to use reverseZ, maximumLevel must be defined.</li>
  261. * <li> <code>{westDegrees}</code>: The Western edge of the tile in geodetic degrees.</li>
  262. * <li> <code>{southDegrees}</code>: The Southern edge of the tile in geodetic degrees.</li>
  263. * <li> <code>{eastDegrees}</code>: The Eastern edge of the tile in geodetic degrees.</li>
  264. * <li> <code>{northDegrees}</code>: The Northern edge of the tile in geodetic degrees.</li>
  265. * <li> <code>{westProjected}</code>: The Western edge of the tile in projected coordinates of the tiling scheme.</li>
  266. * <li> <code>{southProjected}</code>: The Southern edge of the tile in projected coordinates of the tiling scheme.</li>
  267. * <li> <code>{eastProjected}</code>: The Eastern edge of the tile in projected coordinates of the tiling scheme.</li>
  268. * <li> <code>{northProjected}</code>: The Northern edge of the tile in projected coordinates of the tiling scheme.</li>
  269. * <li> <code>{width}</code>: The width of each tile in pixels.</li>
  270. * <li> <code>{height}</code>: The height of each tile in pixels.</li>
  271. * </ul>
  272. * @memberof UrlTemplateImageryProvider.prototype
  273. * @type {string}
  274. * @readonly
  275. */
  276. url: {
  277. get: function () {
  278. return this._resource.url;
  279. },
  280. },
  281. /**
  282. * Gets the URL scheme zero padding for each tile coordinate. The format is '000' where each coordinate will be padded on
  283. * the left with zeros to match the width of the passed string of zeros. e.g. Setting:
  284. * urlSchemeZeroPadding : { '{x}' : '0000'}
  285. * will cause an 'x' value of 12 to return the string '0012' for {x} in the generated URL.
  286. * It has the following keywords:
  287. * <ul>
  288. * <li> <code>{z}</code>: The zero padding for the level of the tile in the tiling scheme.</li>
  289. * <li> <code>{x}</code>: The zero padding for the tile X coordinate in the tiling scheme.</li>
  290. * <li> <code>{y}</code>: The zero padding for the the tile Y coordinate in the tiling scheme.</li>
  291. * <li> <code>{reverseX}</code>: The zero padding for the tile reverseX coordinate in the tiling scheme.</li>
  292. * <li> <code>{reverseY}</code>: The zero padding for the tile reverseY coordinate in the tiling scheme.</li>
  293. * <li> <code>{reverseZ}</code>: The zero padding for the reverseZ coordinate of the tile in the tiling scheme.</li>
  294. * </ul>
  295. * @memberof UrlTemplateImageryProvider.prototype
  296. * @type {object}
  297. * @readonly
  298. */
  299. urlSchemeZeroPadding: {
  300. get: function () {
  301. return this._urlSchemeZeroPadding;
  302. },
  303. },
  304. /**
  305. * Gets the URL template to use to use to pick features. If this property is not specified,
  306. * {@link UrlTemplateImageryProvider#pickFeatures} will immediately return undefined, indicating no
  307. * features picked. The URL template supports all of the keywords supported by the
  308. * {@link UrlTemplateImageryProvider#url} property, plus the following:
  309. * <ul>
  310. * <li><code>{i}</code>: The pixel column (horizontal coordinate) of the picked position, where the Westernmost pixel is 0.</li>
  311. * <li><code>{j}</code>: The pixel row (vertical coordinate) of the picked position, where the Northernmost pixel is 0.</li>
  312. * <li><code>{reverseI}</code>: The pixel column (horizontal coordinate) of the picked position, where the Easternmost pixel is 0.</li>
  313. * <li><code>{reverseJ}</code>: The pixel row (vertical coordinate) of the picked position, where the Southernmost pixel is 0.</li>
  314. * <li><code>{longitudeDegrees}</code>: The longitude of the picked position in degrees.</li>
  315. * <li><code>{latitudeDegrees}</code>: The latitude of the picked position in degrees.</li>
  316. * <li><code>{longitudeProjected}</code>: The longitude of the picked position in the projected coordinates of the tiling scheme.</li>
  317. * <li><code>{latitudeProjected}</code>: The latitude of the picked position in the projected coordinates of the tiling scheme.</li>
  318. * <li><code>{format}</code>: The format in which to get feature information, as specified in the {@link GetFeatureInfoFormat}.</li>
  319. * </ul>
  320. * @memberof UrlTemplateImageryProvider.prototype
  321. * @type {string}
  322. * @readonly
  323. */
  324. pickFeaturesUrl: {
  325. get: function () {
  326. return this._pickFeaturesResource.url;
  327. },
  328. },
  329. /**
  330. * Gets the proxy used by this provider.
  331. * @memberof UrlTemplateImageryProvider.prototype
  332. * @type {Proxy}
  333. * @readonly
  334. * @default undefined
  335. */
  336. proxy: {
  337. get: function () {
  338. return this._resource.proxy;
  339. },
  340. },
  341. /**
  342. * Gets the width of each tile, in pixels.
  343. * @memberof UrlTemplateImageryProvider.prototype
  344. * @type {number}
  345. * @readonly
  346. * @default 256
  347. */
  348. tileWidth: {
  349. get: function () {
  350. return this._tileWidth;
  351. },
  352. },
  353. /**
  354. * Gets the height of each tile, in pixels.
  355. * @memberof UrlTemplateImageryProvider.prototype
  356. * @type {number}
  357. * @readonly
  358. * @default 256
  359. */
  360. tileHeight: {
  361. get: function () {
  362. return this._tileHeight;
  363. },
  364. },
  365. /**
  366. * Gets the maximum level-of-detail that can be requested, or undefined if there is no limit.
  367. * @memberof UrlTemplateImageryProvider.prototype
  368. * @type {number|undefined}
  369. * @readonly
  370. * @default undefined
  371. */
  372. maximumLevel: {
  373. get: function () {
  374. return this._maximumLevel;
  375. },
  376. },
  377. /**
  378. * Gets the minimum level-of-detail that can be requested.
  379. * @memberof UrlTemplateImageryProvider.prototype
  380. * @type {number}
  381. * @readonly
  382. * @default 0
  383. */
  384. minimumLevel: {
  385. get: function () {
  386. return this._minimumLevel;
  387. },
  388. },
  389. /**
  390. * Gets the tiling scheme used by this provider.
  391. * @memberof UrlTemplateImageryProvider.prototype
  392. * @type {TilingScheme}
  393. * @readonly
  394. * @default new WebMercatorTilingScheme()
  395. */
  396. tilingScheme: {
  397. get: function () {
  398. return this._tilingScheme;
  399. },
  400. },
  401. /**
  402. * Gets the rectangle, in radians, of the imagery provided by this instance.
  403. * @memberof UrlTemplateImageryProvider.prototype
  404. * @type {Rectangle}
  405. * @readonly
  406. * @default tilingScheme.rectangle
  407. */
  408. rectangle: {
  409. get: function () {
  410. return this._rectangle;
  411. },
  412. },
  413. /**
  414. * Gets the tile discard policy. If not undefined, the discard policy is responsible
  415. * for filtering out "missing" tiles via its shouldDiscardImage function. If this function
  416. * returns undefined, no tiles are filtered.
  417. * @memberof UrlTemplateImageryProvider.prototype
  418. * @type {TileDiscardPolicy}
  419. * @readonly
  420. * @default undefined
  421. */
  422. tileDiscardPolicy: {
  423. get: function () {
  424. return this._tileDiscardPolicy;
  425. },
  426. },
  427. /**
  428. * Gets an event that is raised when the imagery provider encounters an asynchronous error. By subscribing
  429. * to the event, you will be notified of the error and can potentially recover from it. Event listeners
  430. * are passed an instance of {@link TileProviderError}.
  431. * @memberof UrlTemplateImageryProvider.prototype
  432. * @type {Event}
  433. * @readonly
  434. */
  435. errorEvent: {
  436. get: function () {
  437. return this._errorEvent;
  438. },
  439. },
  440. /**
  441. * Gets the credit to display when this imagery provider is active. Typically this is used to credit
  442. * the source of the imagery.
  443. * @memberof UrlTemplateImageryProvider.prototype
  444. * @type {Credit}
  445. * @readonly
  446. * @default undefined
  447. */
  448. credit: {
  449. get: function () {
  450. return this._credit;
  451. },
  452. },
  453. /**
  454. * Gets a value indicating whether or not the images provided by this imagery provider
  455. * include an alpha channel. If this property is false, an alpha channel, if present, will
  456. * be ignored. If this property is true, any images without an alpha channel will be treated
  457. * as if their alpha is 1.0 everywhere. When this property is false, memory usage
  458. * and texture upload time are reduced.
  459. * @memberof UrlTemplateImageryProvider.prototype
  460. * @type {boolean}
  461. * @readonly
  462. * @default true
  463. */
  464. hasAlphaChannel: {
  465. get: function () {
  466. return this._hasAlphaChannel;
  467. },
  468. },
  469. });
  470. /**
  471. * Gets the credits to be displayed when a given tile is displayed.
  472. *
  473. * @param {number} x The tile X coordinate.
  474. * @param {number} y The tile Y coordinate.
  475. * @param {number} level The tile level;
  476. * @returns {Credit[]} The credits to be displayed when the tile is displayed.
  477. */
  478. UrlTemplateImageryProvider.prototype.getTileCredits = function (x, y, level) {
  479. return undefined;
  480. };
  481. /**
  482. * @param {number} x The tile X coordinate.
  483. * @param {number} y The tile Y coordinate.
  484. * @param {number} level The tile level.
  485. * @param {Request} [request] The request object. Intended for internal use only.
  486. * @returns {Promise<ImageryTypes>|undefined} A promise for the image that will resolve when the image is available, or
  487. * undefined if there are too many active requests to the server, and the request should be retried later.
  488. */
  489. UrlTemplateImageryProvider.prototype.requestImage = function (
  490. x,
  491. y,
  492. level,
  493. request,
  494. ) {
  495. return ImageryProvider.loadImage(
  496. this,
  497. buildImageResource(this, x, y, level, request),
  498. );
  499. };
  500. /**
  501. * Asynchronously determines what features, if any, are located at a given longitude and latitude within
  502. * a tile.
  503. *
  504. * @param {number} x The tile X coordinate.
  505. * @param {number} y The tile Y coordinate.
  506. * @param {number} level The tile level.
  507. * @param {number} longitude The longitude at which to pick features.
  508. * @param {number} latitude The latitude at which to pick features.
  509. * @return {Promise<ImageryLayerFeatureInfo[]>|undefined} A promise for the picked features that will resolve when the asynchronous
  510. * picking completes. The resolved value is an array of {@link ImageryLayerFeatureInfo}
  511. * instances. The array may be empty if no features are found at the given location.
  512. * It may also be undefined if picking is not supported.
  513. */
  514. UrlTemplateImageryProvider.prototype.pickFeatures = function (
  515. x,
  516. y,
  517. level,
  518. longitude,
  519. latitude,
  520. ) {
  521. if (
  522. !this.enablePickFeatures ||
  523. !defined(this._pickFeaturesResource) ||
  524. this._getFeatureInfoFormats.length === 0
  525. ) {
  526. return undefined;
  527. }
  528. let formatIndex = 0;
  529. const that = this;
  530. function handleResponse(format, data) {
  531. return format.callback(data);
  532. }
  533. function doRequest() {
  534. if (formatIndex >= that._getFeatureInfoFormats.length) {
  535. // No valid formats, so no features picked.
  536. return Promise.resolve([]);
  537. }
  538. const format = that._getFeatureInfoFormats[formatIndex];
  539. const resource = buildPickFeaturesResource(
  540. that,
  541. x,
  542. y,
  543. level,
  544. longitude,
  545. latitude,
  546. format.format,
  547. );
  548. ++formatIndex;
  549. if (format.type === "json") {
  550. return resource.fetchJson().then(format.callback).catch(doRequest);
  551. } else if (format.type === "xml") {
  552. return resource.fetchXML().then(format.callback).catch(doRequest);
  553. } else if (format.type === "text" || format.type === "html") {
  554. return resource.fetchText().then(format.callback).catch(doRequest);
  555. }
  556. return resource
  557. .fetch({
  558. responseType: format.format,
  559. })
  560. .then(handleResponse.bind(undefined, format))
  561. .catch(doRequest);
  562. }
  563. return doRequest();
  564. };
  565. let degreesScratchComputed = false;
  566. const degreesScratch = new Rectangle();
  567. let projectedScratchComputed = false;
  568. const projectedScratch = new Rectangle();
  569. function buildImageResource(imageryProvider, x, y, level, request) {
  570. degreesScratchComputed = false;
  571. projectedScratchComputed = false;
  572. const resource = imageryProvider._resource;
  573. const url = resource.getUrlComponent(true);
  574. const allTags = imageryProvider._tags;
  575. const templateValues = {};
  576. const match = url.match(templateRegex);
  577. if (defined(match)) {
  578. match.forEach(function (tag) {
  579. const key = tag.substring(1, tag.length - 1); //strip {}
  580. if (defined(allTags[key])) {
  581. templateValues[key] = allTags[key](imageryProvider, x, y, level);
  582. }
  583. });
  584. }
  585. return resource.getDerivedResource({
  586. request: request,
  587. templateValues: templateValues,
  588. });
  589. }
  590. let ijScratchComputed = false;
  591. const ijScratch = new Cartesian2();
  592. let longitudeLatitudeProjectedScratchComputed = false;
  593. function buildPickFeaturesResource(
  594. imageryProvider,
  595. x,
  596. y,
  597. level,
  598. longitude,
  599. latitude,
  600. format,
  601. ) {
  602. degreesScratchComputed = false;
  603. projectedScratchComputed = false;
  604. ijScratchComputed = false;
  605. longitudeLatitudeProjectedScratchComputed = false;
  606. const resource = imageryProvider._pickFeaturesResource;
  607. const url = resource.getUrlComponent(true);
  608. const allTags = imageryProvider._pickFeaturesTags;
  609. const templateValues = {};
  610. const match = url.match(templateRegex);
  611. if (defined(match)) {
  612. match.forEach(function (tag) {
  613. const key = tag.substring(1, tag.length - 1); //strip {}
  614. if (defined(allTags[key])) {
  615. templateValues[key] = allTags[key](
  616. imageryProvider,
  617. x,
  618. y,
  619. level,
  620. longitude,
  621. latitude,
  622. format,
  623. );
  624. }
  625. });
  626. }
  627. return resource.getDerivedResource({
  628. templateValues: templateValues,
  629. });
  630. }
  631. function padWithZerosIfNecessary(imageryProvider, key, value) {
  632. if (
  633. imageryProvider &&
  634. imageryProvider.urlSchemeZeroPadding &&
  635. imageryProvider.urlSchemeZeroPadding.hasOwnProperty(key)
  636. ) {
  637. const paddingTemplate = imageryProvider.urlSchemeZeroPadding[key];
  638. if (typeof paddingTemplate === "string") {
  639. const paddingTemplateWidth = paddingTemplate.length;
  640. if (paddingTemplateWidth > 1) {
  641. value =
  642. value.length >= paddingTemplateWidth
  643. ? value
  644. : new Array(
  645. paddingTemplateWidth - value.toString().length + 1,
  646. ).join("0") + value;
  647. }
  648. }
  649. }
  650. return value;
  651. }
  652. function xTag(imageryProvider, x, y, level) {
  653. return padWithZerosIfNecessary(imageryProvider, "{x}", x);
  654. }
  655. function reverseXTag(imageryProvider, x, y, level) {
  656. const reverseX =
  657. imageryProvider.tilingScheme.getNumberOfXTilesAtLevel(level) - x - 1;
  658. return padWithZerosIfNecessary(imageryProvider, "{reverseX}", reverseX);
  659. }
  660. function yTag(imageryProvider, x, y, level) {
  661. return padWithZerosIfNecessary(imageryProvider, "{y}", y);
  662. }
  663. function reverseYTag(imageryProvider, x, y, level) {
  664. const reverseY =
  665. imageryProvider.tilingScheme.getNumberOfYTilesAtLevel(level) - y - 1;
  666. return padWithZerosIfNecessary(imageryProvider, "{reverseY}", reverseY);
  667. }
  668. function reverseZTag(imageryProvider, x, y, level) {
  669. const maximumLevel = imageryProvider.maximumLevel;
  670. const reverseZ =
  671. defined(maximumLevel) && level < maximumLevel
  672. ? maximumLevel - level - 1
  673. : level;
  674. return padWithZerosIfNecessary(imageryProvider, "{reverseZ}", reverseZ);
  675. }
  676. function zTag(imageryProvider, x, y, level) {
  677. return padWithZerosIfNecessary(imageryProvider, "{z}", level);
  678. }
  679. function sTag(imageryProvider, x, y, level) {
  680. const index = (x + y + level) % imageryProvider._subdomains.length;
  681. return imageryProvider._subdomains[index];
  682. }
  683. function computeDegrees(imageryProvider, x, y, level) {
  684. if (degreesScratchComputed) {
  685. return;
  686. }
  687. imageryProvider.tilingScheme.tileXYToRectangle(x, y, level, degreesScratch);
  688. degreesScratch.west = CesiumMath.toDegrees(degreesScratch.west);
  689. degreesScratch.south = CesiumMath.toDegrees(degreesScratch.south);
  690. degreesScratch.east = CesiumMath.toDegrees(degreesScratch.east);
  691. degreesScratch.north = CesiumMath.toDegrees(degreesScratch.north);
  692. degreesScratchComputed = true;
  693. }
  694. function westDegreesTag(imageryProvider, x, y, level) {
  695. computeDegrees(imageryProvider, x, y, level);
  696. return degreesScratch.west;
  697. }
  698. function southDegreesTag(imageryProvider, x, y, level) {
  699. computeDegrees(imageryProvider, x, y, level);
  700. return degreesScratch.south;
  701. }
  702. function eastDegreesTag(imageryProvider, x, y, level) {
  703. computeDegrees(imageryProvider, x, y, level);
  704. return degreesScratch.east;
  705. }
  706. function northDegreesTag(imageryProvider, x, y, level) {
  707. computeDegrees(imageryProvider, x, y, level);
  708. return degreesScratch.north;
  709. }
  710. function computeProjected(imageryProvider, x, y, level) {
  711. if (projectedScratchComputed) {
  712. return;
  713. }
  714. imageryProvider.tilingScheme.tileXYToNativeRectangle(
  715. x,
  716. y,
  717. level,
  718. projectedScratch,
  719. );
  720. projectedScratchComputed = true;
  721. }
  722. function westProjectedTag(imageryProvider, x, y, level) {
  723. computeProjected(imageryProvider, x, y, level);
  724. return projectedScratch.west;
  725. }
  726. function southProjectedTag(imageryProvider, x, y, level) {
  727. computeProjected(imageryProvider, x, y, level);
  728. return projectedScratch.south;
  729. }
  730. function eastProjectedTag(imageryProvider, x, y, level) {
  731. computeProjected(imageryProvider, x, y, level);
  732. return projectedScratch.east;
  733. }
  734. function northProjectedTag(imageryProvider, x, y, level) {
  735. computeProjected(imageryProvider, x, y, level);
  736. return projectedScratch.north;
  737. }
  738. function widthTag(imageryProvider, x, y, level) {
  739. return imageryProvider.tileWidth;
  740. }
  741. function heightTag(imageryProvider, x, y, level) {
  742. return imageryProvider.tileHeight;
  743. }
  744. function iTag(imageryProvider, x, y, level, longitude, latitude, format) {
  745. computeIJ(imageryProvider, x, y, level, longitude, latitude);
  746. return ijScratch.x;
  747. }
  748. function jTag(imageryProvider, x, y, level, longitude, latitude, format) {
  749. computeIJ(imageryProvider, x, y, level, longitude, latitude);
  750. return ijScratch.y;
  751. }
  752. function reverseITag(
  753. imageryProvider,
  754. x,
  755. y,
  756. level,
  757. longitude,
  758. latitude,
  759. format,
  760. ) {
  761. computeIJ(imageryProvider, x, y, level, longitude, latitude);
  762. return imageryProvider.tileWidth - ijScratch.x - 1;
  763. }
  764. function reverseJTag(
  765. imageryProvider,
  766. x,
  767. y,
  768. level,
  769. longitude,
  770. latitude,
  771. format,
  772. ) {
  773. computeIJ(imageryProvider, x, y, level, longitude, latitude);
  774. return imageryProvider.tileHeight - ijScratch.y - 1;
  775. }
  776. const rectangleScratch = new Rectangle();
  777. const longitudeLatitudeProjectedScratch = new Cartesian3();
  778. function computeIJ(imageryProvider, x, y, level, longitude, latitude, format) {
  779. if (ijScratchComputed) {
  780. return;
  781. }
  782. computeLongitudeLatitudeProjected(
  783. imageryProvider,
  784. x,
  785. y,
  786. level,
  787. longitude,
  788. latitude,
  789. );
  790. const projected = longitudeLatitudeProjectedScratch;
  791. const rectangle = imageryProvider.tilingScheme.tileXYToNativeRectangle(
  792. x,
  793. y,
  794. level,
  795. rectangleScratch,
  796. );
  797. ijScratch.x =
  798. ((imageryProvider.tileWidth * (projected.x - rectangle.west)) /
  799. rectangle.width) |
  800. 0;
  801. ijScratch.y =
  802. ((imageryProvider.tileHeight * (rectangle.north - projected.y)) /
  803. rectangle.height) |
  804. 0;
  805. ijScratchComputed = true;
  806. }
  807. function longitudeDegreesTag(
  808. imageryProvider,
  809. x,
  810. y,
  811. level,
  812. longitude,
  813. latitude,
  814. format,
  815. ) {
  816. return CesiumMath.toDegrees(longitude);
  817. }
  818. function latitudeDegreesTag(
  819. imageryProvider,
  820. x,
  821. y,
  822. level,
  823. longitude,
  824. latitude,
  825. format,
  826. ) {
  827. return CesiumMath.toDegrees(latitude);
  828. }
  829. function longitudeProjectedTag(
  830. imageryProvider,
  831. x,
  832. y,
  833. level,
  834. longitude,
  835. latitude,
  836. format,
  837. ) {
  838. computeLongitudeLatitudeProjected(
  839. imageryProvider,
  840. x,
  841. y,
  842. level,
  843. longitude,
  844. latitude,
  845. );
  846. return longitudeLatitudeProjectedScratch.x;
  847. }
  848. function latitudeProjectedTag(
  849. imageryProvider,
  850. x,
  851. y,
  852. level,
  853. longitude,
  854. latitude,
  855. format,
  856. ) {
  857. computeLongitudeLatitudeProjected(
  858. imageryProvider,
  859. x,
  860. y,
  861. level,
  862. longitude,
  863. latitude,
  864. );
  865. return longitudeLatitudeProjectedScratch.y;
  866. }
  867. const cartographicScratch = new Cartographic();
  868. function computeLongitudeLatitudeProjected(
  869. imageryProvider,
  870. x,
  871. y,
  872. level,
  873. longitude,
  874. latitude,
  875. format,
  876. ) {
  877. if (longitudeLatitudeProjectedScratchComputed) {
  878. return;
  879. }
  880. if (imageryProvider.tilingScheme.projection instanceof GeographicProjection) {
  881. longitudeLatitudeProjectedScratch.x = CesiumMath.toDegrees(longitude);
  882. longitudeLatitudeProjectedScratch.y = CesiumMath.toDegrees(latitude);
  883. } else {
  884. const cartographic = cartographicScratch;
  885. cartographic.longitude = longitude;
  886. cartographic.latitude = latitude;
  887. imageryProvider.tilingScheme.projection.project(
  888. cartographic,
  889. longitudeLatitudeProjectedScratch,
  890. );
  891. }
  892. longitudeLatitudeProjectedScratchComputed = true;
  893. }
  894. function formatTag(imageryProvider, x, y, level, longitude, latitude, format) {
  895. return format;
  896. }
  897. export default UrlTemplateImageryProvider;