/node_modules/ol3-cesium/ol3/src/ol/geom/multipolygon.js

https://gitlab.com/wanderinghogan/cesium-heatmap · JavaScript · 434 lines · 258 code · 52 blank · 124 comment · 47 complexity · 0347ab0fce8df218e9e4b4e58711b290 MD5 · raw file

  1. goog.provide('ol.geom.MultiPolygon');
  2. goog.require('ol');
  3. goog.require('ol.array');
  4. goog.require('ol.extent');
  5. goog.require('ol.geom.GeometryLayout');
  6. goog.require('ol.geom.GeometryType');
  7. goog.require('ol.geom.MultiPoint');
  8. goog.require('ol.geom.Polygon');
  9. goog.require('ol.geom.SimpleGeometry');
  10. goog.require('ol.geom.flat.area');
  11. goog.require('ol.geom.flat.center');
  12. goog.require('ol.geom.flat.closest');
  13. goog.require('ol.geom.flat.contains');
  14. goog.require('ol.geom.flat.deflate');
  15. goog.require('ol.geom.flat.inflate');
  16. goog.require('ol.geom.flat.interiorpoint');
  17. goog.require('ol.geom.flat.intersectsextent');
  18. goog.require('ol.geom.flat.orient');
  19. goog.require('ol.geom.flat.simplify');
  20. /**
  21. * @classdesc
  22. * Multi-polygon geometry.
  23. *
  24. * @constructor
  25. * @extends {ol.geom.SimpleGeometry}
  26. * @param {Array.<Array.<Array.<ol.Coordinate>>>} coordinates Coordinates.
  27. * @param {ol.geom.GeometryLayout=} opt_layout Layout.
  28. * @api stable
  29. */
  30. ol.geom.MultiPolygon = function(coordinates, opt_layout) {
  31. ol.geom.SimpleGeometry.call(this);
  32. /**
  33. * @type {Array.<Array.<number>>}
  34. * @private
  35. */
  36. this.endss_ = [];
  37. /**
  38. * @private
  39. * @type {number}
  40. */
  41. this.flatInteriorPointsRevision_ = -1;
  42. /**
  43. * @private
  44. * @type {Array.<number>}
  45. */
  46. this.flatInteriorPoints_ = null;
  47. /**
  48. * @private
  49. * @type {number}
  50. */
  51. this.maxDelta_ = -1;
  52. /**
  53. * @private
  54. * @type {number}
  55. */
  56. this.maxDeltaRevision_ = -1;
  57. /**
  58. * @private
  59. * @type {number}
  60. */
  61. this.orientedRevision_ = -1;
  62. /**
  63. * @private
  64. * @type {Array.<number>}
  65. */
  66. this.orientedFlatCoordinates_ = null;
  67. this.setCoordinates(coordinates, opt_layout);
  68. };
  69. ol.inherits(ol.geom.MultiPolygon, ol.geom.SimpleGeometry);
  70. /**
  71. * Append the passed polygon to this multipolygon.
  72. * @param {ol.geom.Polygon} polygon Polygon.
  73. * @api stable
  74. */
  75. ol.geom.MultiPolygon.prototype.appendPolygon = function(polygon) {
  76. goog.DEBUG && console.assert(polygon.getLayout() == this.layout,
  77. 'layout of polygon should match layout');
  78. /** @type {Array.<number>} */
  79. var ends;
  80. if (!this.flatCoordinates) {
  81. this.flatCoordinates = polygon.getFlatCoordinates().slice();
  82. ends = polygon.getEnds().slice();
  83. this.endss_.push();
  84. } else {
  85. var offset = this.flatCoordinates.length;
  86. ol.array.extend(this.flatCoordinates, polygon.getFlatCoordinates());
  87. ends = polygon.getEnds().slice();
  88. var i, ii;
  89. for (i = 0, ii = ends.length; i < ii; ++i) {
  90. ends[i] += offset;
  91. }
  92. }
  93. this.endss_.push(ends);
  94. this.changed();
  95. };
  96. /**
  97. * Make a complete copy of the geometry.
  98. * @return {!ol.geom.MultiPolygon} Clone.
  99. * @api stable
  100. */
  101. ol.geom.MultiPolygon.prototype.clone = function() {
  102. var multiPolygon = new ol.geom.MultiPolygon(null);
  103. var len = this.endss_.length;
  104. var newEndss = new Array(len);
  105. for (var i = 0; i < len; ++i) {
  106. newEndss[i] = this.endss_[i].slice();
  107. }
  108. multiPolygon.setFlatCoordinates(
  109. this.layout, this.flatCoordinates.slice(), newEndss);
  110. return multiPolygon;
  111. };
  112. /**
  113. * @inheritDoc
  114. */
  115. ol.geom.MultiPolygon.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {
  116. if (minSquaredDistance <
  117. ol.extent.closestSquaredDistanceXY(this.getExtent(), x, y)) {
  118. return minSquaredDistance;
  119. }
  120. if (this.maxDeltaRevision_ != this.getRevision()) {
  121. this.maxDelta_ = Math.sqrt(ol.geom.flat.closest.getssMaxSquaredDelta(
  122. this.flatCoordinates, 0, this.endss_, this.stride, 0));
  123. this.maxDeltaRevision_ = this.getRevision();
  124. }
  125. return ol.geom.flat.closest.getssClosestPoint(
  126. this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride,
  127. this.maxDelta_, true, x, y, closestPoint, minSquaredDistance);
  128. };
  129. /**
  130. * @inheritDoc
  131. */
  132. ol.geom.MultiPolygon.prototype.containsXY = function(x, y) {
  133. return ol.geom.flat.contains.linearRingssContainsXY(
  134. this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride, x, y);
  135. };
  136. /**
  137. * Return the area of the multipolygon on projected plane.
  138. * @return {number} Area (on projected plane).
  139. * @api stable
  140. */
  141. ol.geom.MultiPolygon.prototype.getArea = function() {
  142. return ol.geom.flat.area.linearRingss(
  143. this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride);
  144. };
  145. /**
  146. * Get the coordinate array for this geometry. This array has the structure
  147. * of a GeoJSON coordinate array for multi-polygons.
  148. *
  149. * @param {boolean=} opt_right Orient coordinates according to the right-hand
  150. * rule (counter-clockwise for exterior and clockwise for interior rings).
  151. * If `false`, coordinates will be oriented according to the left-hand rule
  152. * (clockwise for exterior and counter-clockwise for interior rings).
  153. * By default, coordinate orientation will depend on how the geometry was
  154. * constructed.
  155. * @return {Array.<Array.<Array.<ol.Coordinate>>>} Coordinates.
  156. * @api stable
  157. */
  158. ol.geom.MultiPolygon.prototype.getCoordinates = function(opt_right) {
  159. var flatCoordinates;
  160. if (opt_right !== undefined) {
  161. flatCoordinates = this.getOrientedFlatCoordinates().slice();
  162. ol.geom.flat.orient.orientLinearRingss(
  163. flatCoordinates, 0, this.endss_, this.stride, opt_right);
  164. } else {
  165. flatCoordinates = this.flatCoordinates;
  166. }
  167. return ol.geom.flat.inflate.coordinatesss(
  168. flatCoordinates, 0, this.endss_, this.stride);
  169. };
  170. /**
  171. * @return {Array.<Array.<number>>} Endss.
  172. */
  173. ol.geom.MultiPolygon.prototype.getEndss = function() {
  174. return this.endss_;
  175. };
  176. /**
  177. * @return {Array.<number>} Flat interior points.
  178. */
  179. ol.geom.MultiPolygon.prototype.getFlatInteriorPoints = function() {
  180. if (this.flatInteriorPointsRevision_ != this.getRevision()) {
  181. var flatCenters = ol.geom.flat.center.linearRingss(
  182. this.flatCoordinates, 0, this.endss_, this.stride);
  183. this.flatInteriorPoints_ = ol.geom.flat.interiorpoint.linearRingss(
  184. this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride,
  185. flatCenters);
  186. this.flatInteriorPointsRevision_ = this.getRevision();
  187. }
  188. return this.flatInteriorPoints_;
  189. };
  190. /**
  191. * Return the interior points as {@link ol.geom.MultiPoint multipoint}.
  192. * @return {ol.geom.MultiPoint} Interior points.
  193. * @api stable
  194. */
  195. ol.geom.MultiPolygon.prototype.getInteriorPoints = function() {
  196. var interiorPoints = new ol.geom.MultiPoint(null);
  197. interiorPoints.setFlatCoordinates(ol.geom.GeometryLayout.XY,
  198. this.getFlatInteriorPoints().slice());
  199. return interiorPoints;
  200. };
  201. /**
  202. * @return {Array.<number>} Oriented flat coordinates.
  203. */
  204. ol.geom.MultiPolygon.prototype.getOrientedFlatCoordinates = function() {
  205. if (this.orientedRevision_ != this.getRevision()) {
  206. var flatCoordinates = this.flatCoordinates;
  207. if (ol.geom.flat.orient.linearRingssAreOriented(
  208. flatCoordinates, 0, this.endss_, this.stride)) {
  209. this.orientedFlatCoordinates_ = flatCoordinates;
  210. } else {
  211. this.orientedFlatCoordinates_ = flatCoordinates.slice();
  212. this.orientedFlatCoordinates_.length =
  213. ol.geom.flat.orient.orientLinearRingss(
  214. this.orientedFlatCoordinates_, 0, this.endss_, this.stride);
  215. }
  216. this.orientedRevision_ = this.getRevision();
  217. }
  218. return this.orientedFlatCoordinates_;
  219. };
  220. /**
  221. * @inheritDoc
  222. */
  223. ol.geom.MultiPolygon.prototype.getSimplifiedGeometryInternal = function(squaredTolerance) {
  224. var simplifiedFlatCoordinates = [];
  225. var simplifiedEndss = [];
  226. simplifiedFlatCoordinates.length = ol.geom.flat.simplify.quantizess(
  227. this.flatCoordinates, 0, this.endss_, this.stride,
  228. Math.sqrt(squaredTolerance),
  229. simplifiedFlatCoordinates, 0, simplifiedEndss);
  230. var simplifiedMultiPolygon = new ol.geom.MultiPolygon(null);
  231. simplifiedMultiPolygon.setFlatCoordinates(
  232. ol.geom.GeometryLayout.XY, simplifiedFlatCoordinates, simplifiedEndss);
  233. return simplifiedMultiPolygon;
  234. };
  235. /**
  236. * Return the polygon at the specified index.
  237. * @param {number} index Index.
  238. * @return {ol.geom.Polygon} Polygon.
  239. * @api stable
  240. */
  241. ol.geom.MultiPolygon.prototype.getPolygon = function(index) {
  242. goog.DEBUG && console.assert(0 <= index && index < this.endss_.length,
  243. 'index should be in between 0 and the length of this.endss_');
  244. if (index < 0 || this.endss_.length <= index) {
  245. return null;
  246. }
  247. var offset;
  248. if (index === 0) {
  249. offset = 0;
  250. } else {
  251. var prevEnds = this.endss_[index - 1];
  252. offset = prevEnds[prevEnds.length - 1];
  253. }
  254. var ends = this.endss_[index].slice();
  255. var end = ends[ends.length - 1];
  256. if (offset !== 0) {
  257. var i, ii;
  258. for (i = 0, ii = ends.length; i < ii; ++i) {
  259. ends[i] -= offset;
  260. }
  261. }
  262. var polygon = new ol.geom.Polygon(null);
  263. polygon.setFlatCoordinates(
  264. this.layout, this.flatCoordinates.slice(offset, end), ends);
  265. return polygon;
  266. };
  267. /**
  268. * Return the polygons of this multipolygon.
  269. * @return {Array.<ol.geom.Polygon>} Polygons.
  270. * @api stable
  271. */
  272. ol.geom.MultiPolygon.prototype.getPolygons = function() {
  273. var layout = this.layout;
  274. var flatCoordinates = this.flatCoordinates;
  275. var endss = this.endss_;
  276. var polygons = [];
  277. var offset = 0;
  278. var i, ii, j, jj;
  279. for (i = 0, ii = endss.length; i < ii; ++i) {
  280. var ends = endss[i].slice();
  281. var end = ends[ends.length - 1];
  282. if (offset !== 0) {
  283. for (j = 0, jj = ends.length; j < jj; ++j) {
  284. ends[j] -= offset;
  285. }
  286. }
  287. var polygon = new ol.geom.Polygon(null);
  288. polygon.setFlatCoordinates(
  289. layout, flatCoordinates.slice(offset, end), ends);
  290. polygons.push(polygon);
  291. offset = end;
  292. }
  293. return polygons;
  294. };
  295. /**
  296. * @inheritDoc
  297. * @api stable
  298. */
  299. ol.geom.MultiPolygon.prototype.getType = function() {
  300. return ol.geom.GeometryType.MULTI_POLYGON;
  301. };
  302. /**
  303. * @inheritDoc
  304. * @api stable
  305. */
  306. ol.geom.MultiPolygon.prototype.intersectsExtent = function(extent) {
  307. return ol.geom.flat.intersectsextent.linearRingss(
  308. this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride, extent);
  309. };
  310. /**
  311. * Set the coordinates of the multipolygon.
  312. * @param {Array.<Array.<Array.<ol.Coordinate>>>} coordinates Coordinates.
  313. * @param {ol.geom.GeometryLayout=} opt_layout Layout.
  314. * @api stable
  315. */
  316. ol.geom.MultiPolygon.prototype.setCoordinates = function(coordinates, opt_layout) {
  317. if (!coordinates) {
  318. this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null, this.endss_);
  319. } else {
  320. this.setLayout(opt_layout, coordinates, 3);
  321. if (!this.flatCoordinates) {
  322. this.flatCoordinates = [];
  323. }
  324. var endss = ol.geom.flat.deflate.coordinatesss(
  325. this.flatCoordinates, 0, coordinates, this.stride, this.endss_);
  326. if (endss.length === 0) {
  327. this.flatCoordinates.length = 0;
  328. } else {
  329. var lastEnds = endss[endss.length - 1];
  330. this.flatCoordinates.length = lastEnds.length === 0 ?
  331. 0 : lastEnds[lastEnds.length - 1];
  332. }
  333. this.changed();
  334. }
  335. };
  336. /**
  337. * @param {ol.geom.GeometryLayout} layout Layout.
  338. * @param {Array.<number>} flatCoordinates Flat coordinates.
  339. * @param {Array.<Array.<number>>} endss Endss.
  340. */
  341. ol.geom.MultiPolygon.prototype.setFlatCoordinates = function(layout, flatCoordinates, endss) {
  342. goog.DEBUG && console.assert(endss, 'endss must be truthy');
  343. if (!flatCoordinates || flatCoordinates.length === 0) {
  344. goog.DEBUG && console.assert(endss.length === 0, 'the length of endss should be 0');
  345. } else {
  346. goog.DEBUG && console.assert(endss.length > 0, 'endss cannot be an empty array');
  347. var ends = endss[endss.length - 1];
  348. goog.DEBUG && console.assert(flatCoordinates.length == ends[ends.length - 1],
  349. 'the length of flatCoordinates should be the last value of ends');
  350. }
  351. this.setFlatCoordinatesInternal(layout, flatCoordinates);
  352. this.endss_ = endss;
  353. this.changed();
  354. };
  355. /**
  356. * @param {Array.<ol.geom.Polygon>} polygons Polygons.
  357. */
  358. ol.geom.MultiPolygon.prototype.setPolygons = function(polygons) {
  359. var layout = this.getLayout();
  360. var flatCoordinates = [];
  361. var endss = [];
  362. var i, ii, ends;
  363. for (i = 0, ii = polygons.length; i < ii; ++i) {
  364. var polygon = polygons[i];
  365. if (i === 0) {
  366. layout = polygon.getLayout();
  367. } else {
  368. // FIXME better handle the case of non-matching layouts
  369. goog.DEBUG && console.assert(polygon.getLayout() == layout,
  370. 'layout of polygon should be layout');
  371. }
  372. var offset = flatCoordinates.length;
  373. ends = polygon.getEnds();
  374. var j, jj;
  375. for (j = 0, jj = ends.length; j < jj; ++j) {
  376. ends[j] += offset;
  377. }
  378. ol.array.extend(flatCoordinates, polygon.getFlatCoordinates());
  379. endss.push(ends);
  380. }
  381. this.setFlatCoordinates(layout, flatCoordinates, endss);
  382. };