Polygon.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. /*global define*/
  2. define([
  3. '../Core/Color',
  4. '../Core/defaultValue',
  5. '../Core/defined',
  6. '../Core/defineProperties',
  7. '../Core/destroyObject',
  8. '../Core/DeveloperError',
  9. '../Core/Ellipsoid',
  10. '../Core/GeometryInstance',
  11. '../Core/Math',
  12. '../Core/PolygonGeometry',
  13. './EllipsoidSurfaceAppearance',
  14. './Material',
  15. './Primitive'
  16. ], function(
  17. Color,
  18. defaultValue,
  19. defined,
  20. defineProperties,
  21. destroyObject,
  22. DeveloperError,
  23. Ellipsoid,
  24. GeometryInstance,
  25. CesiumMath,
  26. PolygonGeometry,
  27. EllipsoidSurfaceAppearance,
  28. Material,
  29. Primitive) {
  30. "use strict";
  31. /**
  32. * A renderable polygon or hierarchy of polygons.
  33. *
  34. * @alias Polygon
  35. * @constructor
  36. *
  37. * @param {Object} [options] Object with the following properties:
  38. * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid that the polygon is drawn on.
  39. * @param {Cartesian3[]} [options.positions] The cartesian positions of the polygon.
  40. * @param {Object} [options.polygonHierarchy] An object defining the vertex positions of each nested polygon as defined in {@link Polygon#configureFromPolygonHierarchy}.
  41. * @param {Number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude in the underlying geometry.
  42. * @param {Number} [options.height=0.0] The height, in meters, that the rectangle is raised above the {@link Polygon#ellipsoid}.
  43. * @param {Number} [options.textureRotationAngle=0.0] The rotation of the texture coordinates, in radians. A positive rotation is counter-clockwise.
  44. * @param {Boolean} [options.show=true] Determines if this primitive will be shown.
  45. * @param {Material} [options.material] The surface appearance of the primitive.
  46. * @param {Object} [options.id] A user-defined object to return when the instance is picked with {@link Scene#pick}
  47. * @param {Boolean} [options.asynchronous=true] Determines if the primitive will be created asynchronously or block until ready.
  48. * @param {Boolean} [options.debugShowBoundingVolume=false] For debugging only. Determines if the primitive's commands' bounding spheres are shown.
  49. *
  50. * @exception {DeveloperError} Either options.positions or options.polygonHierarchy can be provided, but not both.
  51. * @exception {DeveloperError} When options.positions is provided, at least three positions are required.
  52. *
  53. * @demo {@link http://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Polygons.html|Cesium Sandcastle Polygons Demo}
  54. *
  55. * @example
  56. * // Example 1
  57. * var polygon = new Cesium.Polygon({
  58. * positions : Cartesian3.fromDegreesArray([
  59. * 0.0, 0.0,
  60. * 10.0, 0.0,
  61. * 0.0, 10.0
  62. * ]
  63. * });
  64. *
  65. * @example
  66. * // Example 2
  67. * var polygon = new Cesium.Polygon();
  68. * polygon.material.uniforms.color = {
  69. * red : 1.0,
  70. * green : 0.0,
  71. * blue : 0.0,
  72. * alpha : 1.0
  73. * };
  74. * polygon.positions = Cesium.Cartesian3.fromDegreesArray([
  75. * 0.0, 0.0,
  76. * 10.0, 0.0,
  77. * 0.0, 10.0
  78. * ]);
  79. */
  80. var Polygon = function(options) {
  81. options = defaultValue(options, defaultValue.EMPTY_OBJECT);
  82. /**
  83. * The ellipsoid that the polygon is drawn on.
  84. *
  85. * @type Ellipsoid
  86. *
  87. * @default Ellipsoid.WGS84
  88. */
  89. this.ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);
  90. this._ellipsoid = undefined;
  91. /**
  92. * The distance, in radians, between each latitude and longitude in the underlying geometry.
  93. * A lower granularity fits the curvature of the {@link Polygon#ellipsoid} better,
  94. * but uses more triangles.
  95. *
  96. * @type Number
  97. *
  98. * @default CesiumMath.RADIANS_PER_DEGREE
  99. */
  100. this.granularity = defaultValue(options.granularity, CesiumMath.RADIANS_PER_DEGREE);
  101. this._granularity = undefined;
  102. /**
  103. * The height, in meters, that the polygon is raised above the {@link Polygon#ellipsoid}.
  104. *
  105. * @type Number
  106. *
  107. * @default 0.0
  108. */
  109. this.height = defaultValue(options.height, 0.0);
  110. this._height = undefined;
  111. /**
  112. * The angle, in radians, relative to north that the polygon's texture is rotated.
  113. * Positive angles rotate counter-clockwise.
  114. *
  115. * @type Number
  116. *
  117. * @default 0.0
  118. */
  119. this.textureRotationAngle = defaultValue(options.textureRotationAngle, 0.0);
  120. this._textureRotationAngle = undefined;
  121. /**
  122. * Determines if this primitive will be shown.
  123. *
  124. * @type {Boolean}
  125. * @default true
  126. */
  127. this.show = defaultValue(options.show, true);
  128. var material = Material.fromType(Material.ColorType, {
  129. color : new Color(1.0, 1.0, 0.0, 0.5)
  130. });
  131. /**
  132. * The surface appearance of the primitive. This can be one of several built-in {@link Material} objects or a custom material, scripted with
  133. * {@link https://github.com/AnalyticalGraphicsInc/cesium/wiki/Fabric|Fabric}.
  134. * <p>
  135. * The default material is <code>Material.ColorType</code>.
  136. * </p>
  137. *
  138. * @type {Material}
  139. * @default Material.fromType(Material.ColorType)
  140. *
  141. * @see {@link https://github.com/AnalyticalGraphicsInc/cesium/wiki/Fabric|Fabric}
  142. *
  143. * @example
  144. * // 1. Change the color of the default material to yellow
  145. * polygon.material.uniforms.color = new Cesium.Color(1.0, 1.0, 0.0, 1.0);
  146. *
  147. * // 2. Change material to horizontal stripes
  148. * polygon.material = Cesium.Material.fromType( Material.StripeType);
  149. */
  150. this.material = defaultValue(options.material, material);
  151. /**
  152. * User-defined object returned when the polygon is picked.
  153. *
  154. * @type Object
  155. *
  156. * @default undefined
  157. *
  158. * @see Scene#pick
  159. */
  160. this.id = options.id;
  161. this._id = undefined;
  162. /**
  163. * Determines if the geometry instances will be created and batched on
  164. * a web worker.
  165. *
  166. * @type Boolean
  167. *
  168. * @default true
  169. */
  170. this.asynchronous = defaultValue(options.asynchronous, true);
  171. /**
  172. * This property is for debugging only; it is not for production use nor is it optimized.
  173. * <p>
  174. * Draws the bounding sphere for each draw command in the primitive.
  175. * </p>
  176. *
  177. * @type {Boolean}
  178. *
  179. * @default false
  180. */
  181. this.debugShowBoundingVolume = defaultValue(options.debugShowBoundingVolume, false);
  182. this._positions = undefined;
  183. this._polygonHierarchy = undefined;
  184. this._createPrimitive = false;
  185. this._primitive = undefined;
  186. //>>includeStart('debug', pragmas.debug);
  187. if (defined(options.positions) && defined(options.polygonHierarchy)) {
  188. throw new DeveloperError('Either options.positions or options.polygonHierarchy can be provided, but not both.');
  189. }
  190. //>>includeEnd('debug');
  191. if (defined(options.positions)) {
  192. this.positions = options.positions;
  193. } else if (defined(options.polygonHierarchy)) {
  194. this.configureFromPolygonHierarchy(options.polygonHierarchy);
  195. }
  196. };
  197. defineProperties(Polygon.prototype, {
  198. /**
  199. * Gets or sets positions that define the boundary of the polygon.
  200. * @memberof Polygon.prototype
  201. * @type {Cartesian3[]}
  202. * @example
  203. * polygon.positions = Cesium.Cartesian3.fromDegreesArray([
  204. * 0.0, 0.0,
  205. * 10.0, 0.0,
  206. * 0.0, 10.0
  207. * ]);
  208. */
  209. positions: {
  210. get : function() {
  211. return this._positions;
  212. },
  213. set : function(positions) {
  214. // positions can be undefined
  215. //>>includeStart('debug', pragmas.debug);
  216. if (defined(positions) && (positions.length < 3)) {
  217. throw new DeveloperError('At least three positions are required.');
  218. }
  219. //>>includeEnd('debug');
  220. this._positions = positions;
  221. this._polygonHierarchy = undefined;
  222. this._createPrimitive = true;
  223. }
  224. }
  225. });
  226. /**
  227. * Create a set of polygons with holes from a nested hierarchy.
  228. *
  229. * @param {Object} hierarchy An object defining the vertex positions of each nested polygon.
  230. * For example, the following polygon has two holes, and one hole has a hole. <code>holes</code> is optional.
  231. * Leaf nodes only have <code>positions</code>.
  232. * <pre>
  233. * <code>
  234. * {
  235. * positions : [ ... ], // The polygon's outer boundary
  236. * holes : [ // The polygon's inner holes
  237. * {
  238. * positions : [ ... ]
  239. * },
  240. * {
  241. * positions : [ ... ],
  242. * holes : [ // A polygon within a hole
  243. * {
  244. * positions : [ ... ]
  245. * }
  246. * ]
  247. * }
  248. * ]
  249. * }
  250. * </code>
  251. * </pre>
  252. *
  253. * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
  254. *
  255. * @example
  256. * // A triangle within a triangle
  257. * var hierarchy = {
  258. * positions : [
  259. * new Cesium.Cartesian3(-634066.5629045101, -4608738.034138676, 4348640.761750969),
  260. * new Cesium.Cartesian3(-1321523.0597310204, -5108871.981065817, 3570395.2500986718),
  261. * new Cesium.Cartesian3(46839.74837473363, -5303481.972379478, 3530933.5841716)
  262. * ],
  263. * holes : [{
  264. * positions :[
  265. * new Cesium.Cartesian3(-646079.44483647, -4811233.11175887, 4123187.2266941597),
  266. * new Cesium.Cartesian3(-1024015.4454943262, -5072141.413164587, 3716492.6173834214),
  267. * new Cesium.Cartesian3(-234678.22583880965, -5189078.820849883, 3688809.059214336)
  268. * ]
  269. * }]
  270. * };
  271. */
  272. Polygon.prototype.configureFromPolygonHierarchy = function(hierarchy) {
  273. this._positions = undefined;
  274. this._polygonHierarchy = hierarchy;
  275. this._createPrimitive = true;
  276. };
  277. /**
  278. * Called when {@link Viewer} or {@link CesiumWidget} render the scene to
  279. * get the draw commands needed to render this primitive.
  280. * <p>
  281. * Do not call this function directly. This is documented just to
  282. * list the exceptions that may be propagated when the scene is rendered:
  283. * </p>
  284. *
  285. * @exception {DeveloperError} this.ellipsoid must be defined.
  286. * @exception {DeveloperError} this.material must be defined.
  287. * @exception {DeveloperError} this.granularity must be defined.
  288. */
  289. Polygon.prototype.update = function(context, frameState, commandList) {
  290. //>>includeStart('debug', pragmas.debug);
  291. if (!defined(this.ellipsoid)) {
  292. throw new DeveloperError('this.ellipsoid must be defined.');
  293. }
  294. if (!defined(this.material)) {
  295. throw new DeveloperError('this.material must be defined.');
  296. }
  297. if (this.granularity < 0.0) {
  298. throw new DeveloperError('this.granularity must be greater than zero.');
  299. }
  300. //>>includeEnd('debug');
  301. if (!this.show) {
  302. return;
  303. }
  304. if (!this._createPrimitive && (!defined(this._primitive))) {
  305. // No positions/hierarchy to draw
  306. return;
  307. }
  308. if (this._createPrimitive ||
  309. (this._ellipsoid !== this.ellipsoid) ||
  310. (this._granularity !== this.granularity) ||
  311. (this._height !== this.height) ||
  312. (this._textureRotationAngle !== this.textureRotationAngle) ||
  313. (this._id !== this.id)) {
  314. this._createPrimitive = false;
  315. this._ellipsoid = this.ellipsoid;
  316. this._granularity = this.granularity;
  317. this._height = this.height;
  318. this._textureRotationAngle = this.textureRotationAngle;
  319. this._id = this.id;
  320. this._primitive = this._primitive && this._primitive.destroy();
  321. if (!defined(this._positions) && !defined(this._polygonHierarchy)) {
  322. return;
  323. }
  324. var instance;
  325. if (defined(this._positions)) {
  326. instance = new GeometryInstance({
  327. geometry : PolygonGeometry.fromPositions({
  328. positions : this._positions,
  329. height : this.height,
  330. vertexFormat : EllipsoidSurfaceAppearance.VERTEX_FORMAT,
  331. stRotation : this.textureRotationAngle,
  332. ellipsoid : this.ellipsoid,
  333. granularity : this.granularity
  334. }),
  335. id : this.id,
  336. pickPrimitive : this
  337. });
  338. } else {
  339. instance = new GeometryInstance({
  340. geometry : new PolygonGeometry({
  341. polygonHierarchy : this._polygonHierarchy,
  342. height : this.height,
  343. vertexFormat : EllipsoidSurfaceAppearance.VERTEX_FORMAT,
  344. stRotation : this.textureRotationAngle,
  345. ellipsoid : this.ellipsoid,
  346. granularity : this.granularity
  347. }),
  348. id : this.id,
  349. pickPrimitive : this
  350. });
  351. }
  352. this._primitive = new Primitive({
  353. geometryInstances : instance,
  354. appearance : new EllipsoidSurfaceAppearance({
  355. aboveGround : (this.height > 0.0)
  356. }),
  357. asynchronous : this.asynchronous
  358. });
  359. }
  360. var primitive = this._primitive;
  361. primitive.debugShowBoundingVolume = this.debugShowBoundingVolume;
  362. primitive.appearance.material = this.material;
  363. primitive.update(context, frameState, commandList);
  364. };
  365. /**
  366. * Returns true if this object was destroyed; otherwise, false.
  367. * <br /><br />
  368. * If this object was destroyed, it should not be used; calling any function other than
  369. * <code>isDestroyed</code> will result in a {@link DeveloperError} exception.
  370. *
  371. * @returns {Boolean} <code>true</code> if this object was destroyed; otherwise, <code>false</code>.
  372. *
  373. * @see Polygon#destroy
  374. */
  375. Polygon.prototype.isDestroyed = function() {
  376. return false;
  377. };
  378. /**
  379. * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic
  380. * release of WebGL resources, instead of relying on the garbage collector to destroy this object.
  381. * <br /><br />
  382. * Once an object is destroyed, it should not be used; calling any function other than
  383. * <code>isDestroyed</code> will result in a {@link DeveloperError} exception. Therefore,
  384. * assign the return value (<code>undefined</code>) to the object as done in the example.
  385. *
  386. * @returns {undefined}
  387. *
  388. * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
  389. *
  390. * @example
  391. * polygon = polygon && polygon.destroy();
  392. *
  393. * @see Polygon#isDestroyed
  394. */
  395. Polygon.prototype.destroy = function() {
  396. this._primitive = this._primitive && this._primitive.destroy();
  397. return destroyObject(this);
  398. };
  399. return Polygon;
  400. });