createWallOutlineGeometry.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. define(['./defaultValue-fe22d8c0', './Matrix3-41c58dde', './Transforms-bc45e707', './ComponentDatatype-cf1fa08e', './Check-6ede7e26', './GeometryAttribute-a466e9c7', './GeometryAttributes-ad136444', './IndexDatatype-2643aa47', './Math-0a2ac845', './WallGeometryLibrary-007e9883', './Matrix2-e1298525', './RuntimeError-ef395448', './combine-d9581036', './WebGLConstants-0b1ce7ba', './arrayRemoveDuplicates-d2061e85', './PolylinePipeline-896735cc', './EllipsoidGeodesic-5b3623dc', './EllipsoidRhumbLine-ef872433', './IntersectionTests-88c49b2e', './Plane-4c3d403b'], (function (defaultValue, Matrix3, Transforms, ComponentDatatype, Check, GeometryAttribute, GeometryAttributes, IndexDatatype, Math, WallGeometryLibrary, Matrix2, RuntimeError, combine, WebGLConstants, arrayRemoveDuplicates, PolylinePipeline, EllipsoidGeodesic, EllipsoidRhumbLine, IntersectionTests, Plane) { 'use strict';
  2. const scratchCartesian3Position1 = new Matrix3.Cartesian3();
  3. const scratchCartesian3Position2 = new Matrix3.Cartesian3();
  4. /**
  5. * A description of a wall outline. A wall is defined by a series of points,
  6. * which extrude down to the ground. Optionally, they can extrude downwards to a specified height.
  7. *
  8. * @alias WallOutlineGeometry
  9. * @constructor
  10. *
  11. * @param {object} options Object with the following properties:
  12. * @param {Cartesian3[]} options.positions An array of Cartesian objects, which are the points of the wall.
  13. * @param {number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer.
  14. * @param {number[]} [options.maximumHeights] An array parallel to <code>positions</code> that give the maximum height of the
  15. * wall at <code>positions</code>. If undefined, the height of each position in used.
  16. * @param {number[]} [options.minimumHeights] An array parallel to <code>positions</code> that give the minimum height of the
  17. * wall at <code>positions</code>. If undefined, the height at each position is 0.0.
  18. * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid for coordinate manipulation
  19. *
  20. * @exception {DeveloperError} positions length must be greater than or equal to 2.
  21. * @exception {DeveloperError} positions and maximumHeights must have the same length.
  22. * @exception {DeveloperError} positions and minimumHeights must have the same length.
  23. *
  24. * @see WallGeometry#createGeometry
  25. * @see WallGeometry#fromConstantHeight
  26. *
  27. * @example
  28. * // create a wall outline that spans from ground level to 10000 meters
  29. * const wall = new Cesium.WallOutlineGeometry({
  30. * positions : Cesium.Cartesian3.fromDegreesArrayHeights([
  31. * 19.0, 47.0, 10000.0,
  32. * 19.0, 48.0, 10000.0,
  33. * 20.0, 48.0, 10000.0,
  34. * 20.0, 47.0, 10000.0,
  35. * 19.0, 47.0, 10000.0
  36. * ])
  37. * });
  38. * const geometry = Cesium.WallOutlineGeometry.createGeometry(wall);
  39. */
  40. function WallOutlineGeometry(options) {
  41. options = defaultValue.defaultValue(options, defaultValue.defaultValue.EMPTY_OBJECT);
  42. const wallPositions = options.positions;
  43. const maximumHeights = options.maximumHeights;
  44. const minimumHeights = options.minimumHeights;
  45. //>>includeStart('debug', pragmas.debug);
  46. if (!defaultValue.defined(wallPositions)) {
  47. throw new Check.DeveloperError("options.positions is required.");
  48. }
  49. if (
  50. defaultValue.defined(maximumHeights) &&
  51. maximumHeights.length !== wallPositions.length
  52. ) {
  53. throw new Check.DeveloperError(
  54. "options.positions and options.maximumHeights must have the same length."
  55. );
  56. }
  57. if (
  58. defaultValue.defined(minimumHeights) &&
  59. minimumHeights.length !== wallPositions.length
  60. ) {
  61. throw new Check.DeveloperError(
  62. "options.positions and options.minimumHeights must have the same length."
  63. );
  64. }
  65. //>>includeEnd('debug');
  66. const granularity = defaultValue.defaultValue(
  67. options.granularity,
  68. Math.CesiumMath.RADIANS_PER_DEGREE
  69. );
  70. const ellipsoid = defaultValue.defaultValue(options.ellipsoid, Matrix3.Ellipsoid.WGS84);
  71. this._positions = wallPositions;
  72. this._minimumHeights = minimumHeights;
  73. this._maximumHeights = maximumHeights;
  74. this._granularity = granularity;
  75. this._ellipsoid = Matrix3.Ellipsoid.clone(ellipsoid);
  76. this._workerName = "createWallOutlineGeometry";
  77. let numComponents = 1 + wallPositions.length * Matrix3.Cartesian3.packedLength + 2;
  78. if (defaultValue.defined(minimumHeights)) {
  79. numComponents += minimumHeights.length;
  80. }
  81. if (defaultValue.defined(maximumHeights)) {
  82. numComponents += maximumHeights.length;
  83. }
  84. /**
  85. * The number of elements used to pack the object into an array.
  86. * @type {number}
  87. */
  88. this.packedLength = numComponents + Matrix3.Ellipsoid.packedLength + 1;
  89. }
  90. /**
  91. * Stores the provided instance into the provided array.
  92. *
  93. * @param {WallOutlineGeometry} value The value to pack.
  94. * @param {number[]} array The array to pack into.
  95. * @param {number} [startingIndex=0] The index into the array at which to start packing the elements.
  96. *
  97. * @returns {number[]} The array that was packed into
  98. */
  99. WallOutlineGeometry.pack = function (value, array, startingIndex) {
  100. //>>includeStart('debug', pragmas.debug);
  101. if (!defaultValue.defined(value)) {
  102. throw new Check.DeveloperError("value is required");
  103. }
  104. if (!defaultValue.defined(array)) {
  105. throw new Check.DeveloperError("array is required");
  106. }
  107. //>>includeEnd('debug');
  108. startingIndex = defaultValue.defaultValue(startingIndex, 0);
  109. let i;
  110. const positions = value._positions;
  111. let length = positions.length;
  112. array[startingIndex++] = length;
  113. for (i = 0; i < length; ++i, startingIndex += Matrix3.Cartesian3.packedLength) {
  114. Matrix3.Cartesian3.pack(positions[i], array, startingIndex);
  115. }
  116. const minimumHeights = value._minimumHeights;
  117. length = defaultValue.defined(minimumHeights) ? minimumHeights.length : 0;
  118. array[startingIndex++] = length;
  119. if (defaultValue.defined(minimumHeights)) {
  120. for (i = 0; i < length; ++i) {
  121. array[startingIndex++] = minimumHeights[i];
  122. }
  123. }
  124. const maximumHeights = value._maximumHeights;
  125. length = defaultValue.defined(maximumHeights) ? maximumHeights.length : 0;
  126. array[startingIndex++] = length;
  127. if (defaultValue.defined(maximumHeights)) {
  128. for (i = 0; i < length; ++i) {
  129. array[startingIndex++] = maximumHeights[i];
  130. }
  131. }
  132. Matrix3.Ellipsoid.pack(value._ellipsoid, array, startingIndex);
  133. startingIndex += Matrix3.Ellipsoid.packedLength;
  134. array[startingIndex] = value._granularity;
  135. return array;
  136. };
  137. const scratchEllipsoid = Matrix3.Ellipsoid.clone(Matrix3.Ellipsoid.UNIT_SPHERE);
  138. const scratchOptions = {
  139. positions: undefined,
  140. minimumHeights: undefined,
  141. maximumHeights: undefined,
  142. ellipsoid: scratchEllipsoid,
  143. granularity: undefined,
  144. };
  145. /**
  146. * Retrieves an instance from a packed array.
  147. *
  148. * @param {number[]} array The packed array.
  149. * @param {number} [startingIndex=0] The starting index of the element to be unpacked.
  150. * @param {WallOutlineGeometry} [result] The object into which to store the result.
  151. * @returns {WallOutlineGeometry} The modified result parameter or a new WallOutlineGeometry instance if one was not provided.
  152. */
  153. WallOutlineGeometry.unpack = function (array, startingIndex, result) {
  154. //>>includeStart('debug', pragmas.debug);
  155. if (!defaultValue.defined(array)) {
  156. throw new Check.DeveloperError("array is required");
  157. }
  158. //>>includeEnd('debug');
  159. startingIndex = defaultValue.defaultValue(startingIndex, 0);
  160. let i;
  161. let length = array[startingIndex++];
  162. const positions = new Array(length);
  163. for (i = 0; i < length; ++i, startingIndex += Matrix3.Cartesian3.packedLength) {
  164. positions[i] = Matrix3.Cartesian3.unpack(array, startingIndex);
  165. }
  166. length = array[startingIndex++];
  167. let minimumHeights;
  168. if (length > 0) {
  169. minimumHeights = new Array(length);
  170. for (i = 0; i < length; ++i) {
  171. minimumHeights[i] = array[startingIndex++];
  172. }
  173. }
  174. length = array[startingIndex++];
  175. let maximumHeights;
  176. if (length > 0) {
  177. maximumHeights = new Array(length);
  178. for (i = 0; i < length; ++i) {
  179. maximumHeights[i] = array[startingIndex++];
  180. }
  181. }
  182. const ellipsoid = Matrix3.Ellipsoid.unpack(array, startingIndex, scratchEllipsoid);
  183. startingIndex += Matrix3.Ellipsoid.packedLength;
  184. const granularity = array[startingIndex];
  185. if (!defaultValue.defined(result)) {
  186. scratchOptions.positions = positions;
  187. scratchOptions.minimumHeights = minimumHeights;
  188. scratchOptions.maximumHeights = maximumHeights;
  189. scratchOptions.granularity = granularity;
  190. return new WallOutlineGeometry(scratchOptions);
  191. }
  192. result._positions = positions;
  193. result._minimumHeights = minimumHeights;
  194. result._maximumHeights = maximumHeights;
  195. result._ellipsoid = Matrix3.Ellipsoid.clone(ellipsoid, result._ellipsoid);
  196. result._granularity = granularity;
  197. return result;
  198. };
  199. /**
  200. * A description of a walloutline. A wall is defined by a series of points,
  201. * which extrude down to the ground. Optionally, they can extrude downwards to a specified height.
  202. *
  203. * @param {object} options Object with the following properties:
  204. * @param {Cartesian3[]} options.positions An array of Cartesian objects, which are the points of the wall.
  205. * @param {number} [options.maximumHeight] A constant that defines the maximum height of the
  206. * wall at <code>positions</code>. If undefined, the height of each position in used.
  207. * @param {number} [options.minimumHeight] A constant that defines the minimum height of the
  208. * wall at <code>positions</code>. If undefined, the height at each position is 0.0.
  209. * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid for coordinate manipulation
  210. * @returns {WallOutlineGeometry}
  211. *
  212. *
  213. * @example
  214. * // create a wall that spans from 10000 meters to 20000 meters
  215. * const wall = Cesium.WallOutlineGeometry.fromConstantHeights({
  216. * positions : Cesium.Cartesian3.fromDegreesArray([
  217. * 19.0, 47.0,
  218. * 19.0, 48.0,
  219. * 20.0, 48.0,
  220. * 20.0, 47.0,
  221. * 19.0, 47.0,
  222. * ]),
  223. * minimumHeight : 20000.0,
  224. * maximumHeight : 10000.0
  225. * });
  226. * const geometry = Cesium.WallOutlineGeometry.createGeometry(wall);
  227. *
  228. * @see WallOutlineGeometry#createGeometry
  229. */
  230. WallOutlineGeometry.fromConstantHeights = function (options) {
  231. options = defaultValue.defaultValue(options, defaultValue.defaultValue.EMPTY_OBJECT);
  232. const positions = options.positions;
  233. //>>includeStart('debug', pragmas.debug);
  234. if (!defaultValue.defined(positions)) {
  235. throw new Check.DeveloperError("options.positions is required.");
  236. }
  237. //>>includeEnd('debug');
  238. let minHeights;
  239. let maxHeights;
  240. const min = options.minimumHeight;
  241. const max = options.maximumHeight;
  242. const doMin = defaultValue.defined(min);
  243. const doMax = defaultValue.defined(max);
  244. if (doMin || doMax) {
  245. const length = positions.length;
  246. minHeights = doMin ? new Array(length) : undefined;
  247. maxHeights = doMax ? new Array(length) : undefined;
  248. for (let i = 0; i < length; ++i) {
  249. if (doMin) {
  250. minHeights[i] = min;
  251. }
  252. if (doMax) {
  253. maxHeights[i] = max;
  254. }
  255. }
  256. }
  257. const newOptions = {
  258. positions: positions,
  259. maximumHeights: maxHeights,
  260. minimumHeights: minHeights,
  261. ellipsoid: options.ellipsoid,
  262. };
  263. return new WallOutlineGeometry(newOptions);
  264. };
  265. /**
  266. * Computes the geometric representation of a wall outline, including its vertices, indices, and a bounding sphere.
  267. *
  268. * @param {WallOutlineGeometry} wallGeometry A description of the wall outline.
  269. * @returns {Geometry|undefined} The computed vertices and indices.
  270. */
  271. WallOutlineGeometry.createGeometry = function (wallGeometry) {
  272. const wallPositions = wallGeometry._positions;
  273. const minimumHeights = wallGeometry._minimumHeights;
  274. const maximumHeights = wallGeometry._maximumHeights;
  275. const granularity = wallGeometry._granularity;
  276. const ellipsoid = wallGeometry._ellipsoid;
  277. const pos = WallGeometryLibrary.WallGeometryLibrary.computePositions(
  278. ellipsoid,
  279. wallPositions,
  280. maximumHeights,
  281. minimumHeights,
  282. granularity,
  283. false
  284. );
  285. if (!defaultValue.defined(pos)) {
  286. return;
  287. }
  288. const bottomPositions = pos.bottomPositions;
  289. const topPositions = pos.topPositions;
  290. let length = topPositions.length;
  291. let size = length * 2;
  292. const positions = new Float64Array(size);
  293. let positionIndex = 0;
  294. // add lower and upper points one after the other, lower
  295. // points being even and upper points being odd
  296. length /= 3;
  297. let i;
  298. for (i = 0; i < length; ++i) {
  299. const i3 = i * 3;
  300. const topPosition = Matrix3.Cartesian3.fromArray(
  301. topPositions,
  302. i3,
  303. scratchCartesian3Position1
  304. );
  305. const bottomPosition = Matrix3.Cartesian3.fromArray(
  306. bottomPositions,
  307. i3,
  308. scratchCartesian3Position2
  309. );
  310. // insert the lower point
  311. positions[positionIndex++] = bottomPosition.x;
  312. positions[positionIndex++] = bottomPosition.y;
  313. positions[positionIndex++] = bottomPosition.z;
  314. // insert the upper point
  315. positions[positionIndex++] = topPosition.x;
  316. positions[positionIndex++] = topPosition.y;
  317. positions[positionIndex++] = topPosition.z;
  318. }
  319. const attributes = new GeometryAttributes.GeometryAttributes({
  320. position: new GeometryAttribute.GeometryAttribute({
  321. componentDatatype: ComponentDatatype.ComponentDatatype.DOUBLE,
  322. componentsPerAttribute: 3,
  323. values: positions,
  324. }),
  325. });
  326. const numVertices = size / 3;
  327. size = 2 * numVertices - 4 + numVertices;
  328. const indices = IndexDatatype.IndexDatatype.createTypedArray(numVertices, size);
  329. let edgeIndex = 0;
  330. for (i = 0; i < numVertices - 2; i += 2) {
  331. const LL = i;
  332. const LR = i + 2;
  333. const pl = Matrix3.Cartesian3.fromArray(
  334. positions,
  335. LL * 3,
  336. scratchCartesian3Position1
  337. );
  338. const pr = Matrix3.Cartesian3.fromArray(
  339. positions,
  340. LR * 3,
  341. scratchCartesian3Position2
  342. );
  343. if (Matrix3.Cartesian3.equalsEpsilon(pl, pr, Math.CesiumMath.EPSILON10)) {
  344. continue;
  345. }
  346. const UL = i + 1;
  347. const UR = i + 3;
  348. indices[edgeIndex++] = UL;
  349. indices[edgeIndex++] = LL;
  350. indices[edgeIndex++] = UL;
  351. indices[edgeIndex++] = UR;
  352. indices[edgeIndex++] = LL;
  353. indices[edgeIndex++] = LR;
  354. }
  355. indices[edgeIndex++] = numVertices - 2;
  356. indices[edgeIndex++] = numVertices - 1;
  357. return new GeometryAttribute.Geometry({
  358. attributes: attributes,
  359. indices: indices,
  360. primitiveType: GeometryAttribute.PrimitiveType.LINES,
  361. boundingSphere: new Transforms.BoundingSphere.fromVertices(positions),
  362. });
  363. };
  364. function createWallOutlineGeometry(wallGeometry, offset) {
  365. if (defaultValue.defined(offset)) {
  366. wallGeometry = WallOutlineGeometry.unpack(wallGeometry, offset);
  367. }
  368. wallGeometry._ellipsoid = Matrix3.Ellipsoid.clone(wallGeometry._ellipsoid);
  369. return WallOutlineGeometry.createGeometry(wallGeometry);
  370. }
  371. return createWallOutlineGeometry;
  372. }));