"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.GeoOperations = void 0; var turf = require("turf"); var GeoOperations = /** @class */ (function () { function GeoOperations() { } GeoOperations.surfaceAreaInSqMeters = function (feature) { return turf.area(feature); }; GeoOperations.featureIsContainedInAny = function (feature, shouldNotContain, maxOverlapPercentage) { // Returns 'false' if no problematic intersection is found if (feature.geometry.type === "Point") { var coor = feature.geometry.coordinates; for (var _i = 0, shouldNotContain_1 = shouldNotContain; _i < shouldNotContain_1.length; _i++) { var shouldNotContainElement = shouldNotContain_1[_i]; var shouldNotContainBBox = BBox.get(shouldNotContainElement); var featureBBox = BBox.get(feature); if (!featureBBox.overlapsWith(shouldNotContainBBox)) { continue; } if (this.inside(coor, shouldNotContainElement)) { return true; } } return false; } if (feature.geometry.type === "Polygon" || feature.geometry.type === "MultiPolygon") { var poly = feature; var featureBBox = BBox.get(feature); var featureSurface = GeoOperations.surfaceAreaInSqMeters(poly); for (var _a = 0, shouldNotContain_2 = shouldNotContain; _a < shouldNotContain_2.length; _a++) { var shouldNotContainElement = shouldNotContain_2[_a]; var shouldNotContainBBox = BBox.get(shouldNotContainElement); var overlaps = featureBBox.overlapsWith(shouldNotContainBBox); if (!overlaps) { continue; } // Calculate the surface area of the intersection // If it is too big, refuse try { var intersection = turf.intersect(poly, shouldNotContainElement); if (intersection == null) { continue; } var intersectionSize = turf.area(intersection); var ratio = intersectionSize / featureSurface; if (ratio * 100 >= maxOverlapPercentage) { console.log("Refused", poly.id, " due to ", shouldNotContainElement.id, "intersection ratio is ", ratio, "which is bigger then the target ratio of ", (maxOverlapPercentage / 100)); return true; } } catch (exception) { console.log("EXCEPTION CAUGHT WHILE INTERSECTING: ", exception); // We assume that this failed due to an intersection return true; } } return false; // No problematic intersections found } return false; }; /** * Simple check: that every point of the polygon is inside the container * @param polygon * @param container */ GeoOperations.isPolygonInside = function (polygon, container) { for (var _i = 0, _a = polygon.geometry.coordinates[0]; _i < _a.length; _i++) { var coor = _a[_i]; if (!GeoOperations.inside(coor, container)) { return false; } } return true; }; /** * Simple check: one point of the polygon is inside the container * @param polygon * @param container */ GeoOperations.isPolygonTouching = function (polygon, container) { for (var _i = 0, _a = polygon.geometry.coordinates[0]; _i < _a.length; _i++) { var coor = _a[_i]; if (GeoOperations.inside(coor, container)) { return true; } } return false; }; GeoOperations.inside = function (pointCoordinate, feature) { // ray-casting algorithm based on // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html if (feature.geometry.type === "Point") { return false; } var x = pointCoordinate[0]; var y = pointCoordinate[1]; var poly = feature.geometry.coordinates[0]; var inside = false; for (var i = 0, j = poly.length - 1; i < poly.length; j = i++) { var coori = poly[i]; var coorj = poly[j]; var xi = coori[0]; var yi = coori[1]; var xj = coorj[0]; var yj = coorj[1]; var intersect = ((yi > y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); if (intersect) { inside = !inside; } } return inside; }; ; return GeoOperations; }()); exports.GeoOperations = GeoOperations; var BBox = /** @class */ (function () { function BBox(coordinates) { this.maxLat = Number.MIN_VALUE; this.maxLon = Number.MIN_VALUE; this.minLat = Number.MAX_VALUE; this.minLon = Number.MAX_VALUE; for (var _i = 0, coordinates_1 = coordinates; _i < coordinates_1.length; _i++) { var coordinate = coordinates_1[_i]; this.maxLon = Math.max(this.maxLon, coordinate[0]); this.maxLat = Math.max(this.maxLat, coordinate[1]); this.minLon = Math.min(this.minLon, coordinate[0]); this.minLat = Math.min(this.minLat, coordinate[1]); } this.check(); } BBox.prototype.check = function () { if (isNaN(this.maxLon) || isNaN(this.maxLat) || isNaN(this.minLon) || isNaN(this.minLat)) { console.log(this); throw "BBOX has NAN"; } }; BBox.prototype.overlapsWith = function (other) { this.check(); other.check(); if (this.maxLon < other.minLon) { return false; } if (this.maxLat < other.minLat) { return false; } if (this.minLon > other.maxLon) { return false; } if (this.minLat > other.maxLat) { return false; } return true; }; BBox.get = function (feature) { if (feature.bbox === undefined) { if (feature.geometry.type === "MultiPolygon") { var coordinates = []; for (var _i = 0, _a = feature.geometry.coordinates; _i < _a.length; _i++) { var coorlist = _a[_i]; coordinates = coordinates.concat(coorlist[0]); } feature.bbox = new BBox(coordinates); } else if (feature.geometry.type === "Polygon") { feature.bbox = new BBox(feature.geometry.coordinates[0]); } else if (feature.geometry.type === "LineString") { feature.bbox = new BBox(feature.geometry.coordinates); } else if (feature.geometry.type === "Point") { // Point feature.bbox = new BBox([feature.geometry.coordinates]); } else { throw "Cannot calculate bbox, unknown type " + feature.geometry.type; } } return feature.bbox; }; return BBox; }());