GeographicTilingScheme.js 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. import Cartesian2 from "./Cartesian2.js";
  2. import Check from "./Check.js";
  3. import defaultValue from "./defaultValue.js";
  4. import defined from "./defined.js";
  5. import Ellipsoid from "./Ellipsoid.js";
  6. import GeographicProjection from "./GeographicProjection.js";
  7. import CesiumMath from "./Math.js";
  8. import Rectangle from "./Rectangle.js";
  9. /**
  10. * A tiling scheme for geometry referenced to a simple {@link GeographicProjection} where
  11. * longitude and latitude are directly mapped to X and Y. This projection is commonly
  12. * known as geographic, equirectangular, equidistant cylindrical, or plate carrée.
  13. *
  14. * @alias GeographicTilingScheme
  15. * @constructor
  16. *
  17. * @param {Object} [options] Object with the following properties:
  18. * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid whose surface is being tiled. Defaults to
  19. * the WGS84 ellipsoid.
  20. * @param {Rectangle} [options.rectangle=Rectangle.MAX_VALUE] The rectangle, in radians, covered by the tiling scheme.
  21. * @param {Number} [options.numberOfLevelZeroTilesX=2] The number of tiles in the X direction at level zero of
  22. * the tile tree.
  23. * @param {Number} [options.numberOfLevelZeroTilesY=1] The number of tiles in the Y direction at level zero of
  24. * the tile tree.
  25. */
  26. function GeographicTilingScheme(options) {
  27. options = defaultValue(options, defaultValue.EMPTY_OBJECT);
  28. this._ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);
  29. this._rectangle = defaultValue(options.rectangle, Rectangle.MAX_VALUE);
  30. this._projection = new GeographicProjection(this._ellipsoid);
  31. this._numberOfLevelZeroTilesX = defaultValue(
  32. options.numberOfLevelZeroTilesX,
  33. 2
  34. );
  35. this._numberOfLevelZeroTilesY = defaultValue(
  36. options.numberOfLevelZeroTilesY,
  37. 1
  38. );
  39. }
  40. Object.defineProperties(GeographicTilingScheme.prototype, {
  41. /**
  42. * Gets the ellipsoid that is tiled by this tiling scheme.
  43. * @memberof GeographicTilingScheme.prototype
  44. * @type {Ellipsoid}
  45. */
  46. ellipsoid: {
  47. get: function () {
  48. return this._ellipsoid;
  49. },
  50. },
  51. /**
  52. * Gets the rectangle, in radians, covered by this tiling scheme.
  53. * @memberof GeographicTilingScheme.prototype
  54. * @type {Rectangle}
  55. */
  56. rectangle: {
  57. get: function () {
  58. return this._rectangle;
  59. },
  60. },
  61. /**
  62. * Gets the map projection used by this tiling scheme.
  63. * @memberof GeographicTilingScheme.prototype
  64. * @type {MapProjection}
  65. */
  66. projection: {
  67. get: function () {
  68. return this._projection;
  69. },
  70. },
  71. });
  72. /**
  73. * Gets the total number of tiles in the X direction at a specified level-of-detail.
  74. *
  75. * @param {Number} level The level-of-detail.
  76. * @returns {Number} The number of tiles in the X direction at the given level.
  77. */
  78. GeographicTilingScheme.prototype.getNumberOfXTilesAtLevel = function (level) {
  79. return this._numberOfLevelZeroTilesX << level;
  80. };
  81. /**
  82. * Gets the total number of tiles in the Y direction at a specified level-of-detail.
  83. *
  84. * @param {Number} level The level-of-detail.
  85. * @returns {Number} The number of tiles in the Y direction at the given level.
  86. */
  87. GeographicTilingScheme.prototype.getNumberOfYTilesAtLevel = function (level) {
  88. return this._numberOfLevelZeroTilesY << level;
  89. };
  90. /**
  91. * Transforms a rectangle specified in geodetic radians to the native coordinate system
  92. * of this tiling scheme.
  93. *
  94. * @param {Rectangle} rectangle The rectangle to transform.
  95. * @param {Rectangle} [result] The instance to which to copy the result, or undefined if a new instance
  96. * should be created.
  97. * @returns {Rectangle} The specified 'result', or a new object containing the native rectangle if 'result'
  98. * is undefined.
  99. */
  100. GeographicTilingScheme.prototype.rectangleToNativeRectangle = function (
  101. rectangle,
  102. result
  103. ) {
  104. //>>includeStart('debug', pragmas.debug);
  105. Check.defined("rectangle", rectangle);
  106. //>>includeEnd('debug');
  107. const west = CesiumMath.toDegrees(rectangle.west);
  108. const south = CesiumMath.toDegrees(rectangle.south);
  109. const east = CesiumMath.toDegrees(rectangle.east);
  110. const north = CesiumMath.toDegrees(rectangle.north);
  111. if (!defined(result)) {
  112. return new Rectangle(west, south, east, north);
  113. }
  114. result.west = west;
  115. result.south = south;
  116. result.east = east;
  117. result.north = north;
  118. return result;
  119. };
  120. /**
  121. * Converts tile x, y coordinates and level to a rectangle expressed in the native coordinates
  122. * of the tiling scheme.
  123. *
  124. * @param {Number} x The integer x coordinate of the tile.
  125. * @param {Number} y The integer y coordinate of the tile.
  126. * @param {Number} level The tile level-of-detail. Zero is the least detailed.
  127. * @param {Object} [result] The instance to which to copy the result, or undefined if a new instance
  128. * should be created.
  129. * @returns {Rectangle} The specified 'result', or a new object containing the rectangle
  130. * if 'result' is undefined.
  131. */
  132. GeographicTilingScheme.prototype.tileXYToNativeRectangle = function (
  133. x,
  134. y,
  135. level,
  136. result
  137. ) {
  138. const rectangleRadians = this.tileXYToRectangle(x, y, level, result);
  139. rectangleRadians.west = CesiumMath.toDegrees(rectangleRadians.west);
  140. rectangleRadians.south = CesiumMath.toDegrees(rectangleRadians.south);
  141. rectangleRadians.east = CesiumMath.toDegrees(rectangleRadians.east);
  142. rectangleRadians.north = CesiumMath.toDegrees(rectangleRadians.north);
  143. return rectangleRadians;
  144. };
  145. /**
  146. * Converts tile x, y coordinates and level to a cartographic rectangle in radians.
  147. *
  148. * @param {Number} x The integer x coordinate of the tile.
  149. * @param {Number} y The integer y coordinate of the tile.
  150. * @param {Number} level The tile level-of-detail. Zero is the least detailed.
  151. * @param {Object} [result] The instance to which to copy the result, or undefined if a new instance
  152. * should be created.
  153. * @returns {Rectangle} The specified 'result', or a new object containing the rectangle
  154. * if 'result' is undefined.
  155. */
  156. GeographicTilingScheme.prototype.tileXYToRectangle = function (
  157. x,
  158. y,
  159. level,
  160. result
  161. ) {
  162. const rectangle = this._rectangle;
  163. const xTiles = this.getNumberOfXTilesAtLevel(level);
  164. const yTiles = this.getNumberOfYTilesAtLevel(level);
  165. const xTileWidth = rectangle.width / xTiles;
  166. const west = x * xTileWidth + rectangle.west;
  167. const east = (x + 1) * xTileWidth + rectangle.west;
  168. const yTileHeight = rectangle.height / yTiles;
  169. const north = rectangle.north - y * yTileHeight;
  170. const south = rectangle.north - (y + 1) * yTileHeight;
  171. if (!defined(result)) {
  172. result = new Rectangle(west, south, east, north);
  173. }
  174. result.west = west;
  175. result.south = south;
  176. result.east = east;
  177. result.north = north;
  178. return result;
  179. };
  180. /**
  181. * Calculates the tile x, y coordinates of the tile containing
  182. * a given cartographic position.
  183. *
  184. * @param {Cartographic} position The position.
  185. * @param {Number} level The tile level-of-detail. Zero is the least detailed.
  186. * @param {Cartesian2} [result] The instance to which to copy the result, or undefined if a new instance
  187. * should be created.
  188. * @returns {Cartesian2} The specified 'result', or a new object containing the tile x, y coordinates
  189. * if 'result' is undefined.
  190. */
  191. GeographicTilingScheme.prototype.positionToTileXY = function (
  192. position,
  193. level,
  194. result
  195. ) {
  196. const rectangle = this._rectangle;
  197. if (!Rectangle.contains(rectangle, position)) {
  198. // outside the bounds of the tiling scheme
  199. return undefined;
  200. }
  201. const xTiles = this.getNumberOfXTilesAtLevel(level);
  202. const yTiles = this.getNumberOfYTilesAtLevel(level);
  203. const xTileWidth = rectangle.width / xTiles;
  204. const yTileHeight = rectangle.height / yTiles;
  205. let longitude = position.longitude;
  206. if (rectangle.east < rectangle.west) {
  207. longitude += CesiumMath.TWO_PI;
  208. }
  209. let xTileCoordinate = ((longitude - rectangle.west) / xTileWidth) | 0;
  210. if (xTileCoordinate >= xTiles) {
  211. xTileCoordinate = xTiles - 1;
  212. }
  213. let yTileCoordinate =
  214. ((rectangle.north - position.latitude) / yTileHeight) | 0;
  215. if (yTileCoordinate >= yTiles) {
  216. yTileCoordinate = yTiles - 1;
  217. }
  218. if (!defined(result)) {
  219. return new Cartesian2(xTileCoordinate, yTileCoordinate);
  220. }
  221. result.x = xTileCoordinate;
  222. result.y = yTileCoordinate;
  223. return result;
  224. };
  225. export default GeographicTilingScheme;