GeographicTilingScheme.js 9.0 KB

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