createWallOutlineGeometry.js 16 KB

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