PolylineGeometryUpdater.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  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/Ellipsoid',
  11. '../Core/Event',
  12. '../Core/GeometryInstance',
  13. '../Core/Iso8601',
  14. '../Core/PolylineGeometry',
  15. '../Core/PolylinePipeline',
  16. '../Core/ShowGeometryInstanceAttribute',
  17. '../Scene/PolylineCollection',
  18. '../Scene/PolylineColorAppearance',
  19. '../Scene/PolylineMaterialAppearance',
  20. './ColorMaterialProperty',
  21. './ConstantProperty',
  22. './MaterialProperty',
  23. './Property'
  24. ], function(
  25. Color,
  26. ColorGeometryInstanceAttribute,
  27. defaultValue,
  28. defined,
  29. defineProperties,
  30. destroyObject,
  31. DeveloperError,
  32. Ellipsoid,
  33. Event,
  34. GeometryInstance,
  35. Iso8601,
  36. PolylineGeometry,
  37. PolylinePipeline,
  38. ShowGeometryInstanceAttribute,
  39. PolylineCollection,
  40. PolylineColorAppearance,
  41. PolylineMaterialAppearance,
  42. ColorMaterialProperty,
  43. ConstantProperty,
  44. MaterialProperty,
  45. Property) {
  46. "use strict";
  47. //We use this object to create one polyline collection per-scene.
  48. var polylineCollections = {};
  49. var defaultMaterial = ColorMaterialProperty.fromColor(Color.WHITE);
  50. var defaultShow = new ConstantProperty(true);
  51. var GeometryOptions = function(entity) {
  52. this.id = entity;
  53. this.vertexFormat = undefined;
  54. this.positions = undefined;
  55. this.width = undefined;
  56. this.followSurface = undefined;
  57. this.granularity = undefined;
  58. };
  59. /**
  60. * A {@link GeometryUpdater} for polylines.
  61. * Clients do not normally create this class directly, but instead rely on {@link DataSourceDisplay}.
  62. * @alias PolylineGeometryUpdater
  63. * @constructor
  64. *
  65. * @param {Entity} entity The entity containing the geometry to be visualized.
  66. * @param {Scene} scene The scene where visualization is taking place.
  67. */
  68. var PolylineGeometryUpdater = function(entity, scene) {
  69. //>>includeStart('debug', pragmas.debug);
  70. if (!defined(entity)) {
  71. throw new DeveloperError('entity is required');
  72. }
  73. if (!defined(scene)) {
  74. throw new DeveloperError('scene is required');
  75. }
  76. //>>includeEnd('debug');
  77. this._entity = entity;
  78. this._scene = scene;
  79. this._entitySubscription = entity.definitionChanged.addEventListener(PolylineGeometryUpdater.prototype._onEntityPropertyChanged, this);
  80. this._fillEnabled = false;
  81. this._dynamic = false;
  82. this._geometryChanged = new Event();
  83. this._showProperty = undefined;
  84. this._materialProperty = undefined;
  85. this._options = new GeometryOptions(entity);
  86. this._onEntityPropertyChanged(entity, 'polyline', entity.polyline, undefined);
  87. };
  88. defineProperties(PolylineGeometryUpdater, {
  89. /**
  90. * Gets the type of Appearance to use for simple color-based geometry.
  91. * @memberof PolylineGeometryUpdater
  92. * @type {Appearance}
  93. */
  94. perInstanceColorAppearanceType : {
  95. value : PolylineColorAppearance
  96. },
  97. /**
  98. * Gets the type of Appearance to use for material-based geometry.
  99. * @memberof PolylineGeometryUpdater
  100. * @type {Appearance}
  101. */
  102. materialAppearanceType : {
  103. value : PolylineMaterialAppearance
  104. }
  105. });
  106. defineProperties(PolylineGeometryUpdater.prototype, {
  107. /**
  108. * Gets the entity associated with this geometry.
  109. * @memberof PolylineGeometryUpdater.prototype
  110. *
  111. * @type {Entity}
  112. * @readonly
  113. */
  114. entity : {
  115. get : function() {
  116. return this._entity;
  117. }
  118. },
  119. /**
  120. * Gets a value indicating if the geometry has a fill component.
  121. * @memberof PolylineGeometryUpdater.prototype
  122. *
  123. * @type {Boolean}
  124. * @readonly
  125. */
  126. fillEnabled : {
  127. get : function() {
  128. return this._fillEnabled;
  129. }
  130. },
  131. /**
  132. * Gets a value indicating if fill visibility varies with simulation time.
  133. * @memberof PolylineGeometryUpdater.prototype
  134. *
  135. * @type {Boolean}
  136. * @readonly
  137. */
  138. hasConstantFill : {
  139. get : function() {
  140. return !this._fillEnabled || (!defined(this._entity.availability) && Property.isConstant(this._showProperty));
  141. }
  142. },
  143. /**
  144. * Gets the material property used to fill the geometry.
  145. * @memberof PolylineGeometryUpdater.prototype
  146. *
  147. * @type {MaterialProperty}
  148. * @readonly
  149. */
  150. fillMaterialProperty : {
  151. get : function() {
  152. return this._materialProperty;
  153. }
  154. },
  155. /**
  156. * Gets a value indicating if the geometry has an outline component.
  157. * @memberof PolylineGeometryUpdater.prototype
  158. *
  159. * @type {Boolean}
  160. * @readonly
  161. */
  162. outlineEnabled : {
  163. value : false
  164. },
  165. /**
  166. * Gets a value indicating if outline visibility varies with simulation time.
  167. * @memberof PolylineGeometryUpdater.prototype
  168. *
  169. * @type {Boolean}
  170. * @readonly
  171. */
  172. hasConstantOutline : {
  173. value : true
  174. },
  175. /**
  176. * Gets the {@link Color} property for the geometry outline.
  177. * @memberof PolylineGeometryUpdater.prototype
  178. *
  179. * @type {Property}
  180. * @readonly
  181. */
  182. outlineColorProperty : {
  183. value : undefined
  184. },
  185. /**
  186. * Gets a value indicating if the geometry is time-varying.
  187. * If true, all visualization is delegated to the {@link DynamicGeometryUpdater}
  188. * returned by GeometryUpdater#createDynamicUpdater.
  189. * @memberof PolylineGeometryUpdater.prototype
  190. *
  191. * @type {Boolean}
  192. * @readonly
  193. */
  194. isDynamic : {
  195. get : function() {
  196. return this._dynamic;
  197. }
  198. },
  199. /**
  200. * Gets a value indicating if the geometry is closed.
  201. * This property is only valid for static geometry.
  202. * @memberof PolylineGeometryUpdater.prototype
  203. *
  204. * @type {Boolean}
  205. * @readonly
  206. */
  207. isClosed : {
  208. value : false
  209. },
  210. /**
  211. * Gets an event that is raised whenever the public properties
  212. * of this updater change.
  213. * @memberof PolylineGeometryUpdater.prototype
  214. *
  215. * @type {Boolean}
  216. * @readonly
  217. */
  218. geometryChanged : {
  219. get : function() {
  220. return this._geometryChanged;
  221. }
  222. }
  223. });
  224. /**
  225. * Checks if the geometry is outlined at the provided time.
  226. *
  227. * @param {JulianDate} time The time for which to retrieve visibility.
  228. * @returns {Boolean} true if geometry is outlined at the provided time, false otherwise.
  229. */
  230. PolylineGeometryUpdater.prototype.isOutlineVisible = function(time) {
  231. return false;
  232. };
  233. /**
  234. * Checks if the geometry is filled at the provided time.
  235. *
  236. * @param {JulianDate} time The time for which to retrieve visibility.
  237. * @returns {Boolean} true if geometry is filled at the provided time, false otherwise.
  238. */
  239. PolylineGeometryUpdater.prototype.isFilled = function(time) {
  240. var entity = this._entity;
  241. return this._fillEnabled && entity.isAvailable(time) && this._showProperty.getValue(time);
  242. };
  243. /**
  244. * Creates the geometry instance which represents the fill of the geometry.
  245. *
  246. * @param {JulianDate} time The time to use when retrieving initial attribute values.
  247. * @returns {GeometryInstance} The geometry instance representing the filled portion of the geometry.
  248. *
  249. * @exception {DeveloperError} This instance does not represent a filled geometry.
  250. */
  251. PolylineGeometryUpdater.prototype.createFillGeometryInstance = function(time) {
  252. //>>includeStart('debug', pragmas.debug);
  253. if (!defined(time)) {
  254. throw new DeveloperError('time is required.');
  255. }
  256. if (!this._fillEnabled) {
  257. throw new DeveloperError('This instance does not represent a filled geometry.');
  258. }
  259. //>>includeEnd('debug');
  260. var color;
  261. var attributes;
  262. var entity = this._entity;
  263. var isAvailable = entity.isAvailable(time);
  264. var show = new ShowGeometryInstanceAttribute(isAvailable && this._showProperty.getValue(time));
  265. if (this._materialProperty instanceof ColorMaterialProperty) {
  266. var currentColor = Color.WHITE;
  267. if (defined(this._materialProperty.color) && (this._materialProperty.color.isConstant || isAvailable)) {
  268. currentColor = this._materialProperty.color.getValue(time);
  269. }
  270. color = ColorGeometryInstanceAttribute.fromColor(currentColor);
  271. attributes = {
  272. show : show,
  273. color : color
  274. };
  275. } else {
  276. attributes = {
  277. show : show
  278. };
  279. }
  280. return new GeometryInstance({
  281. id : entity,
  282. geometry : new PolylineGeometry(this._options),
  283. attributes : attributes
  284. });
  285. };
  286. /**
  287. * Creates the geometry instance which represents the outline of the geometry.
  288. *
  289. * @param {JulianDate} time The time to use when retrieving initial attribute values.
  290. * @returns {GeometryInstance} The geometry instance representing the outline portion of the geometry.
  291. *
  292. * @exception {DeveloperError} This instance does not represent an outlined geometry.
  293. */
  294. PolylineGeometryUpdater.prototype.createOutlineGeometryInstance = function(time) {
  295. //>>includeStart('debug', pragmas.debug);
  296. throw new DeveloperError('This instance does not represent an outlined geometry.');
  297. //>>includeEnd('debug');
  298. };
  299. /**
  300. * Returns true if this object was destroyed; otherwise, false.
  301. *
  302. * @returns {Boolean} True if this object was destroyed; otherwise, false.
  303. */
  304. PolylineGeometryUpdater.prototype.isDestroyed = function() {
  305. return false;
  306. };
  307. /**
  308. * Destroys and resources used by the object. Once an object is destroyed, it should not be used.
  309. *
  310. * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
  311. */
  312. PolylineGeometryUpdater.prototype.destroy = function() {
  313. this._entitySubscription();
  314. destroyObject(this);
  315. };
  316. PolylineGeometryUpdater.prototype._onEntityPropertyChanged = function(entity, propertyName, newValue, oldValue) {
  317. if (!(propertyName === 'availability' || propertyName === 'polyline')) {
  318. return;
  319. }
  320. var polyline = this._entity.polyline;
  321. if (!defined(polyline)) {
  322. if (this._fillEnabled) {
  323. this._fillEnabled = false;
  324. this._geometryChanged.raiseEvent(this);
  325. }
  326. return;
  327. }
  328. var positionsProperty = polyline.positions;
  329. var show = polyline.show;
  330. if ((defined(show) && show.isConstant && !show.getValue(Iso8601.MINIMUM_VALUE)) || //
  331. (!defined(positionsProperty))) {
  332. if (this._fillEnabled) {
  333. this._fillEnabled = false;
  334. this._geometryChanged.raiseEvent(this);
  335. }
  336. return;
  337. }
  338. var material = defaultValue(polyline.material, defaultMaterial);
  339. var isColorMaterial = material instanceof ColorMaterialProperty;
  340. this._materialProperty = material;
  341. this._showProperty = defaultValue(show, defaultShow);
  342. this._fillEnabled = true;
  343. var width = polyline.width;
  344. var followSurface = polyline.followSurface;
  345. var granularity = polyline.granularity;
  346. if (!positionsProperty.isConstant || !Property.isConstant(width) ||
  347. !Property.isConstant(followSurface) || !Property.isConstant(granularity)) {
  348. if (!this._dynamic) {
  349. this._dynamic = true;
  350. this._geometryChanged.raiseEvent(this);
  351. }
  352. } else {
  353. var options = this._options;
  354. var positions = positionsProperty.getValue(Iso8601.MINIMUM_VALUE, options.positions);
  355. //Because of the way we currently handle reference properties,
  356. //we can't automatically assume the positions are always valid.
  357. if (!defined(positions) || positions.length < 2) {
  358. if (this._fillEnabled) {
  359. this._fillEnabled = false;
  360. this._geometryChanged.raiseEvent(this);
  361. }
  362. return;
  363. }
  364. options.vertexFormat = isColorMaterial ? PolylineColorAppearance.VERTEX_FORMAT : PolylineMaterialAppearance.VERTEX_FORMAT;
  365. options.positions = positions;
  366. options.width = defined(width) ? width.getValue(Iso8601.MINIMUM_VALUE) : undefined;
  367. options.followSurface = defined(followSurface) ? followSurface.getValue(Iso8601.MINIMUM_VALUE) : undefined;
  368. options.granularity = defined(granularity) ? granularity.getValue(Iso8601.MINIMUM_VALUE) : undefined;
  369. this._dynamic = false;
  370. this._geometryChanged.raiseEvent(this);
  371. }
  372. };
  373. /**
  374. * Creates the dynamic updater to be used when GeometryUpdater#isDynamic is true.
  375. *
  376. * @param {PrimitiveCollection} primitives The primitive collection to use.
  377. * @returns {DynamicGeometryUpdater} The dynamic updater used to update the geometry each frame.
  378. *
  379. * @exception {DeveloperError} This instance does not represent dynamic geometry.
  380. */
  381. PolylineGeometryUpdater.prototype.createDynamicUpdater = function(primitives) {
  382. //>>includeStart('debug', pragmas.debug);
  383. if (!this._dynamic) {
  384. throw new DeveloperError('This instance does not represent dynamic geometry.');
  385. }
  386. if (!defined(primitives)) {
  387. throw new DeveloperError('primitives is required.');
  388. }
  389. //>>includeEnd('debug');
  390. return new DynamicGeometryUpdater(primitives, this);
  391. };
  392. /**
  393. * @private
  394. */
  395. var DynamicGeometryUpdater = function(primitives, geometryUpdater) {
  396. var sceneId = geometryUpdater._scene.id;
  397. var polylineCollection = polylineCollections[sceneId];
  398. if (!defined(polylineCollection)) {
  399. polylineCollection = new PolylineCollection();
  400. polylineCollections[sceneId] = polylineCollection;
  401. primitives.add(polylineCollection);
  402. }
  403. var line = polylineCollection.add();
  404. line.id = geometryUpdater._entity;
  405. this._line = line;
  406. this._primitives = primitives;
  407. this._geometryUpdater = geometryUpdater;
  408. this._positions = [];
  409. };
  410. var generateCartesianArcOptions = {
  411. positions : undefined,
  412. granularity : undefined,
  413. height : undefined
  414. };
  415. DynamicGeometryUpdater.prototype.update = function(time) {
  416. var geometryUpdater = this._geometryUpdater;
  417. var entity = geometryUpdater._entity;
  418. var polyline = entity.polyline;
  419. var line = this._line;
  420. if (!entity.isAvailable(time) || !Property.getValueOrDefault(polyline._show, time, true)) {
  421. line.show = false;
  422. return;
  423. }
  424. var positionsProperty = polyline.positions;
  425. var positions = Property.getValueOrUndefined(positionsProperty, time, this._positions);
  426. if (!defined(positions)) {
  427. line.show = false;
  428. return;
  429. }
  430. var followSurface = Property.getValueOrDefault(polyline._followSurface, time, true);
  431. if (followSurface) {
  432. generateCartesianArcOptions.positions = positions;
  433. generateCartesianArcOptions.granularity = Property.getValueOrUndefined(polyline._granularity, time);
  434. generateCartesianArcOptions.height = PolylinePipeline.extractHeights(positions, Ellipsoid.WGS84);
  435. positions = PolylinePipeline.generateCartesianArc(generateCartesianArcOptions);
  436. }
  437. line.show = true;
  438. line.positions = positions;
  439. line.material = MaterialProperty.getValue(time, geometryUpdater.fillMaterialProperty, line.material);
  440. line.width = Property.getValueOrDefault(polyline._width, time, 1);
  441. };
  442. DynamicGeometryUpdater.prototype.isDestroyed = function() {
  443. return false;
  444. };
  445. DynamicGeometryUpdater.prototype.destroy = function() {
  446. var geometryUpdater = this._geometryUpdater;
  447. var sceneId = geometryUpdater._scene.id;
  448. var polylineCollection = polylineCollections[sceneId];
  449. polylineCollection.remove(this._line);
  450. if (polylineCollection.length === 0) {
  451. this._primitives.removeAndDestroy(polylineCollection);
  452. delete polylineCollections[sceneId];
  453. }
  454. destroyObject(this);
  455. };
  456. return PolylineGeometryUpdater;
  457. });