forked from MapComplete/MapComplete
Intermediate refactoring
This commit is contained in:
parent
93db813cfc
commit
069cddf034
103 changed files with 7950 additions and 0 deletions
185
Logic/GeoOperations.js
Normal file
185
Logic/GeoOperations.js
Normal file
|
@ -0,0 +1,185 @@
|
|||
"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;
|
||||
}());
|
Loading…
Add table
Add a link
Reference in a new issue