EdgeRing.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. "use strict";
  2. var __importDefault = (this && this.__importDefault) || function (mod) {
  3. return (mod && mod.__esModule) ? mod : { "default": mod };
  4. };
  5. Object.defineProperty(exports, "__esModule", { value: true });
  6. var util_1 = require("./util");
  7. var helpers_1 = require("@turf/helpers");
  8. var envelope_1 = __importDefault(require("@turf/envelope"));
  9. var boolean_point_in_polygon_1 = __importDefault(require("@turf/boolean-point-in-polygon"));
  10. /**
  11. * Ring of edges which form a polygon.
  12. *
  13. * The ring may be either an outer shell or a hole.
  14. *
  15. * This class is inspired in GEOS's geos::operation::polygonize::EdgeRing
  16. */
  17. var EdgeRing = /** @class */ (function () {
  18. function EdgeRing() {
  19. this.edges = [];
  20. this.polygon = undefined; //< Caches Polygon representation
  21. this.envelope = undefined; //< Caches Envelope representation
  22. }
  23. /**
  24. * Add an edge to the ring, inserting it in the last position.
  25. *
  26. * @memberof EdgeRing
  27. * @param {Edge} edge - Edge to be inserted
  28. */
  29. EdgeRing.prototype.push = function (edge) {
  30. this.edges.push(edge);
  31. this.polygon = this.envelope = undefined;
  32. };
  33. /**
  34. * Get Edge.
  35. *
  36. * @memberof EdgeRing
  37. * @param {number} i - Index
  38. * @returns {Edge} - Edge in the i position
  39. */
  40. EdgeRing.prototype.get = function (i) {
  41. return this.edges[i];
  42. };
  43. Object.defineProperty(EdgeRing.prototype, "length", {
  44. /**
  45. * Getter of length property.
  46. *
  47. * @memberof EdgeRing
  48. * @returns {number} - Length of the edge ring.
  49. */
  50. get: function () {
  51. return this.edges.length;
  52. },
  53. enumerable: true,
  54. configurable: true
  55. });
  56. /**
  57. * Similar to Array.prototype.forEach for the list of Edges in the EdgeRing.
  58. *
  59. * @memberof EdgeRing
  60. * @param {Function} f - The same function to be passed to Array.prototype.forEach
  61. */
  62. EdgeRing.prototype.forEach = function (f) {
  63. this.edges.forEach(f);
  64. };
  65. /**
  66. * Similar to Array.prototype.map for the list of Edges in the EdgeRing.
  67. *
  68. * @memberof EdgeRing
  69. * @param {Function} f - The same function to be passed to Array.prototype.map
  70. * @returns {Array} - The mapped values in the function
  71. */
  72. EdgeRing.prototype.map = function (f) {
  73. return this.edges.map(f);
  74. };
  75. /**
  76. * Similar to Array.prototype.some for the list of Edges in the EdgeRing.
  77. *
  78. * @memberof EdgeRing
  79. * @param {Function} f - The same function to be passed to Array.prototype.some
  80. * @returns {boolean} - True if an Edge check the condition
  81. */
  82. EdgeRing.prototype.some = function (f) {
  83. return this.edges.some(f);
  84. };
  85. /**
  86. * Check if the ring is valid in geomtry terms.
  87. *
  88. * A ring must have either 0 or 4 or more points. The first and the last must be
  89. * equal (in 2D)
  90. * geos::geom::LinearRing::validateConstruction
  91. *
  92. * @memberof EdgeRing
  93. * @returns {boolean} - Validity of the EdgeRing
  94. */
  95. EdgeRing.prototype.isValid = function () {
  96. // TODO: stub
  97. return true;
  98. };
  99. /**
  100. * Tests whether this ring is a hole.
  101. *
  102. * A ring is a hole if it is oriented counter-clockwise.
  103. * Similar implementation of geos::algorithm::CGAlgorithms::isCCW
  104. *
  105. * @memberof EdgeRing
  106. * @returns {boolean} - true: if it is a hole
  107. */
  108. EdgeRing.prototype.isHole = function () {
  109. var _this = this;
  110. // XXX: Assuming Ring is valid
  111. // Find highest point
  112. var hiIndex = this.edges.reduce(function (high, edge, i) {
  113. if (edge.from.coordinates[1] > _this.edges[high].from.coordinates[1])
  114. high = i;
  115. return high;
  116. }, 0), iPrev = (hiIndex === 0 ? this.length : hiIndex) - 1, iNext = (hiIndex + 1) % this.length, disc = util_1.orientationIndex(this.edges[iPrev].from.coordinates, this.edges[hiIndex].from.coordinates, this.edges[iNext].from.coordinates);
  117. if (disc === 0)
  118. return (this.edges[iPrev].from.coordinates[0] >
  119. this.edges[iNext].from.coordinates[0]);
  120. return disc > 0;
  121. };
  122. /**
  123. * Creates a MultiPoint representing the EdgeRing (discarts edges directions).
  124. *
  125. * @memberof EdgeRing
  126. * @returns {Feature<MultiPoint>} - Multipoint representation of the EdgeRing
  127. */
  128. EdgeRing.prototype.toMultiPoint = function () {
  129. return helpers_1.multiPoint(this.edges.map(function (edge) { return edge.from.coordinates; }));
  130. };
  131. /**
  132. * Creates a Polygon representing the EdgeRing.
  133. *
  134. * @memberof EdgeRing
  135. * @returns {Feature<Polygon>} - Polygon representation of the Edge Ring
  136. */
  137. EdgeRing.prototype.toPolygon = function () {
  138. if (this.polygon)
  139. return this.polygon;
  140. var coordinates = this.edges.map(function (edge) { return edge.from.coordinates; });
  141. coordinates.push(this.edges[0].from.coordinates);
  142. return (this.polygon = helpers_1.polygon([coordinates]));
  143. };
  144. /**
  145. * Calculates the envelope of the EdgeRing.
  146. *
  147. * @memberof EdgeRing
  148. * @returns {Feature<Polygon>} - envelope
  149. */
  150. EdgeRing.prototype.getEnvelope = function () {
  151. if (this.envelope)
  152. return this.envelope;
  153. return (this.envelope = envelope_1.default(this.toPolygon()));
  154. };
  155. /**
  156. * `geos::operation::polygonize::EdgeRing::findEdgeRingContaining`
  157. *
  158. * @param {EdgeRing} testEdgeRing - EdgeRing to look in the list
  159. * @param {EdgeRing[]} shellList - List of EdgeRing in which to search
  160. *
  161. * @returns {EdgeRing} - EdgeRing which contains the testEdgeRing
  162. */
  163. EdgeRing.findEdgeRingContaining = function (testEdgeRing, shellList) {
  164. var testEnvelope = testEdgeRing.getEnvelope();
  165. var minEnvelope, minShell;
  166. shellList.forEach(function (shell) {
  167. var tryEnvelope = shell.getEnvelope();
  168. if (minShell)
  169. minEnvelope = minShell.getEnvelope();
  170. // the hole envelope cannot equal the shell envelope
  171. if (util_1.envelopeIsEqual(tryEnvelope, testEnvelope))
  172. return;
  173. if (util_1.envelopeContains(tryEnvelope, testEnvelope)) {
  174. var testEdgeRingCoordinates = testEdgeRing.map(function (edge) { return edge.from.coordinates; });
  175. var testPoint = void 0;
  176. var _loop_1 = function (pt) {
  177. if (!shell.some(function (edge) { return util_1.coordinatesEqual(pt, edge.from.coordinates); })) {
  178. testPoint = pt;
  179. }
  180. };
  181. for (var _i = 0, testEdgeRingCoordinates_1 = testEdgeRingCoordinates; _i < testEdgeRingCoordinates_1.length; _i++) {
  182. var pt = testEdgeRingCoordinates_1[_i];
  183. _loop_1(pt);
  184. }
  185. if (testPoint && shell.inside(helpers_1.point(testPoint))) {
  186. if (!minShell || util_1.envelopeContains(minEnvelope, tryEnvelope))
  187. minShell = shell;
  188. }
  189. }
  190. });
  191. return minShell;
  192. };
  193. /**
  194. * Checks if the point is inside the edgeRing
  195. *
  196. * @param {Feature<Point>} pt - Point to check if it is inside the edgeRing
  197. * @returns {boolean} - True if it is inside, False otherwise
  198. */
  199. EdgeRing.prototype.inside = function (pt) {
  200. return boolean_point_in_polygon_1.default(pt, this.toPolygon());
  201. };
  202. return EdgeRing;
  203. }());
  204. exports.default = EdgeRing;