From 2844c5fa34c4160a19c6a996e2ec3d6b10d528fa Mon Sep 17 00:00:00 2001 From: AdenForshaw Date: Sun, 10 Nov 2024 15:16:24 +1100 Subject: [PATCH] added ./places/builings endpoint for testing --- package-lock.json | 2320 ++++++++++++++++- package.json | 5 +- src/bigquery/bigquery.service.ts | 64 +- src/buildings/buildings.controller.ts | 35 +- src/buildings/buildings.service.ts | 8 +- src/buildings/dto/get-buildings-query.dto.ts | 35 - .../dto/requests/get-buildings-query.dto.ts | 9 + .../dto/responses/building-response.dto.ts | 60 + .../interfaces/building.interface.ts | 30 + .../cloudstorage-cache.service.ts | 22 +- .../dto/requests/get-by-location.dto.ts | 79 + src/common/dto/responses/geometry.dto.ts | 13 + src/common/interfaces/geometry.interface.ts | 8 + src/gcs/gcs.service.ts | 7 +- .../dto/requests/get-places-with-buildings.ts | 14 + src/places/dto/requests/get-places.dto.ts | 14 +- .../dto/{ => responses}/place-response.dto.ts | 62 +- src/places/interfaces/place.interface.ts | 17 +- src/places/places.controller.ts | 84 +- src/places/places.module.ts | 3 +- src/places/places.service.spec.ts | 2 +- src/places/places.service.ts | 2 +- src/utils/geojson.ts | 143 +- .../bq-results/get-buildings-nearby.json | 46 + 24 files changed, 2816 insertions(+), 266 deletions(-) delete mode 100644 src/buildings/dto/get-buildings-query.dto.ts create mode 100644 src/buildings/dto/requests/get-buildings-query.dto.ts create mode 100644 src/buildings/dto/responses/building-response.dto.ts create mode 100644 src/common/dto/requests/get-by-location.dto.ts create mode 100644 src/common/dto/responses/geometry.dto.ts create mode 100644 src/common/interfaces/geometry.interface.ts create mode 100644 src/places/dto/requests/get-places-with-buildings.ts rename src/places/dto/{ => responses}/place-response.dto.ts (77%) create mode 100644 test/mock-data/bq-results/get-buildings-nearby.json diff --git a/package-lock.json b/package-lock.json index 0783f48..037f6cc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "overture-maps-api", - "version": "0.0.6", + "version": "0.1.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "overture-maps-api", - "version": "0.0.6", + "version": "0.1.1", "license": "UNLICENSED", "dependencies": { "@google-cloud/bigquery": "^7.9.1", @@ -16,9 +16,12 @@ "@nestjs/core": "^10.0.0", "@nestjs/platform-express": "^10.0.0", "@nestjs/swagger": "^8.0.1", + "@turf/turf": "^7.1.0", + "@types/geojson": "^7946.0.14", "class-transformer": "^0.5.1", "class-validator": "^0.14.1", "dotenv": "^16.4.5", + "geojson": "^0.5.0", "reflect-metadata": "^0.2.0", "rxjs": "^7.8.1", "swagger-ui-express": "^5.0.1", @@ -2285,149 +2288,2044 @@ } } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "license": "MIT", + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nuxtjs/opencollective": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz", + "integrity": "sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "consola": "^2.15.0", + "node-fetch": "^2.6.1" + }, + "bin": { + "opencollective": "bin/opencollective.js" + }, + "engines": { + "node": ">=8.0.0", + "npm": ">=5.0.0" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@turf/along": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/along/-/along-7.1.0.tgz", + "integrity": "sha512-WLgBZJ/B6CcASF6WL7M+COtHlVP0hBrMbrtKyF7KBlicwRuijJZXDtEQA5oLgr+k1b2HqGN+UqH2A0/E719enQ==", + "dependencies": { + "@turf/bearing": "^7.1.0", + "@turf/destination": "^7.1.0", + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/angle": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/angle/-/angle-7.1.0.tgz", + "integrity": "sha512-YMHEV/YrARsWgWoQuXEWrQMsvB8z67nTMw2eiLZ883V7jwkhWQGvCW6W+/mGgsWQdHppjCZNcKryryhD2GRWVA==", + "dependencies": { + "@turf/bearing": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/rhumb-bearing": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/area": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/area/-/area-7.1.0.tgz", + "integrity": "sha512-w91FEe02/mQfMPRX2pXua48scFuKJ2dSVMF2XmJ6+BJfFiCPxp95I3+Org8+ZsYv93CDNKbf0oLNEPnuQdgs2g==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/bbox": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/bbox/-/bbox-7.1.0.tgz", + "integrity": "sha512-PdWPz9tW86PD78vSZj2fiRaB8JhUHy6piSa/QXb83lucxPK+HTAdzlDQMTKj5okRCU8Ox/25IR2ep9T8NdopRA==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/bbox-clip": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/bbox-clip/-/bbox-clip-7.1.0.tgz", + "integrity": "sha512-PhZubKCzF/afwStUzODqOJluiCbCw244lCtVhXA9F+Pgkhvk8KvbFdgpPquOZ45OwuktrchSB28BrBkSBiadHw==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/bbox-polygon": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/bbox-polygon/-/bbox-polygon-7.1.0.tgz", + "integrity": "sha512-fvZB09ErCZOVlWVDop836hmpKaGUmfXnR9naMhS73A/8nn4M3hELbQtMv2R8gXj7UakXCuxS/i9erdpDFZ2O+g==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/bearing": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/bearing/-/bearing-7.1.0.tgz", + "integrity": "sha512-X5lackrZ6FW+YhgjWxwVFRgWD1j4xm4t5VvE6EE6v/1PVaHQ5OCjf6u1oaLx5LSG+gaHUhjTlAHrn9MYPFaeTA==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/bezier-spline": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/bezier-spline/-/bezier-spline-7.1.0.tgz", + "integrity": "sha512-bhBY70bcVYJEosuW7B/TFtnE5rmPTTpxmJvljhGC0eyM84oNVv7apDBuseb5KdlTOOBIvdD9nIE4qV8lmplp6w==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-clockwise": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/boolean-clockwise/-/boolean-clockwise-7.1.0.tgz", + "integrity": "sha512-H5DYno+gHwZx+VaiC8DUBZXZQlxYecdSvqCfCACWi1uMsKvlht/O+xy65hz2P57lk2smlcV+1ETFVxJlEZduYg==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-concave": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/boolean-concave/-/boolean-concave-7.1.0.tgz", + "integrity": "sha512-IFCN25DI+hvngxIsv4+MPuRJQRl/Lz/xnZgpH82leCn4Jqn5wW7KqKFMz7G4GoKK+93cK5/6ioAxY7hVWBXxJw==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-contains": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/boolean-contains/-/boolean-contains-7.1.0.tgz", + "integrity": "sha512-ldy4j1/RVChYTYjEb4wWaE/JyF1jA87WpsB4eVLic6OcAYJGs7POF1kfKbcdkJJiRBmhI3CXNA+u+m9y4Z/j3g==", + "dependencies": { + "@turf/bbox": "^7.1.0", + "@turf/boolean-point-in-polygon": "^7.1.0", + "@turf/boolean-point-on-line": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-crosses": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/boolean-crosses/-/boolean-crosses-7.1.0.tgz", + "integrity": "sha512-LK8UM3AENycuGinLCDaL0QSznGMnD0XsjFDGnY4KehshiL5Zd8ZsPyKmHOPygUJT9DWeH69iLx459lOc+5Vj2w==", + "dependencies": { + "@turf/boolean-point-in-polygon": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/line-intersect": "^7.1.0", + "@turf/polygon-to-line": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-disjoint": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/boolean-disjoint/-/boolean-disjoint-7.1.0.tgz", + "integrity": "sha512-JapOG03kOCoGeYMWgTQjEifhr1nUoK4Os2cX0iC5X9kvZF4qCHeruX8/rffBQDx7PDKQKusSTXq8B1ISFi0hOw==", + "dependencies": { + "@turf/boolean-point-in-polygon": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/line-intersect": "^7.1.0", + "@turf/meta": "^7.1.0", + "@turf/polygon-to-line": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-equal": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/boolean-equal/-/boolean-equal-7.1.0.tgz", + "integrity": "sha512-deghtFMApc7fNsdXtZdgYR4gsU+TVfowcv666nrvZbPPsXL6NTYGBhDFmYXsJ8gPTCGT9uT0WXppdgT8diWOxA==", + "dependencies": { + "@turf/clean-coords": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "geojson-equality-ts": "^1.0.2", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-intersects": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/boolean-intersects/-/boolean-intersects-7.1.0.tgz", + "integrity": "sha512-gpksWbb0RT+Z3nfqRfoACY3KEFyv2BPaxJ3L76PH67DhHZviq3Nfg85KYbpuhS64FSm+9tXe4IaKn6EjbHo20g==", + "dependencies": { + "@turf/boolean-disjoint": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-overlap": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/boolean-overlap/-/boolean-overlap-7.1.0.tgz", + "integrity": "sha512-mJRN0X8JiPm8eDZk5sLvIrsP03A2GId6ijx4VgSE1AvHwV6qB561KlUbWxga2AScocIfv/y/qd2OCs+/TQSZcg==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/line-intersect": "^7.1.0", + "@turf/line-overlap": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "geojson-equality-ts": "^1.0.2", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-parallel": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/boolean-parallel/-/boolean-parallel-7.1.0.tgz", + "integrity": "sha512-tA84Oux0X91CxUc6c/lZph5W9wUZGNT4fxFOg5Gp1IMTSwtxSYL1LMvKsr/VmMnwdOUkNcqAgU06+t4wBLtDfg==", + "dependencies": { + "@turf/clean-coords": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/line-segment": "^7.1.0", + "@turf/rhumb-bearing": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-point-in-polygon": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/boolean-point-in-polygon/-/boolean-point-in-polygon-7.1.0.tgz", + "integrity": "sha512-mprVsyIQ+ijWTZwbnO4Jhxu94ZW2M2CheqLiRTsGJy0Ooay9v6Av5/Nl3/Gst7ZVXxPqMeMaFYkSzcTc87AKew==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "point-in-polygon-hao": "^1.1.0", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-point-on-line": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/boolean-point-on-line/-/boolean-point-on-line-7.1.0.tgz", + "integrity": "sha512-Kd83EjeTyY4kVMAhcW3Lb8aChwh24BUIhmpE9Or8M+ETNsFGzn9M7qtIySJHLRzKAL3letvWSKXKQPuK1AhAzg==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-touches": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/boolean-touches/-/boolean-touches-7.1.0.tgz", + "integrity": "sha512-qN4LCs3RfVtNAAdn5GpsUFBqoZyAaK9UzSnGSh67GP9sy5M8MEHwM/HAJ5zGWJqQADrczI3U6BRWGLcGfGSz3Q==", + "dependencies": { + "@turf/boolean-point-in-polygon": "^7.1.0", + "@turf/boolean-point-on-line": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-valid": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/boolean-valid/-/boolean-valid-7.1.0.tgz", + "integrity": "sha512-zq1QCfQEyn+piHlvxxDifjmsJn2xl53i4mnKFYdMQI/i09XiX+Fi/MVM3i2hf3D5AsEPsud8Tk7C7rWNCm4nVw==", + "dependencies": { + "@turf/bbox": "^7.1.0", + "@turf/boolean-crosses": "^7.1.0", + "@turf/boolean-disjoint": "^7.1.0", + "@turf/boolean-overlap": "^7.1.0", + "@turf/boolean-point-in-polygon": "^7.1.0", + "@turf/boolean-point-on-line": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/line-intersect": "^7.1.0", + "@types/geojson": "^7946.0.10", + "geojson-polygon-self-intersections": "^1.2.1", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-within": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/boolean-within/-/boolean-within-7.1.0.tgz", + "integrity": "sha512-pgXgKCzYHssADQ1nClB1Q9aWI/dE1elm2jy3B5X59XdoFXKrKDZA+gCHYOYgp2NGO/txzVfl3UKvnxIj54Fa4w==", + "dependencies": { + "@turf/bbox": "^7.1.0", + "@turf/boolean-point-in-polygon": "^7.1.0", + "@turf/boolean-point-on-line": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/buffer": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/buffer/-/buffer-7.1.0.tgz", + "integrity": "sha512-QM3JiCMYA19k5ouO8wJtvICX3Y8XntxVpDfHSKhFFidZcCkMTR2PWWOpwS6EoL3t75rSKw/FOLIPLZGtIu963w==", + "dependencies": { + "@turf/bbox": "^7.1.0", + "@turf/center": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/jsts": "^2.7.1", + "@turf/meta": "^7.1.0", + "@turf/projection": "^7.1.0", + "@types/geojson": "^7946.0.10", + "d3-geo": "1.7.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/center": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/center/-/center-7.1.0.tgz", + "integrity": "sha512-p9AvBMwNZmRg65kU27cGKHAUQnEcdz8Y7f/i5DvaMfm4e8zmawr+hzPKXaUpUfiTyLs8Xt2W9vlOmNGyH+6X3w==", + "dependencies": { + "@turf/bbox": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/center-mean": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/center-mean/-/center-mean-7.1.0.tgz", + "integrity": "sha512-NQZB1LUVsyAD+p0+D4huzX2XVnfVx1yEEI9EX602THmi+g+nkge4SK9OMV11ov/Tv8JJ6aVNVPo/cy1vm/LCIQ==", + "dependencies": { + "@turf/bbox": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/center-median": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/center-median/-/center-median-7.1.0.tgz", + "integrity": "sha512-jx4/Ql5+v41Cd0J/gseNCUbLTzWUT2LUaiXn8eFWDrvmEgqHIx7KJcGcJd5HzV+9zJwng4AXxyh5NMvUR0NjwA==", + "dependencies": { + "@turf/center-mean": "^7.1.0", + "@turf/centroid": "^7.1.0", + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/center-of-mass": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/center-of-mass/-/center-of-mass-7.1.0.tgz", + "integrity": "sha512-j38oBlj7LBoCjZbrIo8EoHVGhk7UQmMLQ1fe8ZPAF9pd05XEL1qxyHKZKdQ/deGISiaEhXCyfLNrKAHAuy25RA==", + "dependencies": { + "@turf/centroid": "^7.1.0", + "@turf/convex": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/centroid": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/centroid/-/centroid-7.1.0.tgz", + "integrity": "sha512-1Y1b2l+ZB1CZ+ITjUCsGqC4/tSjwm/R4OUfDztVqyyCq/VvezkLmTNqvXTGXgfP0GXkpv68iCfxF5M7QdM5pJQ==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/circle": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/circle/-/circle-7.1.0.tgz", + "integrity": "sha512-6qhF1drjwH0Dg3ZB9om1JkWTJfAqBcbtIrAj5UPlrAeHP87hGoCO2ZEsFEAL9Q18vntpivT89Uho/nqQUjJhYw==", + "dependencies": { + "@turf/destination": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/clean-coords": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/clean-coords/-/clean-coords-7.1.0.tgz", + "integrity": "sha512-q1U8UbRVL5cRdwOlNjD8mad8pWjFGe0s4ihg1pSiVNq7i47WASJ3k20yZiUFvuAkyNjV0rZ/A7Jd7WzjcierFg==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/clone": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/clone/-/clone-7.1.0.tgz", + "integrity": "sha512-5R9qeWvL7FDdBIbEemd0eCzOStr09oburDvJ1hRiPCFX6rPgzcZBQ0gDmZzoF4AFcNLb5IwknbLZjVLaUGWtFA==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/clusters": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/clusters/-/clusters-7.1.0.tgz", + "integrity": "sha512-7CY3Ai+5V6q2O9/IgqLpJQrmrTy7aUJjTW1iRan8Tz3WixvxyJHeS3iyRy8Oc0046chQIaHLtyTgKVt2QdsPSA==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/clusters-dbscan": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/clusters-dbscan/-/clusters-dbscan-7.1.0.tgz", + "integrity": "sha512-BmrBTOEaKN5FIED6b3yb3V3ejfK0A2Q3pT9/ji3mcRLJiBaRGeiN5V6gtGXe7PeMYdoqhHykU5Ye2uUtREWRdQ==", + "dependencies": { + "@turf/clone": "^7.1.0", + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "rbush": "^3.0.1", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/clusters-kmeans": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/clusters-kmeans/-/clusters-kmeans-7.1.0.tgz", + "integrity": "sha512-M8cCqR6iE1jDSUF/UU9QdPUFrobZS2fo59TfF1IRHZ2G1EjbcK4GzZcUfmQS6DZraGudYutpMYIuNdm1dPMqdQ==", + "dependencies": { + "@turf/clone": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "skmeans": "0.9.7", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/collect": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/collect/-/collect-7.1.0.tgz", + "integrity": "sha512-6indMWLiKeBh4AsioNeFeFnO0k9U5CBsWAFEje6tOEFI4c+P7LF9mNA9z91H8KkrhegR9XNO5Vm2rmdY63aYXw==", + "dependencies": { + "@turf/bbox": "^7.1.0", + "@turf/boolean-point-in-polygon": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "rbush": "^3.0.1", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/combine": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/combine/-/combine-7.1.0.tgz", + "integrity": "sha512-Xl7bGKKjgzIq2T/IemS6qnIykyuxU6cMxKtz+qLeWJGoNww/BllwxXePSV+dWRPXZTFFj96KIhBXAW0aUjAQKQ==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/concave": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/concave/-/concave-7.1.0.tgz", + "integrity": "sha512-aSid53gYRee4Tjc4pfeI3KI+RoBUnL/hRMilxIPduagTgZZS+cvvk01OQWBKm5UTVfHRGuy0XIqnK8y9RFinDQ==", + "dependencies": { + "@turf/clone": "^7.1.0", + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@turf/tin": "^7.1.0", + "@types/geojson": "^7946.0.10", + "topojson-client": "3.x", + "topojson-server": "3.x", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/convex": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/convex/-/convex-7.1.0.tgz", + "integrity": "sha512-w9fUMZYE36bLrEWEj7L7aVMCB7NBtr2o8G+avRvUIwF4DPqbtcjlcZE9EEBfq44uYdn+/Pke6Iq42T/zyD/cpg==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "concaveman": "^1.2.1", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/destination": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/destination/-/destination-7.1.0.tgz", + "integrity": "sha512-97XuvB0iaAiMg86hrnZ529WwP44TQAA9mmI5PMlchACiA4LFrEtWjjDzvO6234coieoqhrw6dZYcJvd5O2PwrQ==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/difference": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/difference/-/difference-7.1.0.tgz", + "integrity": "sha512-+JVzdskICQ8ULKQ9CpWUM5kBvoXxN4CO78Ez/Ki3/7NXl7+HM/nb12B0OyM8hkJchpb8TsOi0YwyJiKMqEpTBA==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "polygon-clipping": "^0.15.3", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/dissolve": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/dissolve/-/dissolve-7.1.0.tgz", + "integrity": "sha512-fyOnCSYVUZ8SF9kt9ROnQYlkJTE0hpWSoWwbMZQCAR7oVZVPiuPq7eIbzTP+k5jzEAnofsqoGs5qVDTjHcWMiw==", + "dependencies": { + "@turf/flatten": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "polygon-clipping": "^0.15.3", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/distance": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/distance/-/distance-7.1.0.tgz", + "integrity": "sha512-hhNHhxCHB3ddzAGCNY4BtE29OZh+DAJPvUapQz+wOjISnlwvMcwLKvslgHWSYF536QDVe/93FEU2q67+CsZTPA==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/distance-weight": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/distance-weight/-/distance-weight-7.1.0.tgz", + "integrity": "sha512-8m6s4y8Yyt6r3itf44yAJjXC+62UkrkhOpskIfaE0lHcBcvZz9wjboHoBf3bS4l/42E4StcanbFZdjOpODAdZw==", + "dependencies": { + "@turf/centroid": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/ellipse": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/ellipse/-/ellipse-7.1.0.tgz", + "integrity": "sha512-AfOahUmStDExWGPg8ZWxxkgom+fdJs7Mn9DzZH+fV/uZ+je1bLQpbPCUu9/ev6u/HhbYGl4VAL/CeQzjOyy6LQ==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/rhumb-destination": "^7.1.0", + "@turf/transform-rotate": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/envelope": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/envelope/-/envelope-7.1.0.tgz", + "integrity": "sha512-WeLQse9wuxsxhzSqrJA6Ha7rLWnLKgdKY9cfxmJKHSpgqcJyNk60m7+T3UpI/nkGwpfbpeyB3EGC1EWPbxiDUg==", + "dependencies": { + "@turf/bbox": "^7.1.0", + "@turf/bbox-polygon": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/explode": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/explode/-/explode-7.1.0.tgz", + "integrity": "sha512-To+GUbU6HtcHZ8S0w/dw1EbdQIOCXALTr6Ug5/IFg8hIBMJelDpVr3Smwy8uqhDRFinY2eprBwQnDPcd10eCqA==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/flatten": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/flatten/-/flatten-7.1.0.tgz", + "integrity": "sha512-Kb23pqEarcLsdBqnQcK0qTrSMiWNTVb9tOFrNlZc66DIhDLAdpOKG4eqk00CMoUzWTixlnawDgJRqcStRrR4WA==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/flip": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/flip/-/flip-7.1.0.tgz", + "integrity": "sha512-vac73W8WblzzNFanzWYLBzWDIcqc5xczOrtEO07RDEiKEI3Heo0471Jed3v9W506uuOX6/HAiCjXbRjTLjiLfw==", + "dependencies": { + "@turf/clone": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/geojson-rbush": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/geojson-rbush/-/geojson-rbush-7.1.0.tgz", + "integrity": "sha512-j1C7Ohlxa1z644bNOpgibcFGaDLgLXGLOzwF1tfQaP5y7E4PJQUXL0DWIgNb3Ke7gZC05LPHM25a5TRReUfFBQ==", + "dependencies": { + "@turf/bbox": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "rbush": "^3.0.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/great-circle": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/great-circle/-/great-circle-7.1.0.tgz", + "integrity": "sha512-92q5fqUp5oW+FYekUIrUVR5PZBWbOV6NHKHPIiNahiPvtkpZItbbjoO+tGn5+2i8mxZP9FGOthayJe4V0a1xkg==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/helpers": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.1.0.tgz", + "integrity": "sha512-dTeILEUVeNbaEeoZUOhxH5auv7WWlOShbx7QSd4s0T4Z0/iz90z9yaVCtZOLbU89umKotwKaJQltBNO9CzVgaQ==", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/hex-grid": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/hex-grid/-/hex-grid-7.1.0.tgz", + "integrity": "sha512-I+Apx0smOPkMzaS5HHL44YOxSkSUvrz+wtSIETsDFWWLT2xKNkaaEcYU5MkgSoEfQsj082M7EkOIIpocXlA3kg==", + "dependencies": { + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/intersect": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/interpolate": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/interpolate/-/interpolate-7.1.0.tgz", + "integrity": "sha512-VWec1OW9gHZLPS3yYkUXAHKMGQuYO4aqh8WCltT7Ym4efrKqkSOE5T+mBqO68QgcL8nY4kiNa8lxwXd0SfXDSA==", + "dependencies": { + "@turf/bbox": "^7.1.0", + "@turf/centroid": "^7.1.0", + "@turf/clone": "^7.1.0", + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/hex-grid": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@turf/point-grid": "^7.1.0", + "@turf/square-grid": "^7.1.0", + "@turf/triangle-grid": "^7.1.0", + "@types/geojson": "^7946.0.10" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/intersect": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/intersect/-/intersect-7.1.0.tgz", + "integrity": "sha512-T0VhI6yhptX9EoMsuuBETyqV+edyq31SUC8bfuM6kdJ5WwJ0EvUfQoC+3bhMtCOn60lHawrUuGBgW+vCO8KGMg==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "polygon-clipping": "^0.15.3", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/invariant": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-7.1.0.tgz", + "integrity": "sha512-OCLNqkItBYIP1nE9lJGuIUatWGtQ4rhBKAyTfFu0z8npVzGEYzvguEeof8/6LkKmTTEHW53tCjoEhSSzdRh08Q==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/isobands": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/isobands/-/isobands-7.1.0.tgz", + "integrity": "sha512-iMLTOP/K5C05AttF4N1WeV+KrY4O5VWW/abO0N86XCWh1OeqmIUgqIBKEmhDzttAqC0UK2YrUfj0lI1Ez1fYZQ==", + "dependencies": { + "@turf/area": "^7.1.0", + "@turf/bbox": "^7.1.0", + "@turf/boolean-point-in-polygon": "^7.1.0", + "@turf/explode": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "marchingsquares": "^1.3.3", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/isolines": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/isolines/-/isolines-7.1.0.tgz", + "integrity": "sha512-V6QTHXBT5ZsL3s9ZVBJgHYtz3gCFKqNnQLysNE02LE0fVVqaSao3sFrcpghmdDxf0hBCDK8lZVvyRGO6o32LHQ==", + "dependencies": { + "@turf/bbox": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "marchingsquares": "^1.3.3", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/jsts": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@turf/jsts/-/jsts-2.7.1.tgz", + "integrity": "sha512-+nwOKme/aUprsxnLSfr2LylV6eL6T1Tuln+4Hl92uwZ8FrmjDRCH5Bi1LJNVfWCiYgk8+5K+t2zDphWNTsIFDA==", + "dependencies": { + "jsts": "2.7.1" + } + }, + "node_modules/@turf/kinks": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/kinks/-/kinks-7.1.0.tgz", + "integrity": "sha512-KKLYUsyJPU17fODwA81mhHzFYGQYocdbk9NxDPCcdRHvxzM8t95lptkGx/2k/9rXBs1DK7NmyzI4m7zDO0DK7g==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/length": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/length/-/length-7.1.0.tgz", + "integrity": "sha512-wUJj9WLKEudG1ngNao2ZwD+Dt6UkvWIbubuJ6lR6FndFDL3iezFhNGy0IXS+0xH9kXi2apiTnM9Vk5+i8BTEvQ==", + "dependencies": { + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-arc": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/line-arc/-/line-arc-7.1.0.tgz", + "integrity": "sha512-9/bM34PozTyJ5FXXPAzl/j0RpcTImgMFJZ0WhH0pZZEZRum6P0rJnENt2E2qI441zeozQ9H6X5DCiJogDmRUEw==", + "dependencies": { + "@turf/circle": "^7.1.0", + "@turf/destination": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-chunk": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/line-chunk/-/line-chunk-7.1.0.tgz", + "integrity": "sha512-1lIUfqAQvCWAuUNC2ip8UYmM5kDltXOidLPW45Ee1OAIKYGBeFNtjwnxc0mQ40tnfTXclTYLDdOOP9LShspT9w==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/length": "^7.1.0", + "@turf/line-slice-along": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-intersect": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/line-intersect/-/line-intersect-7.1.0.tgz", + "integrity": "sha512-JI3dvOsAoCqd4vUJ134FIzgcC42QpC/tBs+b4OJoxWmwDek3REv4qGaZY6wCg9X4hFSlCKFcnhMIQQZ/n720Qg==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "sweepline-intersections": "^1.5.0", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-offset": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/line-offset/-/line-offset-7.1.0.tgz", + "integrity": "sha512-pz6irzhiQlJurU7DoXada6k3ei7PzY+VpsE/Wotm0D2KEAnoxqum2WK0rqqrhKPHKn+xpUGsHN9W/6K+qtmaHg==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-overlap": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/line-overlap/-/line-overlap-7.1.0.tgz", + "integrity": "sha512-BdHuEoFAtqvVw3LkjCdivG035nfuwZuxji2ijst+mkmDnlv7uwSBudJqcDGjU6up2r8P1mXChS4im4xjUz+lwg==", + "dependencies": { + "@turf/boolean-point-on-line": "^7.1.0", + "@turf/geojson-rbush": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/line-segment": "^7.1.0", + "@turf/meta": "^7.1.0", + "@turf/nearest-point-on-line": "^7.1.0", + "@types/geojson": "^7946.0.10", + "fast-deep-equal": "^3.1.3", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-segment": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/line-segment/-/line-segment-7.1.0.tgz", + "integrity": "sha512-9rgIIH6ZzC3IiWxDQtKsq+j6eu8fRinMkJeusfI9HqOTm4vO02Ll4F/FigjOMOO/6X3TJ+Pqe3gS99TUaBINkw==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-slice": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/line-slice/-/line-slice-7.1.0.tgz", + "integrity": "sha512-44xcjgMQxTa7tTAZlSD3t1cFjHi5SCfAqjg1ONv45EYKsQSonPaxD7LGzCbU5pR2RJjx3R7QRJx2G88hnGcXjQ==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/nearest-point-on-line": "^7.1.0", + "@types/geojson": "^7946.0.10" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-slice-along": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/line-slice-along/-/line-slice-along-7.1.0.tgz", + "integrity": "sha512-UwfnFORZnu4xdnuRXiQM3ODa8f9Q0FBjQF/XHNsPEI/xxmnwgQj3MZiULbAeHUbtU/7psTC7gEjfE3Lf0tcKQw==", + "dependencies": { + "@turf/bearing": "^7.1.0", + "@turf/destination": "^7.1.0", + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-split": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/line-split/-/line-split-7.1.0.tgz", + "integrity": "sha512-QqUAmtlrnEu75cpLOmpEuiYU63BeVwpSKOBllBbu5gkP+7H/WBM/9fh7J0VgHNFHzqZCKiu8v4158k+CZr0QAg==", + "dependencies": { + "@turf/bbox": "^7.1.0", + "@turf/geojson-rbush": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/line-intersect": "^7.1.0", + "@turf/line-segment": "^7.1.0", + "@turf/meta": "^7.1.0", + "@turf/nearest-point-on-line": "^7.1.0", + "@turf/square": "^7.1.0", + "@turf/truncate": "^7.1.0", + "@types/geojson": "^7946.0.10" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-to-polygon": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/line-to-polygon/-/line-to-polygon-7.1.0.tgz", + "integrity": "sha512-n/IWBRbo+l4XDTz4sfQsQm5bU9xex8KrthK397jQasd7a9PiOKGon9Z1t/lddTJhND6ajVyJ3hl+eZMtpQaghQ==", + "dependencies": { + "@turf/bbox": "^7.1.0", + "@turf/clone": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/mask": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/mask/-/mask-7.1.0.tgz", + "integrity": "sha512-d+u3IIiRhe17TDfP/+UMn9qRlJYPJpK7sj6WorsssluGi0yIG/Z24uWpcLskWKSI8NNgkIbDrp+GIYkJi2t7SA==", + "dependencies": { + "@turf/clone": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "polygon-clipping": "^0.15.3", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/meta": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-7.1.0.tgz", + "integrity": "sha512-ZgGpWWiKz797Fe8lfRj7HKCkGR+nSJ/5aKXMyofCvLSc2PuYJs/qyyifDPWjASQQCzseJ7AlF2Pc/XQ/3XkkuA==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/midpoint": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/midpoint/-/midpoint-7.1.0.tgz", + "integrity": "sha512-uiUU9TwRZOCeiTUn8+7oE6MJUvclfq+n6KQ5VCMTZXiRUJjPu7nDLpBle1t2WSv7/w7O0kSQ4FfKXh0gHnkJOw==", + "dependencies": { + "@turf/bearing": "^7.1.0", + "@turf/destination": "^7.1.0", + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/moran-index": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/moran-index/-/moran-index-7.1.0.tgz", + "integrity": "sha512-xsvAr3IRF/C6PlRMoN/ANrRx6c3QFUJgBCIVfI7re+Lkdprrzgw1HZA48ZjP4F91xbhgA1scnRgQdHFi2vO2SA==", + "dependencies": { + "@turf/distance-weight": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/nearest-neighbor-analysis": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/nearest-neighbor-analysis/-/nearest-neighbor-analysis-7.1.0.tgz", + "integrity": "sha512-FAhT8/op3DuvqH0XFhv055JhYq/FC4aaIxEZ4hj8c7W6sYhUHAQgdRZ0tJ1RLe5/h+eXhCTbQ+DFfnfv3klu8g==", + "dependencies": { + "@turf/area": "^7.1.0", + "@turf/bbox": "^7.1.0", + "@turf/bbox-polygon": "^7.1.0", + "@turf/centroid": "^7.1.0", + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@turf/nearest-point": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/nearest-point": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/nearest-point/-/nearest-point-7.1.0.tgz", + "integrity": "sha512-VyInmhqfVWp+jE7sCK95o46qc4tDjAgzbRfRjr+rTgfFS1Sndyy1PdwyNn6TjBFDxiM6e+mjMEeGPjb1smJlEg==", + "dependencies": { + "@turf/clone": "^7.1.0", + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/nearest-point-on-line": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/nearest-point-on-line/-/nearest-point-on-line-7.1.0.tgz", + "integrity": "sha512-aTjAOm7ab0tl5JoxGYRx/J/IbRL1DY1ZCIYQDMEQjK5gOllhclgeBC0wDXDkEZFGaVftjw0W2RtE2I0jX7RG4A==", + "dependencies": { + "@turf/bearing": "^7.1.0", + "@turf/destination": "^7.1.0", + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/line-intersect": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/nearest-point-to-line": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/nearest-point-to-line/-/nearest-point-to-line-7.1.0.tgz", + "integrity": "sha512-rY2F/iY4S6U8H0hIoOI25xMWYEiKywxeTvTvn5GP8KCu+2oemfZROWa7n2+hQDRwO2/uaegrGEpxO7zlFarvzg==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@turf/point-to-line-distance": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/planepoint": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/planepoint/-/planepoint-7.1.0.tgz", + "integrity": "sha512-hFORBkCd7Q0kNUzLqksT4XglLgTQF9tCjG+dbnZ1VehpZu+w+vlHdoW/mY7XCX3Kj1ObiyzVmXffmVYgwXwF6Q==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/point-grid": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/point-grid/-/point-grid-7.1.0.tgz", + "integrity": "sha512-ihuuUcWuCu4Z1+34UYCM5NGsU2DJaB4uE8cS3jDQoUqlc+8ii2ng8kcGEtTwVn0HdPsoKA7bgvSZcisJO0v6Ww==", + "dependencies": { + "@turf/boolean-within": "^7.1.0", + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/point-on-feature": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/point-on-feature/-/point-on-feature-7.1.0.tgz", + "integrity": "sha512-lOO5J9I0diuGbN+r6jViEKRH3qfymsBvv25b7U0MuP8g/YC19ncUXZ86dmKfJx1++Rb485DS9h0nFvPmJpaOdg==", + "dependencies": { + "@turf/boolean-point-in-polygon": "^7.1.0", + "@turf/center": "^7.1.0", + "@turf/explode": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/nearest-point": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/point-to-line-distance": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/point-to-line-distance/-/point-to-line-distance-7.1.0.tgz", + "integrity": "sha512-Ps9eTOCaiNgxDaSNQux0wAcSLcrI0y0zYFaD9HnVm+yCMRliQXneFti2XXotS+gR7TpgnLRAAzyx4VzJMSN2tw==", + "dependencies": { + "@turf/bearing": "^7.1.0", + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@turf/projection": "^7.1.0", + "@turf/rhumb-bearing": "^7.1.0", + "@turf/rhumb-distance": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/points-within-polygon": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/points-within-polygon/-/points-within-polygon-7.1.0.tgz", + "integrity": "sha512-SzqeD9Gcp11rEya+rCVMy6IPuYMrphNEkCiQ39W6ec9hsaqKlruqmtudKhhckMGVLVUUBCQAu5f55yjcDfVW2w==", + "dependencies": { + "@turf/boolean-point-in-polygon": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/polygon-smooth": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/polygon-smooth/-/polygon-smooth-7.1.0.tgz", + "integrity": "sha512-mTlmg4XUP5rKgCP/73N91owkAXIc3t1ZKLuwsJGQM1/Op48T3rJmDwVR/WZIMnVlxl5tFbssWCCB3blj4ivx9g==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/polygon-tangents": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/polygon-tangents/-/polygon-tangents-7.1.0.tgz", + "integrity": "sha512-ffBgHXtkrpgkNs8E6s9sVLSKG4lPGH3WBk294FNKBt9NS+rbhNCv8yTuOMeP0bOm/WizaCq/SUtVryJpUSoI/g==", + "dependencies": { + "@turf/bbox": "^7.1.0", + "@turf/boolean-within": "^7.1.0", + "@turf/explode": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/nearest-point": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/polygon-to-line": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/polygon-to-line/-/polygon-to-line-7.1.0.tgz", + "integrity": "sha512-FBlfyBWNQZCTVGqlJH7LR2VXmvj8AydxrA8zegqek/5oPGtQDeUgIppKmvmuNClqbglhv59QtCUVaDK4bOuCTA==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/polygonize": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/polygonize/-/polygonize-7.1.0.tgz", + "integrity": "sha512-FBjxnOzO29MbE7MWnMPHHYtOo93cQopT5pXhkuPyoKgcTUCntR1+iVFpl5YFbMkYup0j5Oexjo/pbY38lVSZGw==", + "dependencies": { + "@turf/boolean-point-in-polygon": "^7.1.0", + "@turf/envelope": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/projection": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/projection/-/projection-7.1.0.tgz", + "integrity": "sha512-3wHluMoOvXnTe7dfi0kcluTyLNG5MwGsSsK5OA98vkkLH6a1xvItn8e9GcesuT07oB2km/bgefxYEIvjQG5JCA==", + "dependencies": { + "@turf/clone": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/quadrat-analysis": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/quadrat-analysis/-/quadrat-analysis-7.1.0.tgz", + "integrity": "sha512-4O5h9PyWgpqYXja9O+kzr+qk5MUz0IkJqPtt5oWWX5s4jRcLNqiEUf+zi/GDBQkVV8jH3S5klT5CLrF1fxK3hQ==", + "dependencies": { + "@turf/area": "^7.1.0", + "@turf/bbox": "^7.1.0", + "@turf/bbox-polygon": "^7.1.0", + "@turf/centroid": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/point-grid": "^7.1.0", + "@turf/random": "^7.1.0", + "@turf/square-grid": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/random": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/random/-/random-7.1.0.tgz", + "integrity": "sha512-22mXv8ejDMUWkz8DSMMqdZb0s7a0ISJzXt6T9cHovfT//vsotzkVH+5PDxJQjvmigKMnpaUgobHmQss23tAwEQ==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/rectangle-grid": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/rectangle-grid/-/rectangle-grid-7.1.0.tgz", + "integrity": "sha512-4d2AuDj4LfMMJxNHbds5yX1oFR3mIVAB5D7mx6pFB0e+YkQW0mE2dUWhDTFGJZM+n45yqbNQ5hg19bmiXv94ug==", + "dependencies": { + "@turf/boolean-intersects": "^7.1.0", + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/rewind": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/rewind/-/rewind-7.1.0.tgz", + "integrity": "sha512-zX0KDZpeiH89m1vYLTEJdDL6mFyoAsCxcG0P94mXO7/JXWf0AaxzA9MkNnA/d2QYX0G4ioCMjZ5cD6nXb8SXzw==", + "dependencies": { + "@turf/boolean-clockwise": "^7.1.0", + "@turf/clone": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/rhumb-bearing": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/rhumb-bearing/-/rhumb-bearing-7.1.0.tgz", + "integrity": "sha512-ESZt70eOljHVnQMFKIdiu8LIHuQlpZgzh2nqSfV40BrYjsjI/sBKeK+sp2cBWk88nsSDlriPuMTNh4f50Jqpkw==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/rhumb-destination": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/rhumb-destination/-/rhumb-destination-7.1.0.tgz", + "integrity": "sha512-WA2TeO3qrv5ZrzNihtTLLYu8X4kd12WEC6JKElm99XhgLao1/4ao2SJUi43l88HqwbrnNiq4TueGQ6tYpXGU7A==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/rhumb-distance": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/rhumb-distance/-/rhumb-distance-7.1.0.tgz", + "integrity": "sha512-fR1V+yC4E1tnbdThomosiLcv0PQOwbfLSPM8rSWuxbMcJtffsncWxyJ0+N1F5juuHbcdaYhlduX8ri5I0ZCejw==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/sample": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/sample/-/sample-7.1.0.tgz", + "integrity": "sha512-9Iq/Ankr4+sgBoh4FpuVVvoW+AA10eej3FS89Zu79SFdCqUIdT7T42Nn3MlSVj4jMyA1oXyT2HIAlNWkwgLw6Q==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/sector": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/sector/-/sector-7.1.0.tgz", + "integrity": "sha512-2FI2rg//eXpa/l+WJtFfvHaf1NJ7ie2MoJ+RH5dKANtrfoof1Ed+y9dXSyuhem2tp/Srq2GhrjaSofFN5/g5vA==", + "dependencies": { + "@turf/circle": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/line-arc": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/shortest-path": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/shortest-path/-/shortest-path-7.1.0.tgz", + "integrity": "sha512-1UmFhS5zHNacLv5rszoFOXq02BGov1oJvjlDatXsSWAd+Z7tqxpDc8D+41edrXy0ZB0Yxsy6WPNagM6hG9PRaA==", + "dependencies": { + "@turf/bbox": "^7.1.0", + "@turf/bbox-polygon": "^7.1.0", + "@turf/boolean-point-in-polygon": "^7.1.0", + "@turf/clean-coords": "^7.1.0", + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@turf/transform-scale": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/simplify": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/simplify/-/simplify-7.1.0.tgz", + "integrity": "sha512-JypymaoiSiFzGHwEoUkK0OPW1KQSnH3hEsEW3UIRS+apzltJ4HdFovYjsfqQgGZJZ+NJ9+dv7h8pgGLYuqcBUQ==", + "dependencies": { + "@turf/clean-coords": "^7.1.0", + "@turf/clone": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/square": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/square/-/square-7.1.0.tgz", + "integrity": "sha512-ANuA+WXZheGTLW6Veq0i+/B2S4KMhEHAixDv9gQEb9e6FTyqTJVwrqP4CHI3OzA3DZ/ytFf+NTKVofetO/BBQg==", + "dependencies": { + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/square-grid": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/square-grid/-/square-grid-7.1.0.tgz", + "integrity": "sha512-JyhsALULVRlkh8htdTi9aXaXFSUv6wRNbeFbqyGJKKlA5eF+AYmyWdI/BlFGQN27xtbtMPeAuLmj+8jaB2omGw==", "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "@turf/helpers": "^7.1.0", + "@turf/rectangle-grid": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" }, - "engines": { - "node": ">= 8" + "funding": { + "url": "https://opencollective.com/turf" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" + "node_modules/@turf/standard-deviational-ellipse": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/standard-deviational-ellipse/-/standard-deviational-ellipse-7.1.0.tgz", + "integrity": "sha512-JqvQFH/witHh+3XgPC1Qk4+3G8w8WQta2NTJjnGinOgFulH+7RD4DcxCT+XXtCHoeq8IvL9VPJRX3ciaW5nSCg==", + "dependencies": { + "@turf/center-mean": "^7.1.0", + "@turf/ellipse": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@turf/points-within-polygon": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "node_modules/@turf/tag": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/tag/-/tag-7.1.0.tgz", + "integrity": "sha512-cD8TC++DnNmdI1B/apTf3nj2zRNY6SoLRliB8K76OB+70Kev8tOf4ZVgAqOd0u+Hpdg/T6l7dO7fyJ6UouE7jA==", + "dependencies": { + "@turf/boolean-point-in-polygon": "^7.1.0", + "@turf/clone": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" }, - "engines": { - "node": ">= 8" + "funding": { + "url": "https://opencollective.com/turf" } }, - "node_modules/@nuxtjs/opencollective": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz", - "integrity": "sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==", - "license": "MIT", + "node_modules/@turf/tesselate": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/tesselate/-/tesselate-7.1.0.tgz", + "integrity": "sha512-E/Z94Mx6kUjvQVbEcSuM9MbEo2dkOczRe4ZzjhFlLgJh1dCkfRgwYLH49mb2CcfG/me1arxoCgmtG+qgm7LrCg==", "dependencies": { - "chalk": "^4.1.0", - "consola": "^2.15.0", - "node-fetch": "^2.6.1" + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "earcut": "^2.2.4", + "tslib": "^2.6.2" }, - "bin": { - "opencollective": "bin/opencollective.js" + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/tin": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/tin/-/tin-7.1.0.tgz", + "integrity": "sha512-h8Bdm0IYN6OpKHM8lBRWGxkJnZcxL0KYecf8U6pa6DCEYsEXuEExMTvYSD2OmqIsL5ml8P6RjwgyI+dZeE0O9A==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" }, - "engines": { - "node": ">=8.0.0", - "npm": ">=5.0.0" + "funding": { + "url": "https://opencollective.com/turf" } }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" + "node_modules/@turf/transform-rotate": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/transform-rotate/-/transform-rotate-7.1.0.tgz", + "integrity": "sha512-Vp7VBZ6DqaPV8mkwSycksBFRLqSj3y16zg+uEPSCsXUjbFtw9DOLcyH2F5vMpnC2bOpS9NOB4hebhJRwBwAPWQ==", + "dependencies": { + "@turf/centroid": "^7.1.0", + "@turf/clone": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@turf/rhumb-bearing": "^7.1.0", + "@turf/rhumb-destination": "^7.1.0", + "@turf/rhumb-distance": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" } }, - "node_modules/@pkgr/core": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", - "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + "node_modules/@turf/transform-scale": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/transform-scale/-/transform-scale-7.1.0.tgz", + "integrity": "sha512-m5fLnh3JqrWSv0sAC8Aieet/fr5IZND8BFaE9LakMidtNaJqOIPOyVmUoklcrGn6eK6MX+66rRPn+5a1pahlLQ==", + "dependencies": { + "@turf/bbox": "^7.1.0", + "@turf/center": "^7.1.0", + "@turf/centroid": "^7.1.0", + "@turf/clone": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@turf/rhumb-bearing": "^7.1.0", + "@turf/rhumb-destination": "^7.1.0", + "@turf/rhumb-distance": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" }, "funding": { - "url": "https://opencollective.com/unts" + "url": "https://opencollective.com/turf" } }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true, - "license": "MIT" + "node_modules/@turf/transform-translate": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/transform-translate/-/transform-translate-7.1.0.tgz", + "integrity": "sha512-XA6Oh7VqUDrieY9m9/OF4XpBTd8qlfVGi3ObywojCqtHaHKLK3aXwTBZ276i0QKmZqOQA+2jFa9NhgF/TgBDrw==", + "dependencies": { + "@turf/clone": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@turf/rhumb-destination": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", - "dev": true, - "license": "BSD-3-Clause", + "node_modules/@turf/triangle-grid": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/triangle-grid/-/triangle-grid-7.1.0.tgz", + "integrity": "sha512-hrPyRAuX5PKu7txmc/11VPKrlJDR+JGzd+eijupKTspNLR4n2sqZUx8UXqSxZ/1nq06ScTyjIfGQJVzlRS8BTg==", "dependencies": { - "type-detect": "4.0.8" + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/intersect": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" } }, - "node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", - "dev": true, - "license": "BSD-3-Clause", + "node_modules/@turf/truncate": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/truncate/-/truncate-7.1.0.tgz", + "integrity": "sha512-rrF3AML9PGZw2i5wmt53ESI+Ln9cZyCXgJ7QrEvkT8NbE4OFgmw6p8/1xT8+VEWFSpD4gHz+hmM+5FaFxXvtNg==", "dependencies": { - "@sinonjs/commons": "^3.0.0" + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" } }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "license": "MIT", - "engines": { - "node": ">= 10" + "node_modules/@turf/turf": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/turf/-/turf-7.1.0.tgz", + "integrity": "sha512-7NA6tAjbu9oIvIfpRO5AdPrZbFTlUFU02HVA7sLJM9jFeNIZovW09QuDo23uoS2z5l94SXV1GgKKxN5wo7prCw==", + "dependencies": { + "@turf/along": "^7.1.0", + "@turf/angle": "^7.1.0", + "@turf/area": "^7.1.0", + "@turf/bbox": "^7.1.0", + "@turf/bbox-clip": "^7.1.0", + "@turf/bbox-polygon": "^7.1.0", + "@turf/bearing": "^7.1.0", + "@turf/bezier-spline": "^7.1.0", + "@turf/boolean-clockwise": "^7.1.0", + "@turf/boolean-concave": "^7.1.0", + "@turf/boolean-contains": "^7.1.0", + "@turf/boolean-crosses": "^7.1.0", + "@turf/boolean-disjoint": "^7.1.0", + "@turf/boolean-equal": "^7.1.0", + "@turf/boolean-intersects": "^7.1.0", + "@turf/boolean-overlap": "^7.1.0", + "@turf/boolean-parallel": "^7.1.0", + "@turf/boolean-point-in-polygon": "^7.1.0", + "@turf/boolean-point-on-line": "^7.1.0", + "@turf/boolean-touches": "^7.1.0", + "@turf/boolean-valid": "^7.1.0", + "@turf/boolean-within": "^7.1.0", + "@turf/buffer": "^7.1.0", + "@turf/center": "^7.1.0", + "@turf/center-mean": "^7.1.0", + "@turf/center-median": "^7.1.0", + "@turf/center-of-mass": "^7.1.0", + "@turf/centroid": "^7.1.0", + "@turf/circle": "^7.1.0", + "@turf/clean-coords": "^7.1.0", + "@turf/clone": "^7.1.0", + "@turf/clusters": "^7.1.0", + "@turf/clusters-dbscan": "^7.1.0", + "@turf/clusters-kmeans": "^7.1.0", + "@turf/collect": "^7.1.0", + "@turf/combine": "^7.1.0", + "@turf/concave": "^7.1.0", + "@turf/convex": "^7.1.0", + "@turf/destination": "^7.1.0", + "@turf/difference": "^7.1.0", + "@turf/dissolve": "^7.1.0", + "@turf/distance": "^7.1.0", + "@turf/distance-weight": "^7.1.0", + "@turf/ellipse": "^7.1.0", + "@turf/envelope": "^7.1.0", + "@turf/explode": "^7.1.0", + "@turf/flatten": "^7.1.0", + "@turf/flip": "^7.1.0", + "@turf/geojson-rbush": "^7.1.0", + "@turf/great-circle": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/hex-grid": "^7.1.0", + "@turf/interpolate": "^7.1.0", + "@turf/intersect": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/isobands": "^7.1.0", + "@turf/isolines": "^7.1.0", + "@turf/kinks": "^7.1.0", + "@turf/length": "^7.1.0", + "@turf/line-arc": "^7.1.0", + "@turf/line-chunk": "^7.1.0", + "@turf/line-intersect": "^7.1.0", + "@turf/line-offset": "^7.1.0", + "@turf/line-overlap": "^7.1.0", + "@turf/line-segment": "^7.1.0", + "@turf/line-slice": "^7.1.0", + "@turf/line-slice-along": "^7.1.0", + "@turf/line-split": "^7.1.0", + "@turf/line-to-polygon": "^7.1.0", + "@turf/mask": "^7.1.0", + "@turf/meta": "^7.1.0", + "@turf/midpoint": "^7.1.0", + "@turf/moran-index": "^7.1.0", + "@turf/nearest-neighbor-analysis": "^7.1.0", + "@turf/nearest-point": "^7.1.0", + "@turf/nearest-point-on-line": "^7.1.0", + "@turf/nearest-point-to-line": "^7.1.0", + "@turf/planepoint": "^7.1.0", + "@turf/point-grid": "^7.1.0", + "@turf/point-on-feature": "^7.1.0", + "@turf/point-to-line-distance": "^7.1.0", + "@turf/points-within-polygon": "^7.1.0", + "@turf/polygon-smooth": "^7.1.0", + "@turf/polygon-tangents": "^7.1.0", + "@turf/polygon-to-line": "^7.1.0", + "@turf/polygonize": "^7.1.0", + "@turf/projection": "^7.1.0", + "@turf/quadrat-analysis": "^7.1.0", + "@turf/random": "^7.1.0", + "@turf/rectangle-grid": "^7.1.0", + "@turf/rewind": "^7.1.0", + "@turf/rhumb-bearing": "^7.1.0", + "@turf/rhumb-destination": "^7.1.0", + "@turf/rhumb-distance": "^7.1.0", + "@turf/sample": "^7.1.0", + "@turf/sector": "^7.1.0", + "@turf/shortest-path": "^7.1.0", + "@turf/simplify": "^7.1.0", + "@turf/square": "^7.1.0", + "@turf/square-grid": "^7.1.0", + "@turf/standard-deviational-ellipse": "^7.1.0", + "@turf/tag": "^7.1.0", + "@turf/tesselate": "^7.1.0", + "@turf/tin": "^7.1.0", + "@turf/transform-rotate": "^7.1.0", + "@turf/transform-scale": "^7.1.0", + "@turf/transform-translate": "^7.1.0", + "@turf/triangle-grid": "^7.1.0", + "@turf/truncate": "^7.1.0", + "@turf/union": "^7.1.0", + "@turf/unkink-polygon": "^7.1.0", + "@turf/voronoi": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" } }, - "node_modules/@tsconfig/node10": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", - "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true, - "license": "MIT" + "node_modules/@turf/union": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/union/-/union-7.1.0.tgz", + "integrity": "sha512-7VI8jONdBg9qmbfNlLQycPr93l5aU9HGMgWI9M6pb4ERuU2+p8KgffCgs2NyMtP2HxPrKSybzj31g7bnbEKofQ==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "polygon-clipping": "^0.15.3", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true, - "license": "MIT" + "node_modules/@turf/unkink-polygon": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/unkink-polygon/-/unkink-polygon-7.1.0.tgz", + "integrity": "sha512-pqkirni2aLpRA1ELFIuJz+mkjYyJQX8Ar6BflSu1b0ajY/CTrcDxbIv1x8UfvbybLzdJc4Gxzg5mo4cEtSwtaQ==", + "dependencies": { + "@turf/area": "^7.1.0", + "@turf/boolean-point-in-polygon": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "rbush": "^3.0.1", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true, - "license": "MIT" + "node_modules/@turf/voronoi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/voronoi/-/voronoi-7.1.0.tgz", + "integrity": "sha512-xUvzPDG6GaqEekgxd+pjeMKJXOYJ3eFIqUHbTe/ISKzzv3f2cFGiR2VH7ZGXri8d4ozzCQbUQ27ilHPPLf5+xw==", + "dependencies": { + "@turf/clone": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/d3-voronoi": "^1.1.12", + "@types/geojson": "^7946.0.10", + "d3-voronoi": "1.1.2", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } }, "node_modules/@types/babel__core": { "version": "7.20.5", @@ -2508,6 +4406,11 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/d3-voronoi": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@types/d3-voronoi/-/d3-voronoi-1.1.12.tgz", + "integrity": "sha512-DauBl25PKZZ0WVJr42a6CNvI6efsdzofl9sajqZr2Gf5Gu733WkDdUGiPkUHXiUvYGzNNlFQde2wdZdfQPG+yw==" + }, "node_modules/@types/estree": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", @@ -2541,6 +4444,11 @@ "@types/send": "*" } }, + "node_modules/@types/geojson": { + "version": "7946.0.14", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.14.tgz", + "integrity": "sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==" + }, "node_modules/@types/graceful-fs": { "version": "4.1.9", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", @@ -4188,6 +6096,17 @@ "typedarray": "^0.0.6" } }, + "node_modules/concaveman": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/concaveman/-/concaveman-1.2.1.tgz", + "integrity": "sha512-PwZYKaM/ckQSa8peP5JpVr7IMJ4Nn/MHIaWUjP4be+KoZ7Botgs8seAZGpmaOM+UZXawcdYRao/px9ycrCihHw==", + "dependencies": { + "point-in-polygon": "^1.1.0", + "rbush": "^3.0.1", + "robust-predicates": "^2.0.4", + "tinyqueue": "^2.0.3" + } + }, "node_modules/consola": { "version": "2.15.3", "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", @@ -4334,6 +6253,24 @@ "node": ">= 8" } }, + "node_modules/d3-array": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz", + "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==" + }, + "node_modules/d3-geo": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.7.1.tgz", + "integrity": "sha512-O4AempWAr+P5qbk2bC2FuN/sDW4z+dN2wDf9QV3bxQt4M5HfOEeXLgJ/UKQW0+o1Dj8BE+L5kiDbdWUMjsmQpw==", + "dependencies": { + "d3-array": "1" + } + }, + "node_modules/d3-voronoi": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.2.tgz", + "integrity": "sha512-RhGS1u2vavcO7ay7ZNAPo4xeDh/VYeGof3x5ZLJBQgYhLegxr3s5IykvWmJ94FTU6mcbtp4sloqZ54mP6R4Utw==" + }, "node_modules/debug": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", @@ -4546,6 +6483,11 @@ "node": ">= 6" } }, + "node_modules/earcut": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz", + "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==" + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -5183,7 +7125,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, "license": "MIT" }, "node_modules/fast-diff": { @@ -5670,6 +7611,43 @@ "node": ">=6.9.0" } }, + "node_modules/geojson": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/geojson/-/geojson-0.5.0.tgz", + "integrity": "sha512-/Bx5lEn+qRF4TfQ5aLu6NH+UKtvIv7Lhc487y/c8BdludrCTpiWf9wyI0RTyqg49MFefIAvFDuEi5Dfd/zgNxQ==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/geojson-equality-ts": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/geojson-equality-ts/-/geojson-equality-ts-1.0.2.tgz", + "integrity": "sha512-h3Ryq+0mCSN/7yLs0eDgrZhvc9af23o/QuC4aTiuuzP/MRCtd6mf5rLsLRY44jX0RPUfM8c4GqERQmlUxPGPoQ==", + "dependencies": { + "@types/geojson": "^7946.0.14" + } + }, + "node_modules/geojson-polygon-self-intersections": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/geojson-polygon-self-intersections/-/geojson-polygon-self-intersections-1.2.1.tgz", + "integrity": "sha512-/QM1b5u2d172qQVO//9CGRa49jEmclKEsYOQmWP9ooEjj63tBM51m2805xsbxkzlEELQ2REgTf700gUhhlegxA==", + "dependencies": { + "rbush": "^2.0.1" + } + }, + "node_modules/geojson-polygon-self-intersections/node_modules/quickselect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-1.1.1.tgz", + "integrity": "sha512-qN0Gqdw4c4KGPsBOQafj6yj/PA6c/L63f6CaZ/DCF/xF4Esu3jVmKLUDYxghFx8Kb/O7y9tI7x2RjTSXwdK1iQ==" + }, + "node_modules/geojson-polygon-self-intersections/node_modules/rbush": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/rbush/-/rbush-2.0.2.tgz", + "integrity": "sha512-XBOuALcTm+O/H8G90b6pzu6nX6v2zCKiFG4BJho8a+bY6AER6t8uQUZdi5bomQc0AprCWhEGa7ncAbbRap0bRA==", + "dependencies": { + "quickselect": "^1.0.1" + } + }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -7351,6 +9329,14 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jsts": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/jsts/-/jsts-2.7.1.tgz", + "integrity": "sha512-x2wSZHEBK20CY+Wy+BPE7MrFQHW6sIsdaGUMEqmGAio+3gFzQaBYPwLRonUfQf9Ak8pBieqj9tUofX1+WtAEIg==", + "engines": { + "node": ">= 12" + } + }, "node_modules/jwa": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", @@ -7548,6 +9534,11 @@ "tmpl": "1.0.5" } }, + "node_modules/marchingsquares": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/marchingsquares/-/marchingsquares-1.3.3.tgz", + "integrity": "sha512-gz6nNQoVK7Lkh2pZulrT4qd4347S/toG9RXH2pyzhLgkL5mLkBoqgv4EvAGXcV0ikDW72n/OQb3Xe8bGagQZCg==" + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -8278,6 +10269,30 @@ "node": ">=4" } }, + "node_modules/point-in-polygon": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/point-in-polygon/-/point-in-polygon-1.1.0.tgz", + "integrity": "sha512-3ojrFwjnnw8Q9242TzgXuTD+eKiutbzyslcq1ydfu82Db2y+Ogbmyrkpv0Hgj31qwT3lbS9+QAAO/pIQM35XRw==" + }, + "node_modules/point-in-polygon-hao": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/point-in-polygon-hao/-/point-in-polygon-hao-1.1.0.tgz", + "integrity": "sha512-3hTIM2j/v9Lio+wOyur3kckD4NxruZhpowUbEgmyikW+a2Kppjtu1eN+AhnMQtoHW46zld88JiYWv6fxpsDrTQ==" + }, + "node_modules/polygon-clipping": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/polygon-clipping/-/polygon-clipping-0.15.7.tgz", + "integrity": "sha512-nhfdr83ECBg6xtqOAJab1tbksbBAOMUltN60bU+llHVOL0e5Onm1WpAXXWXVB39L8AJFssoIhEVuy/S90MmotA==", + "dependencies": { + "robust-predicates": "^3.0.2", + "splaytree": "^3.1.0" + } + }, + "node_modules/polygon-clipping/node_modules/robust-predicates": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", + "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==" + }, "node_modules/possible-typed-array-names": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", @@ -8450,6 +10465,11 @@ ], "license": "MIT" }, + "node_modules/quickselect": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-2.0.0.tgz", + "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==" + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -8484,6 +10504,14 @@ "node": ">= 0.8" } }, + "node_modules/rbush": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/rbush/-/rbush-3.0.1.tgz", + "integrity": "sha512-XRaVO0YecOpEuIvbhbpTrZgoiI6xBlz6hnlr6EHhd+0x9ase6EmeN+hdwwUaJvLcsFFQ8iWVF1GAK1yB0BWi0w==", + "dependencies": { + "quickselect": "^2.0.0" + } + }, "node_modules/react-is": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", @@ -8702,6 +10730,11 @@ "node": ">=0.10.0" } }, + "node_modules/robust-predicates": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-2.0.4.tgz", + "integrity": "sha512-l4NwboJM74Ilm4VKfbAtFeGq7aEjWL+5kVFcmgFA2MrdnQWx9iE/tUGvxY5HyMI7o/WpSIUFLbC5fbeaHgSCYg==" + }, "node_modules/run-async": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", @@ -8994,6 +11027,11 @@ "dev": true, "license": "MIT" }, + "node_modules/skmeans": { + "version": "0.9.7", + "resolved": "https://registry.npmjs.org/skmeans/-/skmeans-0.9.7.tgz", + "integrity": "sha512-hNj1/oZ7ygsfmPZ7ZfN5MUBRoGg1gtpnImuJBgLO0ljQ67DtJuiQaiYdS4lUA6s0KCwnPhGivtC/WRwIZLkHyg==" + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -9035,6 +11073,11 @@ "node": ">=0.10.0" } }, + "node_modules/splaytree": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/splaytree/-/splaytree-3.1.2.tgz", + "integrity": "sha512-4OM2BJgC5UzrhVnnJA4BkHKGtjXNzzUfpQjCO8I05xYPsfS/VuQDwjCGGMi8rYQilHEV4j8NBqTFbls/PZEE7A==" + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -9321,6 +11364,14 @@ "express": ">=4.0.0 || >=5.0.0-beta" } }, + "node_modules/sweepline-intersections": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sweepline-intersections/-/sweepline-intersections-1.5.0.tgz", + "integrity": "sha512-AoVmx72QHpKtItPu72TzFL+kcYjd67BPLDoR0LarIk+xyaRg+pDTMFXndIEvZf9xEKnJv6JdhgRMnocoG0D3AQ==", + "dependencies": { + "tinyqueue": "^2.0.0" + } + }, "node_modules/symbol-observable": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", @@ -9591,6 +11642,11 @@ "dev": true, "license": "MIT" }, + "node_modules/tinyqueue": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-2.0.3.tgz", + "integrity": "sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA==" + }, "node_modules/tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -9643,6 +11699,40 @@ "node": ">=0.6" } }, + "node_modules/topojson-client": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/topojson-client/-/topojson-client-3.1.0.tgz", + "integrity": "sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==", + "dependencies": { + "commander": "2" + }, + "bin": { + "topo2geo": "bin/topo2geo", + "topomerge": "bin/topomerge", + "topoquantize": "bin/topoquantize" + } + }, + "node_modules/topojson-client/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/topojson-server": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/topojson-server/-/topojson-server-3.0.1.tgz", + "integrity": "sha512-/VS9j/ffKr2XAOjlZ9CgyyeLmgJ9dMwq6Y0YEON8O7p/tGGk+dCWnrE03zEdu7i4L7YsFZLEPZPzCvcB7lEEXw==", + "dependencies": { + "commander": "2" + }, + "bin": { + "geo2topo": "bin/geo2topo" + } + }, + "node_modules/topojson-server/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", diff --git a/package.json b/package.json index c1acabb..a1404ae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "overture-maps-api", - "version": "0.1.0", + "version": "0.1.1", "description": "", "author": "", "private": true, @@ -27,9 +27,12 @@ "@nestjs/core": "^10.0.0", "@nestjs/platform-express": "^10.0.0", "@nestjs/swagger": "^8.0.1", + "@turf/turf": "^7.1.0", + "@types/geojson": "^7946.0.14", "class-transformer": "^0.5.1", "class-validator": "^0.14.1", "dotenv": "^16.4.5", + "geojson": "^0.5.0", "reflect-metadata": "^0.2.0", "rxjs": "^7.8.1", "swagger-ui-express": "^5.0.1", diff --git a/src/bigquery/bigquery.service.ts b/src/bigquery/bigquery.service.ts index be8b02f..51158d7 100644 --- a/src/bigquery/bigquery.service.ts +++ b/src/bigquery/bigquery.service.ts @@ -33,18 +33,57 @@ export class BigQueryService { private parseBuildingRow(row: any): Building { - this.logger.log(row); return { id: row.id, - geometry: parsePolygonToGeoJSON(row.geometry), + geometry: parsePolygonToGeoJSON(row.geometry.value), + bbox: { + xmin: parseFloat(row.bbox.xmin), + xmax: parseFloat(row.bbox.xmax), + ymin: parseFloat(row.bbox.ymin), + ymax: parseFloat(row.bbox.ymax), + }, + version: row.version, + sources: row.sources.list.map((source: any) => ({ + property: source.element.property, + dataset: source.element.dataset, + record_id: source.element.record_id, + update_time: source.element.update_time, + confidence: source.element.confidence ? parseFloat(source.element.confidence) : null, + })), + + subtype: row.subtype, + class: row.class, + names: row.names, + level: row.level, + has_parts: row.has_parts, + height: row.height, + is_underground: row.is_underground, + num_floors: row.num_floors, + num_floors_underground: row.num_floors_underground, + min_height: row.min_height, + min_floor: row.min_floor, + facade_color: row.facade_color, + facade_material: row.facade_material, + roof_material: row.roof_material, + roof_shape: row.roof_shape, + roof_direction: row.roof_direction, + roof_orientation: row.roof_orientation, + roof_color: row.roof_color, + roof_height: row.roof_height, + ext_distance: parseFloat(row.ext_distance), + theme: row.theme, + type: row.type, + + } } private parsePlaceRow(row: any): Place { + return { id: row.id, - geometry: parsePointToGeoJSON(row.geometry), + geometry: parsePointToGeoJSON(row.geometry.value), bbox: { xmin: parseFloat(row.bbox.xmin), xmax: parseFloat(row.bbox.xmax), @@ -88,7 +127,7 @@ export class BigQueryService { region: address.element?.region, country: address.element?.country, })) : [], - distance_m: parseFloat(row.distance_m), + ext_distance: parseFloat(row.ext_distance), } } @@ -192,7 +231,7 @@ export class BigQueryService { longitude: number, radius: number = 1000, limit?: number - ): Promise { + ): Promise { let queryParts: string[] = []; @@ -217,14 +256,14 @@ SET search_area_geometry = ( -- Step 2: Select buildings within the search area SELECT * + ,ST_Distance(geometry, ST_GeogPoint(${longitude}, ${latitude})) AS ext_distance FROM \`bigquery-public-data.overture_maps.building\` AS s -WHERE ST_WITHIN(s.geometry, search_area_geometry) and ST_DWithin(geometry, ST_GeogPoint(${longitude}, ${latitude}), 1000) +WHERE ST_WITHIN(s.geometry, search_area_geometry) and ST_DWithin(geometry, ST_GeogPoint(${longitude}, ${latitude}), ${radius})`); -`) // Order by distance if latitude and longitude are provided if (latitude && longitude) { - queryParts.push(`ORDER BY distance_m`); + queryParts.push(`ORDER BY ext_distance`); } // Limit results if no filters are provided @@ -237,7 +276,7 @@ WHERE ST_WITHIN(s.geometry, search_area_geometry) and ST_DWithin(geometry, ST_Ge this.logger.debug(`Running query: ${query}`); const { rows } = await this.runQuery(query); - return rows.map((row: any) => this.parsePlaceRow(row)); + return rows.map((row: any) => this.parseBuildingRow(row)); } @@ -260,7 +299,7 @@ WHERE ST_WITHIN(s.geometry, search_area_geometry) and ST_DWithin(geometry, ST_Ge queryParts.push(`SELECT *`); if (latitude && longitude) { - queryParts.push(`, ST_Distance(geometry, ST_GeogPoint(${longitude}, ${latitude})) AS distance_m`); + queryParts.push(`, ST_Distance(geometry, ST_GeogPoint(${longitude}, ${latitude})) AS ext_distance`); } queryParts.push(`FROM \`${SOURCE_DATASET}.place\``); @@ -284,7 +323,6 @@ WHERE ST_WITHIN(s.geometry, search_area_geometry) and ST_DWithin(geometry, ST_Ge } if(categories && categories.length > 0){ - console.log(categories); whereClauses.push(`categories.primary IN UNNEST(["${categories.join('","')}"])`); } @@ -299,7 +337,7 @@ WHERE ST_WITHIN(s.geometry, search_area_geometry) and ST_DWithin(geometry, ST_Ge // Order by distance if latitude and longitude are provided if (latitude && longitude) { - queryParts.push(`ORDER BY distance_m`); + queryParts.push(`ORDER BY ext_distance`); } // Limit results if no filters are provided @@ -355,7 +393,7 @@ WHERE ST_WITHIN(s.geometry, search_area_geometry) and ST_DWithin(geometry, ST_Ge billedAmountInGB: Math.round(totalBytesBilled / 1000000000), bytesProcessedInGB: Math.round(totalBytesProcessed / 1000000000), durationMs: Date.now() - start, - costInUSD: Math.round(totalBytesBilled / 1000000000) * 5 + costInUSD: (Math.round(totalBytesBilled / 1000000000) * 5)/100 } const QueryFirstLine = query.split('\n')[0]; diff --git a/src/buildings/buildings.controller.ts b/src/buildings/buildings.controller.ts index 342aca5..ab53a5d 100644 --- a/src/buildings/buildings.controller.ts +++ b/src/buildings/buildings.controller.ts @@ -2,7 +2,36 @@ https://docs.nestjs.com/controllers#controllers */ -import { Controller } from '@nestjs/common'; +import { Controller, Logger, Query,Get } from '@nestjs/common'; +import { BuildingsService } from './buildings.service'; +import { GetBuildingsQuery } from './dto/requests/get-buildings-query.dto'; +import { BuildingDto, toBuildingDto } from './dto/responses/building-response.dto'; +import { wrapAsGeoJSON } from '../utils/geojson'; +import { Format } from '../common/dto/requests/get-by-location.dto'; -@Controller() -export class BuildingsController { } + +@Controller('buildings') +export class BuildingsController { + + logger = new Logger('BuildingsController'); + + constructor( + private readonly buildingsService: BuildingsService, + ) {} + + @Get() + async getBuildings(@Query() query: GetBuildingsQuery): Promise { + + + const buildings = await this.buildingsService.getBuildings(query); + + const dtoResults = buildings.map((building: any) => toBuildingDto(building, query)); + + if(query.format === Format.GEOJSON) { + return wrapAsGeoJSON(dtoResults) + }else{ + return dtoResults + } + } + +} diff --git a/src/buildings/buildings.service.ts b/src/buildings/buildings.service.ts index 986287f..362435c 100644 --- a/src/buildings/buildings.service.ts +++ b/src/buildings/buildings.service.ts @@ -10,7 +10,7 @@ import { AuthedUser, User } from '../decorators/authed-user.decorator'; import { ValidateLatLngUser } from '../decorators/validate-lat-lng-user.decorator'; import { ConfigService } from '@nestjs/config'; import { CloudStorageCacheService } from '../cloudstorage-cache/cloudstorage-cache.service'; -import { GetBuildingsQuery } from './dto/get-buildings-query.dto'; +import { GetBuildingsQuery } from './dto/requests/get-buildings-query.dto'; import { Building } from './interfaces/building.interface'; @Injectable() @@ -25,16 +25,16 @@ export class BuildingsService { ) {} async getBuildings(query: GetBuildingsQuery): Promise { - const { lat, lng, radius } = query; + const { lat, lng, radius,limit } = query; - // Check if cached results exist in GCS + // Check if cached results exist in File Cache const cacheKey = `get-places-brands-${JSON.stringify(query)}`; const cachedResult = await this.cloudStorageCache.getJSON(cacheKey); if (cachedResult) { return cachedResult; } - const results = await this.bigQueryService.getBuildingsNearby( lat, lng, radius,1); + const results = await this.bigQueryService.getBuildingsNearby( lat, lng, radius,limit); await this.cloudStorageCache.storeJSON (results,cacheKey); return results;// } diff --git a/src/buildings/dto/get-buildings-query.dto.ts b/src/buildings/dto/get-buildings-query.dto.ts deleted file mode 100644 index 58a86c1..0000000 --- a/src/buildings/dto/get-buildings-query.dto.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; -import { Transform } from 'class-transformer'; -import { IsNumber, IsOptional, IsString, MaxLength, Min, MinLength, ValidateIf } from 'class-validator'; - -export class GetBuildingsQuery { - - @ApiPropertyOptional({ - description: 'Latitude coordinate. Required if country code is not provided.', - example: 40.7128, - }) - @ValidateIf(o => !o.country) - @IsNumber() - lat?: number; - - @ApiPropertyOptional({ - description: 'Longitude coordinate. Required if country code is not provided.', - example: -74.0060, - }) - @ValidateIf(o => !o.country) - @IsNumber() - lng?: number; - - @ApiPropertyOptional({ - description: 'Search radius in meters, defaulting to 1000 meters if not provided.', - example: 1000, - minimum: 1, - default: 1000, - }) - @ValidateIf(o => !o.country) - @IsOptional() - @IsNumber() - @Min(1) - radius?: number = 1000; // Default radius is 1000 meters if not provided - -} diff --git a/src/buildings/dto/requests/get-buildings-query.dto.ts b/src/buildings/dto/requests/get-buildings-query.dto.ts new file mode 100644 index 0000000..294bf20 --- /dev/null +++ b/src/buildings/dto/requests/get-buildings-query.dto.ts @@ -0,0 +1,9 @@ +import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; +import { Transform } from 'class-transformer'; +import { IsNumber, IsOptional, IsString, MaxLength, Min, MinLength, ValidateIf } from 'class-validator'; +import { GetByLocationDto } from '../../../common/dto/requests/get-by-location.dto'; + +export class GetBuildingsQuery extends GetByLocationDto { + + +} diff --git a/src/buildings/dto/responses/building-response.dto.ts b/src/buildings/dto/responses/building-response.dto.ts new file mode 100644 index 0000000..1c700a7 --- /dev/null +++ b/src/buildings/dto/responses/building-response.dto.ts @@ -0,0 +1,60 @@ +import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; +import { GeometryDto } from '../../../common/dto/responses/geometry.dto'; +import { Building } from '../../interfaces/building.interface'; +import { GetByLocationDto } from 'src/common/dto/requests/get-by-location.dto'; +import { Geometry } from 'geojson'; + +export class BuildingPropertiesDto { + +} + +export class BuildingDto { + @ApiProperty({ description: 'Unique identifier of the place.', example: '12345' }) + id: string; + + @ApiProperty({ description: 'Type of place or feature.', example: 'Point of Interest' }) + type: string; + + @ApiProperty({ + description: 'Geometric representation of the place.', + type: () => GeometryDto, + }) + geometry: Geometry; + + @ApiProperty({ + description: 'Properties and additional details.', + type: () => BuildingPropertiesDto, + }) + properties: BuildingPropertiesDto; + + constructor(data: Building) { + this.id = data.id; + this.geometry = data.geometry; + if(!this.properties) this.properties = new BuildingPropertiesDto(); + //Object.assign(this, data); + } + } + +export const toBuildingDto = (data , requestQuery:GetByLocationDto) => { + + const excludeFieldsFromProperties = ['properties','geometry','ext_distance','bbox']; + const properties = {...data}; + excludeFieldsFromProperties.forEach(field => delete properties[field]); + + const rPlace = new BuildingDto(data) + rPlace.properties = properties; + rPlace.geometry = data.geometry; + + //remove any fields that are not requested + if(requestQuery.includes && requestQuery.includes.length > 0) { + const filteredProperties = {}; + requestQuery.includes.forEach((field) => { + + if(rPlace.properties[field]) { + filteredProperties[field] = rPlace.properties[field]; + } + }); + rPlace.properties = filteredProperties; + } + return rPlace +} \ No newline at end of file diff --git a/src/buildings/interfaces/building.interface.ts b/src/buildings/interfaces/building.interface.ts index 865b316..af99b69 100644 --- a/src/buildings/interfaces/building.interface.ts +++ b/src/buildings/interfaces/building.interface.ts @@ -1,5 +1,35 @@ +import { Source } from "../../places/interfaces/place.interface"; +import { Bbox } from "../../common/interfaces/geometry.interface"; +import { Geometry, Polygon } from "geojson"; export interface Building { + id: string; + geometry: Polygon; + bbox?: Bbox; + version: string; + sources: Source[]; + subtype: string; + class: string; + names: string; + level: string; + has_parts: boolean; + height: number; + is_underground: boolean; + num_floors: number; + num_floors_underground: number; + min_height: number; + min_floor: number; + facade_color: string; + facade_material: string; + roof_material: string; + roof_shape: string; + roof_direction: string; + roof_orientation: string; + roof_color: string; + roof_height: number; + ext_distance: number; + theme: string; + type: string; } \ No newline at end of file diff --git a/src/cloudstorage-cache/cloudstorage-cache.service.ts b/src/cloudstorage-cache/cloudstorage-cache.service.ts index cd61825..71e2d92 100644 --- a/src/cloudstorage-cache/cloudstorage-cache.service.ts +++ b/src/cloudstorage-cache/cloudstorage-cache.service.ts @@ -13,31 +13,13 @@ export class CloudStorageCacheService { } - logger = new Logger('CloudStorageCacheService'); async getJSON (cacheKey: string): Promise { - const gcs = new Storage(); - const bucket = gcs.bucket(process.env.GCS_BUCKET); - const file = bucket.file(cacheKey); - try { - const data = await file.download(); - return JSON.parse(data.toString()); - } catch (error) { - return null; - } + return this.gcsService.getJSON(cacheKey); } async storeJSON(data: any[], cacheKey: string): Promise { - const gcs = new Storage(); - const bucket = gcs.bucket(process.env.GCS_BUCKET); - const file = bucket.file(cacheKey); - try { - await file.save(JSON.stringify(data)); - return true - } catch (error) { - this.logger.error(`Error storing cache: ${error}`); - return false - } + return this.gcsService.storeJSON(data, cacheKey); } } \ No newline at end of file diff --git a/src/common/dto/requests/get-by-location.dto.ts b/src/common/dto/requests/get-by-location.dto.ts new file mode 100644 index 0000000..4f6684d --- /dev/null +++ b/src/common/dto/requests/get-by-location.dto.ts @@ -0,0 +1,79 @@ +import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; +import { Transform, Type } from 'class-transformer'; +import { IsArray, IsIn, IsNumber, IsOptional, IsString, Min, ValidateIf } from 'class-validator'; + +//format string enums +export enum Format { + JSON = 'json', + CSV = 'csv', + GEOJSON = 'geojson', +} + + +export class GetByLocationDto { + @ApiProperty({ + description: 'Latitude coordinate. Required if country code is not provided.', + example: 40.7128, + }) + @ValidateIf(o => !o.country) + @Transform(({ value }) => parseFloat(value)) + @IsNumber() + lat: number; + + @ApiProperty({ + description: 'Longitude coordinate. Required if country code is not provided.', + example: -74.0060, + }) + @ValidateIf(o => !o.country) + @Transform(({ value }) => parseFloat(value)) + @IsNumber() + lng: number; + + @ApiPropertyOptional({ + description: 'Search radius in meters, defaulting to 1000 meters if not provided.', + example: 1000, + minimum: 1, + default: 1000, + }) + @ValidateIf(o => !o.country) + @IsOptional() + @Transform(({ value }) => parseFloat(value)) + @IsNumber() + @Min(1) + radius?: number = 1000; + + @ApiPropertyOptional({ + description: 'Limit on the number of results returned, defaulting to 100 if not provided.', + example: 10, + minimum: 1, + default: 100, + }) + @IsOptional() + @Transform(({ value }) => parseInt(value)) + @IsNumber() + @Min(1) + limit?: number = 100; + + + @ApiPropertyOptional({ + description: 'Response format, defaulting to JSON. Options are "json", "csv", or "geojson".', + example: 'json', + default: 'json', + enum: ['json', 'csv', 'geojson'], + }) + @IsOptional() + @IsString() + @IsIn(['json', 'csv', 'geojson']) + format?: string = 'json'; + + + @ApiPropertyOptional({ + description: 'Array of fields to include in the properties field of the response, provided as a comma-separated string. Any fields not in the list will be excluded from the properties object. This is used to make the response lighter so your application is faster.', + example: ['id', 'geometry', 'properties'], + type: [String], + }) + @IsOptional() + @Transform(({ value }) => String(value).split(',')) + @IsString({ each: true }) + includes?: string[]; +} diff --git a/src/common/dto/responses/geometry.dto.ts b/src/common/dto/responses/geometry.dto.ts new file mode 100644 index 0000000..6a2ac30 --- /dev/null +++ b/src/common/dto/responses/geometry.dto.ts @@ -0,0 +1,13 @@ +import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; + +export class GeometryDto { + @ApiProperty({ description: 'Type of geometry', example: 'Point' }) + type: string; + + @ApiProperty({ + description: 'Coordinates representing the geometry.', + example: [40.7128, -74.0060], + type: [Number], + }) + coordinates: number[]; + } \ No newline at end of file diff --git a/src/common/interfaces/geometry.interface.ts b/src/common/interfaces/geometry.interface.ts new file mode 100644 index 0000000..c433ad2 --- /dev/null +++ b/src/common/interfaces/geometry.interface.ts @@ -0,0 +1,8 @@ + + + export interface Bbox { + xmin: number; + xmax: number; + ymin: number; + ymax: number; + } \ No newline at end of file diff --git a/src/gcs/gcs.service.ts b/src/gcs/gcs.service.ts index ae31c2e..93c25ec 100644 --- a/src/gcs/gcs.service.ts +++ b/src/gcs/gcs.service.ts @@ -41,6 +41,7 @@ export class GcsService { try { const exists = await file.exists(); if (exists[0]) { + this.logger.log('Cached JSON found in GCS.'); const [content] = await file.download(); //get size of file const fileSize = content.length; @@ -54,7 +55,7 @@ export class GcsService { return null; } - async storeJSON(data: any, fileName: string): Promise { + async storeJSON(data: any, fileName: string): Promise { const file = this.bucket.file(this.generateCacheFileName(fileName)); try { @@ -62,9 +63,11 @@ export class GcsService { contentType: 'application/json', resumable: false, }); - this.logger.log('Cached places saved to GCS.'); + this.logger.log('Cache JSON saved to GCS.'); + return true } catch (error) { this.logger.error('Error saving cached places:', error); + return false } } // Method to set lifecycle policy on the bucket diff --git a/src/places/dto/requests/get-places-with-buildings.ts b/src/places/dto/requests/get-places-with-buildings.ts new file mode 100644 index 0000000..d22c028 --- /dev/null +++ b/src/places/dto/requests/get-places-with-buildings.ts @@ -0,0 +1,14 @@ +import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; +import { Transform, Type } from 'class-transformer'; +import { IsArray, IsIn, IsNumber, IsOptional, IsString, Min, ValidateIf } from 'class-validator'; +import { GetByLocationDto } from 'src/common/dto/requests/get-by-location.dto'; +import { GetPlacesDto } from './get-places.dto'; +import { Optional } from '@nestjs/common'; + +export class GetPlacesWithBuildingsDto extends GetPlacesDto { + + @IsOptional() + @Transform(({ value }) => value === 'true') + match_nearest_building?: boolean; + +} diff --git a/src/places/dto/requests/get-places.dto.ts b/src/places/dto/requests/get-places.dto.ts index 971753f..43794e8 100644 --- a/src/places/dto/requests/get-places.dto.ts +++ b/src/places/dto/requests/get-places.dto.ts @@ -1,8 +1,9 @@ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { Transform, Type } from 'class-transformer'; import { IsArray, IsIn, IsNumber, IsOptional, IsString, Min, ValidateIf } from 'class-validator'; +import { GetByLocationDto } from 'src/common/dto/requests/get-by-location.dto'; -export class GetPlacesDto { +export class GetPlacesDto extends GetByLocationDto { @ApiProperty({ description: 'Latitude coordinate. Required if country code is not provided.', example: 40.7128, @@ -43,17 +44,6 @@ export class GetPlacesDto { country?: string; - @ApiPropertyOptional({ - description: 'Limit on the number of results returned, defaulting to 100 if not provided.', - example: 10, - minimum: 1, - default: 100, - }) - @IsOptional() - @Transform(({ value }) => parseInt(value)) - @IsNumber() - @Min(1) - limit?: number = 100; @ApiPropertyOptional({ description: 'Wikidata brand ID associated with the place.', diff --git a/src/places/dto/place-response.dto.ts b/src/places/dto/responses/place-response.dto.ts similarity index 77% rename from src/places/dto/place-response.dto.ts rename to src/places/dto/responses/place-response.dto.ts index b01acc9..9454764 100644 --- a/src/places/dto/place-response.dto.ts +++ b/src/places/dto/responses/place-response.dto.ts @@ -1,7 +1,10 @@ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; -import { Place } from '../interfaces/place.interface'; -import { BrandDto } from './models/brand.dto'; -import { CategoryDto } from './models/category.dto'; +import { Place } from '../../interfaces/place.interface'; +import { BrandDto } from '../models/brand.dto'; +import { CategoryDto } from '../models/category.dto'; +import { GeometryDto } from '../../../common/dto/responses/geometry.dto'; +import { Geometry, Point, Polygon } from 'geojson'; +import { GetByLocationDto } from 'src/common/dto/requests/get-by-location.dto'; export class RulesDto { @ApiProperty({ description: 'Variant of the rule.', example: 'Abbreviation' }) @@ -48,19 +51,8 @@ export class AddressDto { country?: string; } -export class GeometryDto { - @ApiProperty({ description: 'Type of geometry', example: 'Point' }) - type: string; - - @ApiProperty({ - description: 'Coordinates representing the geometry.', - example: [40.7128, -74.0060], - type: [Number], - }) - coordinates: number[]; -} -export class PropertiesDto { +export class PlacePropertiesDto { @ApiProperty({ description: 'Primary category of the place.', type: () => CategoryDto }) categories: CategoryDto; @@ -112,8 +104,16 @@ export class PropertiesDto { }) names: PlaceNamesDto; + + @ApiProperty({ + description: 'Name of the place.', + type: () => PlaceNamesDto, + }) + ext_name?: string; + constructor(data={}) { Object.assign(this, data); + this.ext_name = this.names?.primary; } } @@ -128,32 +128,50 @@ export class PlaceResponseDto { description: 'Geometric representation of the place.', type: () => GeometryDto, }) - geometry: GeometryDto; + geometry: Point|Polygon; @ApiProperty({ description: 'Properties and additional details of the place.', - type: () => PropertiesDto, + type: () => PlacePropertiesDto, }) - properties: PropertiesDto; + properties: PlacePropertiesDto; constructor(place: Place) { this.id = place.id; this.geometry = place.geometry; //if(!this.properties) this.properties = new PropertiesDto(); //Object.assign(this.properties, place); + this.properties = new PlacePropertiesDto(place); + } } -export const toPlaceDto = (place: Place):PlaceResponseDto => { +export const toPlaceDto = (place: Place, requestQuery:GetByLocationDto):PlaceResponseDto => { - const excludeFieldsFromProperties = ['properties','geometry','distance_m','bbox']; - const properties = {...place}; - excludeFieldsFromProperties.forEach(field => delete properties[field]); + const excludeFieldsFromProperties = ['properties','geometry','ext_distance','bbox']; + const rPlace = new PlaceResponseDto(place) + + const properties = {...rPlace.properties}; + excludeFieldsFromProperties.forEach(field => delete properties[field]); + rPlace.properties = properties; + rPlace.geometry = place.geometry; + //remove any fields that are not requested + if(requestQuery.includes && requestQuery.includes.length > 0) { + const filteredProperties = {}; + requestQuery.includes.forEach((field) => { + + if(rPlace.properties[field]) { + filteredProperties[field] = rPlace.properties[field]; + } + }); + //@ts-ignore + rPlace.properties = filteredProperties; +} return rPlace; } diff --git a/src/places/interfaces/place.interface.ts b/src/places/interfaces/place.interface.ts index bc8b8ba..2105bb8 100644 --- a/src/places/interfaces/place.interface.ts +++ b/src/places/interfaces/place.interface.ts @@ -1,7 +1,9 @@ +import { Point, Polygon } from "geojson"; +import { Bbox } from "../../common/interfaces/geometry.interface"; export interface Place { id: string; - geometry: Geometry; + geometry: Point|Polygon; bbox?: Bbox; version: string; sources: Source[]; @@ -14,22 +16,11 @@ export interface Place { phones?: string[]; brand?: Brand; addresses: Address[]; - distance_m?: number; + ext_distance?: number; theme?: string; type?: string; } - export interface Geometry { - type: string; // "Point" - coordinates: number[]; // [longitude, latitude] - } - - export interface Bbox { - xmin: number; - xmax: number; - ymin: number; - ymax: number; - } export interface Source { property: string; diff --git a/src/places/places.controller.ts b/src/places/places.controller.ts index 990db6b..90a42a3 100644 --- a/src/places/places.controller.ts +++ b/src/places/places.controller.ts @@ -3,7 +3,7 @@ import { Controller, Get, Logger, Query, UseGuards } from '@nestjs/common'; import { BigQueryService } from '../bigquery/bigquery.service'; import { GcsService } from '../gcs/gcs.service'; import { GetPlacesDto } from './dto/requests/get-places.dto'; -import { PlaceResponseDto, toPlaceDto } from './dto/place-response.dto'; +import { PlaceResponseDto, toPlaceDto } from './dto/responses/place-response.dto'; import { GetBrandsDto } from './dto/requests/get-brands.dto'; import { IsAuthenticatedGuard } from '../guards/is-authenticated.guard'; import { GetCategoriesDto } from './dto/requests/get-categories.dto'; @@ -14,6 +14,11 @@ import { CategoryResponseDto, toCategoryResponseDto } from './dto/responses/cate import { AuthedUser, User } from '../decorators/authed-user.decorator'; import { ValidateLatLngUser } from '../decorators/validate-lat-lng-user.decorator'; import { PlacesService } from './places.service'; +import { findNearestPolygon, isPointInPolygon, isPointInPolygonWithoutTurf, wrapAsGeoJSON } from '../utils/geojson'; +import { Format } from '../common/dto/requests/get-by-location.dto'; +import { BuildingsService } from '../buildings/buildings.service'; +import { Feature, GeoJsonObject, Geometry } from 'geojson'; +import { GetPlacesWithBuildingsDto } from './dto/requests/get-places-with-buildings'; @ApiTags('places') @ApiSecurity('API_KEY') // Applies the API key security scheme defined in Swagger @@ -24,30 +29,89 @@ export class PlacesController { logger = new Logger('PlacesController'); constructor( - private placesService: PlacesService + private placesService: PlacesService, + private buildingsService: BuildingsService ) {} @Get() @ValidateLatLngUser() - @ApiOperation({ summary: 'Get all Places using Query params as filters' }) + @ApiOperation({ summary: 'Get Places using Query params as filters' }) @ApiQuery({type:GetPlacesDto}) - @ApiResponse({ status: 200, description: 'Return all Places.' , type: PlaceResponseDto, isArray: true}) + @ApiResponse({ status: 200, description: 'Return Places.' , type: PlaceResponseDto, isArray: true}) async getPlaces(@Query() query: GetPlacesDto, @AuthedUser() user: User) { // If no cache, query BigQuery with wikidata and country support const results = await this.placesService.getPlaces(query); - const dtoResults = results.map((place: any) =>toPlaceDto(place)); + const dtoResults = results.map((place: any) =>toPlaceDto(place,query)); - if(query.format === 'geojson') { - return { - "type":"FeatureCollection", - "features": dtoResults - }; + if(query.format === Format.GEOJSON) { + return wrapAsGeoJSON (dtoResults) } return dtoResults } + + @Get('buildings') + //@ValidateLatLngUser() + @ApiOperation({ summary: 'Get Places with their Building shapes using Query params as filters' }) + @ApiQuery({type:GetPlacesWithBuildingsDto}) + @ApiResponse({ status: 200, description: 'Return Places with Buildings.' , type: PlaceResponseDto, isArray: true}) + async getPlacesWithBuildings(@Query() query: GetPlacesWithBuildingsDto, @AuthedUser() user: User) { + + if(query.radius>5000) { + throw new Error("Radius is too large, please use a radius less than 5000 meters") + //ToDo: implement building matching via SQL for larger radius queries + } + + // Execute getPlaces and getBuildings concurrently + const [places, buildings] = await Promise.all([ + this.placesService.getPlaces(query), + //limit should be higher than the number of places as needs more to choose from as places are higher density + this.buildingsService.getBuildings({...query,limit:10000}), + ]); + + // Extract building geometries for quick reference and log a specific building if needed + const buildingGeoms = buildings.map((building) => building.geometry); + this.logger.log(`Building geometries extracted. Looking for specific ID if applicable.`); + + // Find the building containing each place or the nearest neighbor if no match is found + let numMatches = 0; + const results = places.map((place) => { + if (!place.geometry) { + return place; + } + + if(place.geometry.type!="Point") { + return place; + } + + const matchingBuilding = buildings.find((building) => isPointInPolygon(place.geometry, building.geometry)); + + if (matchingBuilding) { + place.geometry = matchingBuilding.geometry; + numMatches++; + } else if (query.match_nearest_building) { + + // If no exact match is found, try to find the nearest building geometry + const nearestGeometry = findNearestPolygon(place.geometry, buildingGeoms, 100); + if (nearestGeometry) { + place.geometry = nearestGeometry; + numMatches++; + } + } + + return place; + }); + + this.logger.log(`Found ${numMatches} matches`); + + // Map results to DTOs and wrap in GeoJSON if requested + const dtoResults = results.map((place) => toPlaceDto(place, query)); + return query.format === Format.GEOJSON ? wrapAsGeoJSON(dtoResults) : dtoResults; + } + + @Get('brands') @ValidateLatLngUser() diff --git a/src/places/places.module.ts b/src/places/places.module.ts index 61323fb..4eb4bb8 100644 --- a/src/places/places.module.ts +++ b/src/places/places.module.ts @@ -9,9 +9,10 @@ import { BigQueryService } from '../bigquery/bigquery.service'; import { GcsService } from '../gcs/gcs.service'; import { ConfigModule } from '@nestjs/config'; import { CloudstorageCacheModule } from '../cloudstorage-cache/cloudstorage-cache.module'; +import { BuildingsModule } from 'src/buildings/buildings.module'; @Module({ - imports: [ConfigModule, CloudstorageCacheModule], + imports: [ConfigModule, CloudstorageCacheModule, BuildingsModule], controllers: [PlacesController], providers: [PlacesService, BigQueryService, GcsService], exports: [PlacesService] diff --git a/src/places/places.service.spec.ts b/src/places/places.service.spec.ts index c38a875..6158147 100644 --- a/src/places/places.service.spec.ts +++ b/src/places/places.service.spec.ts @@ -4,7 +4,7 @@ import { PlacesService } from './places.service'; import { BigQueryService } from '../bigquery/bigquery.service'; import { GcsService } from '../gcs/gcs.service'; import { GetPlacesDto } from './dto/requests/get-places.dto'; -import { PlaceResponseDto, toPlaceDto } from './dto/place-response.dto'; +import { PlaceResponseDto, toPlaceDto } from './dto/responses/place-response.dto'; import { ConfigService } from '@nestjs/config'; import { CloudStorageCacheService } from '../cloudstorage-cache/cloudstorage-cache.service'; diff --git a/src/places/places.service.ts b/src/places/places.service.ts index c83c904..d96ab56 100644 --- a/src/places/places.service.ts +++ b/src/places/places.service.ts @@ -6,7 +6,7 @@ import { Injectable, Logger } from '@nestjs/common'; import { BigQueryService } from '../bigquery/bigquery.service'; import { GcsService } from '../gcs/gcs.service'; import { GetPlacesDto } from './dto/requests/get-places.dto'; -import { PlaceResponseDto, toPlaceDto } from './dto/place-response.dto'; +import { PlaceResponseDto, toPlaceDto } from './dto/responses/place-response.dto'; import { GetBrandsDto } from './dto/requests/get-brands.dto'; import { IsAuthenticatedGuard } from '../guards/is-authenticated.guard'; import { GetCategoriesDto } from './dto/requests/get-categories.dto'; diff --git a/src/utils/geojson.ts b/src/utils/geojson.ts index 4391c12..9999f5a 100644 --- a/src/utils/geojson.ts +++ b/src/utils/geojson.ts @@ -1,18 +1,135 @@ -export const parsePolygonToGeoJSON = (polygon: string): any => { - const coordinates = polygon.split(' ').map((coord) => { - const [lng, lat] = coord.split(',').map((c) => parseFloat(c)); - return [lng, lat]; +/* + +Expect string to be in format "POLYGON((151.2762519003 -33.8915747100951, 151.276258302075 -33.8914594937271, 151.276189186945 -33.8914340614275, 151.276066105576 -33.8914671922852, 151.276054954362 -33.8914667647, 151.275981484004 -33.8914858830191, 151.275999470338 -33.8915335108494, 151.275962780589 -33.8915430560486, 151.275960784231 -33.8915789311803, 151.275923313259 -33.8915774943851, 151.275920283167 -33.8916319459681, 151.275975754972 -33.891634069767, 151.275983409999 -33.8916543402525, 151.275981862028 -33.8916821576985, 151.27603392474 -33.8916841540002, 151.276035202591 -33.8916611558307, 151.276077326459 -33.8916501944598, 151.276088482028 -33.891650622211, 151.276167145946 -33.8916301570429, 151.276169244963 -33.8915924371208, 151.276165426201 -33.8915823250443, 151.276215281919 -33.8915842367227, 151.2762519003 -33.8915747100951))" + +*/ +import * as turf from '@turf/turf' +import { Feature, Point, Polygon } from 'geojson'; +//import geojson + +export const parsePolygonToGeoJSON = (polygon: string): Polygon => { + try{ + if(polygon === undefined){ + return null; + } + let coordinates = polygon + .replace('POLYGON((','') + .replace('))','') + .split(',') + .map((c) => c.trim().split(' ').map((c) => { + { + let num = parseFloat(c); + //temp code whilst investigate if some data is dirty as some coordinates are in unexpected brackets + if(c.charAt(0) === '('){ + c = c.substring(1); + num = parseFloat(c); + } + if(isNaN(num)){ + console.log('Coordinate is NaN', c); + } + return num + } + })); + + //filter out any empty coordinates or where either coordinate is null + coordinates = coordinates.filter((c) => c.length === 2 && c[0] !== null && c[1] !== null); + + //check first pair of coordinates and add it to the end if it is not the same + if(coordinates[0][0] !== coordinates[coordinates.length-1][0] || coordinates[0][1] !== coordinates[coordinates.length-1][1]){ + coordinates.push(coordinates[0]); + } + return { + type: 'Polygon', + coordinates: [coordinates] + }; + }catch(e){ + console.log(e); + return null; + } +} + +/* +export string of POINT(151.2772322 -33.8913828) +*/ +export const parsePointToGeoJSON = (point: string): Point => { + try{ + if(point === undefined){ + return null; + } + const coordinates = point + .replace('POINT(','') + .replace(')','') + .split(' ') + .map((c) => parseFloat(c)); + + + return { + type: 'Point', + coordinates: coordinates + }; + }catch(e){ + console.log(e); + return null; + } +} + +export const wrapAsGeoJSON = (features: any[] = []):any => { + + //add a type: "Feature" to each building + features.forEach((item: any) => { + item.type = "Feature"; }); return { - type: 'Polygon', - coordinates: [coordinates] + "type":"FeatureCollection", + "features": features + }; } -export const parsePointToGeoJSON = (point: string): any => { - const [lng, lat] = point.split(',').map((c) => parseFloat(c)); - return { - type: 'Point', - coordinates: [lng, lat] - }; -} \ No newline at end of file +export const isPointInPolygon = (point: Point|Polygon, polygon: Polygon): boolean => { + + if(point.type!="Point") { + return false + } + return turf.booleanPointInPolygon(point, polygon); +} + +export const isPointInPolygonWithoutTurf = (point: Point, polygon: Polygon): boolean => { + const x = point.coordinates[0]; + const y = point.coordinates[1]; + const vs = polygon.coordinates[0]; + let inside = false; + for (let i = 0, j = vs.length - 1; i < vs.length; j = i++) { + const xi = vs[i][0]; + const yi = vs[i][1]; + const xj = vs[j][0]; + const yj = vs[j][1]; + const intersect = ((yi > y) !== (yj > y)) && (x < ((xj - xi) * (y - yi) / (yj - yi)) + xi); + if (intersect) inside = !inside; + } + return inside; +} + + export const findNearestPolygon = (point: Point, polygons: Polygon[], maxAllowedDistance:number=100): Polygon | null => { + let nearestPolygon: Polygon| null = null; + let minDistance = Infinity; + + for (const polygon of polygons) { + // Calculate the centroid of the polygon + const centroid = turf.centroid(polygon); + + // Calculate the distance from the point to the polygon's centroid + const distance = turf.distance(point, centroid, { units: 'kilometers' }); + + // Check if this is the nearest polygon so far + if (distance < minDistance) { + minDistance = distance; + nearestPolygon = polygon; + } + } + if (minDistance > maxAllowedDistance) { + return null; + } + + return nearestPolygon; + } \ No newline at end of file diff --git a/test/mock-data/bq-results/get-buildings-nearby.json b/test/mock-data/bq-results/get-buildings-nearby.json new file mode 100644 index 0000000..2f20290 --- /dev/null +++ b/test/mock-data/bq-results/get-buildings-nearby.json @@ -0,0 +1,46 @@ +{ + "id": "08bbe0e373042fff0200498cd0c29719", + "geometry": { + "value": "POLYGON((151.2762519003 -33.8915747100951, 151.276258302075 -33.8914594937271, 151.276189186945 -33.8914340614275, 151.276066105576 -33.8914671922852, 151.276054954362 -33.8914667647, 151.275981484004 -33.8914858830191, 151.275999470338 -33.8915335108494, 151.275962780589 -33.8915430560486, 151.275960784231 -33.8915789311803, 151.275923313259 -33.8915774943851, 151.275920283167 -33.8916319459681, 151.275975754972 -33.891634069767, 151.275983409999 -33.8916543402525, 151.275981862028 -33.8916821576985, 151.27603392474 -33.8916841540002, 151.276035202591 -33.8916611558307, 151.276077326459 -33.8916501944598, 151.276088482028 -33.891650622211, 151.276167145946 -33.8916301570429, 151.276169244963 -33.8915924371208, 151.276165426201 -33.8915823250443, 151.276215281919 -33.8915842367227, 151.2762519003 -33.8915747100951))" + }, + "bbox": { + "xmin": 151.27590942382812, + "xmax": 151.27626037597656, + "ymin": -33.891685485839844, + "ymax": -33.89143371582031 + }, + "version": 0, + "sources": { + "list": [ + { + "element": { + "property": "", + "dataset": "Microsoft ML Buildings", + "record_id": "8f1303282937", + "update_time": "2000-01-01T00:00:00.000Z", + "confidence": null + } + } + ] + }, + "subtype": null, + "class": null, + "names": null, + "level": null, + "has_parts": false, + "height": null, + "is_underground": false, + "num_floors": null, + "num_floors_underground": null, + "min_height": null, + "min_floor": null, + "facade_color": null, + "facade_material": null, + "roof_material": null, + "roof_shape": null, + "roof_direction": null, + "roof_orientation": null, + "roof_color": null, + "roof_height": null, + "ext_distance": 40.9340510566911 + } \ No newline at end of file