智慧水务管理系统 - 精河县供水工程综合管理平台

LabelVisualizer.js 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. import AssociativeArray from "../Core/AssociativeArray.js";
  2. import Cartesian2 from "../Core/Cartesian2.js";
  3. import Cartesian3 from "../Core/Cartesian3.js";
  4. import Color from "../Core/Color.js";
  5. import defined from "../Core/defined.js";
  6. import destroyObject from "../Core/destroyObject.js";
  7. import DeveloperError from "../Core/DeveloperError.js";
  8. import DistanceDisplayCondition from "../Core/DistanceDisplayCondition.js";
  9. import NearFarScalar from "../Core/NearFarScalar.js";
  10. import HeightReference from "../Scene/HeightReference.js";
  11. import HorizontalOrigin from "../Scene/HorizontalOrigin.js";
  12. import LabelStyle from "../Scene/LabelStyle.js";
  13. import VerticalOrigin from "../Scene/VerticalOrigin.js";
  14. import BoundingSphereState from "./BoundingSphereState.js";
  15. import Property from "./Property.js";
  16. const defaultScale = 1.0;
  17. const defaultFont = "30px sans-serif";
  18. const defaultStyle = LabelStyle.FILL;
  19. const defaultFillColor = Color.WHITE;
  20. const defaultOutlineColor = Color.BLACK;
  21. const defaultOutlineWidth = 1.0;
  22. const defaultShowBackground = false;
  23. const defaultBackgroundColor = new Color(0.165, 0.165, 0.165, 0.8);
  24. const defaultBackgroundPadding = new Cartesian2(7, 5);
  25. const defaultPixelOffset = Cartesian2.ZERO;
  26. const defaultEyeOffset = Cartesian3.ZERO;
  27. const defaultHeightReference = HeightReference.NONE;
  28. const defaultHorizontalOrigin = HorizontalOrigin.CENTER;
  29. const defaultVerticalOrigin = VerticalOrigin.CENTER;
  30. const positionScratch = new Cartesian3();
  31. const fillColorScratch = new Color();
  32. const outlineColorScratch = new Color();
  33. const backgroundColorScratch = new Color();
  34. const backgroundPaddingScratch = new Cartesian2();
  35. const eyeOffsetScratch = new Cartesian3();
  36. const pixelOffsetScratch = new Cartesian2();
  37. const translucencyByDistanceScratch = new NearFarScalar();
  38. const pixelOffsetScaleByDistanceScratch = new NearFarScalar();
  39. const scaleByDistanceScratch = new NearFarScalar();
  40. const distanceDisplayConditionScratch = new DistanceDisplayCondition();
  41. function EntityData(entity) {
  42. this.entity = entity;
  43. this.label = undefined;
  44. this.index = undefined;
  45. }
  46. /**
  47. * A {@link Visualizer} which maps the {@link LabelGraphics} instance
  48. * in {@link Entity#label} to a {@link Label}.
  49. * @alias LabelVisualizer
  50. * @constructor
  51. *
  52. * @param {EntityCluster} entityCluster The entity cluster to manage the collection of billboards and optionally cluster with other entities.
  53. * @param {EntityCollection} entityCollection The entityCollection to visualize.
  54. */
  55. function LabelVisualizer(entityCluster, entityCollection) {
  56. //>>includeStart('debug', pragmas.debug);
  57. if (!defined(entityCluster)) {
  58. throw new DeveloperError("entityCluster is required.");
  59. }
  60. if (!defined(entityCollection)) {
  61. throw new DeveloperError("entityCollection is required.");
  62. }
  63. //>>includeEnd('debug');
  64. entityCollection.collectionChanged.addEventListener(
  65. LabelVisualizer.prototype._onCollectionChanged,
  66. this,
  67. );
  68. this._cluster = entityCluster;
  69. this._entityCollection = entityCollection;
  70. this._items = new AssociativeArray();
  71. this._onCollectionChanged(entityCollection, entityCollection.values, [], []);
  72. }
  73. /**
  74. * Updates the primitives created by this visualizer to match their
  75. * Entity counterpart at the given time.
  76. *
  77. * @param {JulianDate} time The time to update to.
  78. * @returns {boolean} This function always returns true.
  79. */
  80. LabelVisualizer.prototype.update = function (time) {
  81. //>>includeStart('debug', pragmas.debug);
  82. if (!defined(time)) {
  83. throw new DeveloperError("time is required.");
  84. }
  85. //>>includeEnd('debug');
  86. const items = this._items.values;
  87. const cluster = this._cluster;
  88. for (let i = 0, len = items.length; i < len; i++) {
  89. const item = items[i];
  90. const entity = item.entity;
  91. const labelGraphics = entity._label;
  92. let text;
  93. let label = item.label;
  94. let show =
  95. entity.isShowing &&
  96. entity.isAvailable(time) &&
  97. Property.getValueOrDefault(labelGraphics._show, time, true);
  98. let position;
  99. if (show) {
  100. position = Property.getValueOrUndefined(
  101. entity._position,
  102. time,
  103. positionScratch,
  104. );
  105. text = Property.getValueOrUndefined(labelGraphics._text, time);
  106. show = defined(position) && defined(text);
  107. }
  108. if (!show) {
  109. //don't bother creating or updating anything else
  110. returnPrimitive(item, entity, cluster);
  111. continue;
  112. }
  113. if (!Property.isConstant(entity._position)) {
  114. cluster._clusterDirty = true;
  115. }
  116. let updateClamping = false;
  117. const heightReference = Property.getValueOrDefault(
  118. labelGraphics._heightReference,
  119. time,
  120. defaultHeightReference,
  121. );
  122. if (!defined(label)) {
  123. label = cluster.getLabel(entity);
  124. label.id = entity;
  125. item.label = label;
  126. // If this new label happens to have a position and height reference that match our new values,
  127. // label._updateClamping will not be called automatically. That's a problem because the clamped
  128. // height may be based on different terrain than is now loaded. So we'll manually call
  129. // _updateClamping below.
  130. updateClamping =
  131. Cartesian3.equals(label.position, position) &&
  132. label.heightReference === heightReference;
  133. }
  134. label.show = true;
  135. label.position = position;
  136. label.text = text;
  137. label.scale = Property.getValueOrDefault(
  138. labelGraphics._scale,
  139. time,
  140. defaultScale,
  141. );
  142. label.font = Property.getValueOrDefault(
  143. labelGraphics._font,
  144. time,
  145. defaultFont,
  146. );
  147. label.style = Property.getValueOrDefault(
  148. labelGraphics._style,
  149. time,
  150. defaultStyle,
  151. );
  152. label.fillColor = Property.getValueOrDefault(
  153. labelGraphics._fillColor,
  154. time,
  155. defaultFillColor,
  156. fillColorScratch,
  157. );
  158. label.outlineColor = Property.getValueOrDefault(
  159. labelGraphics._outlineColor,
  160. time,
  161. defaultOutlineColor,
  162. outlineColorScratch,
  163. );
  164. label.outlineWidth = Property.getValueOrDefault(
  165. labelGraphics._outlineWidth,
  166. time,
  167. defaultOutlineWidth,
  168. );
  169. label.showBackground = Property.getValueOrDefault(
  170. labelGraphics._showBackground,
  171. time,
  172. defaultShowBackground,
  173. );
  174. label.backgroundColor = Property.getValueOrDefault(
  175. labelGraphics._backgroundColor,
  176. time,
  177. defaultBackgroundColor,
  178. backgroundColorScratch,
  179. );
  180. label.backgroundPadding = Property.getValueOrDefault(
  181. labelGraphics._backgroundPadding,
  182. time,
  183. defaultBackgroundPadding,
  184. backgroundPaddingScratch,
  185. );
  186. label.pixelOffset = Property.getValueOrDefault(
  187. labelGraphics._pixelOffset,
  188. time,
  189. defaultPixelOffset,
  190. pixelOffsetScratch,
  191. );
  192. label.eyeOffset = Property.getValueOrDefault(
  193. labelGraphics._eyeOffset,
  194. time,
  195. defaultEyeOffset,
  196. eyeOffsetScratch,
  197. );
  198. label.heightReference = heightReference;
  199. label.horizontalOrigin = Property.getValueOrDefault(
  200. labelGraphics._horizontalOrigin,
  201. time,
  202. defaultHorizontalOrigin,
  203. );
  204. label.verticalOrigin = Property.getValueOrDefault(
  205. labelGraphics._verticalOrigin,
  206. time,
  207. defaultVerticalOrigin,
  208. );
  209. label.translucencyByDistance = Property.getValueOrUndefined(
  210. labelGraphics._translucencyByDistance,
  211. time,
  212. translucencyByDistanceScratch,
  213. );
  214. label.pixelOffsetScaleByDistance = Property.getValueOrUndefined(
  215. labelGraphics._pixelOffsetScaleByDistance,
  216. time,
  217. pixelOffsetScaleByDistanceScratch,
  218. );
  219. label.scaleByDistance = Property.getValueOrUndefined(
  220. labelGraphics._scaleByDistance,
  221. time,
  222. scaleByDistanceScratch,
  223. );
  224. label.distanceDisplayCondition = Property.getValueOrUndefined(
  225. labelGraphics._distanceDisplayCondition,
  226. time,
  227. distanceDisplayConditionScratch,
  228. );
  229. label.disableDepthTestDistance = Property.getValueOrUndefined(
  230. labelGraphics._disableDepthTestDistance,
  231. time,
  232. );
  233. if (updateClamping) {
  234. label._updateClamping();
  235. }
  236. }
  237. return true;
  238. };
  239. /**
  240. * Computes a bounding sphere which encloses the visualization produced for the specified entity.
  241. * The bounding sphere is in the fixed frame of the scene's globe.
  242. *
  243. * @param {Entity} entity The entity whose bounding sphere to compute.
  244. * @param {BoundingSphere} result The bounding sphere onto which to store the result.
  245. * @returns {BoundingSphereState} BoundingSphereState.DONE if the result contains the bounding sphere,
  246. * BoundingSphereState.PENDING if the result is still being computed, or
  247. * BoundingSphereState.FAILED if the entity has no visualization in the current scene.
  248. * @private
  249. */
  250. LabelVisualizer.prototype.getBoundingSphere = function (entity, result) {
  251. //>>includeStart('debug', pragmas.debug);
  252. if (!defined(entity)) {
  253. throw new DeveloperError("entity is required.");
  254. }
  255. if (!defined(result)) {
  256. throw new DeveloperError("result is required.");
  257. }
  258. //>>includeEnd('debug');
  259. const item = this._items.get(entity.id);
  260. if (!defined(item) || !defined(item.label)) {
  261. return BoundingSphereState.FAILED;
  262. }
  263. const label = item.label;
  264. result.center = Cartesian3.clone(
  265. label._clampedPosition ?? label.position,
  266. result.center,
  267. );
  268. result.radius = 0;
  269. return BoundingSphereState.DONE;
  270. };
  271. /**
  272. * Returns true if this object was destroyed; otherwise, false.
  273. *
  274. * @returns {boolean} True if this object was destroyed; otherwise, false.
  275. */
  276. LabelVisualizer.prototype.isDestroyed = function () {
  277. return false;
  278. };
  279. /**
  280. * Removes and destroys all primitives created by this instance.
  281. */
  282. LabelVisualizer.prototype.destroy = function () {
  283. this._entityCollection.collectionChanged.removeEventListener(
  284. LabelVisualizer.prototype._onCollectionChanged,
  285. this,
  286. );
  287. const entities = this._entityCollection.values;
  288. for (let i = 0; i < entities.length; i++) {
  289. this._cluster.removeLabel(entities[i]);
  290. }
  291. return destroyObject(this);
  292. };
  293. LabelVisualizer.prototype._onCollectionChanged = function (
  294. entityCollection,
  295. added,
  296. removed,
  297. changed,
  298. ) {
  299. let i;
  300. let entity;
  301. const items = this._items;
  302. const cluster = this._cluster;
  303. for (i = added.length - 1; i > -1; i--) {
  304. entity = added[i];
  305. if (defined(entity._label) && defined(entity._position)) {
  306. items.set(entity.id, new EntityData(entity));
  307. }
  308. }
  309. for (i = changed.length - 1; i > -1; i--) {
  310. entity = changed[i];
  311. if (defined(entity._label) && defined(entity._position)) {
  312. if (!items.contains(entity.id)) {
  313. items.set(entity.id, new EntityData(entity));
  314. }
  315. } else {
  316. returnPrimitive(items.get(entity.id), entity, cluster);
  317. items.remove(entity.id);
  318. }
  319. }
  320. for (i = removed.length - 1; i > -1; i--) {
  321. entity = removed[i];
  322. returnPrimitive(items.get(entity.id), entity, cluster);
  323. items.remove(entity.id);
  324. }
  325. };
  326. function returnPrimitive(item, entity, cluster) {
  327. if (defined(item)) {
  328. item.label = undefined;
  329. cluster.removeLabel(entity);
  330. }
  331. }
  332. export default LabelVisualizer;