Fix multiple bugs after user testing

This commit is contained in:
Pieter Vander Vennet 2020-06-28 23:33:48 +02:00
parent bcdbf6a2dd
commit 9bd37d9cde
20 changed files with 1529 additions and 77 deletions

View file

@ -1,8 +1,15 @@
import * as turf from 'turf'
export class GeoOperations {
static surfaceAreaInSqMeters(feature: any) {
return turf.area(feature);
}
static featureIsContainedInAny(feature: any, shouldNotContain: any[], noTouching: boolean = false): boolean {
static featureIsContainedInAny(feature: any,
shouldNotContain: any[],
maxOverlapPercentage: number): boolean {
// Returns 'false' if no problematic intersection is found
if (feature.geometry.type === "Point") {
const coor = feature.geometry.coordinates;
for (const shouldNotContainElement of shouldNotContain) {
@ -21,38 +28,55 @@ export class GeoOperations {
}
if (feature.geometry.type === "Polygon") {
if (feature.geometry.type === "Polygon" || feature.geometry.type === "MultiPolygon") {
const poly = feature;
let featureBBox = BBox.get(feature);
const featureSurface = GeoOperations.surfaceAreaInSqMeters(poly);
for (const shouldNotContainElement of shouldNotContain) {
let shouldNotContainBBox = BBox.get(shouldNotContainElement);
let featureBBox = BBox.get(feature);
if (!featureBBox.overlapsWith(shouldNotContainBBox)) {
const shouldNotContainBBox = BBox.get(shouldNotContainElement);
const overlaps = featureBBox.overlapsWith(shouldNotContainBBox)
if (!overlaps) {
continue;
}
if (noTouching) {
if (GeoOperations.isPolygonTouching(poly, shouldNotContainElement)) {
return true;
}
} else {
if (GeoOperations.isPolygonInside(poly, shouldNotContainElement)) {
// Calculate the surface area of the intersection
// If it is too big, refuse
try {
const intersection = turf.intersect(poly, shouldNotContainElement);
if (intersection == null) {
continue;
}
const intersectionSize = turf.area(intersection);
const ratio = intersectionSize / featureSurface;
console.log("Intersection ratio", ratio, "intersection:", intersectionSize, "featuresize:", featureSurface, "targetRatio", maxOverlapPercentage / 100);
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
*/
static isPolygonInside(polygon, container) {
private static isPolygonInside(polygon, container) {
for (const coor of polygon.geometry.coordinates[0]) {
if (!GeoOperations.inside(coor, container)) {
return false;
@ -66,7 +90,7 @@ export class GeoOperations {
* @param polygon
* @param container
*/
static isPolygonTouching(polygon, container) {
private static isPolygonTouching(polygon, container) {
for (const coor of polygon.geometry.coordinates[0]) {
if (GeoOperations.inside(coor, container)) {
return true;
@ -76,7 +100,7 @@ export class GeoOperations {
}
static inside(pointCoordinate, feature): boolean {
private static inside(pointCoordinate, feature): boolean {
// ray-casting algorithm based on
// http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
@ -134,10 +158,19 @@ class BBox {
this.minLon = Math.min(this.minLon, coordinate[0]);
this.minLat = Math.min(this.minLat, coordinate[1]);
}
this.check();
}
private check() {
if (isNaN(this.maxLon) || isNaN(this.maxLat) || isNaN(this.minLon) || isNaN(this.minLat)) {
console.log(this);
throw "BBOX has NAN";
}
}
public overlapsWith(other: BBox) {
this.check();
other.check();
if (this.maxLon < other.minLon) {
return false;
}
@ -155,13 +188,22 @@ class BBox {
static get(feature) {
if (feature.bbox === undefined) {
if (feature.geometry.type === "Polygon") {
if (feature.geometry.type === "MultiPolygon") {
let coordinates = [];
for (const coorlist of feature.geometry.coordinates) {
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 {
} else if (feature.geometry.type === "Point") {
// Point
feature.bbox = new BBox([feature.geometry.coordinates]);
} else {
throw "Cannot calculate bbox, unknown type " + feature.geometry.type;
}
}