WallOutlineGeometry.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. import BoundingSphere from './BoundingSphere.js';
  2. import Cartesian3 from './Cartesian3.js';
  3. import ComponentDatatype from './ComponentDatatype.js';
  4. import defaultValue from './defaultValue.js';
  5. import defined from './defined.js';
  6. import DeveloperError from './DeveloperError.js';
  7. import Ellipsoid from './Ellipsoid.js';
  8. import Geometry from './Geometry.js';
  9. import GeometryAttribute from './GeometryAttribute.js';
  10. import GeometryAttributes from './GeometryAttributes.js';
  11. import IndexDatatype from './IndexDatatype.js';
  12. import CesiumMath from './Math.js';
  13. import PrimitiveType from './PrimitiveType.js';
  14. import WallGeometryLibrary from './WallGeometryLibrary.js';
  15. var scratchCartesian3Position1 = new Cartesian3();
  16. var scratchCartesian3Position2 = new Cartesian3();
  17. /**
  18. * A description of a wall outline. A wall is defined by a series of points,
  19. * which extrude down to the ground. Optionally, they can extrude downwards to a specified height.
  20. *
  21. * @alias WallOutlineGeometry
  22. * @constructor
  23. *
  24. * @param {Object} options Object with the following properties:
  25. * @param {Cartesian3[]} options.positions An array of Cartesian objects, which are the points of the wall.
  26. * @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.
  27. * @param {Number[]} [options.maximumHeights] An array parallel to <code>positions</code> that give the maximum height of the
  28. * wall at <code>positions</code>. If undefined, the height of each position in used.
  29. * @param {Number[]} [options.minimumHeights] An array parallel to <code>positions</code> that give the minimum height of the
  30. * wall at <code>positions</code>. If undefined, the height at each position is 0.0.
  31. * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid for coordinate manipulation
  32. *
  33. * @exception {DeveloperError} positions length must be greater than or equal to 2.
  34. * @exception {DeveloperError} positions and maximumHeights must have the same length.
  35. * @exception {DeveloperError} positions and minimumHeights must have the same length.
  36. *
  37. * @see WallGeometry#createGeometry
  38. * @see WallGeometry#fromConstantHeight
  39. *
  40. * @example
  41. * // create a wall outline that spans from ground level to 10000 meters
  42. * var wall = new Cesium.WallOutlineGeometry({
  43. * positions : Cesium.Cartesian3.fromDegreesArrayHeights([
  44. * 19.0, 47.0, 10000.0,
  45. * 19.0, 48.0, 10000.0,
  46. * 20.0, 48.0, 10000.0,
  47. * 20.0, 47.0, 10000.0,
  48. * 19.0, 47.0, 10000.0
  49. * ])
  50. * });
  51. * var geometry = Cesium.WallOutlineGeometry.createGeometry(wall);
  52. */
  53. function WallOutlineGeometry(options) {
  54. options = defaultValue(options, defaultValue.EMPTY_OBJECT);
  55. var wallPositions = options.positions;
  56. var maximumHeights = options.maximumHeights;
  57. var minimumHeights = options.minimumHeights;
  58. //>>includeStart('debug', pragmas.debug);
  59. if (!defined(wallPositions)) {
  60. throw new DeveloperError('options.positions is required.');
  61. }
  62. if (defined(maximumHeights) && maximumHeights.length !== wallPositions.length) {
  63. throw new DeveloperError('options.positions and options.maximumHeights must have the same length.');
  64. }
  65. if (defined(minimumHeights) && minimumHeights.length !== wallPositions.length) {
  66. throw new DeveloperError('options.positions and options.minimumHeights must have the same length.');
  67. }
  68. //>>includeEnd('debug');
  69. var granularity = defaultValue(options.granularity, CesiumMath.RADIANS_PER_DEGREE);
  70. var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);
  71. this._positions = wallPositions;
  72. this._minimumHeights = minimumHeights;
  73. this._maximumHeights = maximumHeights;
  74. this._granularity = granularity;
  75. this._ellipsoid = Ellipsoid.clone(ellipsoid);
  76. this._workerName = 'createWallOutlineGeometry';
  77. var numComponents = 1 + wallPositions.length * Cartesian3.packedLength + 2;
  78. if (defined(minimumHeights)) {
  79. numComponents += minimumHeights.length;
  80. }
  81. if (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 + 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 (!defined(value)) {
  102. throw new DeveloperError('value is required');
  103. }
  104. if (!defined(array)) {
  105. throw new DeveloperError('array is required');
  106. }
  107. //>>includeEnd('debug');
  108. startingIndex = defaultValue(startingIndex, 0);
  109. var i;
  110. var positions = value._positions;
  111. var length = positions.length;
  112. array[startingIndex++] = length;
  113. for (i = 0; i < length; ++i, startingIndex += Cartesian3.packedLength) {
  114. Cartesian3.pack(positions[i], array, startingIndex);
  115. }
  116. var minimumHeights = value._minimumHeights;
  117. length = defined(minimumHeights) ? minimumHeights.length : 0;
  118. array[startingIndex++] = length;
  119. if (defined(minimumHeights)) {
  120. for (i = 0; i < length; ++i) {
  121. array[startingIndex++] = minimumHeights[i];
  122. }
  123. }
  124. var maximumHeights = value._maximumHeights;
  125. length = defined(maximumHeights) ? maximumHeights.length : 0;
  126. array[startingIndex++] = length;
  127. if (defined(maximumHeights)) {
  128. for (i = 0; i < length; ++i) {
  129. array[startingIndex++] = maximumHeights[i];
  130. }
  131. }
  132. Ellipsoid.pack(value._ellipsoid, array, startingIndex);
  133. startingIndex += Ellipsoid.packedLength;
  134. array[startingIndex] = value._granularity;
  135. return array;
  136. };
  137. var scratchEllipsoid = Ellipsoid.clone(Ellipsoid.UNIT_SPHERE);
  138. var 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 (!defined(array)) {
  156. throw new DeveloperError('array is required');
  157. }
  158. //>>includeEnd('debug');
  159. startingIndex = defaultValue(startingIndex, 0);
  160. var i;
  161. var length = array[startingIndex++];
  162. var positions = new Array(length);
  163. for (i = 0; i < length; ++i, startingIndex += Cartesian3.packedLength) {
  164. positions[i] = Cartesian3.unpack(array, startingIndex);
  165. }
  166. length = array[startingIndex++];
  167. var 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. var 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. var ellipsoid = Ellipsoid.unpack(array, startingIndex, scratchEllipsoid);
  183. startingIndex += Ellipsoid.packedLength;
  184. var granularity = array[startingIndex];
  185. if (!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 = 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. * var 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. * var geometry = Cesium.WallOutlineGeometry.createGeometry(wall);
  227. *
  228. * @see WallOutlineGeometry#createGeometry
  229. */
  230. WallOutlineGeometry.fromConstantHeights = function(options) {
  231. options = defaultValue(options, defaultValue.EMPTY_OBJECT);
  232. var positions = options.positions;
  233. //>>includeStart('debug', pragmas.debug);
  234. if (!defined(positions)) {
  235. throw new DeveloperError('options.positions is required.');
  236. }
  237. //>>includeEnd('debug');
  238. var minHeights;
  239. var maxHeights;
  240. var min = options.minimumHeight;
  241. var max = options.maximumHeight;
  242. var doMin = defined(min);
  243. var doMax = defined(max);
  244. if (doMin || doMax) {
  245. var length = positions.length;
  246. minHeights = (doMin) ? new Array(length) : undefined;
  247. maxHeights = (doMax) ? new Array(length) : undefined;
  248. for (var i = 0; i < length; ++i) {
  249. if (doMin) {
  250. minHeights[i] = min;
  251. }
  252. if (doMax) {
  253. maxHeights[i] = max;
  254. }
  255. }
  256. }
  257. var 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. var wallPositions = wallGeometry._positions;
  273. var minimumHeights = wallGeometry._minimumHeights;
  274. var maximumHeights = wallGeometry._maximumHeights;
  275. var granularity = wallGeometry._granularity;
  276. var ellipsoid = wallGeometry._ellipsoid;
  277. var pos = WallGeometryLibrary.computePositions(ellipsoid, wallPositions, maximumHeights, minimumHeights, granularity, false);
  278. if (!defined(pos)) {
  279. return;
  280. }
  281. var bottomPositions = pos.bottomPositions;
  282. var topPositions = pos.topPositions;
  283. var length = topPositions.length;
  284. var size = length * 2;
  285. var positions = new Float64Array(size);
  286. var positionIndex = 0;
  287. // add lower and upper points one after the other, lower
  288. // points being even and upper points being odd
  289. length /= 3;
  290. var i;
  291. for (i = 0; i < length; ++i) {
  292. var i3 = i * 3;
  293. var topPosition = Cartesian3.fromArray(topPositions, i3, scratchCartesian3Position1);
  294. var bottomPosition = Cartesian3.fromArray(bottomPositions, i3, scratchCartesian3Position2);
  295. // insert the lower point
  296. positions[positionIndex++] = bottomPosition.x;
  297. positions[positionIndex++] = bottomPosition.y;
  298. positions[positionIndex++] = bottomPosition.z;
  299. // insert the upper point
  300. positions[positionIndex++] = topPosition.x;
  301. positions[positionIndex++] = topPosition.y;
  302. positions[positionIndex++] = topPosition.z;
  303. }
  304. var attributes = new GeometryAttributes({
  305. position : new GeometryAttribute({
  306. componentDatatype : ComponentDatatype.DOUBLE,
  307. componentsPerAttribute : 3,
  308. values : positions
  309. })
  310. });
  311. var numVertices = size / 3;
  312. size = 2 * numVertices - 4 + numVertices;
  313. var indices = IndexDatatype.createTypedArray(numVertices, size);
  314. var edgeIndex = 0;
  315. for (i = 0; i < numVertices - 2; i += 2) {
  316. var LL = i;
  317. var LR = i + 2;
  318. var pl = Cartesian3.fromArray(positions, LL * 3, scratchCartesian3Position1);
  319. var pr = Cartesian3.fromArray(positions, LR * 3, scratchCartesian3Position2);
  320. if (Cartesian3.equalsEpsilon(pl, pr, CesiumMath.EPSILON10)) {
  321. continue;
  322. }
  323. var UL = i + 1;
  324. var UR = i + 3;
  325. indices[edgeIndex++] = UL;
  326. indices[edgeIndex++] = LL;
  327. indices[edgeIndex++] = UL;
  328. indices[edgeIndex++] = UR;
  329. indices[edgeIndex++] = LL;
  330. indices[edgeIndex++] = LR;
  331. }
  332. indices[edgeIndex++] = numVertices - 2;
  333. indices[edgeIndex++] = numVertices - 1;
  334. return new Geometry({
  335. attributes : attributes,
  336. indices : indices,
  337. primitiveType : PrimitiveType.LINES,
  338. boundingSphere : new BoundingSphere.fromVertices(positions)
  339. });
  340. };
  341. export default WallOutlineGeometry;