From acb651b96feed96c54b5ae307f8c23dd478240e8 Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Wed, 11 Dec 2024 02:12:23 +0100 Subject: [PATCH] Typing: use 'strict' for GeoOperations.ts module --- src/Logic/GeoOperations.ts | 159 +++++++++++++++++++------------------ 1 file changed, 80 insertions(+), 79 deletions(-) diff --git a/src/Logic/GeoOperations.ts b/src/Logic/GeoOperations.ts index d3c6e96e4..db649caba 100644 --- a/src/Logic/GeoOperations.ts +++ b/src/Logic/GeoOperations.ts @@ -1,20 +1,22 @@ import { BBox } from "./BBox" import * as turf from "@turf/turf" -import { AllGeoJSON, booleanWithin, Coord, Lines } from "@turf/turf" +import { AllGeoJSON, booleanWithin, Coord } from "@turf/turf" import { Feature, FeatureCollection, GeoJSON, - Geometry, LineString, MultiLineString, MultiPolygon, Point, Polygon, - Position, + Position } from "geojson" import { Tiles } from "../Models/TileRange" import { Utils } from "../Utils" +import { NearestPointOnLine } from "@turf/nearest-point-on-line" + +"use strict" export class GeoOperations { private static readonly _earthRadius = 6378137 @@ -28,7 +30,7 @@ export class GeoOperations { "behind", "sharp_left", "left", - "slight_left", + "slight_left" ] as const private static reverseBearing = { N: 0, @@ -46,21 +48,21 @@ export class GeoOperations { W: 270, WNW: 292.5, NW: 315, - NNW: 337.5, + NNW: 337.5 } /** * Create a union between two features */ - public static union(f0: Feature, f1: Feature): Feature | null { - return turf.union(f0, f1) + public static union(f0: Feature, f1: Feature): Feature | null { + return turf.union(f0, f1) } - public static intersect(f0: Feature, f1: Feature): Feature | null { - return turf.intersect(f0, f1) + public static intersect(f0: Feature, f1: Feature): Feature | null { + return turf.intersect(f0, f1) } - static surfaceAreaInSqMeters(feature: any) { + static surfaceAreaInSqMeters(feature: Feature): number { return turf.area(feature) } @@ -68,8 +70,8 @@ export class GeoOperations { * Converts a GeoJson feature to a point GeoJson feature * @param feature */ - static centerpoint(feature: any): Feature { - const newFeature: Feature = turf.center(feature) + static centerpoint(feature: Feature): Feature { + const newFeature: Feature = turf.center(feature) newFeature.properties = feature.properties newFeature.id = feature.id return newFeature @@ -83,12 +85,12 @@ export class GeoOperations { */ static centerpointCoordinates(feature: undefined | null): undefined ; static centerpointCoordinates(feature: AllGeoJSON | GeoJSON | undefined): [number, number] | undefined; - static centerpointCoordinates(feature: NonNullable< AllGeoJSON> | NonNullable): NonNullable<[number, number]>; + static centerpointCoordinates(feature: NonNullable | NonNullable): NonNullable<[number, number]>; static centerpointCoordinates(feature: AllGeoJSON | GeoJSON): [number, number] { - if(feature === undefined || feature === null){ + if (feature === undefined || feature === null) { return undefined } - return <[number, number]>turf.center(feature).geometry.coordinates + return <[number, number]>turf.center(feature).geometry.coordinates } /** @@ -140,11 +142,12 @@ export class GeoOperations { * const overlap0 = GeoOperations.calculateOverlap(line0, [polygon]); * overlap.length // => 1 */ - static calculateOverlap(feature: any, otherFeatures: any[]): { feat: any; overlap: number }[] { + static calculateOverlap(feature: Feature, otherFeatures: Feature[]): + { feat: Feature; overlap: number }[] { const featureBBox = BBox.get(feature) - const result: { feat: any; overlap: number }[] = [] + const result: { feat: Feature; overlap: number }[] = [] if (feature.geometry.type === "Point") { - const coor = feature.geometry.coordinates + const coor = <[number,number]> feature.geometry.coordinates for (const otherFeature of otherFeatures) { if ( feature.properties.id !== undefined && @@ -197,7 +200,7 @@ export class GeoOperations { } if (otherFeature.geometry.type === "Point") { - if (this.inside(otherFeature, feature)) { + if (this.inside(> otherFeature, feature)) { result.push({ feat: otherFeature, overlap: undefined }) } continue @@ -263,9 +266,8 @@ export class GeoOperations { const y: number = pointCoordinate[1] if (feature.geometry.type === "MultiPolygon") { - const coordinatess = feature.geometry.coordinates + const coordinatess: [number, number][][][] = <[number, number][][][]>feature.geometry.coordinates for (const coordinates of coordinatess) { - // @ts-ignore const inThisPolygon = GeoOperations.pointInPolygonCoordinates(x, y, coordinates) if (inThisPolygon) { return true @@ -275,24 +277,23 @@ export class GeoOperations { } if (feature.geometry.type === "Polygon") { - // @ts-ignore - return GeoOperations.pointInPolygonCoordinates(x, y, feature.geometry.coordinates) + return GeoOperations.pointInPolygonCoordinates(x, y, <[number, number][][]>feature.geometry.coordinates) } throw "GeoOperations.inside: unsupported geometry type " + feature.geometry.type } - static lengthInMeters(feature: any) { + static lengthInMeters(feature: Feature): number { return turf.length(feature) * 1000 } - static buffer(feature: any, bufferSizeInMeter: number) { + static buffer(feature: Feature, bufferSizeInMeter: number): Feature | FeatureCollection { return turf.buffer(feature, bufferSizeInMeter / 1000, { - units: "kilometers", + units: "kilometers" }) } - static bbox(feature: Feature | FeatureCollection): Feature { + static bbox(feature: Feature | FeatureCollection): Feature { const [lon, lat, lon0, lat0] = turf.bbox(feature) return { type: "Feature", @@ -304,9 +305,9 @@ export class GeoOperations { [lon0, lat], [lon0, lat0], [lon, lat0], - [lon, lat], - ], - }, + [lon, lat] + ] + } } } @@ -324,17 +325,8 @@ export class GeoOperations { public static nearestPoint( way: Feature, point: [number, number] - ): Feature< - Point, - { - index: number - dist: number - location: number - } - > { - return ( - turf.nearestPointOnLine(>way, point, { units: "kilometers" }) - ) + ): NearestPointOnLine { + return turf.nearestPointOnLine(>way, point, { units: "kilometers" }) } /** @@ -352,18 +344,30 @@ export class GeoOperations { way: Feature ): Feature { if (way.geometry.type === "Polygon") { - way = { ...way } - way.geometry = { ...way.geometry } - way.geometry.type = "LineString" - way.geometry.coordinates = (way.geometry).coordinates[0] - } else if (way.geometry.type === "MultiPolygon") { - way = { ...way } - way.geometry = { ...way.geometry } - way.geometry.type = "MultiLineString" - way.geometry.coordinates = (way.geometry).coordinates[0] + return >{ + geometry: { + type: "LineString", + coordinates: way.geometry.coordinates[0] + }, + properties: way.properties + } } - - return way + if (way.geometry.type === "MultiPolygon") { + return >{ + geometry: { + type: "MultiLineString", + coordinates: way.geometry.coordinates[0] + }, + properties: way.properties + } + } + if (way.geometry.type === "LineString") { + return > way + } + if (way.geometry.type === "MultiLineString") { + return > way + } + throw "Invalid geometry to create a way from this" } public static toCSV( @@ -402,9 +406,6 @@ export class GeoOperations { for (const feature of _features) { const properties = feature.properties for (const key in properties) { - if (!properties.hasOwnProperty(key)) { - continue - } addH(key) } } @@ -535,8 +536,8 @@ export class GeoOperations { properties: {}, geometry: { type: "Point", - coordinates: p, - }, + coordinates: p + } } ) } @@ -552,7 +553,7 @@ export class GeoOperations { trackPoints.push(trkpt) } const header = - '' + "" return ( header + "\n" + @@ -591,7 +592,7 @@ export class GeoOperations { trackPoints.push(trkpt) } const header = - '' + "" return ( header + "\n" + @@ -610,21 +611,21 @@ export class GeoOperations { * const copy = GeoOperations.removeOvernoding(feature) * expect(copy.geometry.coordinates[0]).deep.equal([[4.477944199999975,51.02783550000022],[4.477987899999996,51.027818800000034],[4.478004500000021,51.02783399999988],[4.478025499999962,51.02782489999994],[4.478079099999993,51.027873899999896],[4.47801040000006,51.027903799999955],[4.477944199999975,51.02783550000022]]) */ - static removeOvernoding(feature: any) { + static removeOvernoding(feature: Feature) { if (feature.geometry.type !== "LineString" && feature.geometry.type !== "Polygon") { throw "Overnode removal is only supported on linestrings and polygons" } const copy = { ...feature, - geometry: { ...feature.geometry }, + geometry: { ...feature.geometry } } let coordinates: [number, number][] if (feature.geometry.type === "LineString") { - coordinates = [...feature.geometry.coordinates] + coordinates = <[number,number][]> [...feature.geometry.coordinates] copy.geometry.coordinates = coordinates } else { - coordinates = [...feature.geometry.coordinates[0]] + coordinates = <[number,number][]> [...feature.geometry.coordinates[0]] copy.geometry.coordinates[0] = coordinates } @@ -671,12 +672,12 @@ export class GeoOperations { public static along(a: Coord, b: Coord, distanceMeter: number): Coord { return turf.along( - { + >{ type: "Feature", geometry: { type: "LineString", - coordinates: [a, b], - }, + coordinates: [a, b] + } }, distanceMeter, { units: "meters" } @@ -713,8 +714,8 @@ export class GeoOperations { * GeoOperations.completelyWithin(park, pond) // => false */ static completelyWithin( - feature: Feature, - possiblyEnclosingFeature: Feature + feature: Feature, + possiblyEnclosingFeature: Feature ): boolean { return booleanWithin(feature, possiblyEnclosingFeature) } @@ -882,8 +883,8 @@ export class GeoOperations { properties: p.properties, geometry: { type: "LineString", - coordinates: p.geometry.coordinates[0], - }, + coordinates: p.geometry.coordinates[0] + } } } @@ -911,7 +912,7 @@ export class GeoOperations { console.debug("SPlitting way", feature.properties.id) result.push({ ...feature, - geometry: { ...feature.geometry, coordinates: coors.slice(i + 1) }, + geometry: { ...feature.geometry, coordinates: coors.slice(i + 1) } }) coors = coors.slice(0, i + 1) break @@ -920,7 +921,7 @@ export class GeoOperations { } result.push({ ...feature, - geometry: { ...feature.geometry, coordinates: coors }, + geometry: { ...feature.geometry, coordinates: coors } }) } } @@ -1094,8 +1095,8 @@ export class GeoOperations { properties: multiLineStringFeature.properties, geometry: { type: "LineString", - coordinates: coors[0], - }, + coordinates: coors[0] + } } } return { @@ -1103,8 +1104,8 @@ export class GeoOperations { properties: multiLineStringFeature.properties, geometry: { type: "MultiLineString", - coordinates: coors, - }, + coordinates: coors + } } } @@ -1177,7 +1178,7 @@ export class GeoOperations { // Calculate the length of the intersection - let intersectionPoints = turf.lineIntersect(feature, otherFeature) + const intersectionPoints = turf.lineIntersect(feature, otherFeature) if (intersectionPoints.features.length == 0) { // No intersections. // If one point is inside of the polygon, all points are @@ -1190,7 +1191,7 @@ export class GeoOperations { return null } - let intersectionPointsArray = intersectionPoints.features.map((d) => { + const intersectionPointsArray = intersectionPoints.features.map((d) => { return d.geometry.coordinates }) @@ -1212,7 +1213,7 @@ export class GeoOperations { } } - let intersection = turf.lineSlice( + const intersection = turf.lineSlice( turf.point(intersectionPointsArray[0]), turf.point(intersectionPointsArray[1]), feature