EllipsoidOutlineGeometry-2f8770f8.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. /**
  2. * @license
  3. * Cesium - https://github.com/CesiumGS/cesium
  4. * Version 1.95
  5. *
  6. * Copyright 2011-2022 Cesium Contributors
  7. *
  8. * Licensed under the Apache License, Version 2.0 (the "License");
  9. * you may not use this file except in compliance with the License.
  10. * You may obtain a copy of the License at
  11. *
  12. * http://www.apache.org/licenses/LICENSE-2.0
  13. *
  14. * Unless required by applicable law or agreed to in writing, software
  15. * distributed under the License is distributed on an "AS IS" BASIS,
  16. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17. * See the License for the specific language governing permissions and
  18. * limitations under the License.
  19. *
  20. * Columbus View (Pat. Pend.)
  21. *
  22. * Portions licensed separately.
  23. * See https://github.com/CesiumGS/cesium/blob/main/LICENSE.md for full licensing details.
  24. */
  25. define(['exports', './Transforms-273eeb44', './Matrix2-9e1c22e2', './ComponentDatatype-4eeb6d9b', './defaultValue-97284df2', './RuntimeError-4f8ec8a2', './GeometryAttribute-9be2d2e5', './GeometryAttributes-734a3446', './GeometryOffsetAttribute-59b14f45', './IndexDatatype-f228f5fd'], (function (exports, Transforms, Matrix2, ComponentDatatype, defaultValue, RuntimeError, GeometryAttribute, GeometryAttributes, GeometryOffsetAttribute, IndexDatatype) { 'use strict';
  26. const defaultRadii = new Matrix2.Cartesian3(1.0, 1.0, 1.0);
  27. const cos = Math.cos;
  28. const sin = Math.sin;
  29. /**
  30. * A description of the outline of an ellipsoid centered at the origin.
  31. *
  32. * @alias EllipsoidOutlineGeometry
  33. * @constructor
  34. *
  35. * @param {Object} [options] Object with the following properties:
  36. * @param {Cartesian3} [options.radii=Cartesian3(1.0, 1.0, 1.0)] The radii of the ellipsoid in the x, y, and z directions.
  37. * @param {Cartesian3} [options.innerRadii=options.radii] The inner radii of the ellipsoid in the x, y, and z directions.
  38. * @param {Number} [options.minimumClock=0.0] The minimum angle lying in the xy-plane measured from the positive x-axis and toward the positive y-axis.
  39. * @param {Number} [options.maximumClock=2*PI] The maximum angle lying in the xy-plane measured from the positive x-axis and toward the positive y-axis.
  40. * @param {Number} [options.minimumCone=0.0] The minimum angle measured from the positive z-axis and toward the negative z-axis.
  41. * @param {Number} [options.maximumCone=PI] The maximum angle measured from the positive z-axis and toward the negative z-axis.
  42. * @param {Number} [options.stackPartitions=10] The count of stacks for the ellipsoid (1 greater than the number of parallel lines).
  43. * @param {Number} [options.slicePartitions=8] The count of slices for the ellipsoid (Equal to the number of radial lines).
  44. * @param {Number} [options.subdivisions=128] The number of points per line, determining the granularity of the curvature.
  45. *
  46. * @exception {DeveloperError} options.stackPartitions must be greater than or equal to one.
  47. * @exception {DeveloperError} options.slicePartitions must be greater than or equal to zero.
  48. * @exception {DeveloperError} options.subdivisions must be greater than or equal to zero.
  49. *
  50. * @example
  51. * const ellipsoid = new Cesium.EllipsoidOutlineGeometry({
  52. * radii : new Cesium.Cartesian3(1000000.0, 500000.0, 500000.0),
  53. * stackPartitions: 6,
  54. * slicePartitions: 5
  55. * });
  56. * const geometry = Cesium.EllipsoidOutlineGeometry.createGeometry(ellipsoid);
  57. */
  58. function EllipsoidOutlineGeometry(options) {
  59. options = defaultValue.defaultValue(options, defaultValue.defaultValue.EMPTY_OBJECT);
  60. const radii = defaultValue.defaultValue(options.radii, defaultRadii);
  61. const innerRadii = defaultValue.defaultValue(options.innerRadii, radii);
  62. const minimumClock = defaultValue.defaultValue(options.minimumClock, 0.0);
  63. const maximumClock = defaultValue.defaultValue(options.maximumClock, ComponentDatatype.CesiumMath.TWO_PI);
  64. const minimumCone = defaultValue.defaultValue(options.minimumCone, 0.0);
  65. const maximumCone = defaultValue.defaultValue(options.maximumCone, ComponentDatatype.CesiumMath.PI);
  66. const stackPartitions = Math.round(defaultValue.defaultValue(options.stackPartitions, 10));
  67. const slicePartitions = Math.round(defaultValue.defaultValue(options.slicePartitions, 8));
  68. const subdivisions = Math.round(defaultValue.defaultValue(options.subdivisions, 128));
  69. //>>includeStart('debug', pragmas.debug);
  70. if (stackPartitions < 1) {
  71. throw new RuntimeError.DeveloperError("options.stackPartitions cannot be less than 1");
  72. }
  73. if (slicePartitions < 0) {
  74. throw new RuntimeError.DeveloperError("options.slicePartitions cannot be less than 0");
  75. }
  76. if (subdivisions < 0) {
  77. throw new RuntimeError.DeveloperError(
  78. "options.subdivisions must be greater than or equal to zero."
  79. );
  80. }
  81. if (
  82. defaultValue.defined(options.offsetAttribute) &&
  83. options.offsetAttribute === GeometryOffsetAttribute.GeometryOffsetAttribute.TOP
  84. ) {
  85. throw new RuntimeError.DeveloperError(
  86. "GeometryOffsetAttribute.TOP is not a supported options.offsetAttribute for this geometry."
  87. );
  88. }
  89. //>>includeEnd('debug');
  90. this._radii = Matrix2.Cartesian3.clone(radii);
  91. this._innerRadii = Matrix2.Cartesian3.clone(innerRadii);
  92. this._minimumClock = minimumClock;
  93. this._maximumClock = maximumClock;
  94. this._minimumCone = minimumCone;
  95. this._maximumCone = maximumCone;
  96. this._stackPartitions = stackPartitions;
  97. this._slicePartitions = slicePartitions;
  98. this._subdivisions = subdivisions;
  99. this._offsetAttribute = options.offsetAttribute;
  100. this._workerName = "createEllipsoidOutlineGeometry";
  101. }
  102. /**
  103. * The number of elements used to pack the object into an array.
  104. * @type {Number}
  105. */
  106. EllipsoidOutlineGeometry.packedLength = 2 * Matrix2.Cartesian3.packedLength + 8;
  107. /**
  108. * Stores the provided instance into the provided array.
  109. *
  110. * @param {EllipsoidOutlineGeometry} value The value to pack.
  111. * @param {Number[]} array The array to pack into.
  112. * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.
  113. *
  114. * @returns {Number[]} The array that was packed into
  115. */
  116. EllipsoidOutlineGeometry.pack = function (value, array, startingIndex) {
  117. //>>includeStart('debug', pragmas.debug);
  118. if (!defaultValue.defined(value)) {
  119. throw new RuntimeError.DeveloperError("value is required");
  120. }
  121. if (!defaultValue.defined(array)) {
  122. throw new RuntimeError.DeveloperError("array is required");
  123. }
  124. //>>includeEnd('debug');
  125. startingIndex = defaultValue.defaultValue(startingIndex, 0);
  126. Matrix2.Cartesian3.pack(value._radii, array, startingIndex);
  127. startingIndex += Matrix2.Cartesian3.packedLength;
  128. Matrix2.Cartesian3.pack(value._innerRadii, array, startingIndex);
  129. startingIndex += Matrix2.Cartesian3.packedLength;
  130. array[startingIndex++] = value._minimumClock;
  131. array[startingIndex++] = value._maximumClock;
  132. array[startingIndex++] = value._minimumCone;
  133. array[startingIndex++] = value._maximumCone;
  134. array[startingIndex++] = value._stackPartitions;
  135. array[startingIndex++] = value._slicePartitions;
  136. array[startingIndex++] = value._subdivisions;
  137. array[startingIndex] = defaultValue.defaultValue(value._offsetAttribute, -1);
  138. return array;
  139. };
  140. const scratchRadii = new Matrix2.Cartesian3();
  141. const scratchInnerRadii = new Matrix2.Cartesian3();
  142. const scratchOptions = {
  143. radii: scratchRadii,
  144. innerRadii: scratchInnerRadii,
  145. minimumClock: undefined,
  146. maximumClock: undefined,
  147. minimumCone: undefined,
  148. maximumCone: undefined,
  149. stackPartitions: undefined,
  150. slicePartitions: undefined,
  151. subdivisions: undefined,
  152. offsetAttribute: undefined,
  153. };
  154. /**
  155. * Retrieves an instance from a packed array.
  156. *
  157. * @param {Number[]} array The packed array.
  158. * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.
  159. * @param {EllipsoidOutlineGeometry} [result] The object into which to store the result.
  160. * @returns {EllipsoidOutlineGeometry} The modified result parameter or a new EllipsoidOutlineGeometry instance if one was not provided.
  161. */
  162. EllipsoidOutlineGeometry.unpack = function (array, startingIndex, result) {
  163. //>>includeStart('debug', pragmas.debug);
  164. if (!defaultValue.defined(array)) {
  165. throw new RuntimeError.DeveloperError("array is required");
  166. }
  167. //>>includeEnd('debug');
  168. startingIndex = defaultValue.defaultValue(startingIndex, 0);
  169. const radii = Matrix2.Cartesian3.unpack(array, startingIndex, scratchRadii);
  170. startingIndex += Matrix2.Cartesian3.packedLength;
  171. const innerRadii = Matrix2.Cartesian3.unpack(array, startingIndex, scratchInnerRadii);
  172. startingIndex += Matrix2.Cartesian3.packedLength;
  173. const minimumClock = array[startingIndex++];
  174. const maximumClock = array[startingIndex++];
  175. const minimumCone = array[startingIndex++];
  176. const maximumCone = array[startingIndex++];
  177. const stackPartitions = array[startingIndex++];
  178. const slicePartitions = array[startingIndex++];
  179. const subdivisions = array[startingIndex++];
  180. const offsetAttribute = array[startingIndex];
  181. if (!defaultValue.defined(result)) {
  182. scratchOptions.minimumClock = minimumClock;
  183. scratchOptions.maximumClock = maximumClock;
  184. scratchOptions.minimumCone = minimumCone;
  185. scratchOptions.maximumCone = maximumCone;
  186. scratchOptions.stackPartitions = stackPartitions;
  187. scratchOptions.slicePartitions = slicePartitions;
  188. scratchOptions.subdivisions = subdivisions;
  189. scratchOptions.offsetAttribute =
  190. offsetAttribute === -1 ? undefined : offsetAttribute;
  191. return new EllipsoidOutlineGeometry(scratchOptions);
  192. }
  193. result._radii = Matrix2.Cartesian3.clone(radii, result._radii);
  194. result._innerRadii = Matrix2.Cartesian3.clone(innerRadii, result._innerRadii);
  195. result._minimumClock = minimumClock;
  196. result._maximumClock = maximumClock;
  197. result._minimumCone = minimumCone;
  198. result._maximumCone = maximumCone;
  199. result._stackPartitions = stackPartitions;
  200. result._slicePartitions = slicePartitions;
  201. result._subdivisions = subdivisions;
  202. result._offsetAttribute =
  203. offsetAttribute === -1 ? undefined : offsetAttribute;
  204. return result;
  205. };
  206. /**
  207. * Computes the geometric representation of an outline of an ellipsoid, including its vertices, indices, and a bounding sphere.
  208. *
  209. * @param {EllipsoidOutlineGeometry} ellipsoidGeometry A description of the ellipsoid outline.
  210. * @returns {Geometry|undefined} The computed vertices and indices.
  211. */
  212. EllipsoidOutlineGeometry.createGeometry = function (ellipsoidGeometry) {
  213. const radii = ellipsoidGeometry._radii;
  214. if (radii.x <= 0 || radii.y <= 0 || radii.z <= 0) {
  215. return;
  216. }
  217. const innerRadii = ellipsoidGeometry._innerRadii;
  218. if (innerRadii.x <= 0 || innerRadii.y <= 0 || innerRadii.z <= 0) {
  219. return;
  220. }
  221. const minimumClock = ellipsoidGeometry._minimumClock;
  222. const maximumClock = ellipsoidGeometry._maximumClock;
  223. const minimumCone = ellipsoidGeometry._minimumCone;
  224. const maximumCone = ellipsoidGeometry._maximumCone;
  225. const subdivisions = ellipsoidGeometry._subdivisions;
  226. const ellipsoid = Matrix2.Ellipsoid.fromCartesian3(radii);
  227. // Add an extra slice and stack to remain consistent with EllipsoidGeometry
  228. let slicePartitions = ellipsoidGeometry._slicePartitions + 1;
  229. let stackPartitions = ellipsoidGeometry._stackPartitions + 1;
  230. slicePartitions = Math.round(
  231. (slicePartitions * Math.abs(maximumClock - minimumClock)) /
  232. ComponentDatatype.CesiumMath.TWO_PI
  233. );
  234. stackPartitions = Math.round(
  235. (stackPartitions * Math.abs(maximumCone - minimumCone)) / ComponentDatatype.CesiumMath.PI
  236. );
  237. if (slicePartitions < 2) {
  238. slicePartitions = 2;
  239. }
  240. if (stackPartitions < 2) {
  241. stackPartitions = 2;
  242. }
  243. let extraIndices = 0;
  244. let vertexMultiplier = 1.0;
  245. const hasInnerSurface =
  246. innerRadii.x !== radii.x ||
  247. innerRadii.y !== radii.y ||
  248. innerRadii.z !== radii.z;
  249. let isTopOpen = false;
  250. let isBotOpen = false;
  251. if (hasInnerSurface) {
  252. vertexMultiplier = 2.0;
  253. // Add 2x slicePartitions to connect the top/bottom of the outer to
  254. // the top/bottom of the inner
  255. if (minimumCone > 0.0) {
  256. isTopOpen = true;
  257. extraIndices += slicePartitions;
  258. }
  259. if (maximumCone < Math.PI) {
  260. isBotOpen = true;
  261. extraIndices += slicePartitions;
  262. }
  263. }
  264. const vertexCount =
  265. subdivisions * vertexMultiplier * (stackPartitions + slicePartitions);
  266. const positions = new Float64Array(vertexCount * 3);
  267. // Multiply by two because two points define each line segment
  268. const numIndices =
  269. 2 *
  270. (vertexCount +
  271. extraIndices -
  272. (slicePartitions + stackPartitions) * vertexMultiplier);
  273. const indices = IndexDatatype.IndexDatatype.createTypedArray(vertexCount, numIndices);
  274. let i;
  275. let j;
  276. let theta;
  277. let phi;
  278. let index = 0;
  279. // Calculate sin/cos phi
  280. const sinPhi = new Array(stackPartitions);
  281. const cosPhi = new Array(stackPartitions);
  282. for (i = 0; i < stackPartitions; i++) {
  283. phi =
  284. minimumCone + (i * (maximumCone - minimumCone)) / (stackPartitions - 1);
  285. sinPhi[i] = sin(phi);
  286. cosPhi[i] = cos(phi);
  287. }
  288. // Calculate sin/cos theta
  289. const sinTheta = new Array(subdivisions);
  290. const cosTheta = new Array(subdivisions);
  291. for (i = 0; i < subdivisions; i++) {
  292. theta =
  293. minimumClock + (i * (maximumClock - minimumClock)) / (subdivisions - 1);
  294. sinTheta[i] = sin(theta);
  295. cosTheta[i] = cos(theta);
  296. }
  297. // Calculate the latitude lines on the outer surface
  298. for (i = 0; i < stackPartitions; i++) {
  299. for (j = 0; j < subdivisions; j++) {
  300. positions[index++] = radii.x * sinPhi[i] * cosTheta[j];
  301. positions[index++] = radii.y * sinPhi[i] * sinTheta[j];
  302. positions[index++] = radii.z * cosPhi[i];
  303. }
  304. }
  305. // Calculate the latitude lines on the inner surface
  306. if (hasInnerSurface) {
  307. for (i = 0; i < stackPartitions; i++) {
  308. for (j = 0; j < subdivisions; j++) {
  309. positions[index++] = innerRadii.x * sinPhi[i] * cosTheta[j];
  310. positions[index++] = innerRadii.y * sinPhi[i] * sinTheta[j];
  311. positions[index++] = innerRadii.z * cosPhi[i];
  312. }
  313. }
  314. }
  315. // Calculate sin/cos phi
  316. sinPhi.length = subdivisions;
  317. cosPhi.length = subdivisions;
  318. for (i = 0; i < subdivisions; i++) {
  319. phi = minimumCone + (i * (maximumCone - minimumCone)) / (subdivisions - 1);
  320. sinPhi[i] = sin(phi);
  321. cosPhi[i] = cos(phi);
  322. }
  323. // Calculate sin/cos theta for each slice partition
  324. sinTheta.length = slicePartitions;
  325. cosTheta.length = slicePartitions;
  326. for (i = 0; i < slicePartitions; i++) {
  327. theta =
  328. minimumClock +
  329. (i * (maximumClock - minimumClock)) / (slicePartitions - 1);
  330. sinTheta[i] = sin(theta);
  331. cosTheta[i] = cos(theta);
  332. }
  333. // Calculate the longitude lines on the outer surface
  334. for (i = 0; i < subdivisions; i++) {
  335. for (j = 0; j < slicePartitions; j++) {
  336. positions[index++] = radii.x * sinPhi[i] * cosTheta[j];
  337. positions[index++] = radii.y * sinPhi[i] * sinTheta[j];
  338. positions[index++] = radii.z * cosPhi[i];
  339. }
  340. }
  341. // Calculate the longitude lines on the inner surface
  342. if (hasInnerSurface) {
  343. for (i = 0; i < subdivisions; i++) {
  344. for (j = 0; j < slicePartitions; j++) {
  345. positions[index++] = innerRadii.x * sinPhi[i] * cosTheta[j];
  346. positions[index++] = innerRadii.y * sinPhi[i] * sinTheta[j];
  347. positions[index++] = innerRadii.z * cosPhi[i];
  348. }
  349. }
  350. }
  351. // Create indices for the latitude lines
  352. index = 0;
  353. for (i = 0; i < stackPartitions * vertexMultiplier; i++) {
  354. const topOffset = i * subdivisions;
  355. for (j = 0; j < subdivisions - 1; j++) {
  356. indices[index++] = topOffset + j;
  357. indices[index++] = topOffset + j + 1;
  358. }
  359. }
  360. // Create indices for the outer longitude lines
  361. let offset = stackPartitions * subdivisions * vertexMultiplier;
  362. for (i = 0; i < slicePartitions; i++) {
  363. for (j = 0; j < subdivisions - 1; j++) {
  364. indices[index++] = offset + i + j * slicePartitions;
  365. indices[index++] = offset + i + (j + 1) * slicePartitions;
  366. }
  367. }
  368. // Create indices for the inner longitude lines
  369. if (hasInnerSurface) {
  370. offset =
  371. stackPartitions * subdivisions * vertexMultiplier +
  372. slicePartitions * subdivisions;
  373. for (i = 0; i < slicePartitions; i++) {
  374. for (j = 0; j < subdivisions - 1; j++) {
  375. indices[index++] = offset + i + j * slicePartitions;
  376. indices[index++] = offset + i + (j + 1) * slicePartitions;
  377. }
  378. }
  379. }
  380. if (hasInnerSurface) {
  381. let outerOffset = stackPartitions * subdivisions * vertexMultiplier;
  382. let innerOffset = outerOffset + subdivisions * slicePartitions;
  383. if (isTopOpen) {
  384. // Draw lines from the top of the inner surface to the top of the outer surface
  385. for (i = 0; i < slicePartitions; i++) {
  386. indices[index++] = outerOffset + i;
  387. indices[index++] = innerOffset + i;
  388. }
  389. }
  390. if (isBotOpen) {
  391. // Draw lines from the top of the inner surface to the top of the outer surface
  392. outerOffset += subdivisions * slicePartitions - slicePartitions;
  393. innerOffset += subdivisions * slicePartitions - slicePartitions;
  394. for (i = 0; i < slicePartitions; i++) {
  395. indices[index++] = outerOffset + i;
  396. indices[index++] = innerOffset + i;
  397. }
  398. }
  399. }
  400. const attributes = new GeometryAttributes.GeometryAttributes({
  401. position: new GeometryAttribute.GeometryAttribute({
  402. componentDatatype: ComponentDatatype.ComponentDatatype.DOUBLE,
  403. componentsPerAttribute: 3,
  404. values: positions,
  405. }),
  406. });
  407. if (defaultValue.defined(ellipsoidGeometry._offsetAttribute)) {
  408. const length = positions.length;
  409. const offsetValue =
  410. ellipsoidGeometry._offsetAttribute === GeometryOffsetAttribute.GeometryOffsetAttribute.NONE
  411. ? 0
  412. : 1;
  413. const applyOffset = new Uint8Array(length / 3).fill(offsetValue);
  414. attributes.applyOffset = new GeometryAttribute.GeometryAttribute({
  415. componentDatatype: ComponentDatatype.ComponentDatatype.UNSIGNED_BYTE,
  416. componentsPerAttribute: 1,
  417. values: applyOffset,
  418. });
  419. }
  420. return new GeometryAttribute.Geometry({
  421. attributes: attributes,
  422. indices: indices,
  423. primitiveType: GeometryAttribute.PrimitiveType.LINES,
  424. boundingSphere: Transforms.BoundingSphere.fromEllipsoid(ellipsoid),
  425. offsetAttribute: ellipsoidGeometry._offsetAttribute,
  426. });
  427. };
  428. exports.EllipsoidOutlineGeometry = EllipsoidOutlineGeometry;
  429. }));
  430. //# sourceMappingURL=EllipsoidOutlineGeometry-2f8770f8.js.map