CylinderOutlineGeometry.js 8.8 KB

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