RectangleGeometryLibrary.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. import Cartesian3 from "./Cartesian3.js";
  2. import Cartographic from "./Cartographic.js";
  3. import defined from "./defined.js";
  4. import DeveloperError from "./DeveloperError.js";
  5. import GeographicProjection from "./GeographicProjection.js";
  6. import CesiumMath from "./Math.js";
  7. import Matrix2 from "./Matrix2.js";
  8. import Rectangle from "./Rectangle.js";
  9. const cos = Math.cos;
  10. const sin = Math.sin;
  11. const sqrt = Math.sqrt;
  12. /**
  13. * @private
  14. */
  15. const RectangleGeometryLibrary = {};
  16. /**
  17. * @private
  18. */
  19. RectangleGeometryLibrary.computePosition = function (
  20. computedOptions,
  21. ellipsoid,
  22. computeST,
  23. row,
  24. col,
  25. position,
  26. st
  27. ) {
  28. const radiiSquared = ellipsoid.radiiSquared;
  29. const nwCorner = computedOptions.nwCorner;
  30. const rectangle = computedOptions.boundingRectangle;
  31. let stLatitude =
  32. nwCorner.latitude -
  33. computedOptions.granYCos * row +
  34. col * computedOptions.granXSin;
  35. const cosLatitude = cos(stLatitude);
  36. const nZ = sin(stLatitude);
  37. const kZ = radiiSquared.z * nZ;
  38. let stLongitude =
  39. nwCorner.longitude +
  40. row * computedOptions.granYSin +
  41. col * computedOptions.granXCos;
  42. const nX = cosLatitude * cos(stLongitude);
  43. const nY = cosLatitude * sin(stLongitude);
  44. const kX = radiiSquared.x * nX;
  45. const kY = radiiSquared.y * nY;
  46. const gamma = sqrt(kX * nX + kY * nY + kZ * nZ);
  47. position.x = kX / gamma;
  48. position.y = kY / gamma;
  49. position.z = kZ / gamma;
  50. if (computeST) {
  51. const stNwCorner = computedOptions.stNwCorner;
  52. if (defined(stNwCorner)) {
  53. stLatitude =
  54. stNwCorner.latitude -
  55. computedOptions.stGranYCos * row +
  56. col * computedOptions.stGranXSin;
  57. stLongitude =
  58. stNwCorner.longitude +
  59. row * computedOptions.stGranYSin +
  60. col * computedOptions.stGranXCos;
  61. st.x = (stLongitude - computedOptions.stWest) * computedOptions.lonScalar;
  62. st.y = (stLatitude - computedOptions.stSouth) * computedOptions.latScalar;
  63. } else {
  64. st.x = (stLongitude - rectangle.west) * computedOptions.lonScalar;
  65. st.y = (stLatitude - rectangle.south) * computedOptions.latScalar;
  66. }
  67. }
  68. };
  69. const rotationMatrixScratch = new Matrix2();
  70. let nwCartesian = new Cartesian3();
  71. const centerScratch = new Cartographic();
  72. let centerCartesian = new Cartesian3();
  73. const proj = new GeographicProjection();
  74. function getRotationOptions(
  75. nwCorner,
  76. rotation,
  77. granularityX,
  78. granularityY,
  79. center,
  80. width,
  81. height
  82. ) {
  83. const cosRotation = Math.cos(rotation);
  84. const granYCos = granularityY * cosRotation;
  85. const granXCos = granularityX * cosRotation;
  86. const sinRotation = Math.sin(rotation);
  87. const granYSin = granularityY * sinRotation;
  88. const granXSin = granularityX * sinRotation;
  89. nwCartesian = proj.project(nwCorner, nwCartesian);
  90. nwCartesian = Cartesian3.subtract(nwCartesian, centerCartesian, nwCartesian);
  91. const rotationMatrix = Matrix2.fromRotation(rotation, rotationMatrixScratch);
  92. nwCartesian = Matrix2.multiplyByVector(
  93. rotationMatrix,
  94. nwCartesian,
  95. nwCartesian
  96. );
  97. nwCartesian = Cartesian3.add(nwCartesian, centerCartesian, nwCartesian);
  98. nwCorner = proj.unproject(nwCartesian, nwCorner);
  99. width -= 1;
  100. height -= 1;
  101. const latitude = nwCorner.latitude;
  102. const latitude0 = latitude + width * granXSin;
  103. const latitude1 = latitude - granYCos * height;
  104. const latitude2 = latitude - granYCos * height + width * granXSin;
  105. const north = Math.max(latitude, latitude0, latitude1, latitude2);
  106. const south = Math.min(latitude, latitude0, latitude1, latitude2);
  107. const longitude = nwCorner.longitude;
  108. const longitude0 = longitude + width * granXCos;
  109. const longitude1 = longitude + height * granYSin;
  110. const longitude2 = longitude + height * granYSin + width * granXCos;
  111. const east = Math.max(longitude, longitude0, longitude1, longitude2);
  112. const west = Math.min(longitude, longitude0, longitude1, longitude2);
  113. return {
  114. north: north,
  115. south: south,
  116. east: east,
  117. west: west,
  118. granYCos: granYCos,
  119. granYSin: granYSin,
  120. granXCos: granXCos,
  121. granXSin: granXSin,
  122. nwCorner: nwCorner,
  123. };
  124. }
  125. /**
  126. * @private
  127. */
  128. RectangleGeometryLibrary.computeOptions = function (
  129. rectangle,
  130. granularity,
  131. rotation,
  132. stRotation,
  133. boundingRectangleScratch,
  134. nwCornerResult,
  135. stNwCornerResult
  136. ) {
  137. let east = rectangle.east;
  138. let west = rectangle.west;
  139. let north = rectangle.north;
  140. let south = rectangle.south;
  141. let northCap = false;
  142. let southCap = false;
  143. if (north === CesiumMath.PI_OVER_TWO) {
  144. northCap = true;
  145. }
  146. if (south === -CesiumMath.PI_OVER_TWO) {
  147. southCap = true;
  148. }
  149. let dx;
  150. const dy = north - south;
  151. if (west > east) {
  152. dx = CesiumMath.TWO_PI - west + east;
  153. } else {
  154. dx = east - west;
  155. }
  156. const width = Math.ceil(dx / granularity) + 1;
  157. const height = Math.ceil(dy / granularity) + 1;
  158. const granularityX = dx / (width - 1);
  159. const granularityY = dy / (height - 1);
  160. const nwCorner = Rectangle.northwest(rectangle, nwCornerResult);
  161. const center = Rectangle.center(rectangle, centerScratch);
  162. if (rotation !== 0 || stRotation !== 0) {
  163. if (center.longitude < nwCorner.longitude) {
  164. center.longitude += CesiumMath.TWO_PI;
  165. }
  166. centerCartesian = proj.project(center, centerCartesian);
  167. }
  168. const granYCos = granularityY;
  169. const granXCos = granularityX;
  170. const granYSin = 0.0;
  171. const granXSin = 0.0;
  172. const boundingRectangle = Rectangle.clone(
  173. rectangle,
  174. boundingRectangleScratch
  175. );
  176. const computedOptions = {
  177. granYCos: granYCos,
  178. granYSin: granYSin,
  179. granXCos: granXCos,
  180. granXSin: granXSin,
  181. nwCorner: nwCorner,
  182. boundingRectangle: boundingRectangle,
  183. width: width,
  184. height: height,
  185. northCap: northCap,
  186. southCap: southCap,
  187. };
  188. if (rotation !== 0) {
  189. const rotationOptions = getRotationOptions(
  190. nwCorner,
  191. rotation,
  192. granularityX,
  193. granularityY,
  194. center,
  195. width,
  196. height
  197. );
  198. north = rotationOptions.north;
  199. south = rotationOptions.south;
  200. east = rotationOptions.east;
  201. west = rotationOptions.west;
  202. //>>includeStart('debug', pragmas.debug);
  203. if (
  204. north < -CesiumMath.PI_OVER_TWO ||
  205. north > CesiumMath.PI_OVER_TWO ||
  206. south < -CesiumMath.PI_OVER_TWO ||
  207. south > CesiumMath.PI_OVER_TWO
  208. ) {
  209. throw new DeveloperError(
  210. "Rotated rectangle is invalid. It crosses over either the north or south pole."
  211. );
  212. }
  213. //>>includeEnd('debug')
  214. computedOptions.granYCos = rotationOptions.granYCos;
  215. computedOptions.granYSin = rotationOptions.granYSin;
  216. computedOptions.granXCos = rotationOptions.granXCos;
  217. computedOptions.granXSin = rotationOptions.granXSin;
  218. boundingRectangle.north = north;
  219. boundingRectangle.south = south;
  220. boundingRectangle.east = east;
  221. boundingRectangle.west = west;
  222. }
  223. if (stRotation !== 0) {
  224. rotation = rotation - stRotation;
  225. const stNwCorner = Rectangle.northwest(boundingRectangle, stNwCornerResult);
  226. const stRotationOptions = getRotationOptions(
  227. stNwCorner,
  228. rotation,
  229. granularityX,
  230. granularityY,
  231. center,
  232. width,
  233. height
  234. );
  235. computedOptions.stGranYCos = stRotationOptions.granYCos;
  236. computedOptions.stGranXCos = stRotationOptions.granXCos;
  237. computedOptions.stGranYSin = stRotationOptions.granYSin;
  238. computedOptions.stGranXSin = stRotationOptions.granXSin;
  239. computedOptions.stNwCorner = stNwCorner;
  240. computedOptions.stWest = stRotationOptions.west;
  241. computedOptions.stSouth = stRotationOptions.south;
  242. }
  243. return computedOptions;
  244. };
  245. export default RectangleGeometryLibrary;