CylinderGeometryUpdater.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. import Cartesian3 from "../Core/Cartesian3.js";
  2. import Check from "../Core/Check.js";
  3. import Color from "../Core/Color.js";
  4. import ColorGeometryInstanceAttribute from "../Core/ColorGeometryInstanceAttribute.js";
  5. import CylinderGeometry from "../Core/CylinderGeometry.js";
  6. import CylinderOutlineGeometry from "../Core/CylinderOutlineGeometry.js";
  7. import defined from "../Core/defined.js";
  8. import DeveloperError from "../Core/DeveloperError.js";
  9. import DistanceDisplayConditionGeometryInstanceAttribute from "../Core/DistanceDisplayConditionGeometryInstanceAttribute.js";
  10. import GeometryInstance from "../Core/GeometryInstance.js";
  11. import GeometryOffsetAttribute from "../Core/GeometryOffsetAttribute.js";
  12. import Iso8601 from "../Core/Iso8601.js";
  13. import OffsetGeometryInstanceAttribute from "../Core/OffsetGeometryInstanceAttribute.js";
  14. import ShowGeometryInstanceAttribute from "../Core/ShowGeometryInstanceAttribute.js";
  15. import HeightReference from "../Scene/HeightReference.js";
  16. import MaterialAppearance from "../Scene/MaterialAppearance.js";
  17. import PerInstanceColorAppearance from "../Scene/PerInstanceColorAppearance.js";
  18. import ColorMaterialProperty from "./ColorMaterialProperty.js";
  19. import DynamicGeometryUpdater from "./DynamicGeometryUpdater.js";
  20. import GeometryUpdater from "./GeometryUpdater.js";
  21. import heightReferenceOnEntityPropertyChanged from "./heightReferenceOnEntityPropertyChanged.js";
  22. import Property from "./Property.js";
  23. const defaultOffset = Cartesian3.ZERO;
  24. const offsetScratch = new Cartesian3();
  25. const positionScratch = new Cartesian3();
  26. const scratchColor = new Color();
  27. function CylinderGeometryOptions(entity) {
  28. this.id = entity;
  29. this.vertexFormat = undefined;
  30. this.length = undefined;
  31. this.topRadius = undefined;
  32. this.bottomRadius = undefined;
  33. this.slices = undefined;
  34. this.numberOfVerticalLines = undefined;
  35. this.offsetAttribute = undefined;
  36. }
  37. /**
  38. * A {@link GeometryUpdater} for cylinders.
  39. * Clients do not normally create this class directly, but instead rely on {@link DataSourceDisplay}.
  40. * @alias CylinderGeometryUpdater
  41. * @constructor
  42. *
  43. * @param {Entity} entity The entity containing the geometry to be visualized.
  44. * @param {Scene} scene The scene where visualization is taking place.
  45. */
  46. function CylinderGeometryUpdater(entity, scene) {
  47. GeometryUpdater.call(this, {
  48. entity: entity,
  49. scene: scene,
  50. geometryOptions: new CylinderGeometryOptions(entity),
  51. geometryPropertyName: "cylinder",
  52. observedPropertyNames: [
  53. "availability",
  54. "position",
  55. "orientation",
  56. "cylinder",
  57. ],
  58. });
  59. this._onEntityPropertyChanged(entity, "cylinder", entity.cylinder, undefined);
  60. }
  61. if (defined(Object.create)) {
  62. CylinderGeometryUpdater.prototype = Object.create(GeometryUpdater.prototype);
  63. CylinderGeometryUpdater.prototype.constructor = CylinderGeometryUpdater;
  64. }
  65. Object.defineProperties(CylinderGeometryUpdater.prototype, {
  66. /**
  67. * Gets the terrain offset property
  68. * @type {TerrainOffsetProperty}
  69. * @memberof CylinderGeometryUpdater.prototype
  70. * @readonly
  71. * @private
  72. */
  73. terrainOffsetProperty: {
  74. get: function () {
  75. return this._terrainOffsetProperty;
  76. },
  77. },
  78. });
  79. /**
  80. * Creates the geometry instance which represents the fill of the geometry.
  81. *
  82. * @param {JulianDate} time The time to use when retrieving initial attribute values.
  83. * @returns {GeometryInstance} The geometry instance representing the filled portion of the geometry.
  84. *
  85. * @exception {DeveloperError} This instance does not represent a filled geometry.
  86. */
  87. CylinderGeometryUpdater.prototype.createFillGeometryInstance = function (time) {
  88. //>>includeStart('debug', pragmas.debug);
  89. Check.defined("time", time);
  90. if (!this._fillEnabled) {
  91. throw new DeveloperError(
  92. "This instance does not represent a filled geometry."
  93. );
  94. }
  95. //>>includeEnd('debug');
  96. const entity = this._entity;
  97. const isAvailable = entity.isAvailable(time);
  98. const show = new ShowGeometryInstanceAttribute(
  99. isAvailable &&
  100. entity.isShowing &&
  101. this._showProperty.getValue(time) &&
  102. this._fillProperty.getValue(time)
  103. );
  104. const distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(
  105. time
  106. );
  107. const distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(
  108. distanceDisplayCondition
  109. );
  110. const attributes = {
  111. show: show,
  112. distanceDisplayCondition: distanceDisplayConditionAttribute,
  113. color: undefined,
  114. offset: undefined,
  115. };
  116. if (this._materialProperty instanceof ColorMaterialProperty) {
  117. let currentColor;
  118. if (
  119. defined(this._materialProperty.color) &&
  120. (this._materialProperty.color.isConstant || isAvailable)
  121. ) {
  122. currentColor = this._materialProperty.color.getValue(time, scratchColor);
  123. }
  124. if (!defined(currentColor)) {
  125. currentColor = Color.WHITE;
  126. }
  127. attributes.color = ColorGeometryInstanceAttribute.fromColor(currentColor);
  128. }
  129. if (defined(this._options.offsetAttribute)) {
  130. attributes.offset = OffsetGeometryInstanceAttribute.fromCartesian3(
  131. Property.getValueOrDefault(
  132. this._terrainOffsetProperty,
  133. time,
  134. defaultOffset,
  135. offsetScratch
  136. )
  137. );
  138. }
  139. return new GeometryInstance({
  140. id: entity,
  141. geometry: new CylinderGeometry(this._options),
  142. modelMatrix: entity.computeModelMatrixForHeightReference(
  143. time,
  144. entity.cylinder.heightReference,
  145. this._options.length * 0.5,
  146. this._scene.mapProjection.ellipsoid
  147. ),
  148. attributes: attributes,
  149. });
  150. };
  151. /**
  152. * Creates the geometry instance which represents the outline of the geometry.
  153. *
  154. * @param {JulianDate} time The time to use when retrieving initial attribute values.
  155. * @returns {GeometryInstance} The geometry instance representing the outline portion of the geometry.
  156. *
  157. * @exception {DeveloperError} This instance does not represent an outlined geometry.
  158. */
  159. CylinderGeometryUpdater.prototype.createOutlineGeometryInstance = function (
  160. time
  161. ) {
  162. //>>includeStart('debug', pragmas.debug);
  163. Check.defined("time", time);
  164. if (!this._outlineEnabled) {
  165. throw new DeveloperError(
  166. "This instance does not represent an outlined geometry."
  167. );
  168. }
  169. //>>includeEnd('debug');
  170. const entity = this._entity;
  171. const isAvailable = entity.isAvailable(time);
  172. const outlineColor = Property.getValueOrDefault(
  173. this._outlineColorProperty,
  174. time,
  175. Color.BLACK,
  176. scratchColor
  177. );
  178. const distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(
  179. time
  180. );
  181. const attributes = {
  182. show: new ShowGeometryInstanceAttribute(
  183. isAvailable &&
  184. entity.isShowing &&
  185. this._showProperty.getValue(time) &&
  186. this._showOutlineProperty.getValue(time)
  187. ),
  188. color: ColorGeometryInstanceAttribute.fromColor(outlineColor),
  189. distanceDisplayCondition: DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(
  190. distanceDisplayCondition
  191. ),
  192. offset: undefined,
  193. };
  194. if (defined(this._options.offsetAttribute)) {
  195. attributes.offset = OffsetGeometryInstanceAttribute.fromCartesian3(
  196. Property.getValueOrDefault(
  197. this._terrainOffsetProperty,
  198. time,
  199. defaultOffset,
  200. offsetScratch
  201. )
  202. );
  203. }
  204. return new GeometryInstance({
  205. id: entity,
  206. geometry: new CylinderOutlineGeometry(this._options),
  207. modelMatrix: entity.computeModelMatrixForHeightReference(
  208. time,
  209. entity.cylinder.heightReference,
  210. this._options.length * 0.5,
  211. this._scene.mapProjection.ellipsoid
  212. ),
  213. attributes: attributes,
  214. });
  215. };
  216. CylinderGeometryUpdater.prototype._computeCenter = function (time, result) {
  217. return Property.getValueOrUndefined(this._entity.position, time, result);
  218. };
  219. CylinderGeometryUpdater.prototype._isHidden = function (entity, cylinder) {
  220. return (
  221. !defined(entity.position) ||
  222. !defined(cylinder.length) ||
  223. !defined(cylinder.topRadius) ||
  224. !defined(cylinder.bottomRadius) ||
  225. GeometryUpdater.prototype._isHidden.call(this, entity, cylinder)
  226. );
  227. };
  228. CylinderGeometryUpdater.prototype._isDynamic = function (entity, cylinder) {
  229. return (
  230. !entity.position.isConstant || //
  231. !Property.isConstant(entity.orientation) || //
  232. !cylinder.length.isConstant || //
  233. !cylinder.topRadius.isConstant || //
  234. !cylinder.bottomRadius.isConstant || //
  235. !Property.isConstant(cylinder.slices) || //
  236. !Property.isConstant(cylinder.outlineWidth) || //
  237. !Property.isConstant(cylinder.numberOfVerticalLines)
  238. );
  239. };
  240. CylinderGeometryUpdater.prototype._setStaticOptions = function (
  241. entity,
  242. cylinder
  243. ) {
  244. const heightReference = Property.getValueOrDefault(
  245. cylinder.heightReference,
  246. Iso8601.MINIMUM_VALUE,
  247. HeightReference.NONE
  248. );
  249. const options = this._options;
  250. options.vertexFormat =
  251. this._materialProperty instanceof ColorMaterialProperty
  252. ? PerInstanceColorAppearance.VERTEX_FORMAT
  253. : MaterialAppearance.MaterialSupport.TEXTURED.vertexFormat;
  254. options.length = cylinder.length.getValue(Iso8601.MINIMUM_VALUE);
  255. options.topRadius = cylinder.topRadius.getValue(Iso8601.MINIMUM_VALUE);
  256. options.bottomRadius = cylinder.bottomRadius.getValue(Iso8601.MINIMUM_VALUE);
  257. options.slices = Property.getValueOrUndefined(
  258. cylinder.slices,
  259. Iso8601.MINIMUM_VALUE
  260. );
  261. options.numberOfVerticalLines = Property.getValueOrUndefined(
  262. cylinder.numberOfVerticalLines,
  263. Iso8601.MINIMUM_VALUE
  264. );
  265. options.offsetAttribute =
  266. heightReference !== HeightReference.NONE
  267. ? GeometryOffsetAttribute.ALL
  268. : undefined;
  269. };
  270. CylinderGeometryUpdater.prototype._onEntityPropertyChanged = heightReferenceOnEntityPropertyChanged;
  271. CylinderGeometryUpdater.DynamicGeometryUpdater = DynamicCylinderGeometryUpdater;
  272. /**
  273. * @private
  274. */
  275. function DynamicCylinderGeometryUpdater(
  276. geometryUpdater,
  277. primitives,
  278. groundPrimitives
  279. ) {
  280. DynamicGeometryUpdater.call(
  281. this,
  282. geometryUpdater,
  283. primitives,
  284. groundPrimitives
  285. );
  286. }
  287. if (defined(Object.create)) {
  288. DynamicCylinderGeometryUpdater.prototype = Object.create(
  289. DynamicGeometryUpdater.prototype
  290. );
  291. DynamicCylinderGeometryUpdater.prototype.constructor = DynamicCylinderGeometryUpdater;
  292. }
  293. DynamicCylinderGeometryUpdater.prototype._isHidden = function (
  294. entity,
  295. cylinder,
  296. time
  297. ) {
  298. const options = this._options;
  299. const position = Property.getValueOrUndefined(
  300. entity.position,
  301. time,
  302. positionScratch
  303. );
  304. return (
  305. !defined(position) ||
  306. !defined(options.length) ||
  307. !defined(options.topRadius) || //
  308. !defined(options.bottomRadius) ||
  309. DynamicGeometryUpdater.prototype._isHidden.call(
  310. this,
  311. entity,
  312. cylinder,
  313. time
  314. )
  315. );
  316. };
  317. DynamicCylinderGeometryUpdater.prototype._setOptions = function (
  318. entity,
  319. cylinder,
  320. time
  321. ) {
  322. const heightReference = Property.getValueOrDefault(
  323. cylinder.heightReference,
  324. time,
  325. HeightReference.NONE
  326. );
  327. const options = this._options;
  328. options.length = Property.getValueOrUndefined(cylinder.length, time);
  329. options.topRadius = Property.getValueOrUndefined(cylinder.topRadius, time);
  330. options.bottomRadius = Property.getValueOrUndefined(
  331. cylinder.bottomRadius,
  332. time
  333. );
  334. options.slices = Property.getValueOrUndefined(cylinder.slices, time);
  335. options.numberOfVerticalLines = Property.getValueOrUndefined(
  336. cylinder.numberOfVerticalLines,
  337. time
  338. );
  339. options.offsetAttribute =
  340. heightReference !== HeightReference.NONE
  341. ? GeometryOffsetAttribute.ALL
  342. : undefined;
  343. };
  344. export default CylinderGeometryUpdater;