PlaneGeometryUpdater.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  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 ColorGeometryInstanceAttribute from "../Core/ColorGeometryInstanceAttribute.js";
  6. import defined from "../Core/defined.js";
  7. import DeveloperError from "../Core/DeveloperError.js";
  8. import DistanceDisplayConditionGeometryInstanceAttribute from "../Core/DistanceDisplayConditionGeometryInstanceAttribute.js";
  9. import GeometryInstance from "../Core/GeometryInstance.js";
  10. import Iso8601 from "../Core/Iso8601.js";
  11. import CesiumMath from "../Core/Math.js";
  12. import Matrix3 from "../Core/Matrix3.js";
  13. import Matrix4 from "../Core/Matrix4.js";
  14. import PlaneGeometry from "../Core/PlaneGeometry.js";
  15. import PlaneOutlineGeometry from "../Core/PlaneOutlineGeometry.js";
  16. import Quaternion from "../Core/Quaternion.js";
  17. import ShowGeometryInstanceAttribute from "../Core/ShowGeometryInstanceAttribute.js";
  18. import MaterialAppearance from "../Scene/MaterialAppearance.js";
  19. import PerInstanceColorAppearance from "../Scene/PerInstanceColorAppearance.js";
  20. import ColorMaterialProperty from "./ColorMaterialProperty.js";
  21. import DynamicGeometryUpdater from "./DynamicGeometryUpdater.js";
  22. import GeometryUpdater from "./GeometryUpdater.js";
  23. import Property from "./Property.js";
  24. var positionScratch = new Cartesian3();
  25. var scratchColor = new Color();
  26. function PlaneGeometryOptions(entity) {
  27. this.id = entity;
  28. this.vertexFormat = undefined;
  29. this.plane = undefined;
  30. this.dimensions = undefined;
  31. }
  32. /**
  33. * A {@link GeometryUpdater} for planes.
  34. * Clients do not normally create this class directly, but instead rely on {@link DataSourceDisplay}.
  35. * @alias PlaneGeometryUpdater
  36. * @constructor
  37. *
  38. * @param {Entity} entity The entity containing the geometry to be visualized.
  39. * @param {Scene} scene The scene where visualization is taking place.
  40. */
  41. function PlaneGeometryUpdater(entity, scene) {
  42. GeometryUpdater.call(this, {
  43. entity: entity,
  44. scene: scene,
  45. geometryOptions: new PlaneGeometryOptions(entity),
  46. geometryPropertyName: "plane",
  47. observedPropertyNames: ["availability", "position", "orientation", "plane"],
  48. });
  49. this._onEntityPropertyChanged(entity, "plane", entity.plane, undefined);
  50. }
  51. if (defined(Object.create)) {
  52. PlaneGeometryUpdater.prototype = Object.create(GeometryUpdater.prototype);
  53. PlaneGeometryUpdater.prototype.constructor = PlaneGeometryUpdater;
  54. }
  55. /**
  56. * Creates the geometry instance which represents the fill of the geometry.
  57. *
  58. * @param {JulianDate} time The time to use when retrieving initial attribute values.
  59. * @returns {GeometryInstance} The geometry instance representing the filled portion of the geometry.
  60. *
  61. * @exception {DeveloperError} This instance does not represent a filled geometry.
  62. */
  63. PlaneGeometryUpdater.prototype.createFillGeometryInstance = function (time) {
  64. //>>includeStart('debug', pragmas.debug);
  65. Check.defined("time", time);
  66. if (!this._fillEnabled) {
  67. throw new DeveloperError(
  68. "This instance does not represent a filled geometry."
  69. );
  70. }
  71. //>>includeEnd('debug');
  72. var entity = this._entity;
  73. var isAvailable = entity.isAvailable(time);
  74. var attributes;
  75. var color;
  76. var show = new ShowGeometryInstanceAttribute(
  77. isAvailable &&
  78. entity.isShowing &&
  79. this._showProperty.getValue(time) &&
  80. this._fillProperty.getValue(time)
  81. );
  82. var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(
  83. time
  84. );
  85. var distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(
  86. distanceDisplayCondition
  87. );
  88. if (this._materialProperty instanceof ColorMaterialProperty) {
  89. var currentColor;
  90. if (
  91. defined(this._materialProperty.color) &&
  92. (this._materialProperty.color.isConstant || isAvailable)
  93. ) {
  94. currentColor = this._materialProperty.color.getValue(time, scratchColor);
  95. }
  96. if (!defined(currentColor)) {
  97. currentColor = Color.WHITE;
  98. }
  99. color = ColorGeometryInstanceAttribute.fromColor(currentColor);
  100. attributes = {
  101. show: show,
  102. distanceDisplayCondition: distanceDisplayConditionAttribute,
  103. color: color,
  104. };
  105. } else {
  106. attributes = {
  107. show: show,
  108. distanceDisplayCondition: distanceDisplayConditionAttribute,
  109. };
  110. }
  111. var planeGraphics = entity.plane;
  112. var options = this._options;
  113. var modelMatrix = entity.computeModelMatrix(time);
  114. var plane = Property.getValueOrDefault(
  115. planeGraphics.plane,
  116. time,
  117. options.plane
  118. );
  119. var dimensions = Property.getValueOrUndefined(
  120. planeGraphics.dimensions,
  121. time,
  122. options.dimensions
  123. );
  124. options.plane = plane;
  125. options.dimensions = dimensions;
  126. modelMatrix = createPrimitiveMatrix(
  127. plane,
  128. dimensions,
  129. modelMatrix,
  130. this._scene.mapProjection.ellipsoid,
  131. modelMatrix
  132. );
  133. return new GeometryInstance({
  134. id: entity,
  135. geometry: new PlaneGeometry(this._options),
  136. modelMatrix: modelMatrix,
  137. attributes: attributes,
  138. });
  139. };
  140. /**
  141. * Creates the geometry instance which represents the outline of the geometry.
  142. *
  143. * @param {JulianDate} time The time to use when retrieving initial attribute values.
  144. * @returns {GeometryInstance} The geometry instance representing the outline portion of the geometry.
  145. *
  146. * @exception {DeveloperError} This instance does not represent an outlined geometry.
  147. */
  148. PlaneGeometryUpdater.prototype.createOutlineGeometryInstance = function (time) {
  149. //>>includeStart('debug', pragmas.debug);
  150. Check.defined("time", time);
  151. if (!this._outlineEnabled) {
  152. throw new DeveloperError(
  153. "This instance does not represent an outlined geometry."
  154. );
  155. }
  156. //>>includeEnd('debug');
  157. var entity = this._entity;
  158. var isAvailable = entity.isAvailable(time);
  159. var outlineColor = Property.getValueOrDefault(
  160. this._outlineColorProperty,
  161. time,
  162. Color.BLACK,
  163. scratchColor
  164. );
  165. var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(
  166. time
  167. );
  168. var planeGraphics = entity.plane;
  169. var options = this._options;
  170. var modelMatrix = entity.computeModelMatrix(time);
  171. var plane = Property.getValueOrDefault(
  172. planeGraphics.plane,
  173. time,
  174. options.plane
  175. );
  176. var dimensions = Property.getValueOrUndefined(
  177. planeGraphics.dimensions,
  178. time,
  179. options.dimensions
  180. );
  181. options.plane = plane;
  182. options.dimensions = dimensions;
  183. modelMatrix = createPrimitiveMatrix(
  184. plane,
  185. dimensions,
  186. modelMatrix,
  187. this._scene.mapProjection.ellipsoid,
  188. modelMatrix
  189. );
  190. return new GeometryInstance({
  191. id: entity,
  192. geometry: new PlaneOutlineGeometry(),
  193. modelMatrix: modelMatrix,
  194. attributes: {
  195. show: new ShowGeometryInstanceAttribute(
  196. isAvailable &&
  197. entity.isShowing &&
  198. this._showProperty.getValue(time) &&
  199. this._showOutlineProperty.getValue(time)
  200. ),
  201. color: ColorGeometryInstanceAttribute.fromColor(outlineColor),
  202. distanceDisplayCondition: DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(
  203. distanceDisplayCondition
  204. ),
  205. },
  206. });
  207. };
  208. PlaneGeometryUpdater.prototype._isHidden = function (entity, plane) {
  209. return (
  210. !defined(plane.plane) ||
  211. !defined(plane.dimensions) ||
  212. !defined(entity.position) ||
  213. GeometryUpdater.prototype._isHidden.call(this, entity, plane)
  214. );
  215. };
  216. PlaneGeometryUpdater.prototype._getIsClosed = function (options) {
  217. return false;
  218. };
  219. PlaneGeometryUpdater.prototype._isDynamic = function (entity, plane) {
  220. return (
  221. !entity.position.isConstant || //
  222. !Property.isConstant(entity.orientation) || //
  223. !plane.plane.isConstant || //
  224. !plane.dimensions.isConstant || //
  225. !Property.isConstant(plane.outlineWidth)
  226. );
  227. };
  228. PlaneGeometryUpdater.prototype._setStaticOptions = function (entity, plane) {
  229. var isColorMaterial = this._materialProperty instanceof ColorMaterialProperty;
  230. var options = this._options;
  231. options.vertexFormat = isColorMaterial
  232. ? PerInstanceColorAppearance.VERTEX_FORMAT
  233. : MaterialAppearance.MaterialSupport.TEXTURED.vertexFormat;
  234. options.plane = plane.plane.getValue(Iso8601.MINIMUM_VALUE, options.plane);
  235. options.dimensions = plane.dimensions.getValue(
  236. Iso8601.MINIMUM_VALUE,
  237. options.dimensions
  238. );
  239. };
  240. PlaneGeometryUpdater.DynamicGeometryUpdater = DynamicPlaneGeometryUpdater;
  241. /**
  242. * @private
  243. */
  244. function DynamicPlaneGeometryUpdater(
  245. geometryUpdater,
  246. primitives,
  247. groundPrimitives
  248. ) {
  249. DynamicGeometryUpdater.call(
  250. this,
  251. geometryUpdater,
  252. primitives,
  253. groundPrimitives
  254. );
  255. }
  256. if (defined(Object.create)) {
  257. DynamicPlaneGeometryUpdater.prototype = Object.create(
  258. DynamicGeometryUpdater.prototype
  259. );
  260. DynamicPlaneGeometryUpdater.prototype.constructor = DynamicPlaneGeometryUpdater;
  261. }
  262. DynamicPlaneGeometryUpdater.prototype._isHidden = function (
  263. entity,
  264. plane,
  265. time
  266. ) {
  267. var options = this._options;
  268. var position = Property.getValueOrUndefined(
  269. entity.position,
  270. time,
  271. positionScratch
  272. );
  273. return (
  274. !defined(position) ||
  275. !defined(options.plane) ||
  276. !defined(options.dimensions) ||
  277. DynamicGeometryUpdater.prototype._isHidden.call(this, entity, plane, time)
  278. );
  279. };
  280. DynamicPlaneGeometryUpdater.prototype._setOptions = function (
  281. entity,
  282. plane,
  283. time
  284. ) {
  285. var options = this._options;
  286. options.plane = Property.getValueOrDefault(plane.plane, time, options.plane);
  287. options.dimensions = Property.getValueOrUndefined(
  288. plane.dimensions,
  289. time,
  290. options.dimensions
  291. );
  292. };
  293. var scratchAxis = new Cartesian3();
  294. var scratchAxis2 = new Cartesian3();
  295. var scratchTranslation = new Cartesian3();
  296. var scratchNormal = new Cartesian3();
  297. var scratchScale = new Cartesian3();
  298. var scratchQuaternion = new Quaternion();
  299. var scratchMatrix3 = new Matrix3();
  300. function createPrimitiveMatrix(
  301. plane,
  302. dimensions,
  303. transform,
  304. ellipsoid,
  305. result
  306. ) {
  307. var normal = plane.normal;
  308. var distance = plane.distance;
  309. var translation = Cartesian3.multiplyByScalar(
  310. normal,
  311. -distance,
  312. scratchTranslation
  313. );
  314. translation = Matrix4.multiplyByPoint(transform, translation, translation);
  315. var transformedNormal = Matrix4.multiplyByPointAsVector(
  316. transform,
  317. normal,
  318. scratchNormal
  319. );
  320. Cartesian3.normalize(transformedNormal, transformedNormal);
  321. var up = ellipsoid.geodeticSurfaceNormal(translation, scratchAxis2);
  322. if (
  323. CesiumMath.equalsEpsilon(
  324. Math.abs(Cartesian3.dot(up, transformedNormal)),
  325. 1.0,
  326. CesiumMath.EPSILON8
  327. )
  328. ) {
  329. up = Cartesian3.clone(Cartesian3.UNIT_Z, up);
  330. if (
  331. CesiumMath.equalsEpsilon(
  332. Math.abs(Cartesian3.dot(up, transformedNormal)),
  333. 1.0,
  334. CesiumMath.EPSILON8
  335. )
  336. ) {
  337. up = Cartesian3.clone(Cartesian3.UNIT_X, up);
  338. }
  339. }
  340. var left = Cartesian3.cross(up, transformedNormal, scratchAxis);
  341. up = Cartesian3.cross(transformedNormal, left, up);
  342. Cartesian3.normalize(left, left);
  343. Cartesian3.normalize(up, up);
  344. var rotationMatrix = scratchMatrix3;
  345. Matrix3.setColumn(rotationMatrix, 0, left, rotationMatrix);
  346. Matrix3.setColumn(rotationMatrix, 1, up, rotationMatrix);
  347. Matrix3.setColumn(rotationMatrix, 2, transformedNormal, rotationMatrix);
  348. var rotation = Quaternion.fromRotationMatrix(
  349. rotationMatrix,
  350. scratchQuaternion
  351. );
  352. var scale = Cartesian2.clone(dimensions, scratchScale);
  353. scale.z = 1.0;
  354. return Matrix4.fromTranslationQuaternionRotationScale(
  355. translation,
  356. rotation,
  357. scale,
  358. result
  359. );
  360. }
  361. /**
  362. * @private
  363. */
  364. PlaneGeometryUpdater.createPrimitiveMatrix = createPrimitiveMatrix;
  365. export default PlaneGeometryUpdater;