"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); var util_1 = require("./util"); var helpers_1 = require("@turf/helpers"); var envelope_1 = __importDefault(require("@turf/envelope")); var boolean_point_in_polygon_1 = __importDefault(require("@turf/boolean-point-in-polygon")); /** * Ring of edges which form a polygon. * * The ring may be either an outer shell or a hole. * * This class is inspired in GEOS's geos::operation::polygonize::EdgeRing */ var EdgeRing = /** @class */ (function () { function EdgeRing() { this.edges = []; this.polygon = undefined; //< Caches Polygon representation this.envelope = undefined; //< Caches Envelope representation } /** * Add an edge to the ring, inserting it in the last position. * * @memberof EdgeRing * @param {Edge} edge - Edge to be inserted */ EdgeRing.prototype.push = function (edge) { this.edges.push(edge); this.polygon = this.envelope = undefined; }; /** * Get Edge. * * @memberof EdgeRing * @param {number} i - Index * @returns {Edge} - Edge in the i position */ EdgeRing.prototype.get = function (i) { return this.edges[i]; }; Object.defineProperty(EdgeRing.prototype, "length", { /** * Getter of length property. * * @memberof EdgeRing * @returns {number} - Length of the edge ring. */ get: function () { return this.edges.length; }, enumerable: true, configurable: true }); /** * Similar to Array.prototype.forEach for the list of Edges in the EdgeRing. * * @memberof EdgeRing * @param {Function} f - The same function to be passed to Array.prototype.forEach */ EdgeRing.prototype.forEach = function (f) { this.edges.forEach(f); }; /** * Similar to Array.prototype.map for the list of Edges in the EdgeRing. * * @memberof EdgeRing * @param {Function} f - The same function to be passed to Array.prototype.map * @returns {Array} - The mapped values in the function */ EdgeRing.prototype.map = function (f) { return this.edges.map(f); }; /** * Similar to Array.prototype.some for the list of Edges in the EdgeRing. * * @memberof EdgeRing * @param {Function} f - The same function to be passed to Array.prototype.some * @returns {boolean} - True if an Edge check the condition */ EdgeRing.prototype.some = function (f) { return this.edges.some(f); }; /** * Check if the ring is valid in geomtry terms. * * A ring must have either 0 or 4 or more points. The first and the last must be * equal (in 2D) * geos::geom::LinearRing::validateConstruction * * @memberof EdgeRing * @returns {boolean} - Validity of the EdgeRing */ EdgeRing.prototype.isValid = function () { // TODO: stub return true; }; /** * Tests whether this ring is a hole. * * A ring is a hole if it is oriented counter-clockwise. * Similar implementation of geos::algorithm::CGAlgorithms::isCCW * * @memberof EdgeRing * @returns {boolean} - true: if it is a hole */ EdgeRing.prototype.isHole = function () { var _this = this; // XXX: Assuming Ring is valid // Find highest point var hiIndex = this.edges.reduce(function (high, edge, i) { if (edge.from.coordinates[1] > _this.edges[high].from.coordinates[1]) high = i; return high; }, 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); if (disc === 0) return (this.edges[iPrev].from.coordinates[0] > this.edges[iNext].from.coordinates[0]); return disc > 0; }; /** * Creates a MultiPoint representing the EdgeRing (discarts edges directions). * * @memberof EdgeRing * @returns {Feature} - Multipoint representation of the EdgeRing */ EdgeRing.prototype.toMultiPoint = function () { return helpers_1.multiPoint(this.edges.map(function (edge) { return edge.from.coordinates; })); }; /** * Creates a Polygon representing the EdgeRing. * * @memberof EdgeRing * @returns {Feature} - Polygon representation of the Edge Ring */ EdgeRing.prototype.toPolygon = function () { if (this.polygon) return this.polygon; var coordinates = this.edges.map(function (edge) { return edge.from.coordinates; }); coordinates.push(this.edges[0].from.coordinates); return (this.polygon = helpers_1.polygon([coordinates])); }; /** * Calculates the envelope of the EdgeRing. * * @memberof EdgeRing * @returns {Feature} - envelope */ EdgeRing.prototype.getEnvelope = function () { if (this.envelope) return this.envelope; return (this.envelope = envelope_1.default(this.toPolygon())); }; /** * `geos::operation::polygonize::EdgeRing::findEdgeRingContaining` * * @param {EdgeRing} testEdgeRing - EdgeRing to look in the list * @param {EdgeRing[]} shellList - List of EdgeRing in which to search * * @returns {EdgeRing} - EdgeRing which contains the testEdgeRing */ EdgeRing.findEdgeRingContaining = function (testEdgeRing, shellList) { var testEnvelope = testEdgeRing.getEnvelope(); var minEnvelope, minShell; shellList.forEach(function (shell) { var tryEnvelope = shell.getEnvelope(); if (minShell) minEnvelope = minShell.getEnvelope(); // the hole envelope cannot equal the shell envelope if (util_1.envelopeIsEqual(tryEnvelope, testEnvelope)) return; if (util_1.envelopeContains(tryEnvelope, testEnvelope)) { var testEdgeRingCoordinates = testEdgeRing.map(function (edge) { return edge.from.coordinates; }); var testPoint = void 0; var _loop_1 = function (pt) { if (!shell.some(function (edge) { return util_1.coordinatesEqual(pt, edge.from.coordinates); })) { testPoint = pt; } }; for (var _i = 0, testEdgeRingCoordinates_1 = testEdgeRingCoordinates; _i < testEdgeRingCoordinates_1.length; _i++) { var pt = testEdgeRingCoordinates_1[_i]; _loop_1(pt); } if (testPoint && shell.inside(helpers_1.point(testPoint))) { if (!minShell || util_1.envelopeContains(minEnvelope, tryEnvelope)) minShell = shell; } } }); return minShell; }; /** * Checks if the point is inside the edgeRing * * @param {Feature} pt - Point to check if it is inside the edgeRing * @returns {boolean} - True if it is inside, False otherwise */ EdgeRing.prototype.inside = function (pt) { return boolean_point_in_polygon_1.default(pt, this.toPolygon()); }; return EdgeRing; }()); exports.default = EdgeRing;