CylinderOutlineGeometry.js 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. import arrayFill from "./arrayFill.js";
  2. import BoundingSphere from "./BoundingSphere.js";
  3. import Cartesian2 from "./Cartesian2.js";
  4. import Cartesian3 from "./Cartesian3.js";
  5. import Check from "./Check.js";
  6. import ComponentDatatype from "./ComponentDatatype.js";
  7. import CylinderGeometryLibrary from "./CylinderGeometryLibrary.js";
  8. import defaultValue from "./defaultValue.js";
  9. import defined from "./defined.js";
  10. import DeveloperError from "./DeveloperError.js";
  11. import Geometry from "./Geometry.js";
  12. import GeometryAttribute from "./GeometryAttribute.js";
  13. import GeometryAttributes from "./GeometryAttributes.js";
  14. import GeometryOffsetAttribute from "./GeometryOffsetAttribute.js";
  15. import IndexDatatype from "./IndexDatatype.js";
  16. import PrimitiveType from "./PrimitiveType.js";
  17. const radiusScratch = new Cartesian2();
  18. /**
  19. * A description of the outline of a cylinder.
  20. *
  21. * @alias CylinderOutlineGeometry
  22. * @constructor
  23. *
  24. * @param {Object} options Object with the following properties:
  25. * @param {Number} options.length The length of the cylinder.
  26. * @param {Number} options.topRadius The radius of the top of the cylinder.
  27. * @param {Number} options.bottomRadius The radius of the bottom of the cylinder.
  28. * @param {Number} [options.slices=128] The number of edges around the perimeter of the cylinder.
  29. * @param {Number} [options.numberOfVerticalLines=16] Number of lines to draw between the top and bottom surfaces of the cylinder.
  30. *
  31. * @exception {DeveloperError} options.length must be greater than 0.
  32. * @exception {DeveloperError} options.topRadius must be greater than 0.
  33. * @exception {DeveloperError} options.bottomRadius must be greater than 0.
  34. * @exception {DeveloperError} bottomRadius and topRadius cannot both equal 0.
  35. * @exception {DeveloperError} options.slices must be greater than or equal to 3.
  36. *
  37. * @see CylinderOutlineGeometry.createGeometry
  38. *
  39. * @example
  40. * // create cylinder geometry
  41. * const cylinder = new Cesium.CylinderOutlineGeometry({
  42. * length: 200000,
  43. * topRadius: 80000,
  44. * bottomRadius: 200000,
  45. * });
  46. * const geometry = Cesium.CylinderOutlineGeometry.createGeometry(cylinder);
  47. */
  48. function CylinderOutlineGeometry(options) {
  49. options = defaultValue(options, defaultValue.EMPTY_OBJECT);
  50. const length = options.length;
  51. const topRadius = options.topRadius;
  52. const bottomRadius = options.bottomRadius;
  53. const slices = defaultValue(options.slices, 128);
  54. const numberOfVerticalLines = Math.max(
  55. defaultValue(options.numberOfVerticalLines, 16),
  56. 0
  57. );
  58. //>>includeStart('debug', pragmas.debug);
  59. Check.typeOf.number("options.positions", length);
  60. Check.typeOf.number("options.topRadius", topRadius);
  61. Check.typeOf.number("options.bottomRadius", bottomRadius);
  62. Check.typeOf.number.greaterThanOrEquals("options.slices", slices, 3);
  63. if (
  64. defined(options.offsetAttribute) &&
  65. options.offsetAttribute === GeometryOffsetAttribute.TOP
  66. ) {
  67. throw new DeveloperError(
  68. "GeometryOffsetAttribute.TOP is not a supported options.offsetAttribute for this geometry."
  69. );
  70. }
  71. //>>includeEnd('debug');
  72. this._length = length;
  73. this._topRadius = topRadius;
  74. this._bottomRadius = bottomRadius;
  75. this._slices = slices;
  76. this._numberOfVerticalLines = numberOfVerticalLines;
  77. this._offsetAttribute = options.offsetAttribute;
  78. this._workerName = "createCylinderOutlineGeometry";
  79. }
  80. /**
  81. * The number of elements used to pack the object into an array.
  82. * @type {Number}
  83. */
  84. CylinderOutlineGeometry.packedLength = 6;
  85. /**
  86. * Stores the provided instance into the provided array.
  87. *
  88. * @param {CylinderOutlineGeometry} value The value to pack.
  89. * @param {Number[]} array The array to pack into.
  90. * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.
  91. *
  92. * @returns {Number[]} The array that was packed into
  93. */
  94. CylinderOutlineGeometry.pack = function (value, array, startingIndex) {
  95. //>>includeStart('debug', pragmas.debug);
  96. Check.typeOf.object("value", value);
  97. Check.defined("array", array);
  98. //>>includeEnd('debug');
  99. startingIndex = defaultValue(startingIndex, 0);
  100. array[startingIndex++] = value._length;
  101. array[startingIndex++] = value._topRadius;
  102. array[startingIndex++] = value._bottomRadius;
  103. array[startingIndex++] = value._slices;
  104. array[startingIndex++] = value._numberOfVerticalLines;
  105. array[startingIndex] = defaultValue(value._offsetAttribute, -1);
  106. return array;
  107. };
  108. const scratchOptions = {
  109. length: undefined,
  110. topRadius: undefined,
  111. bottomRadius: undefined,
  112. slices: undefined,
  113. numberOfVerticalLines: undefined,
  114. offsetAttribute: undefined,
  115. };
  116. /**
  117. * Retrieves an instance from a packed array.
  118. *
  119. * @param {Number[]} array The packed array.
  120. * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.
  121. * @param {CylinderOutlineGeometry} [result] The object into which to store the result.
  122. * @returns {CylinderOutlineGeometry} The modified result parameter or a new CylinderOutlineGeometry instance if one was not provided.
  123. */
  124. CylinderOutlineGeometry.unpack = function (array, startingIndex, result) {
  125. //>>includeStart('debug', pragmas.debug);
  126. Check.defined("array", array);
  127. //>>includeEnd('debug');
  128. startingIndex = defaultValue(startingIndex, 0);
  129. const length = array[startingIndex++];
  130. const topRadius = array[startingIndex++];
  131. const bottomRadius = array[startingIndex++];
  132. const slices = array[startingIndex++];
  133. const numberOfVerticalLines = array[startingIndex++];
  134. const offsetAttribute = array[startingIndex];
  135. if (!defined(result)) {
  136. scratchOptions.length = length;
  137. scratchOptions.topRadius = topRadius;
  138. scratchOptions.bottomRadius = bottomRadius;
  139. scratchOptions.slices = slices;
  140. scratchOptions.numberOfVerticalLines = numberOfVerticalLines;
  141. scratchOptions.offsetAttribute =
  142. offsetAttribute === -1 ? undefined : offsetAttribute;
  143. return new CylinderOutlineGeometry(scratchOptions);
  144. }
  145. result._length = length;
  146. result._topRadius = topRadius;
  147. result._bottomRadius = bottomRadius;
  148. result._slices = slices;
  149. result._numberOfVerticalLines = numberOfVerticalLines;
  150. result._offsetAttribute =
  151. offsetAttribute === -1 ? undefined : offsetAttribute;
  152. return result;
  153. };
  154. /**
  155. * Computes the geometric representation of an outline of a cylinder, including its vertices, indices, and a bounding sphere.
  156. *
  157. * @param {CylinderOutlineGeometry} cylinderGeometry A description of the cylinder outline.
  158. * @returns {Geometry|undefined} The computed vertices and indices.
  159. */
  160. CylinderOutlineGeometry.createGeometry = function (cylinderGeometry) {
  161. let length = cylinderGeometry._length;
  162. const topRadius = cylinderGeometry._topRadius;
  163. const bottomRadius = cylinderGeometry._bottomRadius;
  164. const slices = cylinderGeometry._slices;
  165. const numberOfVerticalLines = cylinderGeometry._numberOfVerticalLines;
  166. if (
  167. length <= 0 ||
  168. topRadius < 0 ||
  169. bottomRadius < 0 ||
  170. (topRadius === 0 && bottomRadius === 0)
  171. ) {
  172. return;
  173. }
  174. const numVertices = slices * 2;
  175. const positions = CylinderGeometryLibrary.computePositions(
  176. length,
  177. topRadius,
  178. bottomRadius,
  179. slices,
  180. false
  181. );
  182. let numIndices = slices * 2;
  183. let numSide;
  184. if (numberOfVerticalLines > 0) {
  185. const numSideLines = Math.min(numberOfVerticalLines, slices);
  186. numSide = Math.round(slices / numSideLines);
  187. numIndices += numSideLines;
  188. }
  189. const indices = IndexDatatype.createTypedArray(numVertices, numIndices * 2);
  190. let index = 0;
  191. let i;
  192. for (i = 0; i < slices - 1; i++) {
  193. indices[index++] = i;
  194. indices[index++] = i + 1;
  195. indices[index++] = i + slices;
  196. indices[index++] = i + 1 + slices;
  197. }
  198. indices[index++] = slices - 1;
  199. indices[index++] = 0;
  200. indices[index++] = slices + slices - 1;
  201. indices[index++] = slices;
  202. if (numberOfVerticalLines > 0) {
  203. for (i = 0; i < slices; i += numSide) {
  204. indices[index++] = i;
  205. indices[index++] = i + slices;
  206. }
  207. }
  208. const attributes = new GeometryAttributes();
  209. attributes.position = new GeometryAttribute({
  210. componentDatatype: ComponentDatatype.DOUBLE,
  211. componentsPerAttribute: 3,
  212. values: positions,
  213. });
  214. radiusScratch.x = length * 0.5;
  215. radiusScratch.y = Math.max(bottomRadius, topRadius);
  216. const boundingSphere = new BoundingSphere(
  217. Cartesian3.ZERO,
  218. Cartesian2.magnitude(radiusScratch)
  219. );
  220. if (defined(cylinderGeometry._offsetAttribute)) {
  221. length = positions.length;
  222. const applyOffset = new Uint8Array(length / 3);
  223. const offsetValue =
  224. cylinderGeometry._offsetAttribute === GeometryOffsetAttribute.NONE
  225. ? 0
  226. : 1;
  227. arrayFill(applyOffset, offsetValue);
  228. attributes.applyOffset = new GeometryAttribute({
  229. componentDatatype: ComponentDatatype.UNSIGNED_BYTE,
  230. componentsPerAttribute: 1,
  231. values: applyOffset,
  232. });
  233. }
  234. return new Geometry({
  235. attributes: attributes,
  236. indices: indices,
  237. primitiveType: PrimitiveType.LINES,
  238. boundingSphere: boundingSphere,
  239. offsetAttribute: cylinderGeometry._offsetAttribute,
  240. });
  241. };
  242. export default CylinderOutlineGeometry;