RectangleGeometryUpdater.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  1. /*global define*/
  2. define([
  3. '../Core/Color',
  4. '../Core/ColorGeometryInstanceAttribute',
  5. '../Core/defaultValue',
  6. '../Core/defined',
  7. '../Core/defineProperties',
  8. '../Core/destroyObject',
  9. '../Core/DeveloperError',
  10. '../Core/Event',
  11. '../Core/GeometryInstance',
  12. '../Core/Iso8601',
  13. '../Core/RectangleGeometry',
  14. '../Core/RectangleOutlineGeometry',
  15. '../Core/ShowGeometryInstanceAttribute',
  16. '../Scene/MaterialAppearance',
  17. '../Scene/PerInstanceColorAppearance',
  18. '../Scene/Primitive',
  19. './ColorMaterialProperty',
  20. './ConstantProperty',
  21. './MaterialProperty',
  22. './Property'
  23. ], function(
  24. Color,
  25. ColorGeometryInstanceAttribute,
  26. defaultValue,
  27. defined,
  28. defineProperties,
  29. destroyObject,
  30. DeveloperError,
  31. Event,
  32. GeometryInstance,
  33. Iso8601,
  34. RectangleGeometry,
  35. RectangleOutlineGeometry,
  36. ShowGeometryInstanceAttribute,
  37. MaterialAppearance,
  38. PerInstanceColorAppearance,
  39. Primitive,
  40. ColorMaterialProperty,
  41. ConstantProperty,
  42. MaterialProperty,
  43. Property) {
  44. "use strict";
  45. var defaultMaterial = ColorMaterialProperty.fromColor(Color.WHITE);
  46. var defaultShow = new ConstantProperty(true);
  47. var defaultFill = new ConstantProperty(true);
  48. var defaultOutline = new ConstantProperty(false);
  49. var defaultOutlineColor = new ConstantProperty(Color.BLACK);
  50. var scratchColor = new Color();
  51. var GeometryOptions = function(entity) {
  52. this.id = entity;
  53. this.vertexFormat = undefined;
  54. this.rectangle = undefined;
  55. this.closeBottom = undefined;
  56. this.closeTop = undefined;
  57. this.height = undefined;
  58. this.extrudedHeight = undefined;
  59. this.granularity = undefined;
  60. this.stRotation = undefined;
  61. this.rotation = undefined;
  62. };
  63. /**
  64. * A {@link GeometryUpdater} for rectangles.
  65. * Clients do not normally create this class directly, but instead rely on {@link DataSourceDisplay}.
  66. * @alias RectangleGeometryUpdater
  67. * @constructor
  68. *
  69. * @param {Entity} entity The entity containing the geometry to be visualized.
  70. * @param {Scene} scene The scene where visualization is taking place.
  71. */
  72. var RectangleGeometryUpdater = function(entity, scene) {
  73. //>>includeStart('debug', pragmas.debug);
  74. if (!defined(entity)) {
  75. throw new DeveloperError('entity is required');
  76. }
  77. if (!defined(scene)) {
  78. throw new DeveloperError('scene is required');
  79. }
  80. //>>includeEnd('debug');
  81. this._entity = entity;
  82. this._scene = scene;
  83. this._entitySubscription = entity.definitionChanged.addEventListener(RectangleGeometryUpdater.prototype._onEntityPropertyChanged, this);
  84. this._fillEnabled = false;
  85. this._isClosed = false;
  86. this._dynamic = false;
  87. this._outlineEnabled = false;
  88. this._geometryChanged = new Event();
  89. this._showProperty = undefined;
  90. this._materialProperty = undefined;
  91. this._hasConstantOutline = true;
  92. this._showOutlineProperty = undefined;
  93. this._outlineColorProperty = undefined;
  94. this._outlineWidth = 1.0;
  95. this._options = new GeometryOptions(entity);
  96. this._onEntityPropertyChanged(entity, 'rectangle', entity.rectangle, undefined);
  97. };
  98. defineProperties(RectangleGeometryUpdater, {
  99. /**
  100. * Gets the type of Appearance to use for simple color-based geometry.
  101. * @memberof RectangleGeometryUpdater
  102. * @type {Appearance}
  103. */
  104. perInstanceColorAppearanceType : {
  105. value : PerInstanceColorAppearance
  106. },
  107. /**
  108. * Gets the type of Appearance to use for material-based geometry.
  109. * @memberof RectangleGeometryUpdater
  110. * @type {Appearance}
  111. */
  112. materialAppearanceType : {
  113. value : MaterialAppearance
  114. }
  115. });
  116. defineProperties(RectangleGeometryUpdater.prototype, {
  117. /**
  118. * Gets the entity associated with this geometry.
  119. * @memberof RectangleGeometryUpdater.prototype
  120. *
  121. * @type {Entity}
  122. * @readonly
  123. */
  124. entity : {
  125. get : function() {
  126. return this._entity;
  127. }
  128. },
  129. /**
  130. * Gets a value indicating if the geometry has a fill component.
  131. * @memberof RectangleGeometryUpdater.prototype
  132. *
  133. * @type {Boolean}
  134. * @readonly
  135. */
  136. fillEnabled : {
  137. get : function() {
  138. return this._fillEnabled;
  139. }
  140. },
  141. /**
  142. * Gets a value indicating if fill visibility varies with simulation time.
  143. * @memberof RectangleGeometryUpdater.prototype
  144. *
  145. * @type {Boolean}
  146. * @readonly
  147. */
  148. hasConstantFill : {
  149. get : function() {
  150. return !this._fillEnabled ||
  151. (!defined(this._entity.availability) &&
  152. Property.isConstant(this._showProperty) &&
  153. Property.isConstant(this._fillProperty));
  154. }
  155. },
  156. /**
  157. * Gets the material property used to fill the geometry.
  158. * @memberof RectangleGeometryUpdater.prototype
  159. *
  160. * @type {MaterialProperty}
  161. * @readonly
  162. */
  163. fillMaterialProperty : {
  164. get : function() {
  165. return this._materialProperty;
  166. }
  167. },
  168. /**
  169. * Gets a value indicating if the geometry has an outline component.
  170. * @memberof RectangleGeometryUpdater.prototype
  171. *
  172. * @type {Boolean}
  173. * @readonly
  174. */
  175. outlineEnabled : {
  176. get : function() {
  177. return this._outlineEnabled;
  178. }
  179. },
  180. /**
  181. * Gets a value indicating if the geometry has an outline component.
  182. * @memberof RectangleGeometryUpdater.prototype
  183. *
  184. * @type {Boolean}
  185. * @readonly
  186. */
  187. hasConstantOutline : {
  188. get : function() {
  189. return !this._outlineEnabled ||
  190. (!defined(this._entity.availability) &&
  191. Property.isConstant(this._showProperty) &&
  192. Property.isConstant(this._showOutlineProperty));
  193. }
  194. },
  195. /**
  196. * Gets the {@link Color} property for the geometry outline.
  197. * @memberof RectangleGeometryUpdater.prototype
  198. *
  199. * @type {Property}
  200. * @readonly
  201. */
  202. outlineColorProperty : {
  203. get : function() {
  204. return this._outlineColorProperty;
  205. }
  206. },
  207. /**
  208. * Gets the constant with of the geometry outline, in pixels.
  209. * This value is only valid if isDynamic is false.
  210. * @memberof RectangleGeometryUpdater.prototype
  211. *
  212. * @type {Number}
  213. * @readonly
  214. */
  215. outlineWidth : {
  216. get : function() {
  217. return this._outlineWidth;
  218. }
  219. },
  220. /**
  221. * Gets a value indicating if the geometry is time-varying.
  222. * If true, all visualization is delegated to the {@link DynamicGeometryUpdater}
  223. * returned by GeometryUpdater#createDynamicUpdater.
  224. * @memberof RectangleGeometryUpdater.prototype
  225. *
  226. * @type {Boolean}
  227. * @readonly
  228. */
  229. isDynamic : {
  230. get : function() {
  231. return this._dynamic;
  232. }
  233. },
  234. /**
  235. * Gets a value indicating if the geometry is closed.
  236. * This property is only valid for static geometry.
  237. * @memberof RectangleGeometryUpdater.prototype
  238. *
  239. * @type {Boolean}
  240. * @readonly
  241. */
  242. isClosed : {
  243. get : function() {
  244. return this._isClosed;
  245. }
  246. },
  247. /**
  248. * Gets an event that is raised whenever the public properties
  249. * of this updater change.
  250. * @memberof RectangleGeometryUpdater.prototype
  251. *
  252. * @type {Boolean}
  253. * @readonly
  254. */
  255. geometryChanged : {
  256. get : function() {
  257. return this._geometryChanged;
  258. }
  259. }
  260. });
  261. /**
  262. * Checks if the geometry is outlined at the provided time.
  263. *
  264. * @param {JulianDate} time The time for which to retrieve visibility.
  265. * @returns {Boolean} true if geometry is outlined at the provided time, false otherwise.
  266. */
  267. RectangleGeometryUpdater.prototype.isOutlineVisible = function(time) {
  268. var entity = this._entity;
  269. return this._outlineEnabled && entity.isAvailable(time) && this._showProperty.getValue(time) && this._showOutlineProperty.getValue(time);
  270. };
  271. /**
  272. * Checks if the geometry is filled at the provided time.
  273. *
  274. * @param {JulianDate} time The time for which to retrieve visibility.
  275. * @returns {Boolean} true if geometry is filled at the provided time, false otherwise.
  276. */
  277. RectangleGeometryUpdater.prototype.isFilled = function(time) {
  278. var entity = this._entity;
  279. return this._fillEnabled && entity.isAvailable(time) && this._showProperty.getValue(time) && this._fillProperty.getValue(time);
  280. };
  281. /**
  282. * Creates the geometry instance which represents the fill of the geometry.
  283. *
  284. * @param {JulianDate} time The time to use when retrieving initial attribute values.
  285. * @returns {GeometryInstance} The geometry instance representing the filled portion of the geometry.
  286. *
  287. * @exception {DeveloperError} This instance does not represent a filled geometry.
  288. */
  289. RectangleGeometryUpdater.prototype.createFillGeometryInstance = function(time) {
  290. //>>includeStart('debug', pragmas.debug);
  291. if (!defined(time)) {
  292. throw new DeveloperError('time is required.');
  293. }
  294. if (!this._fillEnabled) {
  295. throw new DeveloperError('This instance does not represent a filled geometry.');
  296. }
  297. //>>includeEnd('debug');
  298. var entity = this._entity;
  299. var isAvailable = entity.isAvailable(time);
  300. var attributes;
  301. var color;
  302. var show = new ShowGeometryInstanceAttribute(isAvailable && this._showProperty.getValue(time) && this._fillProperty.getValue(time));
  303. if (this._materialProperty instanceof ColorMaterialProperty) {
  304. var currentColor = Color.WHITE;
  305. if (defined(this._materialProperty.color) && (this._materialProperty.color.isConstant || isAvailable)) {
  306. currentColor = this._materialProperty.color.getValue(time);
  307. }
  308. color = ColorGeometryInstanceAttribute.fromColor(currentColor);
  309. attributes = {
  310. show : show,
  311. color : color
  312. };
  313. } else {
  314. attributes = {
  315. show : show
  316. };
  317. }
  318. return new GeometryInstance({
  319. id : entity,
  320. geometry : new RectangleGeometry(this._options),
  321. attributes : attributes
  322. });
  323. };
  324. /**
  325. * Creates the geometry instance which represents the outline of the geometry.
  326. *
  327. * @param {JulianDate} time The time to use when retrieving initial attribute values.
  328. * @returns {GeometryInstance} The geometry instance representing the outline portion of the geometry.
  329. *
  330. * @exception {DeveloperError} This instance does not represent an outlined geometry.
  331. */
  332. RectangleGeometryUpdater.prototype.createOutlineGeometryInstance = function(time) {
  333. //>>includeStart('debug', pragmas.debug);
  334. if (!defined(time)) {
  335. throw new DeveloperError('time is required.');
  336. }
  337. if (!this._outlineEnabled) {
  338. throw new DeveloperError('This instance does not represent an outlined geometry.');
  339. }
  340. //>>includeEnd('debug');
  341. var entity = this._entity;
  342. var isAvailable = entity.isAvailable(time);
  343. var outlineColor = Property.getValueOrDefault(this._outlineColorProperty, time, Color.BLACK);
  344. return new GeometryInstance({
  345. id : entity,
  346. geometry : new RectangleOutlineGeometry(this._options),
  347. attributes : {
  348. show : new ShowGeometryInstanceAttribute(isAvailable && this._showProperty.getValue(time) && this._showOutlineProperty.getValue(time)),
  349. color : ColorGeometryInstanceAttribute.fromColor(outlineColor)
  350. }
  351. });
  352. };
  353. /**
  354. * Returns true if this object was destroyed; otherwise, false.
  355. *
  356. * @returns {Boolean} True if this object was destroyed; otherwise, false.
  357. */
  358. RectangleGeometryUpdater.prototype.isDestroyed = function() {
  359. return false;
  360. };
  361. /**
  362. * Destroys and resources used by the object. Once an object is destroyed, it should not be used.
  363. *
  364. * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
  365. */
  366. RectangleGeometryUpdater.prototype.destroy = function() {
  367. this._entitySubscription();
  368. destroyObject(this);
  369. };
  370. RectangleGeometryUpdater.prototype._onEntityPropertyChanged = function(entity, propertyName, newValue, oldValue) {
  371. if (!(propertyName === 'availability' || propertyName === 'rectangle')) {
  372. return;
  373. }
  374. var rectangle = this._entity.rectangle;
  375. if (!defined(rectangle)) {
  376. if (this._fillEnabled || this._outlineEnabled) {
  377. this._fillEnabled = false;
  378. this._outlineEnabled = false;
  379. this._geometryChanged.raiseEvent(this);
  380. }
  381. return;
  382. }
  383. var fillProperty = rectangle.fill;
  384. var fillEnabled = defined(fillProperty) && fillProperty.isConstant ? fillProperty.getValue(Iso8601.MINIMUM_VALUE) : true;
  385. var outlineProperty = rectangle.outline;
  386. var outlineEnabled = defined(outlineProperty);
  387. if (outlineEnabled && outlineProperty.isConstant) {
  388. outlineEnabled = outlineProperty.getValue(Iso8601.MINIMUM_VALUE);
  389. }
  390. if (!fillEnabled && !outlineEnabled) {
  391. if (this._fillEnabled || this._outlineEnabled) {
  392. this._fillEnabled = false;
  393. this._outlineEnabled = false;
  394. this._geometryChanged.raiseEvent(this);
  395. }
  396. return;
  397. }
  398. var coordinates = rectangle.coordinates;
  399. var show = rectangle.show;
  400. if ((defined(show) && show.isConstant && !show.getValue(Iso8601.MINIMUM_VALUE)) || //
  401. (!defined(coordinates))) {
  402. if (this._fillEnabled || this._outlineEnabled) {
  403. this._fillEnabled = false;
  404. this._outlineEnabled = false;
  405. this._geometryChanged.raiseEvent(this);
  406. }
  407. return;
  408. }
  409. var material = defaultValue(rectangle.material, defaultMaterial);
  410. var isColorMaterial = material instanceof ColorMaterialProperty;
  411. this._materialProperty = material;
  412. this._fillProperty = defaultValue(fillProperty, defaultFill);
  413. this._showProperty = defaultValue(show, defaultShow);
  414. this._showOutlineProperty = defaultValue(rectangle.outline, defaultOutline);
  415. this._outlineColorProperty = outlineEnabled ? defaultValue(rectangle.outlineColor, defaultOutlineColor) : undefined;
  416. var height = rectangle.height;
  417. var extrudedHeight = rectangle.extrudedHeight;
  418. var granularity = rectangle.granularity;
  419. var stRotation = rectangle.stRotation;
  420. var rotation = rectangle.rotation;
  421. var outlineWidth = rectangle.outlineWidth;
  422. var closeBottom = rectangle.closeBottom;
  423. var closeTop = rectangle.closeTop;
  424. this._fillEnabled = fillEnabled;
  425. this._outlineEnabled = outlineEnabled;
  426. if (!coordinates.isConstant || //
  427. !Property.isConstant(height) || //
  428. !Property.isConstant(extrudedHeight) || //
  429. !Property.isConstant(granularity) || //
  430. !Property.isConstant(stRotation) || //
  431. !Property.isConstant(rotation) || //
  432. !Property.isConstant(outlineWidth) || //
  433. !Property.isConstant(closeBottom) || //
  434. !Property.isConstant(closeTop)) {
  435. if (!this._dynamic) {
  436. this._dynamic = true;
  437. this._geometryChanged.raiseEvent(this);
  438. }
  439. } else {
  440. var options = this._options;
  441. options.vertexFormat = isColorMaterial ? PerInstanceColorAppearance.VERTEX_FORMAT : MaterialAppearance.MaterialSupport.TEXTURED.vertexFormat;
  442. options.rectangle = coordinates.getValue(Iso8601.MINIMUM_VALUE, options.rectangle);
  443. options.height = defined(height) ? height.getValue(Iso8601.MINIMUM_VALUE) : undefined;
  444. options.extrudedHeight = defined(extrudedHeight) ? extrudedHeight.getValue(Iso8601.MINIMUM_VALUE) : undefined;
  445. options.granularity = defined(granularity) ? granularity.getValue(Iso8601.MINIMUM_VALUE) : undefined;
  446. options.stRotation = defined(stRotation) ? stRotation.getValue(Iso8601.MINIMUM_VALUE) : undefined;
  447. options.rotation = defined(rotation) ? rotation.getValue(Iso8601.MINIMUM_VALUE) : undefined;
  448. options.closeBottom = defined(closeBottom) ? closeBottom.getValue(Iso8601.MINIMUM_VALUE) : undefined;
  449. options.closeTop = defined(closeTop) ? closeTop.getValue(Iso8601.MINIMUM_VALUE) : undefined;
  450. this._isClosed = defined(extrudedHeight) && defined(options.closeTop) && defined(options.closeBottom) && options.closeTop && options.closeBottom;
  451. this._outlineWidth = defined(outlineWidth) ? outlineWidth.getValue(Iso8601.MINIMUM_VALUE) : 1.0;
  452. this._dynamic = false;
  453. this._geometryChanged.raiseEvent(this);
  454. }
  455. };
  456. /**
  457. * Creates the dynamic updater to be used when GeometryUpdater#isDynamic is true.
  458. *
  459. * @param {PrimitiveCollection} primitives The primitive collection to use.
  460. * @returns {DynamicGeometryUpdater} The dynamic updater used to update the geometry each frame.
  461. *
  462. * @exception {DeveloperError} This instance does not represent dynamic geometry.
  463. */
  464. RectangleGeometryUpdater.prototype.createDynamicUpdater = function(primitives) {
  465. //>>includeStart('debug', pragmas.debug);
  466. if (!this._dynamic) {
  467. throw new DeveloperError('This instance does not represent dynamic geometry.');
  468. }
  469. if (!defined(primitives)) {
  470. throw new DeveloperError('primitives is required.');
  471. }
  472. //>>includeEnd('debug');
  473. return new DynamicGeometryUpdater(primitives, this);
  474. };
  475. /**
  476. * @private
  477. */
  478. var DynamicGeometryUpdater = function(primitives, geometryUpdater) {
  479. this._primitives = primitives;
  480. this._primitive = undefined;
  481. this._outlinePrimitive = undefined;
  482. this._geometryUpdater = geometryUpdater;
  483. this._options = new GeometryOptions(geometryUpdater._entity);
  484. };
  485. DynamicGeometryUpdater.prototype.update = function(time) {
  486. //>>includeStart('debug', pragmas.debug);
  487. if (!defined(time)) {
  488. throw new DeveloperError('time is required.');
  489. }
  490. //>>includeEnd('debug');
  491. var primitives = this._primitives;
  492. primitives.remove(this._primitive);
  493. primitives.remove(this._outlinePrimitive);
  494. var geometryUpdater = this._geometryUpdater;
  495. var entity = geometryUpdater._entity;
  496. var rectangle = entity.rectangle;
  497. if (!entity.isAvailable(time) || !Property.getValueOrDefault(rectangle.show, time, true)) {
  498. return;
  499. }
  500. var options = this._options;
  501. var coordinates = Property.getValueOrUndefined(rectangle.coordinates, time, options.rectangle);
  502. if (!defined(coordinates)) {
  503. return;
  504. }
  505. options.rectangle = coordinates;
  506. options.height = Property.getValueOrUndefined(rectangle.height, time);
  507. options.extrudedHeight = Property.getValueOrUndefined(rectangle.extrudedHeight, time);
  508. options.granularity = Property.getValueOrUndefined(rectangle.granularity, time);
  509. options.stRotation = Property.getValueOrUndefined(rectangle.stRotation, time);
  510. options.rotation = Property.getValueOrUndefined(rectangle.rotation, time);
  511. options.closeBottom = Property.getValueOrUndefined(rectangle.closeBottom, time);
  512. options.closeTop = Property.getValueOrUndefined(rectangle.closeTop, time);
  513. if (Property.getValueOrDefault(rectangle.fill, time, true)) {
  514. var material = MaterialProperty.getValue(time, geometryUpdater.fillMaterialProperty, this._material);
  515. this._material = material;
  516. var appearance = new MaterialAppearance({
  517. material : material,
  518. translucent : material.isTranslucent(),
  519. closed : defined(options.extrudedHeight)
  520. });
  521. options.vertexFormat = appearance.vertexFormat;
  522. this._primitive = primitives.add(new Primitive({
  523. geometryInstances : new GeometryInstance({
  524. id : entity,
  525. geometry : new RectangleGeometry(options)
  526. }),
  527. appearance : appearance,
  528. asynchronous : false
  529. }));
  530. }
  531. if (Property.getValueOrDefault(rectangle.outline, time, false)) {
  532. options.vertexFormat = PerInstanceColorAppearance.VERTEX_FORMAT;
  533. var outlineColor = Property.getValueOrClonedDefault(rectangle.outlineColor, time, Color.BLACK, scratchColor);
  534. var outlineWidth = Property.getValueOrDefault(rectangle.outlineWidth, 1.0);
  535. var translucent = outlineColor.alpha !== 1.0;
  536. this._outlinePrimitive = primitives.add(new Primitive({
  537. geometryInstances : new GeometryInstance({
  538. id : entity,
  539. geometry : new RectangleOutlineGeometry(options),
  540. attributes : {
  541. color : ColorGeometryInstanceAttribute.fromColor(outlineColor)
  542. }
  543. }),
  544. appearance : new PerInstanceColorAppearance({
  545. flat : true,
  546. translucent : translucent,
  547. renderState : {
  548. lineWidth : geometryUpdater._scene.clampLineWidth(outlineWidth)
  549. }
  550. }),
  551. asynchronous : false
  552. }));
  553. }
  554. };
  555. DynamicGeometryUpdater.prototype.isDestroyed = function() {
  556. return false;
  557. };
  558. DynamicGeometryUpdater.prototype.destroy = function() {
  559. var primitives = this._primitives;
  560. primitives.removeAndDestroy(this._primitive);
  561. primitives.removeAndDestroy(this._outlinePrimitive);
  562. destroyObject(this);
  563. };
  564. return RectangleGeometryUpdater;
  565. });