CumulusCloud.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. import Cartesian2 from "../Core/Cartesian2.js";
  2. import Cartesian3 from "../Core/Cartesian3.js";
  3. import Check from "../Core/Check.js";
  4. import Color from "../Core/Color.js";
  5. import defaultValue from "../Core/defaultValue.js";
  6. import defined from "../Core/defined.js";
  7. /**
  8. * <div class="notice">
  9. * A cloud is created and its initial properties are set by calling {@link CloudCollection#add}.
  10. * and {@link CloudCollection#remove}. Do not call the constructor directly.
  11. * </div>
  12. * A cumulus cloud billboard positioned in the 3D scene, that is created and rendered using a {@link CloudCollection}.
  13. * <br /><br />
  14. * <div align='center'>
  15. * <img src='Images/CumulusCloud.png' width='400' height='300' /><br />
  16. * Example cumulus clouds
  17. * </div>
  18. * @alias CumulusCloud
  19. *
  20. * @performance Similar to {@link Billboard}, reading a property, e.g., {@link CumulusCloud#show},
  21. * takes constant time. Assigning to a property is constant time but results in
  22. * CPU to GPU traffic when {@link CloudCollection#update} is called. The per-cloud traffic is
  23. * the same regardless of how many properties were updated. If most clouds in a collection need to be
  24. * updated, it may be more efficient to clear the collection with {@link CloudCollection#removeAll}
  25. * and add new clouds instead of modifying each one.
  26. *
  27. * @see CloudCollection
  28. * @see CloudCollection#add
  29. *
  30. * @internalConstructor
  31. * @class
  32. *
  33. * @demo {@link https://sandcastle.cesium.com/index.html?src=Cloud%20Parameters.html|Cesium Sandcastle Cloud Parameters Demo}
  34. */
  35. function CumulusCloud(options, cloudCollection) {
  36. options = defaultValue(options, defaultValue.EMPTY_OBJECT);
  37. this._show = defaultValue(options.show, true);
  38. this._position = Cartesian3.clone(
  39. defaultValue(options.position, Cartesian3.ZERO)
  40. );
  41. if (!defined(options.scale) && defined(options.maximumSize)) {
  42. this._maximumSize = Cartesian3.clone(options.maximumSize);
  43. this._scale = new Cartesian2(this._maximumSize.x, this._maximumSize.y);
  44. } else {
  45. this._scale = Cartesian2.clone(
  46. defaultValue(options.scale, new Cartesian2(20.0, 12.0))
  47. );
  48. const defaultMaxSize = new Cartesian3(
  49. this._scale.x,
  50. this._scale.y,
  51. Math.min(this._scale.x, this._scale.y) / 1.5
  52. );
  53. this._maximumSize = Cartesian3.clone(
  54. defaultValue(options.maximumSize, defaultMaxSize)
  55. );
  56. }
  57. this._slice = defaultValue(options.slice, -1.0);
  58. this._color = Color.clone(defaultValue(options.color, Color.WHITE));
  59. this._brightness = defaultValue(options.brightness, 1.0);
  60. this._cloudCollection = cloudCollection;
  61. this._index = -1; // Used by CloudCollection
  62. }
  63. const SHOW_INDEX = (CumulusCloud.SHOW_INDEX = 0);
  64. const POSITION_INDEX = (CumulusCloud.POSITION_INDEX = 1);
  65. const SCALE_INDEX = (CumulusCloud.SCALE_INDEX = 2);
  66. const MAXIMUM_SIZE_INDEX = (CumulusCloud.MAXIMUM_SIZE_INDEX = 3);
  67. const SLICE_INDEX = (CumulusCloud.SLICE_INDEX = 4);
  68. const BRIGHTNESS_INDEX = (CumulusCloud.BRIGHTNESS_INDEX = 5);
  69. const COLOR_INDEX = (CumulusCloud.COLOR_INDEX = 6);
  70. CumulusCloud.NUMBER_OF_PROPERTIES = 7;
  71. function makeDirty(cloud, propertyChanged) {
  72. const cloudCollection = cloud._cloudCollection;
  73. if (defined(cloudCollection)) {
  74. cloudCollection._updateCloud(cloud, propertyChanged);
  75. cloud._dirty = true;
  76. }
  77. }
  78. Object.defineProperties(CumulusCloud.prototype, {
  79. /**
  80. * Determines if this cumulus cloud will be shown. Use this to hide or show a cloud, instead
  81. * of removing it and re-adding it to the collection.
  82. * @memberof CumulusCloud.prototype
  83. * @type {boolean}
  84. * @default true
  85. */
  86. show: {
  87. get: function () {
  88. return this._show;
  89. },
  90. set: function (value) {
  91. //>>includeStart('debug', pragmas.debug);
  92. Check.typeOf.bool("value", value);
  93. //>>includeEnd('debug');
  94. if (this._show !== value) {
  95. this._show = value;
  96. makeDirty(this, SHOW_INDEX);
  97. }
  98. },
  99. },
  100. /**
  101. * Gets or sets the Cartesian position of this cumulus cloud.
  102. * @memberof CumulusCloud.prototype
  103. * @type {Cartesian3}
  104. */
  105. position: {
  106. get: function () {
  107. return this._position;
  108. },
  109. set: function (value) {
  110. //>>includeStart('debug', pragmas.debug)
  111. Check.typeOf.object("value", value);
  112. //>>includeEnd('debug');
  113. const position = this._position;
  114. if (!Cartesian3.equals(position, value)) {
  115. Cartesian3.clone(value, position);
  116. makeDirty(this, POSITION_INDEX);
  117. }
  118. },
  119. },
  120. /**
  121. * <p>Gets or sets the scale of the cumulus cloud billboard in meters.
  122. * The <code>scale</code> property will affect the size of the billboard,
  123. * but not the cloud's actual appearance.</p>
  124. * <div align='center'>
  125. * <table border='0' cellpadding='5'><tr>
  126. * <td align='center'>
  127. * <code>cloud.scale = new Cesium.Cartesian2(12, 8);</code><br/>
  128. * <img src='Images/CumulusCloud.scalex12y8.png' width='250' height='158' />
  129. * </td>
  130. * <td align='center'>
  131. * <code>cloud.scale = new Cesium.Cartesian2(24, 10);</code><br/>
  132. * <img src='Images/CumulusCloud.scalex24y10.png' width='250' height='158' />
  133. * </td>
  134. * </tr></table>
  135. * </div>
  136. *
  137. * <p>To modify the cloud's appearance, modify its <code>maximumSize</code>
  138. * and <code>slice</code> properties.</p>
  139. * @memberof CumulusCloud.prototype
  140. * @type {Cartesian2}
  141. *
  142. * @see CumulusCloud#maximumSize
  143. * @see CumulusCloud#slice
  144. */
  145. scale: {
  146. get: function () {
  147. return this._scale;
  148. },
  149. set: function (value) {
  150. //>>includeStart('debug', pragmas.debug)
  151. Check.typeOf.object("value", value);
  152. //>>includeEnd('debug');
  153. const scale = this._scale;
  154. if (!Cartesian2.equals(scale, value)) {
  155. Cartesian2.clone(value, scale);
  156. makeDirty(this, SCALE_INDEX);
  157. }
  158. },
  159. },
  160. /**
  161. * <p>Gets or sets the maximum size of the cumulus cloud rendered on the billboard.
  162. * This defines a maximum ellipsoid volume that the cloud can appear in.
  163. * Rather than guaranteeing a specific size, this specifies a boundary for the
  164. * cloud to appear in, and changing it can affect the shape of the cloud.</p>
  165. * <p>Changing the z-value of <code>maximumSize</code> has the most dramatic effect
  166. * on the cloud's appearance because it changes the depth of the cloud, and thus the
  167. * positions at which the cloud-shaping texture is sampled.</p>
  168. * <div align='center'>
  169. * <table border='0' cellpadding='5'>
  170. * <tr>
  171. * <td align='center'>
  172. * <code>cloud.maximumSize = new Cesium.Cartesian3(14, 9, 10);</code><br/>
  173. * <img src='Images/CumulusCloud.maximumSizex14y9z10.png' width='250' height='158' />
  174. * </td>
  175. * <td align='center'>
  176. * <code>cloud.maximumSize.x = 25;</code><br/>
  177. * <img src='Images/CumulusCloud.maximumSizex25.png' width='250' height='158' />
  178. * </td>
  179. * </tr>
  180. * <tr>
  181. * <td align='center'>
  182. * <code>cloud.maximumSize.y = 5;</code><br/>
  183. * <img src='Images/CumulusCloud.maximumSizey5.png' width='250' height='158' />
  184. * </td>
  185. * <td align='center'>
  186. * <code>cloud.maximumSize.z = 17;</code><br/>
  187. * <img src='Images/CumulusCloud.maximumSizez17.png' width='250' height='158' />
  188. * </td>
  189. * </tr>
  190. * </table>
  191. * </div>
  192. *
  193. * <p>To modify the billboard's actual size, modify the cloud's <code>scale</code> property.</p>
  194. * @memberof CumulusCloud.prototype
  195. * @type {Cartesian3}
  196. *
  197. * @see CumulusCloud#scale
  198. */
  199. maximumSize: {
  200. get: function () {
  201. return this._maximumSize;
  202. },
  203. set: function (value) {
  204. //>>includeStart('debug', pragmas.debug)
  205. Check.typeOf.object("value", value);
  206. //>>includeEnd('debug');
  207. const maximumSize = this._maximumSize;
  208. if (!Cartesian3.equals(maximumSize, value)) {
  209. Cartesian3.clone(value, maximumSize);
  210. makeDirty(this, MAXIMUM_SIZE_INDEX);
  211. }
  212. },
  213. },
  214. /**
  215. * Sets the color of the cloud
  216. * @memberof CumulusCloud.prototype
  217. * @type {Color}
  218. * @default Color.WHITE
  219. */
  220. color: {
  221. get: function () {
  222. return this._color;
  223. },
  224. set: function (value) {
  225. //>>includeStart('debug', pragmas.debug)
  226. Check.typeOf.object("value", value);
  227. //>>includeEnd('debug');
  228. const color = this._color;
  229. if (!Color.equals(color, value)) {
  230. Color.clone(value, color);
  231. makeDirty(this, COLOR_INDEX);
  232. }
  233. },
  234. },
  235. /**
  236. * <p>Gets or sets the "slice" of the cloud that is rendered on the billboard, i.e.
  237. * the specific cross-section of the cloud chosen for the billboard's appearance.
  238. * Given a value between 0 and 1, the slice specifies how deeply into the cloud
  239. * to intersect based on its maximum size in the z-direction.</p>
  240. * <div align='center'>
  241. * <table border='0' cellpadding='5'><tr>
  242. * <td align='center'><code>cloud.slice = 0.32;</code><br/><img src='Images/CumulusCloud.slice0.32.png' width='250' height='158' /></td>
  243. * <td align='center'><code>cloud.slice = 0.5;</code><br/><img src='Images/CumulusCloud.slice0.5.png' width='250' height='158' /></td>
  244. * <td align='center'><code>cloud.slice = 0.6;</code><br/><img src='Images/CumulusCloud.slice0.6.png' width='250' height='158' /></td>
  245. * </tr></table>
  246. * </div>
  247. *
  248. * <br />
  249. * <p>Due to the nature in which this slice is calculated,
  250. * values below <code>0.2</code> may result in cross-sections that are too small,
  251. * and the edge of the ellipsoid will be visible. Similarly, values above <code>0.7</code>
  252. * will cause the cloud to appear smaller. Values outside the range <code>[0.1, 0.9]</code>
  253. * should be avoided entirely because they do not produce desirable results.</p>
  254. *
  255. * <div align='center'>
  256. * <table border='0' cellpadding='5'><tr>
  257. * <td align='center'><code>cloud.slice = 0.08;</code><br/><img src='Images/CumulusCloud.slice0.08.png' width='250' height='158' /></td>
  258. * <td align='center'><code>cloud.slice = 0.8;</code><br/><img src='Images/CumulusCloud.slice0.8.png' width='250' height='158' /></td>
  259. * </tr></table>
  260. * </div>
  261. *
  262. * <p>If <code>slice</code> is set to a negative number, the cloud will not render a cross-section.
  263. * Instead, it will render the outside of the ellipsoid that is visible. For clouds with
  264. * small values of `maximumSize.z`, this can produce good-looking results, but for larger
  265. * clouds, this can result in a cloud that is undesirably warped to the ellipsoid volume.</p>
  266. *
  267. * <div align='center'>
  268. * <table border='0' cellpadding='5'><tr>
  269. * <td align='center'>
  270. * <code>cloud.slice = -1.0;<br/>cloud.maximumSize.z = 18;</code><br/>
  271. * <img src='Images/CumulusCloud.slice-1z18.png' width='250' height='158' />
  272. * </td>
  273. * <td align='center'>
  274. * <code>cloud.slice = -1.0;<br/>cloud.maximumSize.z = 30;</code><br/>
  275. * <img src='Images/CumulusCloud.slice-1z30.png' width='250' height='158' /></td>
  276. * </tr></table>
  277. * </div>
  278. *
  279. * @memberof CumulusCloud.prototype
  280. * @type {number}
  281. * @default -1.0
  282. */
  283. slice: {
  284. get: function () {
  285. return this._slice;
  286. },
  287. set: function (value) {
  288. //>>includeStart('debug', pragmas.debug)
  289. Check.typeOf.number("value", value);
  290. //>>includeEnd('debug');
  291. const slice = this._slice;
  292. if (slice !== value) {
  293. this._slice = value;
  294. makeDirty(this, SLICE_INDEX);
  295. }
  296. },
  297. },
  298. /**
  299. * Gets or sets the brightness of the cloud. This can be used to give clouds
  300. * a darker, grayer appearance.
  301. * <br /><br />
  302. * <div align='center'>
  303. * <table border='0' cellpadding='5'><tr>
  304. * <td align='center'><code>cloud.brightness = 1.0;</code><br/><img src='Images/CumulusCloud.brightness1.png' width='250' height='158' /></td>
  305. * <td align='center'><code>cloud.brightness = 0.6;</code><br/><img src='Images/CumulusCloud.brightness0.6.png' width='250' height='158' /></td>
  306. * <td align='center'><code>cloud.brightness = 0.0;</code><br/><img src='Images/CumulusCloud.brightness0.png' width='250' height='158' /></td>
  307. * </tr></table>
  308. * </div>
  309. * @memberof CumulusCloud.prototype
  310. * @type {number}
  311. * @default 1.0
  312. */
  313. brightness: {
  314. get: function () {
  315. return this._brightness;
  316. },
  317. set: function (value) {
  318. //>>includeStart('debug', pragmas.debug)
  319. Check.typeOf.number("value", value);
  320. //>>includeEnd('debug');
  321. const brightness = this._brightness;
  322. if (brightness !== value) {
  323. this._brightness = value;
  324. makeDirty(this, BRIGHTNESS_INDEX);
  325. }
  326. },
  327. },
  328. });
  329. CumulusCloud.prototype._destroy = function () {
  330. this._cloudCollection = undefined;
  331. };
  332. export default CumulusCloud;