diff --git a/README.md b/README.md index 8acde4bb..2aab7470 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,19 @@ This module is already included in [`biigle/biigle`](https://github.com/biigle/b 2. Add `Biigle\Modules\Geo\GeoServiceProvider::class` to the `providers` array in `config/app.php`. 3. Run `php artisan vendor:publish --tag=public` to publish the public assets of this module. +## Set up + +Add geo-overlay disk to `config/filesystems.php`. + +```php +'geo-overlays' => [ + 'driver' => 'local', + 'root' => storage_path('app/public/geo-overlays'), + 'url' => env('APP_URL').'/storage/geo-overlays', + 'visibility' => 'public', + ], +``` + ## Developing Take a look at the [development guide](https://github.com/biigle/core/blob/master/DEVELOPING.md) of the core repository to get started with the development setup. diff --git a/composer.json b/composer.json index 2d457d3a..e851a283 100644 --- a/composer.json +++ b/composer.json @@ -18,5 +18,9 @@ "psr-4": { "Biigle\\Modules\\Geo\\": "src" } + }, + "require": { + "lychee-org/php-exif": "^1.0", + "php-coord/php-coord": "^5.11" } } diff --git a/composer.lock b/composer.lock new file mode 100644 index 00000000..0292c5ff --- /dev/null +++ b/composer.lock @@ -0,0 +1,1481 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "a597ba2414262fa780e11462edee3458", + "packages": [ + { + "name": "composer/pcre", + "version": "3.3.2", + "source": { + "type": "git", + "url": "https://github.com/composer/pcre.git", + "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e", + "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<1.11.10" + }, + "require-dev": { + "phpstan/phpstan": "^1.12 || ^2", + "phpstan/phpstan-strict-rules": "^1 || ^2", + "phpunit/phpunit": "^8 || ^9" + }, + "type": "library", + "extra": { + "phpstan": { + "includes": [ + "extension.neon" + ] + }, + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Pcre\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "keywords": [ + "PCRE", + "preg", + "regex", + "regular expression" + ], + "support": { + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/3.3.2" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-11-12T16:29:46+00:00" + }, + { + "name": "evenement/evenement", + "version": "v3.0.2", + "source": { + "type": "git", + "url": "https://github.com/igorw/evenement.git", + "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/igorw/evenement/zipball/0a16b0d71ab13284339abb99d9d2bd813640efbc", + "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc", + "shasum": "" + }, + "require": { + "php": ">=7.0" + }, + "require-dev": { + "phpunit/phpunit": "^9 || ^6" + }, + "type": "library", + "autoload": { + "psr-4": { + "Evenement\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" + } + ], + "description": "Événement is a very simple event dispatching library for PHP", + "keywords": [ + "event-dispatcher", + "event-emitter" + ], + "support": { + "issues": "https://github.com/igorw/evenement/issues", + "source": "https://github.com/igorw/evenement/tree/v3.0.2" + }, + "time": "2023-08-08T05:53:35+00:00" + }, + { + "name": "fylax/forceutf8", + "version": "v3.0.3", + "source": { + "type": "git", + "url": "https://github.com/Fylax/forceutf8.git", + "reference": "efaa4ec353ce35931ef469632fece63df4c5a301" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Fylax/forceutf8/zipball/efaa4ec353ce35931ef469632fece63df4c5a301", + "reference": "efaa4ec353ce35931ef469632fece63df4c5a301", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.6" + }, + "suggest": { + "ext-iconv": "To convert non-UTF-8 strings to UTF-8", + "ext-mbstring": "To convert non-UTF-8 strings to UTF-8" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/neitanod/forceutf8", + "name": "neitanod/forceutf8" + } + }, + "autoload": { + "psr-4": { + "ForceUTF8\\": "ForceUTF8" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nico Caprioli", + "email": "nico.caprioli@gmail.com", + "role": "Developer" + } + ], + "description": "PHP Class Encoding featuring popular Encoding::toUTF8() function --formerly known as forceUTF8()-- that fixes mixed encoded strings.", + "homepage": "https://github.com/Fylax/forceutf8", + "support": { + "issues": "https://github.com/Fylax/forceutf8/issues", + "source": "https://github.com/Fylax/forceutf8/tree/v3.0.3" + }, + "time": "2023-06-06T09:49:33+00:00" + }, + { + "name": "lychee-org/php-exif", + "version": "v1.0.4", + "source": { + "type": "git", + "url": "https://github.com/LycheeOrg/php-exif.git", + "reference": "b9535df9fa455ae0e6820b327a031a63121de890" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/LycheeOrg/php-exif/zipball/b9535df9fa455ae0e6820b327a031a63121de890", + "reference": "b9535df9fa455ae0e6820b327a031a63121de890", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "fylax/forceutf8": "^3.0.3", + "php": "^8.2", + "php-ffmpeg/php-ffmpeg": "^1.2", + "thecodingmachine/safe": "^2.5" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.51", + "infection/infection": "^0.27.10", + "lychee-org/phpstan-lychee": "^1.0.4", + "php-parallel-lint/php-parallel-lint": "^1.3.2", + "phpmd/phpmd": "^2.15", + "phpunit/phpunit": "^9.5.10", + "squizlabs/php_codesniffer": "^3.9", + "thecodingmachine/phpstan-safe-rule": "^1.2" + }, + "suggest": { + "FFmpeg": "Use FFmpeg/FFprobe as adapter", + "ext-exif": "Use exif PHP extension as adapter", + "ext-imagick": "Use ImageMagick as adapter", + "ext-mbstring": "Support UTC-16 characters in EXIF data with exif PHP extension", + "lib-exiftool": "Use perl lib exiftool as adapter" + }, + "type": "library", + "autoload": { + "psr-0": { + "PHPExif": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Tom Van Herreweghe", + "homepage": "http://theanalogguy.be", + "role": "Developer" + } + ], + "description": "Object-Oriented EXIF parsing", + "keywords": [ + "IPTC", + "ImageMagick", + "exif", + "exiftool", + "ffmpeg", + "ffprobe", + "imagick", + "jpeg", + "tiff" + ], + "support": { + "issues": "https://github.com/LycheeOrg/php-exif/issues", + "source": "https://github.com/LycheeOrg/php-exif/tree/v1.0.4" + }, + "time": "2024-07-01T21:08:54+00:00" + }, + { + "name": "opis/json-schema", + "version": "2.6.0", + "source": { + "type": "git", + "url": "https://github.com/opis/json-schema.git", + "reference": "8458763e0dd0b6baa310e04f1829fc73da4e8c8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opis/json-schema/zipball/8458763e0dd0b6baa310e04f1829fc73da4e8c8a", + "reference": "8458763e0dd0b6baa310e04f1829fc73da4e8c8a", + "shasum": "" + }, + "require": { + "ext-json": "*", + "opis/string": "^2.1", + "opis/uri": "^1.0", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "ext-bcmath": "*", + "ext-intl": "*", + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Opis\\JsonSchema\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Sorin Sarca", + "email": "sarca_sorin@hotmail.com" + }, + { + "name": "Marius Sarca", + "email": "marius.sarca@gmail.com" + } + ], + "description": "Json Schema Validator for PHP", + "homepage": "https://opis.io/json-schema", + "keywords": [ + "json", + "json-schema", + "schema", + "validation", + "validator" + ], + "support": { + "issues": "https://github.com/opis/json-schema/issues", + "source": "https://github.com/opis/json-schema/tree/2.6.0" + }, + "time": "2025-10-17T12:46:48+00:00" + }, + { + "name": "opis/string", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/opis/string.git", + "reference": "3e4d2aaff518ac518530b89bb26ed40f4503635e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opis/string/zipball/3e4d2aaff518ac518530b89bb26ed40f4503635e", + "reference": "3e4d2aaff518ac518530b89bb26ed40f4503635e", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "ext-json": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Opis\\String\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Marius Sarca", + "email": "marius.sarca@gmail.com" + }, + { + "name": "Sorin Sarca", + "email": "sarca_sorin@hotmail.com" + } + ], + "description": "Multibyte strings as objects", + "homepage": "https://opis.io/string", + "keywords": [ + "multi-byte", + "opis", + "string", + "string manipulation", + "utf-8" + ], + "support": { + "issues": "https://github.com/opis/string/issues", + "source": "https://github.com/opis/string/tree/2.1.0" + }, + "time": "2025-10-17T12:38:41+00:00" + }, + { + "name": "opis/uri", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/opis/uri.git", + "reference": "0f3ca49ab1a5e4a6681c286e0b2cc081b93a7d5a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opis/uri/zipball/0f3ca49ab1a5e4a6681c286e0b2cc081b93a7d5a", + "reference": "0f3ca49ab1a5e4a6681c286e0b2cc081b93a7d5a", + "shasum": "" + }, + "require": { + "opis/string": "^2.0", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Opis\\Uri\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Marius Sarca", + "email": "marius.sarca@gmail.com" + }, + { + "name": "Sorin Sarca", + "email": "sarca_sorin@hotmail.com" + } + ], + "description": "Build, parse and validate URIs and URI-templates", + "homepage": "https://opis.io", + "keywords": [ + "URI Template", + "parse url", + "punycode", + "uri", + "uri components", + "url", + "validate uri" + ], + "support": { + "issues": "https://github.com/opis/uri/issues", + "source": "https://github.com/opis/uri/tree/1.1.0" + }, + "time": "2021-05-22T15:57:08+00:00" + }, + { + "name": "php-coord/php-coord", + "version": "v5.11.1", + "source": { + "type": "git", + "url": "https://github.com/dvdoug/PHPCoord.git", + "reference": "d9b9677a79570c6facff981ecc324e4e215ef6b9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dvdoug/PHPCoord/zipball/d9b9677a79570c6facff981ecc324e4e215ef6b9", + "reference": "d9b9677a79570c6facff981ecc324e4e215ef6b9", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.1", + "composer/pcre": "^3.1", + "ext-zip": "*", + "opis/json-schema": "^2.3", + "php": "^8.1" + }, + "require-dev": { + "ext-json": "*", + "ext-sqlite3": "*", + "friendsofphp/php-cs-fixer": "^3.84", + "nikic/php-parser": "^5.0", + "php-coord/datapack-africa": "dev-master", + "php-coord/datapack-antarctic": "dev-master", + "php-coord/datapack-arctic": "dev-master", + "php-coord/datapack-asia": "dev-master", + "php-coord/datapack-europe": "dev-master", + "php-coord/datapack-northamerica": "dev-master", + "php-coord/datapack-oceania": "dev-master", + "php-coord/datapack-southamerica": "dev-master", + "phpstan/phpstan": "^1.12", + "phpunit/phpunit": "^10.5||^11.5" + }, + "suggest": { + "php-coord/datapack-africa": "High-accuracy addon datapack for Africa", + "php-coord/datapack-antarctic": "High-accuracy addon datapack for the Antarctic", + "php-coord/datapack-arctic": "High-accuracy addon datapack for the Arctic", + "php-coord/datapack-asia": "High-accuracy addon datapack for Asia", + "php-coord/datapack-europe": "High-accuracy addon datapack for Europe", + "php-coord/datapack-northamerica": "High-accuracy addon datapack for North America", + "php-coord/datapack-oceania": "High-accuracy addon datapack for Oceania", + "php-coord/datapack-southamerica": "High-accuracy addon datapack for South America" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "files": [ + "src/bc_namespace.php" + ], + "psr-4": { + "PHPCoord\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "(MIT and proprietary)" + ], + "authors": [ + { + "name": "Doug Wright", + "role": "Developer" + } + ], + "description": "PHPCoord is a PHP library to aid in handling coordinates. It can convert coordinates for a point from one system to another and also calculate distance between points.", + "homepage": "https://www.phpcoord.net/", + "keywords": [ + "UTM", + "coord", + "ed50", + "epsg", + "etrs", + "gda", + "geo", + "grid ref", + "latitude", + "longitude", + "map", + "nad", + "nzmg", + "osgb3", + "projection", + "wgs84" + ], + "support": { + "issues": "https://github.com/dvdoug/PHPCoord/issues", + "source": "https://github.com/dvdoug/PHPCoord/tree/v5.11.1" + }, + "funding": [ + { + "url": "https://github.com/dvdoug", + "type": "github" + } + ], + "time": "2025-08-13T23:10:47+00:00" + }, + { + "name": "php-ffmpeg/php-ffmpeg", + "version": "v1.3.2", + "source": { + "type": "git", + "url": "https://github.com/PHP-FFMpeg/PHP-FFMpeg.git", + "reference": "8e74bdc07ad200da7a6cfb21ec2652875e4368e0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-FFMpeg/PHP-FFMpeg/zipball/8e74bdc07ad200da7a6cfb21ec2652875e4368e0", + "reference": "8e74bdc07ad200da7a6cfb21ec2652875e4368e0", + "shasum": "" + }, + "require": { + "evenement/evenement": "^3.0", + "php": "^8.0 || ^8.1 || ^8.2 || ^8.3 || ^8.4", + "psr/log": "^1.0 || ^2.0 || ^3.0", + "spatie/temporary-directory": "^2.0", + "symfony/cache": "^5.4 || ^6.0 || ^7.0", + "symfony/process": "^5.4 || ^6.0 || ^7.0" + }, + "require-dev": { + "mockery/mockery": "^1.5", + "phpunit/phpunit": "^9.5.10 || ^10.0" + }, + "suggest": { + "php-ffmpeg/extras": "A compilation of common audio & video drivers for PHP-FFMpeg" + }, + "type": "library", + "autoload": { + "psr-4": { + "FFMpeg\\": "src/FFMpeg", + "Alchemy\\BinaryDriver\\": "src/Alchemy/BinaryDriver" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Romain Neutron", + "email": "imprec@gmail.com", + "homepage": "http://www.lickmychip.com/" + }, + { + "name": "Phraseanet Team", + "email": "info@alchemy.fr", + "homepage": "http://www.phraseanet.com/" + }, + { + "name": "Patrik Karisch", + "email": "patrik@karisch.guru", + "homepage": "http://www.karisch.guru" + }, + { + "name": "Romain Biard", + "email": "romain.biard@gmail.com", + "homepage": "https://www.strime.io/" + }, + { + "name": "Jens Hausdorf", + "email": "hello@jens-hausdorf.de", + "homepage": "https://jens-hausdorf.de" + }, + { + "name": "Pascal Baljet", + "email": "pascal@protone.media", + "homepage": "https://protone.media" + } + ], + "description": "FFMpeg PHP, an Object Oriented library to communicate with AVconv / ffmpeg", + "keywords": [ + "audio", + "audio processing", + "avconv", + "avprobe", + "ffmpeg", + "ffprobe", + "video", + "video processing" + ], + "support": { + "issues": "https://github.com/PHP-FFMpeg/PHP-FFMpeg/issues", + "source": "https://github.com/PHP-FFMpeg/PHP-FFMpeg/tree/v1.3.2" + }, + "time": "2025-04-01T20:36:46+00:00" + }, + { + "name": "psr/cache", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/cache.git", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for caching libraries", + "keywords": [ + "cache", + "psr", + "psr-6" + ], + "support": { + "source": "https://github.com/php-fig/cache/tree/3.0.0" + }, + "time": "2021-02-03T23:26:27+00:00" + }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/log", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.2" + }, + "time": "2024-09-11T13:17:53+00:00" + }, + { + "name": "spatie/temporary-directory", + "version": "2.3.0", + "source": { + "type": "git", + "url": "https://github.com/spatie/temporary-directory.git", + "reference": "580eddfe9a0a41a902cac6eeb8f066b42e65a32b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/temporary-directory/zipball/580eddfe9a0a41a902cac6eeb8f066b42e65a32b", + "reference": "580eddfe9a0a41a902cac6eeb8f066b42e65a32b", + "shasum": "" + }, + "require": { + "php": "^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\TemporaryDirectory\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Alex Vanderbist", + "email": "alex@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "Easily create, use and destroy temporary directories", + "homepage": "https://github.com/spatie/temporary-directory", + "keywords": [ + "php", + "spatie", + "temporary-directory" + ], + "support": { + "issues": "https://github.com/spatie/temporary-directory/issues", + "source": "https://github.com/spatie/temporary-directory/tree/2.3.0" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + }, + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2025-01-13T13:04:43+00:00" + }, + { + "name": "symfony/cache", + "version": "v7.3.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/cache.git", + "reference": "bf8afc8ffd4bfd3d9c373e417f041d9f1e5b863f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/cache/zipball/bf8afc8ffd4bfd3d9c373e417f041d9f1e5b863f", + "reference": "bf8afc8ffd4bfd3d9c373e417f041d9f1e5b863f", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/cache": "^2.0|^3.0", + "psr/log": "^1.1|^2|^3", + "symfony/cache-contracts": "^3.6", + "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/var-exporter": "^6.4|^7.0" + }, + "conflict": { + "doctrine/dbal": "<3.6", + "symfony/dependency-injection": "<6.4", + "symfony/http-kernel": "<6.4", + "symfony/var-dumper": "<6.4" + }, + "provide": { + "psr/cache-implementation": "2.0|3.0", + "psr/simple-cache-implementation": "1.0|2.0|3.0", + "symfony/cache-implementation": "1.1|2.0|3.0" + }, + "require-dev": { + "cache/integration-tests": "dev-master", + "doctrine/dbal": "^3.6|^4", + "predis/predis": "^1.1|^2.0", + "psr/simple-cache": "^1.0|^2.0|^3.0", + "symfony/clock": "^6.4|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/filesystem": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Cache\\": "" + }, + "classmap": [ + "Traits/ValueWrapper.php" + ], + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides extended PSR-6, PSR-16 (and tags) implementations", + "homepage": "https://symfony.com", + "keywords": [ + "caching", + "psr6" + ], + "support": { + "source": "https://github.com/symfony/cache/tree/v7.3.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-09-11T10:12:26+00:00" + }, + { + "name": "symfony/cache-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/cache-contracts.git", + "reference": "5d68a57d66910405e5c0b63d6f0af941e66fc868" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/5d68a57d66910405e5c0b63d6f0af941e66fc868", + "reference": "5d68a57d66910405e5c0b63d6f0af941e66fc868", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/cache": "^3.0" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Cache\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to caching", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/cache-contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-03-13T15:25:07+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "symfony/process", + "version": "v7.3.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "f24f8f316367b30810810d4eb30c543d7003ff3b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/f24f8f316367b30810810d4eb30c543d7003ff3b", + "reference": "f24f8f316367b30810810d4eb30c543d7003ff3b", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Executes commands in sub-processes", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v7.3.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-09-11T10:12:26+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-25T09:37:31+00:00" + }, + { + "name": "symfony/var-exporter", + "version": "v7.3.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-exporter.git", + "reference": "0f020b544a30a7fe8ba972e53ee48a74c0bc87f4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/0f020b544a30a7fe8ba972e53ee48a74c0bc87f4", + "reference": "0f020b544a30a7fe8ba972e53ee48a74c0bc87f4", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "require-dev": { + "symfony/property-access": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\VarExporter\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Allows exporting any serializable PHP data structure to plain PHP code", + "homepage": "https://symfony.com", + "keywords": [ + "clone", + "construct", + "export", + "hydrate", + "instantiate", + "lazy-loading", + "proxy", + "serialize" + ], + "support": { + "source": "https://github.com/symfony/var-exporter/tree/v7.3.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-09-11T10:12:26+00:00" + }, + { + "name": "thecodingmachine/safe", + "version": "v2.5.0", + "source": { + "type": "git", + "url": "https://github.com/thecodingmachine/safe.git", + "reference": "3115ecd6b4391662b4931daac4eba6b07a2ac1f0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thecodingmachine/safe/zipball/3115ecd6b4391662b4931daac4eba6b07a2ac1f0", + "reference": "3115ecd6b4391662b4931daac4eba6b07a2ac1f0", + "shasum": "" + }, + "require": { + "php": "^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.5", + "phpunit/phpunit": "^9.5", + "squizlabs/php_codesniffer": "^3.2", + "thecodingmachine/phpstan-strict-rules": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2.x-dev" + } + }, + "autoload": { + "files": [ + "deprecated/apc.php", + "deprecated/array.php", + "deprecated/datetime.php", + "deprecated/libevent.php", + "deprecated/misc.php", + "deprecated/password.php", + "deprecated/mssql.php", + "deprecated/stats.php", + "deprecated/strings.php", + "lib/special_cases.php", + "deprecated/mysqli.php", + "generated/apache.php", + "generated/apcu.php", + "generated/array.php", + "generated/bzip2.php", + "generated/calendar.php", + "generated/classobj.php", + "generated/com.php", + "generated/cubrid.php", + "generated/curl.php", + "generated/datetime.php", + "generated/dir.php", + "generated/eio.php", + "generated/errorfunc.php", + "generated/exec.php", + "generated/fileinfo.php", + "generated/filesystem.php", + "generated/filter.php", + "generated/fpm.php", + "generated/ftp.php", + "generated/funchand.php", + "generated/gettext.php", + "generated/gmp.php", + "generated/gnupg.php", + "generated/hash.php", + "generated/ibase.php", + "generated/ibmDb2.php", + "generated/iconv.php", + "generated/image.php", + "generated/imap.php", + "generated/info.php", + "generated/inotify.php", + "generated/json.php", + "generated/ldap.php", + "generated/libxml.php", + "generated/lzf.php", + "generated/mailparse.php", + "generated/mbstring.php", + "generated/misc.php", + "generated/mysql.php", + "generated/network.php", + "generated/oci8.php", + "generated/opcache.php", + "generated/openssl.php", + "generated/outcontrol.php", + "generated/pcntl.php", + "generated/pcre.php", + "generated/pgsql.php", + "generated/posix.php", + "generated/ps.php", + "generated/pspell.php", + "generated/readline.php", + "generated/rpminfo.php", + "generated/rrd.php", + "generated/sem.php", + "generated/session.php", + "generated/shmop.php", + "generated/sockets.php", + "generated/sodium.php", + "generated/solr.php", + "generated/spl.php", + "generated/sqlsrv.php", + "generated/ssdeep.php", + "generated/ssh2.php", + "generated/stream.php", + "generated/strings.php", + "generated/swoole.php", + "generated/uodbc.php", + "generated/uopz.php", + "generated/url.php", + "generated/var.php", + "generated/xdiff.php", + "generated/xml.php", + "generated/xmlrpc.php", + "generated/yaml.php", + "generated/yaz.php", + "generated/zip.php", + "generated/zlib.php" + ], + "classmap": [ + "lib/DateTime.php", + "lib/DateTimeImmutable.php", + "lib/Exceptions/", + "deprecated/Exceptions/", + "generated/Exceptions/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHP core functions that throw exceptions instead of returning FALSE on error", + "support": { + "issues": "https://github.com/thecodingmachine/safe/issues", + "source": "https://github.com/thecodingmachine/safe/tree/v2.5.0" + }, + "time": "2023-04-05T11:54:14+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [], + "plugin-api-version": "2.3.0" +} diff --git a/package-lock.json b/package-lock.json index 75ad124f..6cb7de84 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,8 @@ "version": "0.0.1", "license": "GPL-3.0-only", "dependencies": { - "@biigle/ol": "^9.2.4" + "@biigle/ol": "^9.2.4", + "vuedraggable": "^4.1.0" }, "devDependencies": { "@vitejs/plugin-vue": "^5.2.1", @@ -36,7 +37,6 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", - "dev": true, "license": "MIT", "peer": true, "engines": { @@ -47,7 +47,6 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -151,7 +150,6 @@ "version": "7.27.0", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", - "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -168,7 +166,6 @@ "version": "7.27.0", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", - "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -667,7 +664,6 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true, "license": "MIT", "peer": true }, @@ -1330,7 +1326,6 @@ "version": "3.5.13", "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.13.tgz", "integrity": "sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==", - "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -1345,7 +1340,6 @@ "version": "3.5.13", "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz", "integrity": "sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==", - "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -1357,7 +1351,6 @@ "version": "3.5.13", "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.13.tgz", "integrity": "sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==", - "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -1376,7 +1369,6 @@ "version": "3.5.13", "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.13.tgz", "integrity": "sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==", - "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -1388,7 +1380,6 @@ "version": "3.5.13", "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.13.tgz", "integrity": "sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==", - "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -1399,7 +1390,6 @@ "version": "3.5.13", "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.13.tgz", "integrity": "sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==", - "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -1411,7 +1401,6 @@ "version": "3.5.13", "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.13.tgz", "integrity": "sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==", - "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -1425,7 +1414,6 @@ "version": "3.5.13", "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.13.tgz", "integrity": "sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==", - "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -1440,7 +1428,6 @@ "version": "3.5.13", "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.13.tgz", "integrity": "sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==", - "dev": true, "license": "MIT", "peer": true }, @@ -1575,9 +1562,9 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -1721,7 +1708,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true, "license": "MIT", "peer": true }, @@ -1808,7 +1794,6 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, "license": "BSD-2-Clause", "peer": true, "engines": { @@ -2109,7 +2094,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true, "license": "MIT", "peer": true }, @@ -2643,7 +2627,6 @@ "version": "0.30.17", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", - "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -2698,7 +2681,6 @@ "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, "funding": [ { "type": "github", @@ -2841,7 +2823,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, "license": "ISC" }, "node_modules/picomatch": { @@ -2861,7 +2842,6 @@ "version": "8.5.3", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", - "dev": true, "funding": [ { "type": "opencollective", @@ -3193,11 +3173,15 @@ "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, + "node_modules/sortablejs": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.14.0.tgz", + "integrity": "sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w==" + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -3606,7 +3590,6 @@ "version": "3.5.13", "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.13.tgz", "integrity": "sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==", - "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -3685,6 +3668,17 @@ "semver": "bin/semver.js" } }, + "node_modules/vuedraggable": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/vuedraggable/-/vuedraggable-4.1.0.tgz", + "integrity": "sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==", + "dependencies": { + "sortablejs": "1.14.0" + }, + "peerDependencies": { + "vue": "^3.0.1" + } + }, "node_modules/web-worker": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.5.0.tgz", diff --git a/package.json b/package.json index b96a3ed1..eddcc102 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,8 @@ "vite-plugin-static-copy": "^2.3.2" }, "dependencies": { - "@biigle/ol": "^9.2.4" + "@biigle/ol": "^9.2.4", + "vuedraggable": "^4.1.0" }, "type": "module" } diff --git a/src/Console/Commands/Config.php b/src/Console/Commands/Config.php new file mode 100644 index 00000000..68daec0b --- /dev/null +++ b/src/Console/Commands/Config.php @@ -0,0 +1,37 @@ +call('vendor:publish', [ + '--provider' => ServiceProvider::class, + '--tag' => ['config'], + '--force' => true, + ]); + } +} diff --git a/src/Database/factories/GeoOverlayFactory.php b/src/Database/factories/GeoOverlayFactory.php new file mode 100644 index 00000000..b783daee --- /dev/null +++ b/src/Database/factories/GeoOverlayFactory.php @@ -0,0 +1,49 @@ + $this->faker->company(), + 'volume_id' => Volume::factory(), + 'type' => 'geotiff', + 'browsing_layer' => false, + 'layer_index' => null, + 'attrs' => [ + 'top_left_lng' => $this->faker->randomFloat(), + 'top_left_lat' => $this->faker->randomFloat(), + 'bottom_right_lng' => $this->faker->randomFloat(), + 'bottom_right_lat' => $this->faker->randomFloat(), + 'width' => $this->faker->randomNumber(), + 'height' => $this->faker->randomNumber() + ] + ]; + } + + public function webMap() + { + return $this->state(function (array $attributes) { + return [ + 'type' => 'webmap', + 'attrs' => [ + 'layer' => $this->faker->word(), + 'url' => $this->faker->url() + ] + ]; + }); + } +} diff --git a/src/Database/migrations/2017_04_27_123209_create_geo_overlays_table.php b/src/Database/migrations/2017_04_27_123209_create_geo_overlays_table.php index 7e4d932e..ca631175 100644 --- a/src/Database/migrations/2017_04_27_123209_create_geo_overlays_table.php +++ b/src/Database/migrations/2017_04_27_123209_create_geo_overlays_table.php @@ -35,9 +35,9 @@ public function up() $table->integer('volume_id')->unsigned()->index(); $table->foreign('volume_id') - ->references('id') - ->on('volumes') - ->onDelete('cascade'); + ->references('id') + ->on('volumes') + ->onDelete('cascade'); }); } diff --git a/src/Database/migrations/2020_12_14_130300_remove_geo_overlays_table.php b/src/Database/migrations/2020_12_14_130300_remove_geo_overlays_table.php index ba0656e2..30c5edc6 100644 --- a/src/Database/migrations/2020_12_14_130300_remove_geo_overlays_table.php +++ b/src/Database/migrations/2020_12_14_130300_remove_geo_overlays_table.php @@ -48,9 +48,9 @@ public function down() $table->integer('volume_id')->unsigned()->index(); $table->foreign('volume_id') - ->references('id') - ->on('volumes') - ->onDelete('cascade'); + ->references('id') + ->on('volumes') + ->onDelete('cascade'); }); } } diff --git a/src/Database/migrations/2024_07_30_155058_add_geo_overlays_table.php b/src/Database/migrations/2024_07_30_155058_add_geo_overlays_table.php new file mode 100644 index 00000000..48a688c6 --- /dev/null +++ b/src/Database/migrations/2024_07_30_155058_add_geo_overlays_table.php @@ -0,0 +1,56 @@ +increments('id'); + // A short description of the overlay. + $table->string('name', 512); + $table->integer('volume_id')->unsigned()->index(); + $table->foreign('volume_id') + ->references('id') + ->on('volumes') + ->onDelete('cascade'); + $table->string('type', 10)->nullable(); + $table->boolean('browsing_layer')->default(0); + $table->boolean('context_layer')->default(0); + // the position of the overlay (can be set by the user) in case of mutliple uploaded overlays in the same volume + $table->integer('layer_index')->nullable(); + // follwoing attributes are possible in attrs-column: + // if(type == 'geotiff'): 'top_left_lat', 'top_left_lng', 'bottom_right_lat', 'bottom_right_lng', 'width', 'height' + // if(type == 'webmap'): 'url', 'layers' + $table->json('attrs')->default('{}'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::drop('geo_overlays'); + } +} diff --git a/src/Database/migrations/2025_12_04_085344_edit_geo_overlays.php b/src/Database/migrations/2025_12_04_085344_edit_geo_overlays.php new file mode 100644 index 00000000..d86c2649 --- /dev/null +++ b/src/Database/migrations/2025_12_04_085344_edit_geo_overlays.php @@ -0,0 +1,29 @@ +dropColumn('context_layer'); + $table->boolean('browsing_layer')->default(1)->change(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('geo_overlays', function (Blueprint $table) { + $table->boolean('context_layer')->default(0); + $table->boolean('browsing_layer')->default(0)->change(); + }); + } +}; diff --git a/src/Database/migrations/2025_12_19_083937_extend_geo_overlays.php b/src/Database/migrations/2025_12_19_083937_extend_geo_overlays.php new file mode 100644 index 00000000..d985edf6 --- /dev/null +++ b/src/Database/migrations/2025_12_19_083937_extend_geo_overlays.php @@ -0,0 +1,27 @@ +boolean('processed')->default(0); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('geo_overlays', function (Blueprint $table) { + $table->dropColumn('processed'); + }); + } +}; diff --git a/src/Database/migrations/2026_02_19_080850_make_name_unique.php b/src/Database/migrations/2026_02_19_080850_make_name_unique.php new file mode 100644 index 00000000..1cb1c228 --- /dev/null +++ b/src/Database/migrations/2026_02_19_080850_make_name_unique.php @@ -0,0 +1,28 @@ +unique('name'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('geo_overlays', function (Blueprint $table) { + $table->dropUnique('name'); + }); + } +}; diff --git a/src/Events/GeoTiffUploadFailed.php b/src/Events/GeoTiffUploadFailed.php new file mode 100644 index 00000000..a6afbce4 --- /dev/null +++ b/src/Events/GeoTiffUploadFailed.php @@ -0,0 +1,65 @@ +user = $user; + $this->message = $message; + } + + /** + * Get the channels the event should broadcast on. + * + * @return \Illuminate\Broadcasting\Channel|array + */ + public function broadcastOn() + { + return new UserChannel($this->user); + } + + /** + * Get the data to broadcast. + * + * @return array + */ + public function broadcastWith() + { + return [ + 'error' => $this->message + ]; + } +} diff --git a/src/Events/GeoTiffUploadSucceeded.php b/src/Events/GeoTiffUploadSucceeded.php new file mode 100644 index 00000000..68543de5 --- /dev/null +++ b/src/Events/GeoTiffUploadSucceeded.php @@ -0,0 +1,71 @@ +overlay = $overlay; + $this->user = $user; + } + + /** + * Get the channels the event should broadcast on. + * + * @return \Illuminate\Broadcasting\Channel|array + */ + public function broadcastOn() + { + return new UserChannel($this->user); + } + + /** + * Get the data to broadcast. + * + * @return array + */ + public function broadcastWith() + { + $this->overlay->processed = true; + $this->overlay->save(); + + return [ + 'overlay' => $this->overlay, + ]; + } +} diff --git a/src/Exceptions/ConvertModelSpaceException.php b/src/Exceptions/ConvertModelSpaceException.php new file mode 100644 index 00000000..0077804d --- /dev/null +++ b/src/Exceptions/ConvertModelSpaceException.php @@ -0,0 +1,12 @@ +key = $key; + } + + public function getMessageArray() + { + return [$this->key => $this->message]; + } +} diff --git a/src/GeoOverlay.php b/src/GeoOverlay.php new file mode 100644 index 00000000..908e6212 --- /dev/null +++ b/src/GeoOverlay.php @@ -0,0 +1,207 @@ +url', + 'attrs->layers', + 'attrs->top_left_lng', + 'attrs->top_left_lat', + 'attrs->bottom_right_lng', + 'attrs->bottom_right_lat' + ]; + + /** + * The attributes that should be casted to native types. + * + * @var array + */ + protected $casts = [ + 'attrs' => 'array', + ]; + + /** + * The volume, this overlay belongs to. + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ + public function volume() + { + return $this->belongsTo(Volume::class); + } + + /** + * Get the local path to the overlay image file. + * + * @return string + */ + public function getPathAttribute() + { + return "{$this->id}/{$this->id}_original.tif"; + } + + /** + * Store the uploaded image file of the geo overlay. + * + * @param UploadedFile $file + */ + public function storeFile(UploadedFile $file) + { + Storage::disk(config('geo.tiles.overlay_storage_disk')) + ->putFileAs($this->id, $file, "{$this->id}_original.tif"); + } + + /** + * Delete the uploaded image file of the geo overlay. + * + */ + public function deleteFile() + { + $exists = Storage::disk(config('geo.tiles.overlay_storage_disk')) + ->exists($this->id); + + if ($exists) { + Storage::disk(config('geo.tiles.overlay_storage_disk')) + ->deleteDirectory($this->id); + } + } + + /** + * Returns model's factory + * + * @return GeoOverlayFactory + */ + protected static function newFactory() + { + return GeoOverlayFactory::new(); + } + + /** + * Builds object by using the given data and saves it. + * + * @param mixed $id Id of the used volume + * @param mixed $name File name + * @param string $type GeoOverlay type (geotiff or webmap) + * @param int $layerIdx Layer index of overlay + * @param mixed $attrs Array containing the corresponding attributes + * @return GeoOverlay + */ + public static function build($id, $name, $type, $layerIdx, $attrs) + { + $overlay = new static; + $overlay->volume_id = $id; + $overlay->type = $type; + $overlay->name = $name; + $overlay->layer_index = $layerIdx; + $overlay->attrs = []; + $round = fn($c) => round($c, 13); + $coords = array_map($round, $attrs[0]); + + if ($type === 'geotiff') { + $overlay = self::createGeoTiff($overlay, $coords, $attrs); + } else { + $overlay = self::createWebMap($overlay, $coords, $attrs); + } + + $overlay->save(); + return $overlay; + } + + /** + * Add geoTiff data to overlay + * + * @param GeoOverlay $overlay to be used + * @param array $coords extent coodrinates + * @param array $attrs geotiff attributes + * + * @return GeoOverlay + */ + protected static function createGeoTiff($overlay, $coords, $attrs) + { + $overlay = self::setExtent($overlay, $coords); + [$w, $h] = $attrs[1]; + $overlay->attrs = array_merge($overlay->attrs, [ + "width" => $w, + "height" => $h + ]); + return $overlay; + } + + /** + * Add webMap data to overlay + * + * @param GeoOverlay $overlay to be used + * @param array $coords extent coodrinates + * @param array $attrs geotiff attributes + * + * @return GeoOverlay + */ + protected static function createWebMap($overlay, $coords, $attrs) + { + // ignore coords if webmap server does not provide supported epsg codes + if (count($coords) > 0) { + $overlay = self::setExtent($overlay, $coords); + } + + $url = $attrs[1]; + $layer = $attrs[2]; + + $overlay->attrs = array_merge($overlay->attrs, [ + 'url' => $url, + 'layer' => $layer, + ]); + // set to true since overlay will not be tiled + $overlay->processed = true; + return $overlay; + } + + /** + * Set extent coordinates + * + * @param GeoOverlay $overlay to be used + * @param array $coords + * + * @return GeoOverlay + */ + protected static function setExtent($overlay, $coords) + { + $overlay->attrs = [ + "top_left_lng" => $coords[0], + "top_left_lat" => $coords[1], + "bottom_right_lng" => $coords[2], + "bottom_right_lat" => $coords[3], + ]; + return $overlay; + } +} diff --git a/src/GeoServiceProvider.php b/src/GeoServiceProvider.php index d6996896..775bc6ce 100644 --- a/src/GeoServiceProvider.php +++ b/src/GeoServiceProvider.php @@ -4,6 +4,7 @@ use Biigle\Services\Modules; use Illuminate\Routing\Router; +use Biigle\Modules\Geo\GeoOverlay; use Illuminate\Support\ServiceProvider; class GeoServiceProvider extends ServiceProvider @@ -18,34 +19,41 @@ class GeoServiceProvider extends ServiceProvider */ public function boot(Modules $modules, Router $router) { - $this->loadViewsFrom(__DIR__.'/resources/views', 'geo'); - $this->loadMigrationsFrom(__DIR__.'/Database/migrations'); + $this->loadViewsFrom(__DIR__ . '/resources/views', 'geo'); + $this->loadMigrationsFrom(__DIR__ . '/Database/migrations'); $this->publishes([ - __DIR__.'/public' => public_path('vendor/geo'), + __DIR__ . '/public' => public_path('vendor/geo'), ], 'public'); $this->publishes([ - __DIR__.'/config/geo.php' => config_path('geo.php'), + __DIR__ . '/config/geo.php' => config_path('geo.php'), ], 'config'); $router->group([ 'namespace' => 'Biigle\Modules\Geo\Http\Controllers', 'middleware' => 'web', ], function ($router) { - require __DIR__.'/routes.php'; + require __DIR__ . '/routes.php'; }); + \Biigle\Volume::observe(new Observers\VolumeObserver); + GeoOverlay::observe(new Observers\GeoOverlayObserver); + $modules->register('geo', [ 'viewMixins' => [ 'imagesIndex', 'manualTutorial', + 'manualVolumes', 'volumesSidebar', 'volumesScripts', 'projectsShowTabs', - 'volumesStyles' + 'volumesStyles', + 'volumesEditRight', + 'volumesEditScripts', + 'volumesEditStyles' ], - 'apidoc' => [__DIR__.'/Http/Controllers/Api/'], + 'apidoc' => [__DIR__ . '/Http/Controllers/Api/'], ]); } @@ -56,10 +64,18 @@ public function boot(Modules $modules, Router $router) */ public function register() { + $this->mergeConfigFrom(__DIR__ . '/config/geo.php', 'geo'); + $this->app->singleton('command.geo.publish', function ($app) { return new \Biigle\Modules\Geo\Console\Commands\Publish(); }); $this->commands('command.geo.publish'); + + + $this->app->singleton('command.geo.config', function ($app) { + return new \Biigle\Modules\Geo\Console\Commands\Config(); + }); + $this->commands('command.geo.config'); } /** @@ -71,6 +87,7 @@ public function provides() { return [ 'command.geo.publish', + 'command.geo.config', ]; } } diff --git a/src/Http/Controllers/Api/GeoOverlayController.php b/src/Http/Controllers/Api/GeoOverlayController.php new file mode 100644 index 00000000..beab573a --- /dev/null +++ b/src/Http/Controllers/Api/GeoOverlayController.php @@ -0,0 +1,93 @@ + 0, + * 'name' => 'overlay_name', + * 'volume_id' => 1, + * 'layer_index' => 4 + * ] + * ] + * + */ + public function updateGeoOverlays(UpdateOverlay $request) + { + $updated_overlays = $request->input('updated_overlays'); + GeoOverlay::upsert($updated_overlays, ['id'], [$request->updateKey]); + } + + /** + * Returns overlay data + * + * @param int $id Volume id + * + * @return Response + */ + public function getOverlays(int $id) + { + $volume = Volume::findOrFail($id); + $this->authorize('access', $volume); + + if ($volume->isVideoVolume()) { + abort(Response::HTTP_NOT_FOUND); + } + + $overlays = GeoOverlay::where('volume_id', $volume->id) + ->where('processed', true) + ->orderBy('layer_index', 'desc') + ->get(); + + $urlTemplate = Storage::disk(config('geo.tiles.overlay_storage_disk'))->url(':id/:id_tiles/'); + // Use the full template, since openalayer's default file extension is JPG + $urlTemplate .= "{TileGroup}/{z}-{x}-{y}.png"; + + return response([ + 'geoOverlays' => $overlays, + 'urlTemplate' => $urlTemplate + ]); + } + + /** + * Deletes the geo overlay. + * + * @api {delete} geo-overlays/:id Delete a geo overlay + * @apiGroup Geo + * @apiName DestroyGeoOverlay + * @apiPermission projectAdmin + * + * @apiParam {Number} id The geo overlay ID. + * + * @param int $id geo overlay id + */ + public function destroy($id) + { + $overlay = GeoOverlay::findOrFail($id); + $this->authorize('update', $overlay->volume); + + $overlay->delete(); + } +} diff --git a/src/Http/Controllers/Api/GeoTiffOverlayController.php b/src/Http/Controllers/Api/GeoTiffOverlayController.php new file mode 100644 index 00000000..0a1fe82e --- /dev/null +++ b/src/Http/Controllers/Api/GeoTiffOverlayController.php @@ -0,0 +1,84 @@ + 1 + * "name" => "standardEPSG2013.tif" + * "type" => "geotiff" + * "browsing_layer" => true + * "layer_index" => 1 + * "attrs" => [ + * "top_left_lng" => -2.9213164328107 + * "top_left_lat" => 57.096651484989 + * "bottom_right_lng" => -2.9185182540292 + * "bottom_right_lat" => 57.097626526122 + * "width" => 3 + * "height" => 2 + * ] + * } + * + * @param StoreGeotiffOverlay $request + * + * @return GeoOverlay + */ + public function storeGeoTiff(StoreGeotiffOverlay $request) + { + $file = $request->file('geotiff'); + $fileName = $file->getClientOriginalName(); + // create GeoManager-class from uploadedFile + $geotiff = $request->geotiff; + $volumeId = $request->volume->id; + $layerIdx = $request->input('layer_index'); + + $pixelDimensions = $geotiff->getPixelSize(); + $epsg = $geotiff->getEpsgCode(); + + try { + $coords = $geotiff->getCoords(); + $overlay = GeoOverlay::build($volumeId, $fileName, 'geotiff', $layerIdx, [$coords, $pixelDimensions]); + $overlay->storeFile($file); + TileSingleOverlay::dispatch($overlay, $request->user(), $geotiff->exif); + return $overlay->fresh(); + + } catch (ConvertModelSpaceException | TransformCoordsException | Exception $e) { + $msg = []; + if ($e instanceof ConvertModelSpaceException) { + $msg = ['affineTransformation' => $e->getMessage()]; + } else if ($e instanceof TransformCoordsException) { + $msg = [ + 'failedTransformation' => + "Could not transform CRS. Please convert EPSG:$epsg to EPSG:4326 (WGS84) before uploading." + ]; + } else { + $msg = ['failedUpload' => "The file \"$fileName\" could not be uploaded. Please try again."]; + } + throw ValidationException::withMessages($msg); + } + } +} diff --git a/src/Http/Controllers/Api/ProjectImageAnnotationLabelController.php b/src/Http/Controllers/Api/ProjectImageAnnotationLabelController.php index 24e6128c..8a4a3d83 100644 --- a/src/Http/Controllers/Api/ProjectImageAnnotationLabelController.php +++ b/src/Http/Controllers/Api/ProjectImageAnnotationLabelController.php @@ -36,14 +36,14 @@ public function index($pid, $lid) $this->authorize('access', $project); return ImageAnnotation::join('image_annotation_labels', 'image_annotations.id', '=', 'image_annotation_labels.annotation_id') - ->join('images', 'image_annotations.image_id', '=', 'images.id') - ->where('image_annotation_labels.label_id', $lid) - ->whereIn('images.volume_id', function ($query) use ($pid) { - return $query->select('volume_id') - ->from('project_volume') - ->where('project_id', $pid); - }) - ->groupBy('images.id') - ->pluck('images.id'); + ->join('images', 'image_annotations.image_id', '=', 'images.id') + ->where('image_annotation_labels.label_id', $lid) + ->whereIn('images.volume_id', function ($query) use ($pid) { + return $query->select('volume_id') + ->from('project_volume') + ->where('project_id', $pid); + }) + ->groupBy('images.id') + ->pluck('images.id'); } } diff --git a/src/Http/Controllers/Api/WebMapOverlayController.php b/src/Http/Controllers/Api/WebMapOverlayController.php new file mode 100644 index 00000000..464613b5 --- /dev/null +++ b/src/Http/Controllers/Api/WebMapOverlayController.php @@ -0,0 +1,57 @@ + 1 + * "name" => "Title_0" + * "type" => "webmap" + * "browsing_layer" => true + * "layer_index" => 1 + * "attrs" => { + * "top_left_lng" => "-2.9198048485707", + * "top_left_lat" => "57.0974838573358", + * "bottom_right_lng" => "-2.9170062535908", + * "bottom_right_lat" => "57.0984589659731", + * "url" => https://example.com, + * "layer" => "Layer_1" + * } + * } + * + * @param StoreWebMapOverlay $request + * @return GeoOverlay + */ + public function store(StoreWebMapOverlay $request) + { + $volumeId = $request->volume->id; + $layerIdx = $request->input('layer_index'); + $webmapSource = $request->webmapSource; + + [$layerTitle, $layerName] = $webmapSource->getLayer(); + $coords = $webmapSource->getCoords($layerName); + + $overlay = GeoOverlay::build($volumeId, $layerName, 'webmap', $layerIdx, [$coords, $webmapSource->baseUrl, $layerTitle]); + return $overlay->fresh(); + } +} diff --git a/src/Http/Requests/StoreGeotiffOverlay.php b/src/Http/Requests/StoreGeotiffOverlay.php new file mode 100644 index 00000000..32713123 --- /dev/null +++ b/src/Http/Requests/StoreGeotiffOverlay.php @@ -0,0 +1,123 @@ +geotiff = $geotiff; + } + + /** + * Determine if the user is authorized to make this request. + * + * @return bool + */ + public function authorize() + { + $this->volume = Volume::findOrFail($this->route('id')); + + return $this->user()->can('update', $this->volume); + } + + /** + * Get the validation rules that apply to the request. + * make sure th file is in tiff format and not bigger than 50GB (52.430.000 kilobytes) + * + * @return array + */ + public function rules() + { + $overlayCount = GeoOverlay::where('volume_id', $this->volume->id)->count(); + return [ + 'geotiff' => 'required|file|mimetypes:image/tiff', + 'layer_index' => "required|integer|between:0,$overlayCount", + ]; + } + + /** + * Configure the validator instance. + * + * @param \Illuminate\Validation\Validator $validator + * @return void + */ + public function withValidator($validator) + { + if ($validator->errors()->isNotEmpty()) { + return; + } + + $validator->after(function ($validator) { + + if ($this->volume->isVideoVolume()) { + throw ValidationException::withMessages(["id" => "Geo overlays are not available for video volumes."]); + } + + $file = $this->file('geotiff'); + $fileName = $file->getClientOriginalName(); + $fileNameShort = Str::limit($fileName, 25); + + if ($file->getSize() === 0) { + throw ValidationException::withMessages(["size" => "The geoTIFF \"{$fileNameShort}\" is empty."]); + } + + $overlayExists = GeoOverlay::where('volume_id', $this->volume->id) + ->where('type', 'geotiff') + ->where('name', $fileName) + ->exists(); + + if ($overlayExists) { + throw ValidationException::withMessages(["fileExists" => "The geoTIFF \"{$fileNameShort}\" has already been uploaded."]); + } + + $this->geotiff->useFile($file); + + $colorCount = $this->geotiff->getKey('IFD0:SamplesPerPixel'); + if (!is_null($colorCount) && $colorCount > 4) { + $validator->errors()->add('invalidColorSpace', "Invalid color space. The image can have at most 4 color channels, but $colorCount channels are given."); + } + + $modelType = $this->geotiff->getCoordSystemType(); + $epsg = $this->geotiff->getEpsgCode(); + + if (is_null($modelType)) { + throw ValidationException::withMessages(["MissingModelType" => "The geoTIFF file does not have the required GTModelTypeTag."]); + } + + if ($modelType != 'projected' && $epsg != 4326) { + $validator->errors()->add('wrongModelType', "The coordinate reference system (CRS) of type '{$modelType}' is not supported. Please use a 'projected' CRS or EPSG:4326 instead."); + } + + if (is_null($epsg)) { + $validator->errors()->add('noPCSKEY', "Did not detect the 'ProjectedCSType' or 'GeographicType' geokey in the geoTIFF metadata."); + } elseif ($epsg === 0) { + $validator->errors()->add('unDefined', "The coordinate reference system (CRS) is undefined. Please use a 'projected' CRS or EPSG:4326 instead."); + } elseif ($epsg === 32767) { + $validator->errors()->add('userDefined', "User-defined coordinate reference systems (CRS) are not supported. Please use a 'projected' CRS or EPSG:4326 instead."); + } + }); + } + +} diff --git a/src/Http/Requests/StoreWebMapOverlay.php b/src/Http/Requests/StoreWebMapOverlay.php new file mode 100644 index 00000000..040794b5 --- /dev/null +++ b/src/Http/Requests/StoreWebMapOverlay.php @@ -0,0 +1,107 @@ +webmapSource = $webmapSource; + } + + /** + * Determine if the user is authorized to make this request. + */ + public function authorize(): bool + { + $this->volume = Volume::findOrFail($this->route('id')); + + return $this->user()->can('update', $this->volume); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array|string> + */ + public function rules(): array + { + $overlayCount = GeoOverlay::where('volume_id', $this->volume->id)->count(); + return [ + 'url' => 'required|url:http,https|max:512', + 'layer_index' => "required|integer|between:0,$overlayCount", + ]; + } + + public function withValidator($validator) + { + if ($validator->errors()->isNotEmpty()) { + return; + } + + $validator->after(function ($validator) { + $url = $this->input('url'); + $host = parse_url($url)['host']; + // Remove brackets from urls with ip6 adresses + $host = trim($host, '[]'); + + if ($host === 'localhost' || filter_var($host, FILTER_VALIDATE_IP)) { + throw ValidationException::withMessages(['url' => "URL must not contain 'localhost' or any IP adress."]); + } + + try { + $this->webmapSource->useUrl($url); + } catch (WebMapSourceException | Exception $e) { + $msg = []; + + if ($e instanceof WebMapSourceException) { + $msg = $e->getMessageArray(); + } + + throw ValidationException::withMessages($msg); + } + + $overlay = GeoOverlay::where('volume_id', $this->volume->id) + ->where('type', 'webmap') + ->where('name', $this->webmapSource->getLayer()[1]); + + if ($overlay->exists()) { + $name = Str::limit($overlay->first()->name, 40); + $validator->errors()->add( + 'duplicate', + "The resource \"{$name}\" has already been uploaded.", + ); + } + }); + } +} diff --git a/src/Http/Requests/UpdateOverlay.php b/src/Http/Requests/UpdateOverlay.php new file mode 100644 index 00000000..26d2bc3a --- /dev/null +++ b/src/Http/Requests/UpdateOverlay.php @@ -0,0 +1,96 @@ +volume = Volume::findOrFail($this->route('id')); + + return $this->user()->can('update', $this->volume); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array|string> + */ + public function rules(): array + { + $overlayCount = GeoOverlay::where('volume_id', $this->volume->id)->count(); + $overlayCount = $overlayCount === 0 ? 0 : $overlayCount - 1; + return [ + 'updated_overlays' => "required|array", + 'updated_overlays.*.id' => "required|integer|gte:0", + 'updated_overlays.*.volume_id' => "required|integer|gte:0", + 'updated_overlays.*.name' => "required|string|max:512", + 'updated_overlays.*.layer_index' => "filled|integer|between:0,$overlayCount", + 'updated_overlays.*.browsing_layer' => "filled|boolean", + ]; + } + + public function withValidator($validator) + { + if ($validator->errors()->isNotEmpty()) { + return; + } + + $validator->after(function ($validator) { + $this->updateKey = isset($this->input('updated_overlays')[0]['layer_index']) ? 'layer_index' : 'browsing_layer'; + foreach ($this->input('updated_overlays') as $overlay) { + $hasBothKeys = isset($overlay['layer_index']) && isset($overlay['browsing_layer']); + $hasNoKeys = !(isset($overlay['layer_index']) || isset($overlay['browsing_layer'])); + if ($hasBothKeys || $hasNoKeys) { + $validator->errors()->add('invalidUpdateKey', 'Either layer_index or browsing_layer must be filled.'); + break; + } + + if (!isset($overlay[$this->updateKey])) { + $validator->errors()->add('invalidRequest', "Request must not contain browsing_layer and layer_index."); + break; + } + } + + $ids = array_map(fn($e) => $e['id'], $this->input('updated_overlays')); + $overlays = GeoOverlay::whereIn('id', $ids); + + // Check if overlay belongs to volume + $overlayVolIds = $overlays->pluck('volume_id')->unique(); + if ($overlayVolIds->count() > 1 || $overlayVolIds->first() != $this->volume->id) { + $volId = $this->volume->id; + $validator->errors()->add('invalidIds', "GeoOverlay(s) do not belong to volume with id $volId"); + } + + // Check if overlays exist + if (count($ids) != $overlays->count()) { + $invalidIds = collect($ids)->reject(fn($id) => $overlays->pluck('id')->contains($id)); + $invalidIds = $invalidIds->sort()->join(", "); + $validator->errors()->add('invalidIds', "GeoOverlay(s) with ids \"$invalidIds\" do not exist."); + } + }); + } +} diff --git a/src/Jobs/TileSingleOverlay.php b/src/Jobs/TileSingleOverlay.php new file mode 100644 index 00000000..e09c369b --- /dev/null +++ b/src/Jobs/TileSingleOverlay.php @@ -0,0 +1,272 @@ +id}/{$overlay->id}_tiles"); + $this->overlay = $overlay; + $this->tempPath = config('geo.tiles.tmp_dir') . "/{$overlay->id}"; + $this->exif = $exif; + $this->user = $user; + } + + /** + * Execute the job. + * + * @return void + */ + public function handle() + { + try { + $this->genericFile = new GenericFile("{$this->storage}://{$this->overlay->path}"); + FileCache::getOnce($this->genericFile, [$this, 'generateTiles']); + $this->uploadToStorage(); + $this->overlay->save(); + GeoTiffUploadSucceeded::dispatch($this->overlay, $this->user); + } finally { + File::deleteDirectory($this->tempPath); + } + } + + /** + * Generate tiles for the object and put them to temporary storage. + * + * @param File $file + * @param string $path Path to the cached image file. + */ + public function generateTiles($file, $path) + { + $this->vipsImage = $this->getVipsImage($path); + $this->validateImage(); + + $min = $this->vipsImage->min(); + $noDataValue = $this->exif['IFD0:GDALNoData'] ?? null; + + // Check if the minimum is the real minimum and not the noDataValue + if ($noDataValue !== null) { + $minIsNoDataValue = $noDataValue == $min || $min != 0 && $noDataValue / $min >= 0.999; + // If image's minimum equals the no data value, + // return the minimum because otherwise comparisons with the no data value would not work + $noDataValue = $minIsNoDataValue ? $min : $noDataValue; + $min = $this->getNextMin($min, $noDataValue, $minIsNoDataValue); + } + + $max = $this->vipsImage->max(); + $isBlackImg = $min == 0 && $max == 0; + + if (!$isBlackImg && $this->vipsImage->bands === 1) { + // Must be called before imageNormalization since pixel values could be changed + $alpha = $this->maybeGenerateAlphaMask($noDataValue); + + // If a smaller or larger range is used, normalize the pixel range to the enhance contrast + $this->vipsImage = $this->imageNormalization($min, $max); + + $this->vipsImage = $this->maybeAddAlpha($alpha); + + if ($this->vipsImage->format != 'uchar') { + $this->vipsImage = $this->vipsImage->cast('uchar'); + } + } + + // Add bit depth to prevent segmentation faults when processing float images + $this->vipsImage->dzsave($this->tempPath, [ + 'layout' => 'zoomify', + 'container' => 'fs', + 'strip' => true, + 'suffix' => '.png[bitdepth=8]', + ]); + } + + /** + * Check whether image color channel count is valid. + * If more than 4 channels are given, fail this job and dispatch a fail event. + * + * @return void + */ + protected function validateImage() + { + // Fail job if image doesn't use BW, Grayscale or RGB(A) color space + if ($this->vipsImage->bands > 4) { + $file = $this->overlay->name; + $ccount = $this->vipsImage->bands; + $msg = "Upload of '$file' failed. Image can have at most 4 color channels, but $ccount channels are given."; + $this->failAndNotify($msg); + } + } + + /** + * + * Get the image's minimum by ignoring the no data values if they are present + * + * @return float + */ + protected function getNextMin($min, $noDataValue, $minIsNoDataValue) + { + if (!$minIsNoDataValue && $noDataValue >= $min) { + return $min; + } + + // Exclude no data values since they do not represent the minimum + return $this->vipsImage + ->more($noDataValue) + ->ifthenelse($this->vipsImage, 9999, ['blend' => false]) + ->min(); + } + + /** + * Generates an alpha mask for images containing the no data value. + * Otherwise, return null. + * + * @return VipsImage|null + */ + protected function maybeGenerateAlphaMask($noDataValue) + { + if ($noDataValue === null) { + return; + } + + $mask = $this->vipsImage->notEq($noDataValue); + $containsNoDataValue = $mask->min() == 0; + // Create alpha mask if image contains noData values + return $containsNoDataValue ? $mask : null; + } + + /** + * Adds the alpha mask to an image if the image contains no data values + * + * @param mixed $alpha + * + * @return VipsImage + */ + protected function maybeAddAlpha($alpha) + { + if ($alpha === null) { + return $this->vipsImage; + } + + // alpha mask is a 'uchar' matrix which must have the same format as the image + $alpha = $alpha->cast($this->vipsImage->format); + // Set transparency to 0 if pixel is a no data value + return $this->vipsImage->bandjoin($alpha); + } + + /** + * Get the vips image instance. + * + * @param string $path + * + * @return \Jcupitt\Vips\Image + */ + protected function getVipsImage($path) + { + return VipsImage::newFromFile($path); + } + + /** + * Normalize the image band to 0 to 255 to enhance contrast + * since some images use only a very small pixel range. + * + * @param float $min minimum value of color-level of the input image + * @param float $max maximum value of color-level of the input image + * + * @return \Jcupitt\Vips\Image + */ + protected function imageNormalization($min, $max) + { + if ($min == 0 && $max == 255) { + return $this->vipsImage; + } + + // band intensity normalization x' = (x - $min) / ($max - $min) * 255 + return $this->vipsImage + ->subtract($min) + ->multiply(255 / ($max - $min)) + ->rint(); + } + + /** + * Delete overlay, dispatch fail event and fail job. + * + * @param mixed $msg Error message + * + * @return void + */ + protected function failAndNotify($msg) + { + if (GeoOverlay::where('id', $this->overlay->id)->exists()) { + $this->overlay->delete(); + } + GeoTiffUploadFailed::dispatch($this->user, $msg); + $this->fail(); + } + + /** + * Dispatch fail event after job failed + * + * @param mixed $exception + * + * @return void + */ + public function failed(?Throwable $exception) + { + $file = $this->overlay->name; + $this->failAndNotify("Upload of '$file' failed. Please try again."); + } +} diff --git a/src/Observers/GeoOverlayObserver.php b/src/Observers/GeoOverlayObserver.php new file mode 100644 index 00000000..5f611a59 --- /dev/null +++ b/src/Observers/GeoOverlayObserver.php @@ -0,0 +1,22 @@ +type === 'geotiff') { + $overlay->deleteFile(); + } + } +} diff --git a/src/Observers/VolumeObserver.php b/src/Observers/VolumeObserver.php new file mode 100644 index 00000000..93fa2f16 --- /dev/null +++ b/src/Observers/VolumeObserver.php @@ -0,0 +1,23 @@ +id) + ->where('type', '=', 'geotiff') + ->each(fn($overlay) => $overlay->deleteFile()); + } +} diff --git a/src/Services/Support/GeoManager.php b/src/Services/Support/GeoManager.php new file mode 100644 index 00000000..4054eeac --- /dev/null +++ b/src/Services/Support/GeoManager.php @@ -0,0 +1,306 @@ +exif = $this->getExifData($file); + } + + /** + * Returns exif data of a file + * + * @param mixed $file to be read + * @return array containing the exif data + */ + protected function getExifData($file) + { + // reader with Exiftool adapter + $reader = Reader::factory(ReaderType::EXIFTOOL); + return $reader->read($file)->getRawData(); + } + + /** + * Return the geoKey if it exists in the geoTIFF metadata + * + * @return null/object at $geoKey from exif-array + */ + public function getKey($geoKey) + { + if (array_key_exists($geoKey, $this->exif)) { + return $this->exif[$geoKey]; + } + return null; + } + + /** + * Retrieve the overlay size (width, height) of the geoTIFF file in pixels + * + * @return Array the pixel width and height [$width, $height] + */ + public function getPixelSize() + { + $width = $this->exif['IFD0:ImageWidth']; + $height = $this->exif['IFD0:ImageHeight']; + return [$width, $height]; + } + + /** + * Retrieve the overlay size (col, row) of the geoTIFF file in raster-size + * + * @return Array the raster column and row count in raster-space + */ + public function getRasterSize($corners) + { + $pixelScale = array_map('floatval', explode(" ", $this->exif['IFD0:PixelScale'])); + // [$top_left, $bottom_left, $top_right, $bottom_right]; + $raster_rows = abs(($corners[0][1] - $corners[1][1]) / $pixelScale[1]); + $raster_cols = abs(($corners[2][0] - $corners[0][0]) / $pixelScale[0]); + return [$raster_cols, $raster_rows]; + } + + /** + * Retrieve the overlay size (width, height) of the geoTIFF file in model-space + * + * @return Array the model-space width and height [$width, $height] + */ + public function getModelSize($coords) + { + $width = number_format($coords[2] - $coords[0], 13); + $height = number_format($coords[3] - $coords[1], 13); + return [$width, $height]; + } + + /** + * Retreive the four corner coordinates of the geoTIFF in raster space + * + * @return Array the outer coordinates [$top_left, $bottom_left, $top_right, $bottom_right] + */ + protected function getCorners() + { + [$width, $height] = $this->getPixelSize(); + + // for top-left corner, extract the ModelTiePoint Coordinates (in raster space: I,J) + $top_left = [0, 0]; + $bottom_left = [0, $height]; + $top_right = [$width, 0]; + $bottom_right = [$width, $height]; + // return the corners + return [$top_left, $bottom_left, $top_right, $bottom_right]; + } + + /** + * Convert corners from RASTER-SPACE to MODEL-SPACE + * + * @param $corners Top left and bottom right corner + * + * @throws ConvertModelSpaceException if PixelScale is ill-defined and ModelTransformation is not given + * + * @return array containing the transformed coordinates + */ + protected function convertToModelSpace($corners) + { + if ((!isset($this->exif['IFD0:PixelScale']) || !isset($this->exif['IFD0:ModelTiePoint'])) && !isset($this->exif['IFD0:ModelTransform'])) { + throw new ConvertModelSpaceException("Either ModelTransform or PixelScale and ModelTiePoint must be present."); + } + + $useModelTransform = isset($this->exif['IFD0:ModelTransform']); + + // see https://github.com/opengeospatial/geotiff/blob/master/GeoTIFF_Standard/standard/annex-b.adoc#coordinate-transformations + $projected = $useModelTransform ? $this->useModelTransform($corners) : $this->useModelTiePoint($corners); + return $this->getMinMaxCoordinate($projected); + } + + public function useModelTransform($corners) + { + // another way of transforming raster- to model-space with ModelTransformationTag (only 2D case implemented) + $model_transform = array_map('doubleval', explode(" ", $this->exif['IFD0:ModelTransform'])); + $keys = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']; + $var_array = array_combine($keys, array_slice($model_transform, 0, count($keys))); + // make variables availabe + extract($var_array); + $projected = []; + // transformation matrix for raster- to model-space, multiply with modelTiePoint (I,J,K) + // | a b 0 d | + // | e f 0 h | + // | 0 0 0 0 | + foreach ($corners as $corner) { + $projected[] = [ + (($a * $corner[0]) + ($b * $corner[1]) + $d), + (($e * $corner[0]) + ($f * $corner[1]) + $h) + ]; + } + return $projected; + } + + public function useModelTiePoint($corners) + { + $pixelScale = array_map('floatval', explode(" ", $this->exif['IFD0:PixelScale'])); + // if pixelScale is ill-defined, use modelTransform + if ($pixelScale[0] == 0 && $pixelScale[1] == 0) { + throw new ConvertModelSpaceException("The first two values of PixelScales must be greater than zero."); + } + + // modelTiePointTag = (I,J,K,X,Y,Z) + $modelTiePoints = array_map('floatval', explode(" ", $this->exif['IFD0:ModelTiePoint'])); + $tie_point_keys = ['I', 'J', 'K', 'X', 'Y', 'Z']; + $tie_points_combined = array_combine($tie_point_keys, $modelTiePoints); + // make variables availabe ($I, $J, $K, $X, $Y, $Z) + extract($tie_points_combined); + // modelTiePointTag = (I,J,K,X,Y,Z) + // Tx = X - I*Sx + $Tx = $X - ($I * $pixelScale[0]); + // Ty = Y + J*Sy + $Ty = $Y + ($J * $pixelScale[1]); + // Tz = Z - K*Sz (if not 0; aka. the 2D-case) + // $Tz = $pixelScale[2] === 0 ? 0 : ($Z - ($K * $pixelScale[1])); + + // transformation matrix for relationship between raster and model space + // | Sx * I + Tx | + // | Sy * J + Ty | + // | Sz * k + Tz | + foreach ($corners as $corner) { + $projected[] = [ + ($pixelScale[0] * $corner[0]) + $Tx, + -($pixelScale[1] * $corner[1]) + $Ty, + ]; + } + // get the minimum and maximum coordinates of the geoTIFF + return $projected; + } + + public function getCoords() + { + // Convert corners from RASTER-SPACE to MODEL-SPACE + $epsg = $this->getEpsgCode(); + $corners = $this->getCorners(); + $coords = $this->convertToModelSpace($corners); + $coords = $this->transformToEPSG4326($coords, "EPSG:{$epsg}"); + return $this->maybeFixCoords($coords); + } + + /** + * Return the min and max coordinate in model-space + * + * @param $projected coordinates of the geoTIFF corners + * + * @return array + */ + protected function getMinMaxCoordinate($projected) + { + $x_coordinates = array_map(fn($pt) => $pt[0], $projected); + $y_coordinates = array_map(fn($pt) => $pt[1], $projected); + + return [ + min($x_coordinates), + min($y_coordinates), + max($x_coordinates), + max($y_coordinates) + ]; + } + + /** + * Return epsg code from geoTIFF + * + * @return int|null + */ + public function getEpsgCode() + { + $type = $this->getCoordSystemType(); + + if (is_null($type) || !in_array($type, ['projected', 'geographic'])) { + return null; + } + + return intval( + $this->getKey( + $type === 'projected' ? 'GeoTiff:ProjectedCSType' : 'GeoTiff:GeographicType' + ) + ); + } + + /** + * Retreive the type of coordinate reference system used in the geoTIFF. + * + * @return string the coordinate system type + */ + public function getCoordSystemType() + { + $modelTypeKey = $this->getKey('GeoTiff:GTModelType'); + + switch ($modelTypeKey) { + case 1: + $modelType = 'projected'; + break; + case 2: + $modelType = 'geographic'; + break; + case 3: + $modelType = 'geocentric'; + break; + case 32767: + $modelType = 'user-defined'; + break; + default: + $modelType = null; + } + + return $modelType; + } + +} diff --git a/src/Services/Support/Transformer.php b/src/Services/Support/Transformer.php new file mode 100644 index 00000000..e7b8791f --- /dev/null +++ b/src/Services/Support/Transformer.php @@ -0,0 +1,100 @@ +convert($toCRS); + $transformed_coords = array_merge( + $transformed_coords, + [ + $to->getLongitude()->getValue(), + $to->getLatitude()->getValue() + ] + ); + } + } catch (Exception $e) { + throw new TransformCoordsException(); + } + return $transformed_coords; + } + + /** + * Check if the CRS is projected + * + * @param mixed $code EPSG code + * + * @return bool true if the CRS is projected, otherwise false + */ + public function isProjected($code) + { + try { + $code = str_replace(':', '::', $code); + Projected::fromSRID("urn:ogc:def:crs:" . $code); + } catch (Exception $e) { + return false; + } + return true; + } + + /** + * Fix corner sorting from UR -> LL to LL -> UR + * + * @param mixed $coords + * + * @return array + */ + public function maybeFixCoords($coords) + { + // Handle coordinates at wrap point + // Transform edges: + // _ _ + // from | + |_ to |_ + | + if ($coords[0] > $coords[2]) { + $coords[2] += 360; + } + + return $coords; + } + +} diff --git a/src/Services/Support/WebMapSource.php b/src/Services/Support/WebMapSource.php new file mode 100644 index 00000000..ee0a734d --- /dev/null +++ b/src/Services/Support/WebMapSource.php @@ -0,0 +1,248 @@ +rawUrl = $url; + $this->parsedUrl = parse_url($url); + $this->baseUrl = $this->unparseUrlBase(); + $this->xml = $this->getCapabilities(); + [$this->layerTitle, $this->layerName] = $this->extractLayerNameAndTitle(); + } + + /** + * Checks if the url contains any query-parameters + * + * @return bool + */ + public function isQueryUrl() + { + return !is_null(parse_url($this->rawUrl, PHP_URL_QUERY)); + } + + /** + * Re-assemble a parsed url and return only the url-base + * + * @return string + */ + protected function unparseUrlBase() + { + $scheme = isset($this->parsedUrl['scheme']) ? $this->parsedUrl['scheme'] . '://' : ''; + $host = isset($this->parsedUrl['host']) ? $this->parsedUrl['host'] : ''; + $port = isset($this->parsedUrl['port']) ? ':' . $this->parsedUrl['port'] : ''; + $user = isset($this->parsedUrl['user']) ? $this->parsedUrl['user'] : ''; + $pass = isset($this->parsedUrl['pass']) ? ':' . $this->parsedUrl['pass'] : ''; + $pass = ($user || $pass) ? "$pass@" : ''; + $path = isset($this->parsedUrl['path']) ? $this->parsedUrl['path'] : ''; + + return "$scheme$user$pass$host$port$path"; + } + + /** + * Checks whether the base-url is an actual WMS resource and sets global XML variable + * + * @throws WebMapSourceException if xml is invalid + * + * @return \SimpleXMLElement xml from source + */ + protected function getCapabilities() + { + $wmsRequest = $this->request($this->baseUrl . '?service=wms&version=1.1.1&request=GetCapabilities'); + libxml_use_internal_errors(true); // suppress all XML errors + $xml = simplexml_load_string($wmsRequest); + + // xml can be a non-boolean value which is interpreted as boolean false + if ($xml === false) { + throw new WebMapSourceException("The url does not lead to a WMS resource.", "invalidWMS"); + } + + return $xml; + } + + /** + * Get coordinates of layer + * + * @param string $layerString Name of used layer + * + * @return array Extent coordinates or empty array if no epsg is supported + */ + public function getCoords($layerString) + { + $coord_info = $this->xml->xpath('(//*[local-name()="Layer"]/*[Name="' . $layerString . '"])[1]/BoundingBox[@SRS="EPSG:4326"]'); + + if (count($coord_info) > 0) { + $coord_info = (array) $coord_info[0]; + $coord_info = $coord_info['@attributes']; + $res = [$coord_info['minx'], $coord_info['miny'], $coord_info['maxx'], $coord_info['maxy']]; + return $res; + } + + $coord_info = $this->xml->xpath('(//*[local-name()="Layer"]/*[Name="' . $layerString . '"])[1]/BoundingBox'); + foreach ($coord_info as $arr) { + $coords = (array) $arr; + $coords = $coords['@attributes']; + $pcrs = $coords['SRS']; + if ($this->isProjected($pcrs)) { + try { + $res = $this->transformToEPSG4326([$coords['minx'], $coords['miny'], $coords['maxx'], $coords['maxy']], $pcrs); + return $this->maybeFixCoords($res); + } catch (Exception $e) { + // retry with next epsg code + } + } + } + return []; + } + + /** + * Request file from source + * + * @param string $url of source + * @return bool|string request response + */ + protected function request($url) + { + return file_get_contents($url); + } + + /** + * Search the getCapabilities xml and find the first valid layer of the wms-resource + * + * @return array containing the title and name of the layer. + * + * @throws WebMapSourceException if xml contains no valid layer. + */ + protected function firstValidLayer() + { + // select only those layers that have no Child layers within them + $layers = $this->xml->xpath('//*[local-name()="Layer"][not(.//*[local-name()="Layer"])]'); + // loop over layers and return first valid layer title and name + foreach ($layers as $layer) { + $webmapTitle = (string) $layer->Title; + // Excerpt from OpenGIS 'Web Map Server Implementation Specification': + // If, and only if, a layer has a , then it is a map layer that can be requested + // If the layer has a Title but no Name, then that layer is only a category title for + // all the layers nested within (the latter case should not occur due to xpath query above) + if (!empty($layer->Name) && !empty((string) $layer->Name)) { + $webmapLayers = (string) $layer->Name; + return [$webmapTitle, $webmapLayers]; + } + } + throw new WebMapSourceException("Could not find any valid layers within the WMS resource.", "noValidLayer"); + } + + /** + * Finds the corresponding Title to a WMS Layer-Name (defaults to input name) + * + * @throws WebMapSourceException if layer name does not exist + * + * @param $layerString A Layer Name of the WMS + * + * @return null|string + */ + protected function getLayerTitle($layerString) + { + // xpath query to find the corresponding layer-title in the getCapabilities xml + $titleArray = $this->xml->xpath('(//*[local-name()="Layer"]/*[Name="' . $layerString . '"])[1]/Title'); + + if (count($titleArray) === 0) { + throw new WebMapSourceException("Layer with name \"$layerString\" does not exist.", "noValidLayer"); + } + + return (string) $titleArray[0]; + } + + /** + * Return layer name if it is present in the url. + * + * @return null|string + */ + protected function getLayerNameFromUrl() + { + parse_str(urldecode($this->parsedUrl['query']), $output); + + if (empty($output) || empty($output['layers'])) { + return; + } + + return $output['layers']; + } + + /** + * Return layer title and name + * + * @return array + */ + protected function extractLayerNameAndTitle() + { + if ($this->isQueryUrl()) { + $layerName = $this->getLayerNameFromUrl(); + if ($layerName) { + $webmapTitle = $this->getLayerTitle($layerName); + return [$webmapTitle, $layerName]; + } + } + + return $this->firstValidLayer(); + } + + public function getLayer() + { + return [$this->layerTitle, $this->layerName]; + } +} diff --git a/src/config/geo.php b/src/config/geo.php new file mode 100644 index 00000000..3ccdeb1f --- /dev/null +++ b/src/config/geo.php @@ -0,0 +1,17 @@ + [ + /* + | Directory to temporarily store the tiles when they are generated. + */ + 'tmp_dir' => sys_get_temp_dir(), + + /* + | Storage disk where the geo overlay images will be stored. + */ + 'overlay_storage_disk' => env('GEO_OVERLAY_STORAGE_DISK', 'geo-overlays'), + ] + +]; diff --git a/src/public/assets/imageMap-mzZ_8F5g.js b/src/public/assets/imageMap-mzZ_8F5g.js new file mode 100644 index 00000000..6bc382b5 --- /dev/null +++ b/src/public/assets/imageMap-mzZ_8F5g.js @@ -0,0 +1,10 @@ +var Al=Object.defineProperty;var Pl=(s,t,e)=>t in s?Al(s,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):s[t]=e;var Qr=(s,t,e)=>Pl(s,typeof t!="symbol"?t+"":t,e);import{createElementBlock as Ol,openBlock as Fl}from"vue";class ae{constructor(t){this.propagationStopped,this.defaultPrevented,this.type=t,this.target=null}preventDefault(){this.defaultPrevented=!0}stopPropagation(){this.propagationStopped=!0}}const ti={PROPERTYCHANGE:"propertychange"};class fr{constructor(){this.disposed=!1}dispose(){this.disposed||(this.disposed=!0,this.disposeInternal())}disposeInternal(){}}function Dl(s,t,e){let i,n;e=e||pe;let r=0,o=s.length,a=!1;for(;r>1),n=+e(s[i],t),n<0?r=i+1:(o=i,a=!n);return a?r:~r}function pe(s,t){return s>t?1:s0?n-1:n}return i-1}if(e>0){for(let n=1;n0||o===0)})}function ei(){return!0}function wn(){return!1}function Si(){}function ea(s){let t=!1,e,i,n;return function(){const r=Array.prototype.slice.call(arguments);return(!t||this!==n||!We(r,i))&&(t=!0,n=this,i=r,e=s.apply(this,arguments)),e}}function Gl(s){function t(){let e;try{e=s()}catch(i){return Promise.reject(i)}return e instanceof Promise?e:Promise.resolve(e)}return t()}function Di(s){for(const t in s)delete s[t]}function bi(s){let t;for(t in s)return!1;return!t}class hs extends fr{constructor(t){super(),this.eventTarget_=t,this.pendingRemovals_=null,this.dispatching_=null,this.listeners_=null}addEventListener(t,e){if(!t||!e)return;const i=this.listeners_||(this.listeners_={}),n=i[t]||(i[t]=[]);n.includes(e)||n.push(e)}dispatchEvent(t){const e=typeof t=="string",i=e?t:t.type,n=this.listeners_&&this.listeners_[i];if(!n)return;const r=e?new ae(t):t;r.target||(r.target=this.eventTarget_||this);const o=this.dispatching_||(this.dispatching_={}),a=this.pendingRemovals_||(this.pendingRemovals_={});i in o||(o[i]=0,a[i]=0),++o[i];let l;for(let c=0,h=n.length;c0:!1}removeEventListener(t,e){if(!this.listeners_)return;const i=this.listeners_[t];if(!i)return;const n=i.indexOf(e);n!==-1&&(this.pendingRemovals_&&t in this.pendingRemovals_?(i[n]=Si,++this.pendingRemovals_[t]):(i.splice(n,1),i.length===0&&delete this.listeners_[t]))}}const z={CHANGE:"change",ERROR:"error",CONTEXTMENU:"contextmenu",CLICK:"click",DBLCLICK:"dblclick",KEYDOWN:"keydown",KEYPRESS:"keypress",LOAD:"load",TOUCHMOVE:"touchmove",WHEEL:"wheel"};function q(s,t,e,i,n){if(i&&i!==s&&(e=e.bind(i)),n){const o=e;e=function(){s.removeEventListener(t,e),o.apply(this,arguments)}}const r={target:s,type:t,listener:e};return s.addEventListener(t,e),r}function on(s,t,e,i){return q(s,t,e,i,!0)}function it(s){s&&s.target&&(s.target.removeEventListener(s.type,s.listener),Di(s))}class Cn extends hs{constructor(){super(),this.on=this.onInternal,this.once=this.onceInternal,this.un=this.unInternal,this.revision_=0}changed(){++this.revision_,this.dispatchEvent(z.CHANGE)}getRevision(){return this.revision_}onInternal(t,e){if(Array.isArray(t)){const i=t.length,n=new Array(i);for(let r=0;r0}}else if(t.type==st.POINTERDOWN){const i=this.handleDownEvent(t);this.handlingDownUpSequence=i,e=this.stopDown(i)}else t.type==st.POINTERMOVE&&this.handleMoveEvent(t);return!e}handleMoveEvent(t){}handleUpEvent(t){return!1}stopDown(t){return t}updateTrackedPointers_(t){t.activePointers&&(this.targetPointers=t.activePointers)}}function mr(s){const t=s.length;let e=0,i=0;for(let n=0;nMath.round(e*io[i])/io[i]).join(", ")+")"}const ut={UNKNOWN:0,INTERSECTING:1,ABOVE:2,RIGHT:4,BELOW:8,LEFT:16};function no(s){const t=zt();for(let e=0,i=s.length;en&&(l=l|ut.RIGHT),ar&&(l=l|ut.ABOVE),l===ut.UNKNOWN&&(l=ut.INTERSECTING),l}function zt(){return[1/0,1/0,-1/0,-1/0]}function Ce(s,t,e,i,n){return n?(n[0]=s,n[1]=t,n[2]=e,n[3]=i,n):[s,t,e,i]}function Tn(s){return Ce(1/0,1/0,-1/0,-1/0,s)}function aa(s,t){const e=s[0],i=s[1];return Ce(e,i,e,i,t)}function pr(s,t,e,i,n){const r=Tn(n);return la(r,s,t,e,i)}function Mi(s,t){return s[0]==t[0]&&s[2]==t[2]&&s[1]==t[1]&&s[3]==t[3]}function jl(s,t){return t[0]s[2]&&(s[2]=t[2]),t[1]s[3]&&(s[3]=t[3]),s}function en(s,t){t[0]s[2]&&(s[2]=t[0]),t[1]s[3]&&(s[3]=t[1])}function la(s,t,e,i,n){for(;et[0]?i[0]=s[0]:i[0]=t[0],s[1]>t[1]?i[1]=s[1]:i[1]=t[1],s[2]=t[0]&&s[1]<=t[3]&&s[3]>=t[1]}function In(s){return s[2]=o&&_<=l),!i&&r&ut.RIGHT&&!(n&ut.RIGHT)&&(m=f-(d-l)*g,i=m>=a&&m<=c),!i&&r&ut.BELOW&&!(n&ut.BELOW)&&(_=d-(f-a)/g,i=_>=o&&_<=l),!i&&r&ut.LEFT&&!(n&ut.LEFT)&&(m=f-(d-o)*g,i=m>=a&&m<=c)}return i}function th(s,t,e,i){if(In(s))return Tn(e);let n=[];n=[s[0],s[1],s[2],s[1],s[2],s[3],s[0],s[3]],t(n,n,2);const r=[],o=[];for(let a=0,l=n.length;a=e[2])){const n=B(e),o=Math.floor((i[0]-e[0])/n)*n;s[0]-=o,s[2]-=o}return s}function ua(s,t,e){if(t.canWrapX()){const i=t.getExtent();if(!isFinite(s[0])||!isFinite(s[2]))return[[i[0],s[1],i[2],s[3]]];ca(s,t);const n=B(i);if(B(s)>n&&!e)return[[i[0],s[1],i[2],s[3]]];if(s[0]i[2])return[[s[0],s[1],i[2],s[3]],[i[0],s[1],s[2]-n,s[3]]]}return[s]}const Ai={radians:6370997/(2*Math.PI),degrees:2*Math.PI*6370997/360,ft:.3048,m:1,"us-ft":1200/3937};class yr{constructor(t){this.code_=t.code,this.units_=t.units,this.extent_=t.extent!==void 0?t.extent:null,this.worldExtent_=t.worldExtent!==void 0?t.worldExtent:null,this.axisOrientation_=t.axisOrientation!==void 0?t.axisOrientation:"enu",this.global_=t.global!==void 0?t.global:!1,this.canWrapX_=!!(this.global_&&this.extent_),this.getPointResolutionFunc_=t.getPointResolution,this.defaultTileGrid_=null,this.metersPerUnit_=t.metersPerUnit}canWrapX(){return this.canWrapX_}getCode(){return this.code_}getExtent(){return this.extent_}getUnits(){return this.units_}getMetersPerUnit(){return this.metersPerUnit_||Ai[this.units_]}getWorldExtent(){return this.worldExtent_}getAxisOrientation(){return this.axisOrientation_}isGlobal(){return this.global_}setGlobal(t){this.global_=t,this.canWrapX_=!!(t&&this.extent_)}getDefaultTileGrid(){return this.defaultTileGrid_}setDefaultTileGrid(t){this.defaultTileGrid_=t}setExtent(t){this.extent_=t,this.canWrapX_=!!(this.global_&&t)}setWorldExtent(t){this.worldExtent_=t}setGetPointResolution(t){this.getPointResolutionFunc_=t}getPointResolutionFunc(){return this.getPointResolutionFunc_}}const Sn=6378137,wi=Math.PI*Sn,eh=[-wi,-wi,wi,wi],ih=[-180,-85,180,85],Dn=Sn*Math.log(Math.tan(Math.PI/2));class ci extends yr{constructor(t){super({code:t,units:"m",extent:eh,global:!0,worldExtent:ih,getPointResolution:function(e,i){return e/Math.cosh(i[1]/Sn)}})}}const so=[new ci("EPSG:3857"),new ci("EPSG:102100"),new ci("EPSG:102113"),new ci("EPSG:900913"),new ci("http://www.opengis.net/def/crs/EPSG/0/3857"),new ci("http://www.opengis.net/gml/srs/epsg.xml#3857")];function nh(s,t,e){const i=s.length;e=e>1?e:2,t===void 0&&(e>2?t=s.slice():t=new Array(i));for(let n=0;nDn?r=Dn:r<-Dn&&(r=-Dn),t[n+1]=r}return t}function sh(s,t,e){const i=s.length;e=e>1?e:2,t===void 0&&(e>2?t=s.slice():t=new Array(i));for(let n=0;n1?(e=n,i=r):l>0&&(e+=o*l,i+=a*l)}return Ri(s,t,e,i)}function Ri(s,t,e,i){const n=e-s,r=i-t;return n*n+r*r}function uh(s){const t=s.length;for(let i=0;ir&&(r=l,n=a)}if(r===0)return null;const o=s[n];s[n]=s[i],s[i]=o;for(let a=i+1;a=0;i--){e[i]=s[i][t]/s[i][i];for(let n=i-1;n>=0;n--)s[n][t]-=s[n][i]*e[i]}return e}function jn(s){return s*Math.PI/180}function Qe(s,t){const e=s%t;return e*t<0?e+t:e}function Zt(s,t,e){return s+e*(t-s)}function ds(s,t){const e=Math.pow(10,t);return Math.round(s*e)/e}function ao(s,t){return Math.round(ds(s,t))}function kn(s,t){return Math.floor(ds(s,t))}function Nn(s,t){return Math.ceil(ds(s,t))}function da(s,t){const e=(""+s).split("."),i=(""+t).split(".");for(let n=0;no)return 1;if(o>r)return-1}return 0}function dh(s,t){return s[0]+=+t[0],s[1]+=+t[1],s}function qn(s,t){let e=!0;for(let i=s.length-1;i>=0;--i)if(s[i]!=t[i]){e=!1;break}return e}function Er(s,t){const e=Math.cos(t),i=Math.sin(t),n=s[0]*e-s[1]*i,r=s[1]*e+s[0]*i;return s[0]=n,s[1]=r,s}function fh(s,t){return s[0]*=t,s[1]*=t,s}function fa(s,t){if(t.canWrapX()){const e=B(t.getExtent()),i=gh(s,t,e);i&&(s[0]-=i*e)}return s}function gh(s,t,e){const i=t.getExtent();let n=0;return t.canWrapX()&&(s[0]i[2])&&(e=e||B(i),n=Math.floor((s[0]-i[0])/e)),n}const _h=63710088e-1;function lo(s,t,e){e=e||_h;const i=jn(s[1]),n=jn(t[1]),r=(n-i)/2,o=jn(t[0]-s[0])/2,a=Math.sin(r)*Math.sin(r)+Math.sin(o)*Math.sin(o)*Math.cos(i)*Math.cos(n);return 2*e*Math.atan2(Math.sqrt(a),Math.sqrt(1-a))}function ga(...s){console.warn(...s)}let ir=!0;function _a(s){ir=!1}function xr(s,t){if(t!==void 0){for(let e=0,i=s.length;e=a?t[r+l]:o[l]}return e}}function Eh(s,t,e,i){const n=Mt(s),r=Mt(t);Pi(n,r,co(e)),Pi(r,n,co(i))}function xh(s,t){return _a(),vr(s,"EPSG:4326","EPSG:3857")}function mi(s,t){if(s===t)return!0;const e=s.getUnits()===t.getUnits();return(s.getCode()===t.getCode()||Cr(s,t)===xr)&&e}function Cr(s,t){const e=s.getCode(),i=t.getCode();let n=hh(e,i);return n||(n=ma),n}function ln(s,t){const e=Mt(s),i=Mt(t);return Cr(e,i)}function vr(s,t,e){return ln(t,e)(s,void 0,s.length)}function uo(s,t,e,i){const n=ln(t,e);return th(s,n,void 0)}function nr(s,t){return s}function fe(s,t){return ir&&!qn(s,[0,0])&&s[0]>=-180&&s[0]<=180&&s[1]>=-90&&s[1]<=90&&(ir=!1,ga("Call useGeographic() from ol/proj once to work with [longitude, latitude] coordinates.")),s}function pa(s,t){return s}function De(s,t){return s}function wh(){ho(so),ho(oo),yh(oo,so,nh,sh)}wh();function Ne(s,t,e,i,n,r){r=r||[];let o=0;for(let a=t;a{if(!i)return this.getSimplifiedGeometry(e);const n=this.clone();return n.applyTransform(i),n.getSimplifiedGeometry(e)})}simplifyTransformed(t,e){return this.simplifyTransformedInternal(this.getRevision(),t,e)}clone(){return J()}closestPointXY(t,e,i,n){return J()}containsXY(t,e){const i=this.getClosestPoint([t,e]);return i[0]===t&&i[1]===e}getClosestPoint(t,e){return e=e||[NaN,NaN],this.closestPointXY(t[0],t[1],e,1/0),e}intersectsCoordinate(t){return this.containsXY(t[0],t[1])}computeExtent(t){return J()}getExtent(t){if(this.extentRevision_!=this.getRevision()){const e=this.computeExtent(this.extent_);(isNaN(e[0])||isNaN(e[1]))&&Tn(e),this.extentRevision_=this.getRevision()}return $l(this.extent_,t)}rotate(t,e){J()}scale(t,e,i){J()}simplify(t){return this.getSimplifiedGeometry(t*t)}getSimplifiedGeometry(t){return J()}getType(){return J()}applyTransform(t){J()}intersectsExtent(t){return J()}translate(t,e){J()}transform(t,e){const i=Mt(t),n=i.getUnits()=="tile-pixels"?function(r,o,a){const l=i.getExtent(),c=i.getWorldExtent(),h=at(c)/at(l);return we(fo,c[0],c[3],h,-h,0,0,0),Ne(r,0,r.length,a,fo,o),ln(i,e)(r,o,a)}:ln(i,e);return this.applyTransform(n),this}}class Tr extends Th{constructor(){super(),this.layout="XY",this.stride=2,this.flatCoordinates}computeExtent(t){return pr(this.flatCoordinates,0,this.flatCoordinates.length,this.stride,t)}getCoordinates(){return J()}getFirstCoordinate(){return this.flatCoordinates.slice(0,this.stride)}getFlatCoordinates(){return this.flatCoordinates}getLastCoordinate(){return this.flatCoordinates.slice(this.flatCoordinates.length-this.stride)}getLayout(){return this.layout}getSimplifiedGeometry(t){if(this.simplifiedGeometryRevision!==this.getRevision()&&(this.simplifiedGeometryMaxMinSquaredTolerance=0,this.simplifiedGeometryRevision=this.getRevision()),t<0||this.simplifiedGeometryMaxMinSquaredTolerance!==0&&t<=this.simplifiedGeometryMaxMinSquaredTolerance)return this;const e=this.getSimplifiedGeometryInternal(t);return e.getFlatCoordinates().length1)u=e;else if(d>0){for(let f=0;fn&&(n=c),r=a,o=l}return n}function Sh(s,t,e,i,n){for(let r=0,o=e.length;r0;){const u=c.pop(),d=c.pop();let f=0;const g=s[d],_=s[d+1],m=s[u],p=s[u+1];for(let y=d+i;yf&&(h=y,f=x)}f>n&&(l[(h-t)/i]=1,d+i0&&_>f)&&(g<0&&m0&&m>g)){c=u,h=d;continue}r[o++]=c,r[o++]=h,a=c,l=h,c=u,h=d}return r[o++]=c,r[o++]=h,o}function Ca(s,t,e,i,n,r,o,a){for(let l=0,c=e.length;lr&&(c-a)*(r-l)-(n-a)*(h-l)>0&&o++:h<=r&&(c-a)*(r-l)-(n-a)*(h-l)<0&&o--,a=c,l=h}return o!==0}function Ta(s,t,e,i,n,r){if(e.length===0||!$e(s,t,e[0],i,n,r))return!1;for(let o=1,a=e.length;op&&(c=(h+u)/2,Ta(s,t,e,i,c,g)&&(m=c,p=y)),h=u}return isNaN(m)&&(m=n[r]),o?(o.push(m,g,p),o):[m,g,p]}function Dh(s,t,e,i,n){let r=[];for(let o=0,a=e.length;o=n[0]&&r[2]<=n[2]||r[1]>=n[1]&&r[3]<=n[3]?!0:kh(s,t,e,i,function(o,a){return Ql(n,o,a)}):!1}function Ia(s,t,e,i,n){return!!(Ra(s,t,e,i,n)||$e(s,t,e,i,n[0],n[1])||$e(s,t,e,i,n[0],n[3])||$e(s,t,e,i,n[2],n[1])||$e(s,t,e,i,n[2],n[3]))}function Nh(s,t,e,i,n){if(!Ia(s,t,e[0],i,n))return!1;if(e.length===1)return!0;for(let r=1,o=e.length;r0}function zh(s,t,e,i,n){n=n!==void 0?n:!1;for(let r=0,o=e.length;r=this.minArea_}getGeometry(){return this.box_.getGeometry()}handleDragEvent(t){this.startPixel_&&(this.box_.setPixels(this.startPixel_,t.pixel),this.dispatchEvent(new Gn(Ui.BOXDRAG,t.coordinate,t)))}handleUpEvent(t){if(!this.startPixel_)return!1;this.box_.setMap(null);const e=this.boxEndCondition_(t,this.startPixel_,t.pixel);return e&&this.onBoxEnd(t),this.dispatchEvent(new Gn(e?Ui.BOXEND:Ui.BOXCANCEL,t.coordinate,t)),!1}handleDownEvent(t){return this.condition_(t)?(this.startPixel_=t.pixel,this.box_.setMap(t.map),this.box_.setPixels(this.startPixel_,this.startPixel_),this.dispatchEvent(new Gn(Ui.BOXSTART,t.coordinate,t)),!0):!1}onBoxEnd(t){}setActive(t){t||(this.box_.setMap(null),this.startPixel_&&(this.dispatchEvent(new Gn(Ui.BOXCANCEL,this.startPixel_,null)),this.startPixel_=null)),super.setActive(t)}}class un extends Qt{constructor(t){if(super(),this.on,this.once,this.un,this.id_=void 0,this.geometryName_="geometry",this.style_=null,this.styleFunction_=void 0,this.geometryChangeKey_=null,this.addChangeListener(this.geometryName_,this.handleGeometryChanged_),t)if(typeof t.getSimplifiedGeometry=="function"){const e=t;this.setGeometry(e)}else{const e=t;this.setProperties(e)}}clone(){const t=new un(this.hasProperties()?this.getProperties():null);t.setGeometryName(this.getGeometryName());const e=this.getGeometry();e&&t.setGeometry(e.clone());const i=this.getStyle();return i&&t.setStyle(i),t}getGeometry(){return this.get(this.geometryName_)}getId(){return this.id_}getGeometryName(){return this.geometryName_}getStyle(){return this.style_}getStyleFunction(){return this.styleFunction_}handleGeometryChange_(){this.changed()}handleGeometryChanged_(){this.geometryChangeKey_&&(it(this.geometryChangeKey_),this.geometryChangeKey_=null);const t=this.getGeometry();t&&(this.geometryChangeKey_=q(t,z.CHANGE,this.handleGeometryChange_,this)),this.changed()}setGeometry(t){this.set(this.geometryName_,t)}setStyle(t){this.style_=t,this.styleFunction_=t?Jh(t):void 0,this.changed()}setId(t){this.id_=t,this.changed()}setGeometryName(t){this.removeChangeListener(this.geometryName_,this.handleGeometryChanged_),this.geometryName_=t,this.addChangeListener(this.geometryName_,this.handleGeometryChanged_),this.handleGeometryChanged_()}}function Jh(s){if(typeof s=="function")return s;let t;return Array.isArray(s)?t=s:($(typeof s.getZIndex=="function","Expected an `ol/style/Style` or an array of `ol/style/Style.js`"),t=[s]),function(){return t}}const tt={OPACITY:"opacity",VISIBLE:"visible",EXTENT:"extent",Z_INDEX:"zIndex",MAX_RESOLUTION:"maxResolution",MIN_RESOLUTION:"minResolution",MAX_ZOOM:"maxZoom",MIN_ZOOM:"minZoom",SOURCE:"source",MAP:"map"};class Na extends Qt{constructor(t){super(),this.on,this.once,this.un,this.background_=t.background;const e=Object.assign({},t);typeof t.properties=="object"&&(delete e.properties,Object.assign(e,t.properties)),e[tt.OPACITY]=t.opacity!==void 0?t.opacity:1,$(typeof e[tt.OPACITY]=="number","Layer opacity must be a number"),e[tt.VISIBLE]=t.visible!==void 0?t.visible:!0,e[tt.Z_INDEX]=t.zIndex,e[tt.MAX_RESOLUTION]=t.maxResolution!==void 0?t.maxResolution:1/0,e[tt.MIN_RESOLUTION]=t.minResolution!==void 0?t.minResolution:0,e[tt.MIN_ZOOM]=t.minZoom!==void 0?t.minZoom:-1/0,e[tt.MAX_ZOOM]=t.maxZoom!==void 0?t.maxZoom:1/0,this.className_=e.className!==void 0?e.className:"ol-layer",delete e.className,this.setProperties(e),this.state_=null}getBackground(){return this.background_}getClassName(){return this.className_}getLayerState(t){const e=this.state_||{layer:this,managed:t===void 0?!0:t},i=this.getZIndex();return e.opacity=ht(Math.round(this.getOpacity()*100)/100,0,1),e.visible=this.getVisible(),e.extent=this.getExtent(),e.zIndex=i===void 0&&!e.managed?1/0:i,e.maxResolution=this.getMaxResolution(),e.minResolution=Math.max(this.getMinResolution(),0),e.minZoom=this.getMinZoom(),e.maxZoom=this.getMaxZoom(),this.state_=e,e}getLayersArray(t){return J()}getLayerStatesArray(t){return J()}getExtent(){return this.get(tt.EXTENT)}getMaxResolution(){return this.get(tt.MAX_RESOLUTION)}getMinResolution(){return this.get(tt.MIN_RESOLUTION)}getMinZoom(){return this.get(tt.MIN_ZOOM)}getMaxZoom(){return this.get(tt.MAX_ZOOM)}getOpacity(){return this.get(tt.OPACITY)}getSourceState(){return J()}getVisible(){return this.get(tt.VISIBLE)}getZIndex(){return this.get(tt.Z_INDEX)}setBackground(t){this.background_=t,this.changed()}setExtent(t){this.set(tt.EXTENT,t)}setMaxResolution(t){this.set(tt.MAX_RESOLUTION,t)}setMinResolution(t){this.set(tt.MIN_RESOLUTION,t)}setMaxZoom(t){this.set(tt.MAX_ZOOM,t)}setMinZoom(t){this.set(tt.MIN_ZOOM,t)}setOpacity(t){$(typeof t=="number","Layer opacity must be a number"),this.set(tt.OPACITY,t)}setVisible(t){this.set(tt.VISIBLE,t)}setZIndex(t){this.set(tt.Z_INDEX,t)}disposeInternal(){this.state_&&(this.state_.layer=null,this.state_=null),super.disposeInternal()}}const ft={ADD:"add",REMOVE:"remove"},Eo={LENGTH:"length"};class zn extends ae{constructor(t,e,i){super(t),this.element=e,this.index=i}}class Nt extends Qt{constructor(t,e){if(super(),this.on,this.once,this.un,e=e||{},this.unique_=!!e.unique,this.array_=t||[],this.unique_)for(let i=0,n=this.array_.length;i0;)this.pop()}extend(t){for(let e=0,i=t.length;ethis.getLength())throw new Error("Index out of bounds: "+t);this.unique_&&this.assertUnique_(e),this.array_.splice(t,0,e),this.updateLength_(),this.dispatchEvent(new zn(ft.ADD,e,t))}pop(){return this.removeAt(this.getLength()-1)}push(t){this.unique_&&this.assertUnique_(t);const e=this.getLength();return this.insertAt(e,t),this.getLength()}remove(t){const e=this.array_;for(let i=0,n=e.length;i=this.getLength())return;const e=this.array_[t];return this.array_.splice(t,1),this.updateLength_(),this.dispatchEvent(new zn(ft.REMOVE,e,t)),e}setAt(t,e){const i=this.getLength();if(t>=i){this.insertAt(t,e);return}if(t<0)throw new Error("Index out of bounds: "+t);this.unique_&&this.assertUnique_(e,t);const n=this.array_[t];this.array_[t]=e,this.dispatchEvent(new zn(ft.REMOVE,n,t)),this.dispatchEvent(new zn(ft.ADD,e,t))}updateLength_(){this.set(Eo.LENGTH,this.array_.length)}assertUnique_(t,e){for(let i=0,n=this.array_.length;if&&(d=(f+d)/2,f=d),g>_&&(g=(_+g)/2,_=g);let m=ht(i[0],d,f),p=ht(i[1],g,_);if(o&&e&&n){const y=30*n;m+=-y*Math.log(1+Math.max(0,d-i[0])/y)+y*Math.log(1+Math.max(0,i[0]-f)/y),p+=-y*Math.log(1+Math.max(0,g-i[1])/y)+y*Math.log(1+Math.max(0,i[1]-_)/y)}return[m,p]}}function tc(s){return s}function Lr(s,t,e,i){const n=B(t)/e[0],r=at(t)/e[1];return i?Math.min(s,Math.max(n,r)):Math.min(s,Math.min(n,r))}function Mr(s,t,e){let i=Math.min(s,t);const n=50;return i*=Math.log(1+n*Math.max(0,s/t-1))/n+1,e&&(i=Math.max(i,e),i/=Math.log(1+n*Math.max(0,e/s-1))/n+1),ht(i,e/2,t*2)}function ec(s,t,e,i){return t=t!==void 0?t:!0,function(n,r,o,a){if(n!==void 0){const l=s[0],c=s[s.length-1],h=e?Lr(l,e,o,i):l;if(a)return t?Mr(n,h,c):ht(n,c,h);const u=Math.min(h,n),d=Math.floor(gr(s,u,r));return s[d]>h&&d1&&typeof arguments[e-1]=="function"&&(i=arguments[e-1],--e);let n=0;for(;n0}getInteracting(){return this.hints_[wt.INTERACTING]>0}cancelAnimations(){this.setHint(wt.ANIMATING,-this.hints_[wt.ANIMATING]);let t;for(let e=0,i=this.animations_.length;e=0;--i){const n=this.animations_[i];let r=!0;for(let o=0,a=n.length;o0?c/l.duration:1;h>=1?(l.complete=!0,h=1):r=!1;const u=l.easing(h);if(l.sourceCenter){const d=l.sourceCenter[0],f=l.sourceCenter[1],g=l.targetCenter[0],_=l.targetCenter[1];this.nextCenter_=l.targetCenter;const m=d+u*(g-d),p=f+u*(_-f);this.targetCenter_=[m,p]}if(l.sourceResolution&&l.targetResolution){const d=u===1?l.targetResolution:l.sourceResolution+u*(l.targetResolution-l.sourceResolution);if(l.anchor){const f=this.getViewportSize_(this.getRotation()),g=this.constraints_.resolution(d,0,f,!0);this.targetCenter_=this.calculateCenterZoom(g,l.anchor)}this.nextResolution_=l.targetResolution,this.targetResolution_=d,this.applyTargetState_(!0)}if(l.sourceRotation!==void 0&&l.targetRotation!==void 0){const d=u===1?Qe(l.targetRotation+Math.PI,2*Math.PI)-Math.PI:l.sourceRotation+u*(l.targetRotation-l.sourceRotation);if(l.anchor){const f=this.constraints_.rotation(d,!0);this.targetCenter_=this.calculateCenterRotate(f,l.anchor)}this.nextRotation_=l.targetRotation,this.targetRotation_=d}if(this.applyTargetState_(!0),e=!0,!l.complete)break}if(r){this.animations_[i]=null,this.setHint(wt.ANIMATING,-1),this.nextCenter_=null,this.nextResolution_=NaN,this.nextRotation_=NaN;const o=n[0].callback;o&&Wn(o,!0)}}this.animations_=this.animations_.filter(Boolean),e&&this.updateAnimationKey_===void 0&&(this.updateAnimationKey_=requestAnimationFrame(this.updateAnimations_.bind(this)))}calculateCenterRotate(t,e){let i;const n=this.getCenterInternal();return n!==void 0&&(i=[n[0]-e[0],n[1]-e[1]],Er(i,t-this.getRotation()),dh(i,e)),i}calculateCenterZoom(t,e){let i;const n=this.getCenterInternal(),r=this.getResolution();if(n!==void 0&&r!==void 0){const o=e[0]-t*(e[0]-n[0])/r,a=e[1]-t*(e[1]-n[1])/r;i=[o,a]}return i}getViewportSize_(t){const e=this.viewportSize_;if(t){const i=e[0],n=e[1];return[Math.abs(i*Math.cos(t))+Math.abs(n*Math.sin(t)),Math.abs(i*Math.sin(t))+Math.abs(n*Math.cos(t))]}return e}setViewportSize(t){this.viewportSize_=Array.isArray(t)?t.slice():[100,100],this.getAnimating()||this.resolveConstraints(0)}getCenter(){const t=this.getCenterInternal();return t&&nr(t,this.getProjection())}getCenterInternal(){return this.get(Dt.CENTER)}getConstraints(){return this.constraints_}getConstrainResolution(){return this.get("constrainResolution")}getHints(t){return t!==void 0?(t[0]=this.hints_[0],t[1]=this.hints_[1],t):this.hints_.slice()}calculateExtent(t){const e=this.calculateExtentInternal(t);return pa(e,this.getProjection())}calculateExtentInternal(t){t=t||this.getViewportSizeMinusPadding_();const e=this.getCenterInternal();$(e,"The view center is not defined");const i=this.getResolution();$(i!==void 0,"The view resolution is not defined");const n=this.getRotation();return $(n!==void 0,"The view rotation is not defined"),Qs(e,i,n,t)}getMaxResolution(){return this.maxResolution_}getMinResolution(){return this.minResolution_}getMaxZoom(){return this.getZoomForResolution(this.minResolution_)}setMaxZoom(t){this.applyOptions_(this.getUpdatedOptions_({maxZoom:t}))}getMinZoom(){return this.getZoomForResolution(this.maxResolution_)}setMinZoom(t){this.applyOptions_(this.getUpdatedOptions_({minZoom:t}))}setConstrainResolution(t){this.applyOptions_(this.getUpdatedOptions_({constrainResolution:t}))}getProjection(){return this.projection_}getResolution(){return this.get(Dt.RESOLUTION)}getResolutions(){return this.resolutions_}getResolutionForExtent(t,e){return this.getResolutionForExtentInternal(De(t,this.getProjection()),e)}getResolutionForExtentInternal(t,e){e=e||this.getViewportSizeMinusPadding_();const i=B(t)/e[0],n=at(t)/e[1];return Math.max(i,n)}getResolutionForValueFunction(t){t=t||2;const e=this.getConstrainedResolution(this.maxResolution_),i=this.minResolution_,n=Math.log(e/i)/Math.log(t);return function(r){return e/Math.pow(t,r*n)}}getRotation(){return this.get(Dt.ROTATION)}getValueForResolutionFunction(t){const e=Math.log(t||2),i=this.getConstrainedResolution(this.maxResolution_),n=this.minResolution_,r=Math.log(i/n)/e;return function(o){return Math.log(i/o)/e/r}}getViewportSizeMinusPadding_(t){let e=this.getViewportSize_(t);const i=this.padding_;return i&&(e=[e[0]-i[1]-i[3],e[1]-i[0]-i[2]]),e}getState(){const t=this.getProjection(),e=this.getResolution(),i=this.getRotation();let n=this.getCenterInternal();const r=this.padding_;if(r){const o=this.getViewportSizeMinusPadding_();n=Fs(n,this.getViewportSize_(),[o[0]/2+r[3],o[1]/2+r[0]],e,i)}return{center:n.slice(0),projection:t!==void 0?t:null,resolution:e,nextCenter:this.nextCenter_,nextResolution:this.nextResolution_,nextRotation:this.nextRotation_,rotation:i,zoom:this.getZoom()}}getViewStateAndExtent(){return{viewState:this.getState(),extent:this.calculateExtent()}}getZoom(){let t;const e=this.getResolution();return e!==void 0&&(t=this.getZoomForResolution(e)),t}getZoomForResolution(t){let e=this.minZoom_||0,i,n;if(this.resolutions_){const r=gr(this.resolutions_,t,1);e=r,i=this.resolutions_[r],r==this.resolutions_.length-1?n=2:n=i/this.resolutions_[r+1]}else i=this.maxResolution_,n=this.zoomFactor_;return e+Math.log(i/t)/Math.log(n)}getResolutionForZoom(t){if(this.resolutions_){if(this.resolutions_.length<=1)return 0;const e=ht(Math.floor(t),0,this.resolutions_.length-2),i=this.resolutions_[e]/this.resolutions_[e+1];return this.resolutions_[e]/Math.pow(i,ht(t-e,0,1))}return this.maxResolution_/Math.pow(this.zoomFactor_,t-this.minZoom_)}fit(t,e){let i;if($(Array.isArray(t)||typeof t.getSimplifiedGeometry=="function","Invalid extent or geometry provided as `geometry`"),Array.isArray(t)){$(!In(t),"Cannot fit empty extent provided as `geometry`");const n=De(t,this.getProjection());i=Jn(n)}else if(t.getType()==="Circle"){const n=De(t.getExtent(),this.getProjection());i=Jn(n),i.rotate(this.getRotation(),Ge(n))}else i=t;this.fitInternal(i,e)}rotatedExtentForGeometry(t){const e=this.getRotation(),i=Math.cos(e),n=Math.sin(-e),r=t.getFlatCoordinates(),o=t.getStride();let a=1/0,l=1/0,c=-1/0,h=-1/0;for(let u=0,d=r.length;u{this.dispatchEvent("sourceready")},0))),this.changed()}getFeatures(t){return this.renderer_?this.renderer_.getFeatures(t):Promise.resolve([])}getData(t){return!this.renderer_||!this.rendered?null:this.renderer_.getData(t)}isVisible(t){let e;const i=this.getMapInternal();!t&&i&&(t=i.getView()),t instanceof Ut?e={viewState:t.getState(),extent:t.calculateExtent()}:e=t,!e.layerStatesArray&&i&&(e.layerStatesArray=i.getLayerGroup().getLayerStatesArray());let n;e.layerStatesArray?n=e.layerStatesArray.find(o=>o.layer===this):n=this.getLayerState();const r=this.getExtent();return Pr(n,e.viewState)&&(!r||Pt(r,e.extent))}getAttributions(t){if(!this.isVisible(t))return[];let e;const i=this.getSource();if(i&&(e=i.getAttributions()),!e)return[];const n=t instanceof Ut?t.getViewStateAndExtent():t;let r=e(n);return Array.isArray(r)||(r=[r]),r}render(t,e){const i=this.getRenderer();return i.prepareFrame(t)?(this.rendered=!0,i.renderFrame(t,e)):null}unrender(){this.rendered=!1}getDeclutter(){}renderDeclutter(t,e){}renderDeferred(t){const e=this.getRenderer();e&&e.renderDeferred(t)}setMapInternal(t){t||this.unrender(),this.set(tt.MAP,t)}getMapInternal(){return this.get(tt.MAP)}setMap(t){this.mapPrecomposeKey_&&(it(this.mapPrecomposeKey_),this.mapPrecomposeKey_=null),t||this.changed(),this.mapRenderKey_&&(it(this.mapRenderKey_),this.mapRenderKey_=null),t&&(this.mapPrecomposeKey_=q(t,jt.PRECOMPOSE,function(e){const n=e.frameState.layerStatesArray,r=this.getLayerState(!1);$(!n.some(function(o){return o.layer===r.layer}),"A layer can only be added to the map once. Use either `layer.setMap()` or `map.addLayer()`, not both."),n.push(r)},this),this.mapRenderKey_=q(this,z.CHANGE,t.render,t),this.changed())}setSource(t){this.set(tt.SOURCE,t)}getRenderer(){return this.renderer_||(this.renderer_=this.createRenderer()),this.renderer_}hasRenderer(){return!!this.renderer_}createRenderer(){return null}disposeInternal(){this.renderer_&&(this.renderer_.dispose(),delete this.renderer_),this.setSource(null),super.disposeInternal()}}function Pr(s,t){if(!s.visible)return!1;const e=t.resolution;if(e=s.maxResolution)return!1;const i=t.zoom;return i>s.minZoom&&i<=s.maxZoom}function hc(s,t,e,i,n){Ga(s,t,e||0,i||s.length-1,n||cc)}function Ga(s,t,e,i,n){for(;i>e;){if(i-e>600){var r=i-e+1,o=t-e+1,a=Math.log(r),l=.5*Math.exp(2*a/3),c=.5*Math.sqrt(a*l*(r-l)/r)*(o-r/2<0?-1:1),h=Math.max(e,Math.floor(t-o*l/r+c)),u=Math.min(i,Math.floor(t+(r-o)*l/r+c));Ga(s,t,h,u,n)}var d=s[t],f=e,g=i;for(Ki(s,e,t),n(s[i],d)>0&&Ki(s,e,i);f0;)g--}n(s[e],d)===0?Ki(s,e,g):(g++,Ki(s,g,i)),g<=t&&(e=g+1),t<=g&&(i=g-1)}}function Ki(s,t,e){var i=s[t];s[t]=s[e],s[e]=i}function cc(s,t){return st?1:0}let za=class{constructor(t=9){this._maxEntries=Math.max(4,t),this._minEntries=Math.max(2,Math.ceil(this._maxEntries*.4)),this.clear()}all(){return this._all(this.data,[])}search(t){let e=this.data;const i=[];if(!Yn(t,e))return i;const n=this.toBBox,r=[];for(;e;){for(let o=0;o=0&&r[e].children.length>this._maxEntries;)this._split(r,e),e--;this._adjustParentBBoxes(n,r,e)}_split(t,e){const i=t[e],n=i.children.length,r=this._minEntries;this._chooseSplitAxis(i,r,n);const o=this._chooseSplitIndex(i,r,n),a=pi(i.children.splice(o,i.children.length-o));a.height=i.height,a.leaf=i.leaf,ui(i,this.toBBox),ui(a,this.toBBox),e?t[e-1].children.push(a):this._splitRoot(i,a)}_splitRoot(t,e){this.data=pi([t,e]),this.data.height=t.height+1,this.data.leaf=!1,ui(this.data,this.toBBox)}_chooseSplitIndex(t,e,i){let n,r=1/0,o=1/0;for(let a=e;a<=i-e;a++){const l=Ji(t,0,a,this.toBBox),c=Ji(t,a,i,this.toBBox),h=_c(l,c),u=Ds(l)+Ds(c);h=e;c--){const h=t.children[c];Qi(a,t.leaf?r(h):h),l+=Xn(a)}return l}_adjustParentBBoxes(t,e,i){for(let n=i;n>=0;n--)Qi(e[n],t)}_condense(t){for(let e=t.length-1,i;e>=0;e--)t[e].children.length===0?e>0?(i=t[e-1].children,i.splice(i.indexOf(t[e]),1)):this.clear():ui(t[e],this.toBBox)}};function uc(s,t,e){if(!e)return t.indexOf(s);for(let i=0;i=s.minX&&t.maxY>=s.minY}function pi(s){return{children:s,height:1,leaf:!0,minX:1/0,minY:1/0,maxX:-1/0,maxY:-1/0}}function vo(s,t,e,i,n){const r=[t,e];for(;r.length;){if(e=r.pop(),t=r.pop(),e-t<=i)continue;const o=t+Math.ceil((e-t)/i/2)*i;hc(s,o,t,e,n),r.push(t,o,o,e)}}const V={IDLE:0,LOADING:1,LOADED:2,ERROR:3};function To(s){return s[0]>0&&s[1]>0}function mc(s,t,e){return e===void 0&&(e=[0,0]),e[0]=s[0]*t+.5|0,e[1]=s[1]*t+.5|0,e}function Ft(s,t){return Array.isArray(s)?s:(t===void 0?t=[s,s]:(t[0]=s,t[1]=s),t)}class ms{constructor(t){this.opacity_=t.opacity,this.rotateWithView_=t.rotateWithView,this.rotation_=t.rotation,this.scale_=t.scale,this.scaleArray_=Ft(t.scale),this.displacement_=t.displacement,this.declutterMode_=t.declutterMode}clone(){const t=this.getScale();return new ms({opacity:this.getOpacity(),scale:Array.isArray(t)?t.slice():t,rotation:this.getRotation(),rotateWithView:this.getRotateWithView(),displacement:this.getDisplacement().slice(),declutterMode:this.getDeclutterMode()})}getOpacity(){return this.opacity_}getRotateWithView(){return this.rotateWithView_}getRotation(){return this.rotation_}getScale(){return this.scale_}getScaleArray(){return this.scaleArray_}getDisplacement(){return this.displacement_}getDeclutterMode(){return this.declutterMode_}getAnchor(){return J()}getImage(t){return J()}getHitDetectionImage(){return J()}getPixelRatio(t){return 1}getImageState(){return J()}getImageSize(){return J()}getOrigin(){return J()}getSize(){return J()}setDisplacement(t){this.displacement_=t}setOpacity(t){this.opacity_=t}setRotateWithView(t){this.rotateWithView_=t}setRotation(t){this.rotation_=t}setScale(t){this.scale_=t,this.scaleArray_=Ft(t)}listenImageChange(t){J()}load(){J()}unlistenImageChange(t){J()}ready(){return Promise.resolve()}}const dn={name:"rgb",min:[0,0,0],max:[255,255,255],channel:["red","green","blue"],alias:["RGB"]},Ct={name:"xyz",min:[0,0,0],channel:["X","Y","Z"],alias:["XYZ","ciexyz","cie1931"],whitepoint:{2:{A:[109.85,100,35.585],C:[98.074,100,118.232],D50:[96.422,100,82.521],D55:[95.682,100,92.149],D65:[95.045592705167,100,108.9057750759878],D75:[94.972,100,122.638],F2:[99.187,100,67.395],F7:[95.044,100,108.755],F11:[100.966,100,64.37],E:[100,100,100]},10:{A:[111.144,100,35.2],C:[97.285,100,116.145],D50:[96.72,100,81.427],D55:[95.799,100,90.926],D65:[94.811,100,107.304],D75:[94.416,100,120.641],F2:[103.28,100,69.026],F7:[95.792,100,107.687],F11:[103.866,100,65.627],E:[100,100,100]}}};Ct.max=Ct.whitepoint[2].D65;Ct.rgb=function(s,t){t=t||Ct.whitepoint[2].E;var e=s[0]/t[0],i=s[1]/t[1],n=s[2]/t[2],r,o,a;return r=e*3.240969941904521+i*-1.537383177570093+n*-.498610760293,o=e*-.96924363628087+i*1.87596750150772+n*.041555057407175,a=e*.055630079696993+i*-.20397695888897+n*1.056971514242878,r=r>.0031308?1.055*Math.pow(r,1/2.4)-.055:r=r*12.92,o=o>.0031308?1.055*Math.pow(o,1/2.4)-.055:o=o*12.92,a=a>.0031308?1.055*Math.pow(a,1/2.4)-.055:a=a*12.92,r=Math.min(Math.max(0,r),1),o=Math.min(Math.max(0,o),1),a=Math.min(Math.max(0,a),1),[r*255,o*255,a*255]};dn.xyz=function(s,t){var e=s[0]/255,i=s[1]/255,n=s[2]/255;e=e>.04045?Math.pow((e+.055)/1.055,2.4):e/12.92,i=i>.04045?Math.pow((i+.055)/1.055,2.4):i/12.92,n=n>.04045?Math.pow((n+.055)/1.055,2.4):n/12.92;var r=e*.41239079926595+i*.35758433938387+n*.18048078840183,o=e*.21263900587151+i*.71516867876775+n*.072192315360733,a=e*.019330818715591+i*.11919477979462+n*.95053215224966;return t=t||Ct.whitepoint[2].E,[r*t[0],o*t[1],a*t[2]]};var Or={name:"luv",min:[0,-134,-140],max:[100,224,122],channel:["lightness","u","v"],alias:["LUV","cieluv","cie1976"],xyz:function(s,t,e){var i,n,r,o,a,l,c,h,u,d,f,g,_;if(r=s[0],o=s[1],a=s[2],r===0)return[0,0,0];var m=.0011070564598794539;return t=t||"D65",e=e||2,u=Ct.whitepoint[e][t][0],d=Ct.whitepoint[e][t][1],f=Ct.whitepoint[e][t][2],g=4*u/(u+15*d+3*f),_=9*d/(u+15*d+3*f),i=o/(13*r)+g||0,n=a/(13*r)+_||0,c=r>8?d*Math.pow((r+16)/116,3):d*r*m,l=c*9*i/(4*n)||0,h=c*(12-3*i-20*n)/(4*n)||0,[l,c,h]}};Ct.luv=function(s,t,e){var i,n,r,o,a,l,c,h,u,d,f,g,_,m=.008856451679035631,p=903.2962962962961;t=t||"D65",e=e||2,u=Ct.whitepoint[e][t][0],d=Ct.whitepoint[e][t][1],f=Ct.whitepoint[e][t][2],g=4*u/(u+15*d+3*f),_=9*d/(u+15*d+3*f),l=s[0],c=s[1],h=s[2],i=4*l/(l+15*c+3*h)||0,n=9*c/(l+15*c+3*h)||0;var y=c/d;return r=y<=m?p*y:116*Math.pow(y,1/3)-16,o=13*r*(i-g),a=13*r*(n-_),[r,o,a]};var Wa={name:"lchuv",channel:["lightness","chroma","hue"],alias:["LCHuv","cielchuv"],min:[0,0,0],max:[100,100,360],luv:function(s){var t=s[0],e=s[1],i=s[2],n,r,o;return o=i/360*2*Math.PI,n=e*Math.cos(o),r=e*Math.sin(o),[t,n,r]},xyz:function(s){return Or.xyz(Wa.luv(s))}};Or.lchuv=function(s){var t=s[0],e=s[1],i=s[2],n=Math.sqrt(e*e+i*i),r=Math.atan2(i,e),o=r*360/2/Math.PI;return o<0&&(o+=360),[t,n,o]};Ct.lchuv=function(s){return Or.lchuv(Ct.luv(s))};const Ro={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]};var Io={red:0,orange:60,yellow:120,green:180,blue:240,purple:300};function pc(s){var h,u;var t,e=[],i=1,n;if(typeof s=="number")return{space:"rgb",values:[s>>>16,(s&65280)>>>8,s&255],alpha:1};if(typeof s=="number")return{space:"rgb",values:[s>>>16,(s&65280)>>>8,s&255],alpha:1};if(s=String(s).toLowerCase(),Ro[s])e=Ro[s].slice(),n="rgb";else if(s==="transparent")i=0,n="rgb",e=[0,0,0];else if(s[0]==="#"){var r=s.slice(1),o=r.length,a=o<=4;i=1,a?(e=[parseInt(r[0]+r[0],16),parseInt(r[1]+r[1],16),parseInt(r[2]+r[2],16)],o===4&&(i=parseInt(r[3]+r[3],16)/255)):(e=[parseInt(r[0]+r[1],16),parseInt(r[2]+r[3],16),parseInt(r[4]+r[5],16)],o===8&&(i=parseInt(r[6]+r[7],16)/255)),e[0]||(e[0]=0),e[1]||(e[1]=0),e[2]||(e[2]=0),n="rgb"}else if(t=/^((?:rgba?|hs[lvb]a?|hwba?|cmyk?|xy[zy]|gray|lab|lchu?v?|[ly]uv|lms|oklch|oklab|color))\s*\(([^\)]*)\)/.exec(s)){var l=t[1];n=l.replace(/a$/,"");var c=n==="cmyk"?4:n==="gray"?1:3;e=t[2].trim().split(/\s*[,\/]\s*|\s+/),n==="color"&&(n=e.shift()),e=e.map(function(d,f){if(d[d.length-1]==="%")return d=parseFloat(d)/100,f===3?d:n==="rgb"?d*255:n[0]==="h"||n[0]==="l"&&!f?d*100:n==="lab"?d*125:n==="lch"?f<2?d*150:d*360:n[0]==="o"&&!f?d:n==="oklab"?d*.4:n==="oklch"?f<2?d*.4:d*360:d;if(n[f]==="h"||f===2&&n[n.length-1]==="h"){if(Io[d]!==void 0)return Io[d];if(d.endsWith("deg"))return parseFloat(d);if(d.endsWith("turn"))return parseFloat(d)*360;if(d.endsWith("grad"))return parseFloat(d)*360/400;if(d.endsWith("rad"))return parseFloat(d)*180/Math.PI}return d==="none"?0:parseFloat(d)}),i=e.length>c?e.pop():1}else/[0-9](?:\s|\/|,)/.test(s)&&(e=s.match(/([0-9]+)/g).map(function(d){return parseFloat(d)}),n=((u=(h=s.match(/([a-z])/ig))==null?void 0:h.join(""))==null?void 0:u.toLowerCase())||"rgb");return{space:n,values:e,alpha:i}}var Ns={name:"hsl",min:[0,0,0],max:[360,100,100],channel:["hue","saturation","lightness"],alias:["HSL"],rgb:function(s){var t=s[0]/360,e=s[1]/100,i=s[2]/100,n,r,o,a,l,c=0;if(e===0)return l=i*255,[l,l,l];for(r=i<.5?i*(1+e):i+e-i*e,n=2*i-r,a=[0,0,0];c<3;)o=t+1/3*-(c-1),o<0?o++:o>1&&o--,l=6*o<1?n+(r-n)*6*o:2*o<1?r:3*o<2?n+(r-n)*(2/3-o)*6:n,a[c++]=l*255;return a}};dn.hsl=function(s){var t=s[0]/255,e=s[1]/255,i=s[2]/255,n=Math.min(t,e,i),r=Math.max(t,e,i),o=r-n,a,l,c;return r===n?a=0:t===r?a=(e-i)/o:e===r?a=2+(i-t)/o:i===r&&(a=4+(t-e)/o),a=Math.min(a*60,360),a<0&&(a+=360),c=(n+r)/2,r===n?l=0:c<=.5?l=o/(r+n):l=o/(2-r-n),[a,l*100,c*100]};function yc(s){Array.isArray(s)&&s.raw&&(s=String.raw(...arguments)),s instanceof Number&&(s=+s);var t,e=pc(s);if(!e.space)return[];const i=e.space[0]==="h"?Ns.min:dn.min,n=e.space[0]==="h"?Ns.max:dn.max;return t=Array(3),t[0]=Math.min(Math.max(e.values[0],i[0]),n[0]),t[1]=Math.min(Math.max(e.values[1],i[1]),n[1]),t[2]=Math.min(Math.max(e.values[2],i[2]),n[2]),e.space[0]==="h"&&(t=Ns.rgb(t)),t.push(Math.min(Math.max(e.alpha,0),1)),t}function Ec(s){return typeof s=="string"?s:Dr(s)}const xc=1024,ji={};let Gs=0;function wc(s){if(s.length===4)return s;const t=s.slice();return t[3]=1,t}function So(s){const t=Ct.lchuv(dn.xyz(s));return t[3]=s[3],t}function Cc(s){const t=Ct.rgb(Wa.xyz(s));return t[3]=s[3],t}function Fr(s){if(ji.hasOwnProperty(s))return ji[s];if(Gs>=xc){let e=0;for(const i in ji)(e++&3)===0&&(delete ji[i],--Gs)}const t=yc(s);if(t.length!==4)throw new Error('Failed to parse "'+s+'" as color');for(const e of t)if(isNaN(e))throw new Error('Failed to parse "'+s+'" as color');return Xa(t),ji[s]=t,++Gs,t}function fn(s){return Array.isArray(s)?s:Fr(s)}function Xa(s){return s[0]=ht(s[0]+.5|0,0,255),s[1]=ht(s[1]+.5|0,0,255),s[2]=ht(s[2]+.5|0,0,255),s[3]=ht(s[3],0,1),s}function Dr(s){let t=s[0];t!=(t|0)&&(t=t+.5|0);let e=s[1];e!=(e|0)&&(e=e+.5|0);let i=s[2];i!=(i|0)&&(i=i+.5|0);const n=s[3]===void 0?1:Math.round(s[3]*1e3)/1e3;return"rgba("+t+","+e+","+i+","+n+")"}function vc(s){try{return Fr(s),!0}catch{return!1}}function gt(s,t,e,i){let n;return e&&e.length?n=e.shift():ba?n=new OffscreenCanvas(s||300,t||300):n=document.createElement("canvas"),s&&(n.width=s),t&&(n.height=t),n.getContext("2d",i)}let zs;function Qn(){return zs||(zs=gt(1,1)),zs}function ps(s){const t=s.canvas;t.width=1,t.height=1,s.clearRect(0,0,1,1)}function Tc(s){let t=s.offsetWidth;const e=getComputedStyle(s);return t+=parseInt(e.marginLeft,10)+parseInt(e.marginRight,10),t}function Rc(s){let t=s.offsetHeight;const e=getComputedStyle(s);return t+=parseInt(e.marginTop,10)+parseInt(e.marginBottom,10),t}function ts(s,t){const e=t.parentNode;e&&e.replaceChild(s,t)}function es(s){return s&&s.parentNode?s.parentNode.removeChild(s):null}function Ya(s){for(;s.lastChild;)s.removeChild(s.lastChild)}function Ic(s,t){const e=s.childNodes;for(let i=0;;++i){const n=e[i],r=t[i];if(!n&&!r)break;if(n!==r){if(!n){s.appendChild(r);continue}if(!r){s.removeChild(n),--i;continue}s.insertBefore(r,n)}}}function Sc(s,t,e){const i=s;let n=!0,r=!1,o=!1;const a=[on(i,z.LOAD,function(){o=!0,r||t()})];return i.src&&La?(r=!0,i.decode().then(function(){n&&t()}).catch(function(l){n&&(o?t():e())})):a.push(on(i,z.ERROR,e)),function(){n=!1,a.forEach(it)}}function bc(s,t){return new Promise((e,i)=>{function n(){o(),e(s)}function r(){o(),i(new Error("Image load error"))}function o(){s.removeEventListener("load",n),s.removeEventListener("error",r)}s.addEventListener("load",n),s.addEventListener("error",r)})}function Lc(s,t){return t&&(s.src=t),s.src&&La?new Promise((e,i)=>s.decode().then(()=>e(s)).catch(n=>s.complete&&s.width?e(s):i(n))):bc(s)}class Mc{constructor(){this.cache_={},this.patternCache_={},this.cacheSize_=0,this.maxCacheSize_=32}clear(){this.cache_={},this.patternCache_={},this.cacheSize_=0}canExpireCache(){return this.cacheSize_>this.maxCacheSize_}expire(){if(this.canExpireCache()){let t=0;for(const e in this.cache_){const i=this.cache_[e];(t++&3)===0&&!i.hasListener()&&(delete this.cache_[e],delete this.patternCache_[e],--this.cacheSize_)}}}get(t,e,i){const n=Ws(t,e,i);return n in this.cache_?this.cache_[n]:null}getPattern(t,e,i){const n=Ws(t,e,i);return n in this.patternCache_?this.patternCache_[n]:null}set(t,e,i,n,r){const o=Ws(t,e,i),a=o in this.cache_;this.cache_[o]=n,r&&(n.getImageState()===V.IDLE&&n.load(),n.getImageState()===V.LOADING?n.ready().then(()=>{this.patternCache_[o]=Qn().createPattern(n.getImage(1),"repeat")}):this.patternCache_[o]=Qn().createPattern(n.getImage(1),"repeat")),a||++this.cacheSize_}setSize(t){this.maxCacheSize_=t,this.expire()}}function Ws(s,t,e){const i=e?fn(e):"null";return t+":"+s+":"+i}const ne=new Mc;let qi=null;class Ac extends hs{constructor(t,e,i,n,r){super(),this.hitDetectionImage_=null,this.image_=t,this.crossOrigin_=i,this.canvas_={},this.color_=r,this.imageState_=n===void 0?V.IDLE:n,this.size_=t&&t.width&&t.height?[t.width,t.height]:null,this.src_=e,this.tainted_,this.ready_=null}initializeImage_(){this.image_=new Image,this.crossOrigin_!==null&&(this.image_.crossOrigin=this.crossOrigin_)}isTainted_(){if(this.tainted_===void 0&&this.imageState_===V.LOADED){qi||(qi=gt(1,1,void 0,{willReadFrequently:!0})),qi.drawImage(this.image_,0,0);try{qi.getImageData(0,0,1,1),this.tainted_=!1}catch{qi=null,this.tainted_=!0}}return this.tainted_===!0}dispatchChangeEvent_(){this.dispatchEvent(z.CHANGE)}handleImageError_(){this.imageState_=V.ERROR,this.dispatchChangeEvent_()}handleImageLoad_(){this.imageState_=V.LOADED,this.size_=[this.image_.width,this.image_.height],this.dispatchChangeEvent_()}getImage(t){return this.image_||this.initializeImage_(),this.replaceColor_(t),this.canvas_[t]?this.canvas_[t]:this.image_}getPixelRatio(t){return this.replaceColor_(t),this.canvas_[t]?t:1}getImageState(){return this.imageState_}getHitDetectionImage(){if(this.image_||this.initializeImage_(),!this.hitDetectionImage_)if(this.isTainted_()){const t=this.size_[0],e=this.size_[1],i=gt(t,e);i.fillRect(0,0,t,e),this.hitDetectionImage_=i.canvas}else this.hitDetectionImage_=this.image_;return this.hitDetectionImage_}getSize(){return this.size_}getSrc(){return this.src_}load(){if(this.imageState_===V.IDLE){this.image_||this.initializeImage_(),this.imageState_=V.LOADING;try{this.src_!==void 0&&(this.image_.src=this.src_)}catch{this.handleImageError_()}this.image_ instanceof HTMLImageElement&&Lc(this.image_,this.src_).then(t=>{this.image_=t,this.handleImageLoad_()}).catch(this.handleImageError_.bind(this))}}replaceColor_(t){if(!this.color_||this.canvas_[t]||this.imageState_!==V.LOADED)return;const e=this.image_,i=document.createElement("canvas");i.width=Math.ceil(e.width*t),i.height=Math.ceil(e.height*t);const n=i.getContext("2d");n.scale(t,t),n.drawImage(e,0,0),n.globalCompositeOperation="multiply",n.fillStyle=Ec(this.color_),n.fillRect(0,0,i.width/t,i.height/t),n.globalCompositeOperation="destination-in",n.drawImage(e,0,0),this.canvas_[t]=i}ready(){return this.ready_||(this.ready_=new Promise(t=>{this.imageState_===V.LOADED||this.imageState_===V.ERROR?t():this.addEventListener(z.CHANGE,function e(){(this.imageState_===V.LOADED||this.imageState_===V.ERROR)&&(this.removeEventListener(z.CHANGE,e),t())})})),this.ready_}}function kr(s,t,e,i,n,r){let o=t===void 0?void 0:ne.get(t,e,n);return o||(o=new Ac(s,s&&"src"in s?s.src||void 0:t,e,i,n),ne.set(t,e,n,o,r)),r&&o&&!ne.getPattern(t,e,n)&&ne.set(t,e,n,o,r),o}function se(s){return s?Array.isArray(s)?Dr(s):typeof s=="object"&&"src"in s?Pc(s):s:null}function Pc(s){if(!s.offset||!s.size)return ne.getPattern(s.src,"anonymous",s.color);const t=s.src+":"+s.offset,e=ne.getPattern(t,void 0,s.color);if(e)return e;const i=ne.get(s.src,"anonymous",null);if(i.getImageState()!==V.LOADED)return null;const n=gt(s.size[0],s.size[1]);return n.drawImage(i.getImage(1),s.offset[0],s.offset[1],s.size[0],s.size[1],0,0,s.size[0],s.size[1]),kr(n.canvas,t,void 0,V.LOADED,s.color,!0),ne.getPattern(t,void 0,s.color)}const Vn="ol-hidden",Oc="ol-selectable",ni="ol-unselectable",bn="ol-control",is="ol-collapsed",Fc=new RegExp(["^\\s*(?=(?:(?:[-a-z]+\\s*){0,2}(italic|oblique))?)","(?=(?:(?:[-a-z]+\\s*){0,2}(small-caps))?)","(?=(?:(?:[-a-z]+\\s*){0,2}(bold(?:er)?|lighter|[1-9]00 ))?)","(?:(?:normal|\\1|\\2|\\3)\\s*){0,3}((?:xx?-)?","(?:small|large)|medium|smaller|larger|[\\.\\d]+(?:\\%|in|[cem]m|ex|p[ctx]))","(?:\\s*\\/\\s*(normal|[\\.\\d]+(?:\\%|in|[cem]m|ex|p[ctx])?))",`?\\s*([-,\\"\\'\\sa-z]+?)\\s*$`].join(""),"i"),bo=["style","variant","weight","size","lineHeight","family"],Va=function(s){const t=s.match(Fc);if(!t)return null;const e={lineHeight:"normal",size:"1.2em",style:"normal",weight:"normal",variant:"normal"};for(let i=0,n=bo.length;iMath.max(n,ss(s,r)),0);return e[t]=i,i}function Nc(s,t){const e=[],i=[],n=[];let r=0,o=0,a=0,l=0;for(let c=0,h=t.length;c<=h;c+=2){const u=t[c];if(u===` +`||c===h){r=Math.max(r,o),n.push(o),o=0,a+=l,l=0;continue}const d=t[c+1]||s.font,f=ss(d,u);e.push(f),o+=f;const g=kc(d);i.push(g),l=Math.max(l,g)}return{width:r,height:a,widths:e,heights:i,lineWidths:n}}function Gc(s,t,e,i,n,r,o,a,l,c,h){s.save(),e!==1&&(s.globalAlpha===void 0?s.globalAlpha=u=>u.globalAlpha*=e:s.globalAlpha*=e),t&&s.transform.apply(s,t),i.contextInstructions?(s.translate(l,c),s.scale(h[0],h[1]),zc(i,s)):h[0]<0||h[1]<0?(s.translate(l,c),s.scale(h[0],h[1]),s.drawImage(i,n,r,o,a,0,0,o,a)):s.drawImage(i,n,r,o,a,l,c,o*h[0],a*h[1]),s.restore()}function zc(s,t){const e=s.contextInstructions;for(let i=0,n=e.length;ithis.imageState_=V.LOADED),this.render()}clone(){const t=this.getScale(),e=new ys({fill:this.getFill()?this.getFill().clone():void 0,points:this.getPoints(),radius:this.getRadius(),radius2:this.getRadius2(),angle:this.getAngle(),stroke:this.getStroke()?this.getStroke().clone():void 0,rotation:this.getRotation(),rotateWithView:this.getRotateWithView(),scale:Array.isArray(t)?t.slice():t,displacement:this.getDisplacement().slice(),declutterMode:this.getDeclutterMode()});return e.setOpacity(this.getOpacity()),e}getAnchor(){const t=this.size_,e=this.getDisplacement(),i=this.getScaleArray();return[t[0]/2-e[0]/i[0],t[1]/2+e[1]/i[1]]}getAngle(){return this.angle_}getFill(){return this.fill_}setFill(t){this.fill_=t,this.render()}getHitDetectionImage(){return this.hitDetectionCanvas_||(this.hitDetectionCanvas_=this.createHitDetectionCanvas_(this.renderOptions_)),this.hitDetectionCanvas_}getImage(t){let e=this.canvases_[t];if(!e){const i=this.renderOptions_,n=gt(i.size*t,i.size*t);this.draw_(i,n,t),e=n.canvas,this.canvases_[t]=e}return e}getPixelRatio(t){return t}getImageSize(){return this.size_}getImageState(){return this.imageState_}getOrigin(){return this.origin_}getPoints(){return this.points_}getRadius(){return this.radius_}getRadius2(){return this.radius2_}getSize(){return this.size_}getStroke(){return this.stroke_}setStroke(t){this.stroke_=t,this.render()}listenImageChange(t){}load(){}unlistenImageChange(t){}calculateLineJoinSize_(t,e,i){if(e===0||this.points_===1/0||t!=="bevel"&&t!=="miter")return e;let n=this.radius_,r=this.radius2_===void 0?n:this.radius2_;if(n{this.patternImage_=null}),e.getImageState()===V.IDLE&&e.load(),e.getImageState()===V.LOADING&&(this.patternImage_=e)}this.color_=t}loading(){return!!this.patternImage_}ready(){return this.patternImage_?this.patternImage_.ready():Promise.resolve()}}class xe{constructor(t){t=t||{},this.color_=t.color!==void 0?t.color:null,this.lineCap_=t.lineCap,this.lineDash_=t.lineDash!==void 0?t.lineDash:null,this.lineDashOffset_=t.lineDashOffset,this.lineJoin_=t.lineJoin,this.miterLimit_=t.miterLimit,this.width_=t.width}clone(){const t=this.getColor();return new xe({color:Array.isArray(t)?t.slice():t||void 0,lineCap:this.getLineCap(),lineDash:this.getLineDash()?this.getLineDash().slice():void 0,lineDashOffset:this.getLineDashOffset(),lineJoin:this.getLineJoin(),miterLimit:this.getMiterLimit(),width:this.getWidth()})}getColor(){return this.color_}getLineCap(){return this.lineCap_}getLineDash(){return this.lineDash_}getLineDashOffset(){return this.lineDashOffset_}getLineJoin(){return this.lineJoin_}getMiterLimit(){return this.miterLimit_}getWidth(){return this.width_}setColor(t){this.color_=t}setLineCap(t){this.lineCap_=t}setLineDash(t){this.lineDash_=t}setLineDashOffset(t){this.lineDashOffset_=t}setLineJoin(t){this.lineJoin_=t}setMiterLimit(t){this.miterLimit_=t}setWidth(t){this.width_=t}}class Gt{constructor(t){t=t||{},this.geometry_=null,this.geometryFunction_=Mo,t.geometry!==void 0&&this.setGeometry(t.geometry),this.fill_=t.fill!==void 0?t.fill:null,this.image_=t.image!==void 0?t.image:null,this.renderer_=t.renderer!==void 0?t.renderer:null,this.hitDetectionRenderer_=t.hitDetectionRenderer!==void 0?t.hitDetectionRenderer:null,this.stroke_=t.stroke!==void 0?t.stroke:null,this.text_=t.text!==void 0?t.text:null,this.zIndex_=t.zIndex}clone(){let t=this.getGeometry();return t&&typeof t=="object"&&(t=t.clone()),new Gt({geometry:t??void 0,fill:this.getFill()?this.getFill().clone():void 0,image:this.getImage()?this.getImage().clone():void 0,renderer:this.getRenderer()??void 0,stroke:this.getStroke()?this.getStroke().clone():void 0,text:this.getText()?this.getText().clone():void 0,zIndex:this.getZIndex()})}getRenderer(){return this.renderer_}setRenderer(t){this.renderer_=t}setHitDetectionRenderer(t){this.hitDetectionRenderer_=t}getHitDetectionRenderer(){return this.hitDetectionRenderer_}getGeometry(){return this.geometry_}getGeometryFunction(){return this.geometryFunction_}getFill(){return this.fill_}setFill(t){this.fill_=t}getImage(){return this.image_}setImage(t){this.image_=t}getStroke(){return this.stroke_}setStroke(t){this.stroke_=t}getText(){return this.text_}setText(t){this.text_=t}getZIndex(){return this.zIndex_}setGeometry(t){typeof t=="function"?this.geometryFunction_=t:typeof t=="string"?this.geometryFunction_=function(e){return e.get(t)}:t?t!==void 0&&(this.geometryFunction_=function(){return t}):this.geometryFunction_=Mo,this.geometry_=t}setZIndex(t){this.zIndex_=t}}function Wc(s){let t;if(typeof s=="function")t=s;else{let e;Array.isArray(s)?e=s:($(typeof s.getZIndex=="function","Expected an `Style` or an array of `Style`"),e=[s]),t=function(){return e}}return t}let Xs=null;function Ua(s,t){if(!Xs){const e=new ve({color:"rgba(255,255,255,0.4)"}),i=new xe({color:"#3399CC",width:1.25});Xs=[new Gt({image:new si({fill:e,stroke:i,radius:5}),fill:e,stroke:i})]}return Xs}function Xc(){const s={},t=[255,255,255,1],e=[0,153,255,1],i=3;return s.Polygon=[new Gt({fill:new ve({color:[255,255,255,.5]})})],s.MultiPolygon=s.Polygon,s.LineString=[new Gt({stroke:new xe({color:t,width:i+2})}),new Gt({stroke:new xe({color:e,width:i})})],s.MultiLineString=s.LineString,s.Circle=s.Polygon.concat(s.LineString),s.Point=[new Gt({image:new si({radius:i*2,fill:new ve({color:e}),stroke:new xe({color:t,width:i/2})}),zIndex:1/0})],s.MultiPoint=s.Point,s.GeometryCollection=s.Polygon.concat(s.LineString,s.Point),s}function Mo(s){return s.getGeometry()}function Ao(s,t,e,i){return e!==void 0&&i!==void 0?[e/s,i/t]:e!==void 0?e/s:i!==void 0?i/t:1}class Es extends ms{constructor(t){t=t||{};const e=t.opacity!==void 0?t.opacity:1,i=t.rotation!==void 0?t.rotation:0,n=t.scale!==void 0?t.scale:1,r=t.rotateWithView!==void 0?t.rotateWithView:!1;super({opacity:e,rotation:i,scale:n,displacement:t.displacement!==void 0?t.displacement:[0,0],rotateWithView:r,declutterMode:t.declutterMode}),this.anchor_=t.anchor!==void 0?t.anchor:[.5,.5],this.normalizedAnchor_=null,this.anchorOrigin_=t.anchorOrigin!==void 0?t.anchorOrigin:"top-left",this.anchorXUnits_=t.anchorXUnits!==void 0?t.anchorXUnits:"fraction",this.anchorYUnits_=t.anchorYUnits!==void 0?t.anchorYUnits:"fraction",this.crossOrigin_=t.crossOrigin!==void 0?t.crossOrigin:null;const o=t.img!==void 0?t.img:null;let a=t.src;$(!(a!==void 0&&o),"`image` and `src` cannot be provided at the same time"),(a===void 0||a.length===0)&&o&&(a=o.src||U(o)),$(a!==void 0&&a.length>0,"A defined and non-empty `src` or `image` must be provided"),$(!((t.width!==void 0||t.height!==void 0)&&t.scale!==void 0),"`width` or `height` cannot be provided together with `scale`");let l;if(t.src!==void 0?l=V.IDLE:o!==void 0&&("complete"in o?o.complete?l=o.src?V.LOADED:V.IDLE:l=V.LOADING:l=V.LOADED),this.color_=t.color!==void 0?fn(t.color):null,this.iconImage_=kr(o,a,this.crossOrigin_,l,this.color_),this.offset_=t.offset!==void 0?t.offset:[0,0],this.offsetOrigin_=t.offsetOrigin!==void 0?t.offsetOrigin:"top-left",this.origin_=null,this.size_=t.size!==void 0?t.size:null,t.width!==void 0||t.height!==void 0){let c,h;if(t.size)[c,h]=t.size;else{const u=this.getImage(1);if(u.width&&u.height)c=u.width,h=u.height;else if(u instanceof HTMLImageElement){this.initialOptions_=t;const d=()=>{if(this.unlistenImageChange(d),!this.initialOptions_)return;const f=this.iconImage_.getSize();this.setScale(Ao(f[0],f[1],t.width,t.height))};this.listenImageChange(d);return}}c!==void 0&&this.setScale(Ao(c,h,t.width,t.height))}}clone(){let t,e,i;return this.initialOptions_?(e=this.initialOptions_.width,i=this.initialOptions_.height):(t=this.getScale(),t=Array.isArray(t)?t.slice():t),new Es({anchor:this.anchor_.slice(),anchorOrigin:this.anchorOrigin_,anchorXUnits:this.anchorXUnits_,anchorYUnits:this.anchorYUnits_,color:this.color_&&this.color_.slice?this.color_.slice():this.color_||void 0,crossOrigin:this.crossOrigin_,offset:this.offset_.slice(),offsetOrigin:this.offsetOrigin_,opacity:this.getOpacity(),rotateWithView:this.getRotateWithView(),rotation:this.getRotation(),scale:t,width:e,height:i,size:this.size_!==null?this.size_.slice():void 0,src:this.getSrc(),displacement:this.getDisplacement().slice(),declutterMode:this.getDeclutterMode()})}getAnchor(){let t=this.normalizedAnchor_;if(!t){t=this.anchor_;const n=this.getSize();if(this.anchorXUnits_=="fraction"||this.anchorYUnits_=="fraction"){if(!n)return null;t=this.anchor_.slice(),this.anchorXUnits_=="fraction"&&(t[0]*=n[0]),this.anchorYUnits_=="fraction"&&(t[1]*=n[1])}if(this.anchorOrigin_!="top-left"){if(!n)return null;t===this.anchor_&&(t=this.anchor_.slice()),(this.anchorOrigin_=="top-right"||this.anchorOrigin_=="bottom-right")&&(t[0]=-t[0]+n[0]),(this.anchorOrigin_=="bottom-left"||this.anchorOrigin_=="bottom-right")&&(t[1]=-t[1]+n[1])}this.normalizedAnchor_=t}const e=this.getDisplacement(),i=this.getScaleArray();return[t[0]-e[0]/i[0],t[1]+e[1]/i[1]]}setAnchor(t){this.anchor_=t,this.normalizedAnchor_=null}getColor(){return this.color_}getImage(t){return this.iconImage_.getImage(t)}getPixelRatio(t){return this.iconImage_.getPixelRatio(t)}getImageSize(){return this.iconImage_.getSize()}getImageState(){return this.iconImage_.getImageState()}getHitDetectionImage(){return this.iconImage_.getHitDetectionImage()}getOrigin(){if(this.origin_)return this.origin_;let t=this.offset_;if(this.offsetOrigin_!="top-left"){const e=this.getSize(),i=this.iconImage_.getSize();if(!e||!i)return null;t=t.slice(),(this.offsetOrigin_=="top-right"||this.offsetOrigin_=="bottom-right")&&(t[0]=i[0]-e[0]-t[0]),(this.offsetOrigin_=="bottom-left"||this.offsetOrigin_=="bottom-right")&&(t[1]=i[1]-e[1]-t[1])}return this.origin_=t,this.origin_}getSrc(){return this.iconImage_.getSrc()}getSize(){return this.size_?this.size_:this.iconImage_.getSize()}getWidth(){const t=this.getScaleArray();if(this.size_)return this.size_[0]*t[0];if(this.iconImage_.getImageState()==V.LOADED)return this.iconImage_.getSize()[0]*t[0]}getHeight(){const t=this.getScaleArray();if(this.size_)return this.size_[1]*t[1];if(this.iconImage_.getImageState()==V.LOADED)return this.iconImage_.getSize()[1]*t[1]}setScale(t){delete this.initialOptions_,super.setScale(t)}listenImageChange(t){this.iconImage_.addEventListener(z.CHANGE,t)}load(){this.iconImage_.load()}unlistenImageChange(t){this.iconImage_.removeEventListener(z.CHANGE,t)}ready(){return this.iconImage_.ready()}}const Yc="#333";class Nr{constructor(t){t=t||{},this.font_=t.font,this.rotation_=t.rotation,this.rotateWithView_=t.rotateWithView,this.scale_=t.scale,this.scaleArray_=Ft(t.scale!==void 0?t.scale:1),this.text_=t.text,this.textAlign_=t.textAlign,this.justify_=t.justify,this.repeat_=t.repeat,this.textBaseline_=t.textBaseline,this.fill_=t.fill!==void 0?t.fill:new ve({color:Yc}),this.maxAngle_=t.maxAngle!==void 0?t.maxAngle:Math.PI/4,this.placement_=t.placement!==void 0?t.placement:"point",this.overflow_=!!t.overflow,this.stroke_=t.stroke!==void 0?t.stroke:null,this.offsetX_=t.offsetX!==void 0?t.offsetX:0,this.offsetY_=t.offsetY!==void 0?t.offsetY:0,this.backgroundFill_=t.backgroundFill?t.backgroundFill:null,this.backgroundStroke_=t.backgroundStroke?t.backgroundStroke:null,this.padding_=t.padding===void 0?null:t.padding,this.declutterMode_=t.declutterMode}clone(){const t=this.getScale();return new Nr({font:this.getFont(),placement:this.getPlacement(),repeat:this.getRepeat(),maxAngle:this.getMaxAngle(),overflow:this.getOverflow(),rotation:this.getRotation(),rotateWithView:this.getRotateWithView(),scale:Array.isArray(t)?t.slice():t,text:this.getText(),textAlign:this.getTextAlign(),justify:this.getJustify(),textBaseline:this.getTextBaseline(),fill:this.getFill()?this.getFill().clone():void 0,stroke:this.getStroke()?this.getStroke().clone():void 0,offsetX:this.getOffsetX(),offsetY:this.getOffsetY(),backgroundFill:this.getBackgroundFill()?this.getBackgroundFill().clone():void 0,backgroundStroke:this.getBackgroundStroke()?this.getBackgroundStroke().clone():void 0,padding:this.getPadding()||void 0,declutterMode:this.getDeclutterMode()})}getOverflow(){return this.overflow_}getFont(){return this.font_}getMaxAngle(){return this.maxAngle_}getPlacement(){return this.placement_}getRepeat(){return this.repeat_}getOffsetX(){return this.offsetX_}getOffsetY(){return this.offsetY_}getFill(){return this.fill_}getRotateWithView(){return this.rotateWithView_}getRotation(){return this.rotation_}getScale(){return this.scale_}getScaleArray(){return this.scaleArray_}getStroke(){return this.stroke_}getText(){return this.text_}getTextAlign(){return this.textAlign_}getJustify(){return this.justify_}getTextBaseline(){return this.textBaseline_}getBackgroundFill(){return this.backgroundFill_}getBackgroundStroke(){return this.backgroundStroke_}getPadding(){return this.padding_}getDeclutterMode(){return this.declutterMode_}setOverflow(t){this.overflow_=t}setFont(t){this.font_=t}setMaxAngle(t){this.maxAngle_=t}setOffsetX(t){this.offsetX_=t}setOffsetY(t){this.offsetY_=t}setPlacement(t){this.placement_=t}setRepeat(t){this.repeat_=t}setRotateWithView(t){this.rotateWithView_=t}setFill(t){this.fill_=t}setRotation(t){this.rotation_=t}setScale(t){this.scale_=t,this.scaleArray_=Ft(t!==void 0?t:1)}setStroke(t){this.stroke_=t}setText(t){this.text_=t}setTextAlign(t){this.textAlign_=t}setJustify(t){this.justify_=t}setTextBaseline(t){this.textBaseline_=t}setBackgroundFill(t){this.backgroundFill_=t}setBackgroundStroke(t){this.backgroundStroke_=t}setPadding(t){this.padding_=t}}let ri=0;const Gi=0,ot=1<",GreaterThanOrEqualTo:">=",LessThan:"<",LessThanOrEqualTo:"<=",Multiply:"*",Divide:"/",Add:"+",Subtract:"-",Clamp:"clamp",Mod:"%",Pow:"^",Abs:"abs",Floor:"floor",Ceil:"ceil",Round:"round",Sin:"sin",Cos:"cos",Atan:"atan",Sqrt:"sqrt",Match:"match",Between:"between",Interpolate:"interpolate",Coalesce:"coalesce",Case:"case",In:"in",Number:"number",String:"string",Array:"array",Color:"color",Id:"id",Band:"band",Palette:"palette",ToString:"to-string"},Kc={[C.Get]:N(([s,t])=>t!==void 0?Uc(t.value):xt,X(1,2),jc),[C.Var]:N(([s])=>s.type,X(1,1),qc),[C.Id]:N(L|kt,Hi,Hc),[C.Concat]:N(kt,X(2,1/0),H(xt)),[C.GeometryType]:N(kt,Hi,$c),[C.Resolution]:N(L,Hi),[C.Zoom]:N(L,Hi),[C.Time]:N(L,Hi),[C.Any]:N(ot,X(2,1/0),H(ot)),[C.All]:N(ot,X(2,1/0),H(ot)),[C.Not]:N(ot,X(1,1),H(ot)),[C.Equal]:N(ot,X(2,2),H(xt),Se),[C.NotEqual]:N(ot,X(2,2),H(xt),Se),[C.GreaterThan]:N(ot,X(2,2),H(xt),Se),[C.GreaterThanOrEqualTo]:N(ot,X(2,2),H(xt),Se),[C.LessThan]:N(ot,X(2,2),H(xt),Se),[C.LessThanOrEqualTo]:N(ot,X(2,2),H(xt),Se),[C.Multiply]:N(s=>{let t=L|dt;for(let e=0;e{let t=xt;for(let e=1;e{let t=xt;for(let e=2;e{let t=dt|L;for(let e=3;e{let t=xt;for(let e=1;es.length===2?re|sn:s.length===3||s.length===4?re|dt:re,X(1,1/0),H(L)),[C.Color]:N(dt,X(1,4),H(L)),[C.Band]:N(L,X(1,3),H(L)),[C.Palette]:N(dt,X(2,2),nu),[C.ToString]:N(kt,X(1,1),H(ot|L|kt|dt))};function jc(s,t){const e=Q(s[1],t);if(!(e instanceof ke))throw new Error("Expected a literal argument for get operation");if(typeof e.value!="string")throw new Error("Expected a string argument for get operation");if(t.properties.add(e.value),s.length===3){const i=Q(s[2],t);return[e,i]}return[e]}function qc(s,t,e,i){const n=s[1];if(typeof n!="string")throw new Error("Expected a string argument for var operation");if(t.variables.add(n),!("variables"in t.style)||t.style.variables[n]===void 0)return[new ke(xt,n)];const r=t.style.variables[n],o=Q(r,t);if(o.value=n,i&&!oe(i,o.type))throw new Error(`The variable ${n} has type ${vt(o.type)} but the following type was expected: ${vt(i)}`);return[o]}function Hc(s,t){t.featureId=!0}function $c(s,t){t.geometryType=!0}function Hi(s,t){const e=s[0];if(s.length!==1)throw new Error(`Expected no arguments for ${e} operation`);return[]}function X(s,t){return function(e,i){const n=e[0],r=e.length-1;if(s===t){if(r!==s){const o=s===1?"":"s";throw new Error(`Expected ${s} argument${o} for ${n}, got ${r}`)}}else if(rt){const o=t===1/0?`${s} or more`:`${s} to ${t}`;throw new Error(`Expected ${o} arguments for ${n}, got ${r}`)}}}function H(s){return function(t,e){const i=t[0],n=t.length-1,r=new Array(n);for(let o=0;oi.featureId;case C.GeometryType:return i=>i.geometryType;case C.Concat:{const i=s.args.map(n=>Jt(n));return n=>"".concat(...i.map(r=>r(n).toString()))}case C.Resolution:return i=>i.resolution;case C.Any:case C.All:case C.Between:case C.In:case C.Not:return lu(s);case C.Equal:case C.NotEqual:case C.LessThan:case C.LessThanOrEqualTo:case C.GreaterThan:case C.GreaterThanOrEqualTo:return au(s);case C.Multiply:case C.Divide:case C.Add:case C.Subtract:case C.Clamp:case C.Mod:case C.Pow:case C.Abs:case C.Floor:case C.Ceil:case C.Round:case C.Sin:case C.Cos:case C.Atan:case C.Sqrt:return hu(s);case C.Case:return cu(s);case C.Match:return uu(s);case C.Interpolate:return du(s);case C.ToString:return fu(s);default:throw new Error(`Unsupported operator ${e}`)}}function ru(s,t){const e=s.operator,i=s.args.length,n=new Array(i);for(let r=0;r{for(let o=0;o{for(let o=0;on.properties[i];case C.Var:return n=>n.variables[i];default:throw new Error(`Unsupported accessor operator ${s.operator}`)}}function au(s,t){const e=s.operator,i=Jt(s.args[0]),n=Jt(s.args[1]);switch(e){case C.Equal:return r=>i(r)===n(r);case C.NotEqual:return r=>i(r)!==n(r);case C.LessThan:return r=>i(r)i(r)<=n(r);case C.GreaterThan:return r=>i(r)>n(r);case C.GreaterThanOrEqualTo:return r=>i(r)>=n(r);default:throw new Error(`Unsupported comparison operator ${e}`)}}function lu(s,t){const e=s.operator,i=s.args.length,n=new Array(i);for(let r=0;r{for(let o=0;o{for(let o=0;o{const o=n[0](r),a=n[1](r),l=n[2](r);return o>=a&&o<=l};case C.In:return r=>{const o=n[0](r);for(let a=1;a!n[0](r);default:throw new Error(`Unsupported logical operator ${e}`)}}function hu(s,t){const e=s.operator,i=s.args.length,n=new Array(i);for(let r=0;r{let o=1;for(let a=0;an[0](r)/n[1](r);case C.Add:return r=>{let o=0;for(let a=0;an[0](r)-n[1](r);case C.Clamp:return r=>{const o=n[0](r),a=n[1](r);if(ol?l:o};case C.Mod:return r=>n[0](r)%n[1](r);case C.Pow:return r=>Math.pow(n[0](r),n[1](r));case C.Abs:return r=>Math.abs(n[0](r));case C.Floor:return r=>Math.floor(n[0](r));case C.Ceil:return r=>Math.ceil(n[0](r));case C.Round:return r=>Math.round(n[0](r));case C.Sin:return r=>Math.sin(n[0](r));case C.Cos:return r=>Math.cos(n[0](r));case C.Atan:return i===2?r=>Math.atan2(n[0](r),n[1](r)):r=>Math.atan(n[0](r));case C.Sqrt:return r=>Math.sqrt(n[0](r));default:throw new Error(`Unsupported numeric operator ${e}`)}}function cu(s,t){const e=s.args.length,i=new Array(e);for(let n=0;n{for(let r=0;r{const r=i[0](n);for(let o=1;o{const r=i[0](n),o=i[1](n);let a,l;for(let c=2;c=o)return c===2?u:d?gu(r,o,a,l,h,u):tn(r,o,a,l,h,u);a=h,l=u}return l}}function fu(s,t){const e=s.operator,i=s.args.length,n=new Array(i);for(let r=0;r{const o=n[0](r);return s.args[0].type===dt?Dr(o):o.toString()};default:throw new Error(`Unsupported convert operator ${e}`)}}function tn(s,t,e,i,n,r){const o=n-e;if(o===0)return i;const a=t-e,l=s===1?a/o:(Math.pow(s,a)-1)/(Math.pow(s,o)-1);return i+l*(r-i)}function gu(s,t,e,i,n,r){if(n-e===0)return i;const a=So(i),l=So(r);let c=l[2]-a[2];c>180?c-=360:c<-180&&(c+=360);const h=[tn(s,t,e,a[0],n,l[0]),tn(s,t,e,a[1],n,l[1]),a[2]+tn(s,t,e,0,n,c),tn(s,t,e,i[3],n,r[3])];return Xa(Cc(h))}function _u(s){return!0}function mu(s){const t=ja(),e=pu(s,t),i=Ha();return function(n,r){if(i.properties=n.getPropertiesInternal(),i.resolution=r,t.featureId){const o=n.getId();o!==void 0?i.featureId=o:i.featureId=null}return t.geometryType&&(i.geometryType=qa(n.getGeometry())),e(i)}}function Oo(s){const t=ja(),e=s.length,i=new Array(e);for(let o=0;o4)throw new Error(`Expected a color with 3 or 4 values for ${t}`);return e}function tl(s,t){const e=Ln(s,t);if(e.length!==2)throw new Error(`Expected an array of two numbers for ${t}`);return e}function bu(s,t){return typeof s=="number"?s:tl(s,t)}const No={RENDER_ORDER:"renderOrder"};class el extends _s{constructor(t){t=t||{};const e=Object.assign({},t);delete e.style,delete e.renderBuffer,delete e.updateWhileAnimating,delete e.updateWhileInteracting,super(e),this.declutter_=t.declutter?String(t.declutter):void 0,this.renderBuffer_=t.renderBuffer!==void 0?t.renderBuffer:100,this.style_=null,this.styleFunction_=void 0,this.setStyle(t.style),this.updateWhileAnimating_=t.updateWhileAnimating!==void 0?t.updateWhileAnimating:!1,this.updateWhileInteracting_=t.updateWhileInteracting!==void 0?t.updateWhileInteracting:!1}getDeclutter(){return this.declutter_}getFeatures(t){return super.getFeatures(t)}getRenderBuffer(){return this.renderBuffer_}getRenderOrder(){return this.get(No.RENDER_ORDER)}getStyle(){return this.style_}getStyleFunction(){return this.styleFunction_}getUpdateWhileAnimating(){return this.updateWhileAnimating_}getUpdateWhileInteracting(){return this.updateWhileInteracting_}renderDeclutter(t,e){const i=this.getDeclutter();i in t.declutter||(t.declutter[i]=new za(9)),this.getRenderer().renderDeclutter(t,e)}setRenderOrder(t){this.set(No.RENDER_ORDER,t)}setStyle(t){this.style_=t===void 0?Ua:t;const e=Lu(t);this.styleFunction_=t===null?void 0:Wc(e),this.changed()}}function Lu(s){if(s===void 0)return Ua;if(!s)return null;if(typeof s=="function"||s instanceof Gt)return s;if(!Array.isArray(s))return Oo([s]);if(s.length===0)return[];const t=s.length,e=s[0];if(e instanceof Gt){const n=new Array(t);for(let r=0;r=0;--x){const v=_[x],T=v.layer;if(T.hasRenderer()&&Pr(v,h)&&a.call(l,T)){const R=T.getRenderer(),I=T.getSource();if(R&&I){const F=I.getWrapX()?f:t,O=u.bind(null,v.managed);y[0]=F[0]+g[w][0],y[1]=F[1]+g[w][1],c=R.forEachFeatureAtCoordinate(y,e,i,O,p)}if(c)return c}}if(p.length===0)return;const E=1/p.length;return p.forEach((w,x)=>w.distanceSq+=x*E),p.sort((w,x)=>w.distanceSq-x.distanceSq),p.some(w=>c=w.callback(w.feature,w.layer,w.geometry)),c}hasFeatureAtCoordinate(t,e,i,n,r,o){return this.forEachFeatureAtCoordinate(t,e,i,n,ei,this,r,o)!==void 0}getMap(){return this.map_}renderFrame(t){J()}scheduleExpireIconCache(t){ne.canExpireCache()&&t.postRenderFunctions.push(Au)}}function Au(s,t){ne.expire()}class il extends ae{constructor(t,e,i,n){super(t),this.inversePixelTransform=e,this.frameState=i,this.context=n}}class Pu extends Mu{constructor(t){super(t),this.fontChangeListenerKey_=q(ge,ti.PROPERTYCHANGE,t.redrawText.bind(t)),this.element_=document.createElement("div");const e=this.element_.style;e.position="absolute",e.width="100%",e.height="100%",e.zIndex="0",this.element_.className=ni+" ol-layers";const i=t.getViewport();i.insertBefore(this.element_,i.firstChild||null),this.children_=[],this.renderedVisible_=!0}dispatchRenderEvent(t,e){const i=this.getMap();if(i.hasListener(t)){const n=new il(t,void 0,e);i.dispatchEvent(n)}}disposeInternal(){it(this.fontChangeListenerKey_),this.element_.parentNode.removeChild(this.element_),super.disposeInternal()}renderFrame(t){if(!t){this.renderedVisible_&&(this.element_.style.display="none",this.renderedVisible_=!1);return}this.calculateMatrices2D(t),this.dispatchRenderEvent(jt.PRECOMPOSE,t);const e=t.layerStatesArray.sort(function(a,l){return a.zIndex-l.zIndex});e.some(a=>a.layer instanceof el&&a.layer.getDeclutter())&&(t.declutter={});const n=t.viewState;this.children_.length=0;const r=[];let o=null;for(let a=0,l=e.length;a=0;--i){const n=e[i],r=n.layer;r.getDeclutter()&&r.renderDeclutter(t,n)}e.forEach(i=>i.layer.renderDeferred(t))}}}class Ei extends ae{constructor(t,e,i){super(t),this.map=e,this.frameState=i!==void 0?i:null}}class Pe extends Ei{constructor(t,e,i,n,r,o){super(t,e,r),this.originalEvent=i,this.pixel_=null,this.coordinate_=null,this.dragging=n!==void 0?n:!1,this.activePointers=o}get pixel(){return this.pixel_||(this.pixel_=this.map.getEventPixel(this.originalEvent)),this.pixel_}set pixel(t){this.pixel_=t}get coordinate(){return this.coordinate_||(this.coordinate_=this.map.getCoordinateFromPixel(this.pixel)),this.coordinate_}set coordinate(t){this.coordinate_=t}preventDefault(){super.preventDefault(),"preventDefault"in this.originalEvent&&this.originalEvent.preventDefault()}stopPropagation(){super.stopPropagation(),"stopPropagation"in this.originalEvent&&this.originalEvent.stopPropagation()}}const hr={POINTERMOVE:"pointermove",POINTERDOWN:"pointerdown"};class Ou extends hs{constructor(t,e){super(t),this.map_=t,this.clickTimeoutId_,this.emulateClicks_=!1,this.dragging_=!1,this.dragListenerKeys_=[],this.moveTolerance_=e===void 0?1:e,this.down_=null;const i=this.map_.getViewport();this.activePointers_=[],this.trackedTouches_={},this.element_=i,this.pointerdownListenerKey_=q(i,hr.POINTERDOWN,this.handlePointerDown_,this),this.originalPointerMoveEvent_,this.relayedListenerKey_=q(i,hr.POINTERMOVE,this.relayMoveEvent_,this),this.boundHandleTouchMove_=this.handleTouchMove_.bind(this),this.element_.addEventListener(z.TOUCHMOVE,this.boundHandleTouchMove_,Ma?{passive:!1}:!1)}emulateClick_(t){let e=new Pe(st.CLICK,this.map_,t);this.dispatchEvent(e),this.clickTimeoutId_!==void 0?(clearTimeout(this.clickTimeoutId_),this.clickTimeoutId_=void 0,e=new Pe(st.DBLCLICK,this.map_,t),this.dispatchEvent(e)):this.clickTimeoutId_=setTimeout(()=>{this.clickTimeoutId_=void 0;const i=new Pe(st.SINGLECLICK,this.map_,t);this.dispatchEvent(i)},250)}updateActivePointers_(t){const e=t,i=e.pointerId;if(e.type==st.POINTERUP||e.type==st.POINTERCANCEL){delete this.trackedTouches_[i];for(const n in this.trackedTouches_)if(this.trackedTouches_[n].target!==e.target){delete this.trackedTouches_[n];break}}else(e.type==st.POINTERDOWN||e.type==st.POINTERMOVE)&&(this.trackedTouches_[i]=e);this.activePointers_=Object.values(this.trackedTouches_)}handlePointerUp_(t){this.updateActivePointers_(t);const e=new Pe(st.POINTERUP,this.map_,t,void 0,void 0,this.activePointers_);this.dispatchEvent(e),this.emulateClicks_&&!e.defaultPrevented&&!this.dragging_&&this.isMouseActionButton_(t)&&this.emulateClick_(this.down_),this.activePointers_.length===0&&(this.dragListenerKeys_.forEach(it),this.dragListenerKeys_.length=0,this.dragging_=!1,this.down_=null)}isMouseActionButton_(t){return t.button===0}handlePointerDown_(t){this.emulateClicks_=this.activePointers_.length===0,this.updateActivePointers_(t);const e=new Pe(st.POINTERDOWN,this.map_,t,void 0,void 0,this.activePointers_);if(this.dispatchEvent(e),this.down_=new PointerEvent(t.type,t),Object.defineProperty(this.down_,"target",{writable:!1,value:t.target}),this.dragListenerKeys_.length===0){const i=this.map_.getOwnerDocument();this.dragListenerKeys_.push(q(i,st.POINTERMOVE,this.handlePointerMove_,this),q(i,st.POINTERUP,this.handlePointerUp_,this),q(this.element_,st.POINTERCANCEL,this.handlePointerUp_,this)),this.element_.getRootNode&&this.element_.getRootNode()!==i&&this.dragListenerKeys_.push(q(this.element_.getRootNode(),st.POINTERUP,this.handlePointerUp_,this))}}handlePointerMove_(t){if(this.isMoving_(t)){this.updateActivePointers_(t),this.dragging_=!0;const e=new Pe(st.POINTERDRAG,this.map_,t,this.dragging_,void 0,this.activePointers_);this.dispatchEvent(e)}}relayMoveEvent_(t){this.originalPointerMoveEvent_=t;const e=!!(this.down_&&this.isMoving_(t));this.dispatchEvent(new Pe(st.POINTERMOVE,this.map_,t,e))}handleTouchMove_(t){const e=this.originalPointerMoveEvent_;(!e||e.defaultPrevented)&&(typeof t.cancelable!="boolean"||t.cancelable===!0)&&t.preventDefault()}isMoving_(t){return this.dragging_||Math.abs(t.clientX-this.down_.clientX)>this.moveTolerance_||Math.abs(t.clientY-this.down_.clientY)>this.moveTolerance_}disposeInternal(){this.relayedListenerKey_&&(it(this.relayedListenerKey_),this.relayedListenerKey_=null),this.element_.removeEventListener(z.TOUCHMOVE,this.boundHandleTouchMove_),this.pointerdownListenerKey_&&(it(this.pointerdownListenerKey_),this.pointerdownListenerKey_=null),this.dragListenerKeys_.forEach(it),this.dragListenerKeys_.length=0,this.element_=null,super.disposeInternal()}}const te={POSTRENDER:"postrender",MOVESTART:"movestart",MOVEEND:"moveend",LOADSTART:"loadstart",LOADEND:"loadend"},ct={LAYERGROUP:"layergroup",SIZE:"size",TARGET:"target",VIEW:"view"},as=1/0;class Fu{constructor(t,e){this.priorityFunction_=t,this.keyFunction_=e,this.elements_=[],this.priorities_=[],this.queuedElements_={}}clear(){this.elements_.length=0,this.priorities_.length=0,Di(this.queuedElements_)}dequeue(){const t=this.elements_,e=this.priorities_,i=t[0];t.length==1?(t.length=0,e.length=0):(t[0]=t.pop(),e[0]=e.pop(),this.siftUp_(0));const n=this.keyFunction_(i);return delete this.queuedElements_[n],i}enqueue(t){$(!(this.keyFunction_(t)in this.queuedElements_),"Tried to enqueue an `element` that was already added to the queue");const e=this.priorityFunction_(t);return e!=as?(this.elements_.push(t),this.priorities_.push(e),this.queuedElements_[this.keyFunction_(t)]=!0,this.siftDown_(0,this.elements_.length-1),!0):!1}getCount(){return this.elements_.length}getLeftChildIndex_(t){return t*2+1}getRightChildIndex_(t){return t*2+2}getParentIndex_(t){return t-1>>1}heapify_(){let t;for(t=(this.elements_.length>>1)-1;t>=0;t--)this.siftUp_(t)}isEmpty(){return this.elements_.length===0}isKeyQueued(t){return t in this.queuedElements_}isQueued(t){return this.isKeyQueued(this.keyFunction_(t))}siftUp_(t){const e=this.elements_,i=this.priorities_,n=e.length,r=e[t],o=i[t],a=t;for(;t>1;){const l=this.getLeftChildIndex_(t),c=this.getRightChildIndex_(t),h=ct;){const a=this.getParentIndex_(e);if(n[a]>o)i[e]=i[a],n[e]=n[a],e=a;else break}i[e]=r,n[e]=o}reprioritize(){const t=this.priorityFunction_,e=this.elements_,i=this.priorities_;let n=0;const r=e.length;let o,a,l;for(a=0;a0;)r=this.dequeue()[0],o=r.getKey(),n=r.getState(),n===P.IDLE&&!(o in this.tilesLoadingKeys_)&&(this.tilesLoadingKeys_[o]=!0,++this.tilesLoading_,++i,r.load())}}function ku(s,t,e,i,n){if(!s||!(e in s.wantedTiles)||!s.wantedTiles[e][t.getKey()])return as;const r=s.viewState.center,o=i[0]-r[0],a=i[1]-r[1];return 65536*Math.log(n)+Math.sqrt(o*o+a*a)/n}class zi extends Qt{constructor(t){super();const e=t.element;e&&!t.target&&!e.style.pointerEvents&&(e.style.pointerEvents="auto"),this.element=e||null,this.target_=null,this.map_=null,this.listenerKeys=[],t.render&&(this.render=t.render),t.target&&this.setTarget(t.target)}disposeInternal(){es(this.element),super.disposeInternal()}getMap(){return this.map_}setMap(t){this.map_&&es(this.element);for(let e=0,i=this.listenerKeys.length;en.getAttributions(t)))),i=!this.getMap().getAllLayers().some(n=>n.getSource()&&n.getSource().getAttributionsCollapsible()===!1);return this.overrideCollapsible_||this.setCollapsible(i),e}async updateElement_(t){if(!t){this.renderedVisible_&&(this.element.style.display="none",this.renderedVisible_=!1);return}const e=await Promise.all(this.collectSourceAttributions_(t).map(n=>Gl(()=>n))),i=e.length>0;if(this.renderedVisible_!=i&&(this.element.style.display=i?"":"none",this.renderedVisible_=i),!We(e,this.renderedAttributions_)){Ya(this.ulElement_);for(let n=0,r=e.length;n0&&i%(2*Math.PI)!==0?e.animate({rotation:0,duration:this.duration_,easing:ki}):e.setRotation(0))}render(t){const e=t.frameState;if(!e)return;const i=e.viewState.rotation;if(i!=this.rotation_){const n="rotate("+i+"rad)";if(this.autoHide_){const r=this.element.classList.contains(Vn);!r&&i===0?this.element.classList.add(Vn):r&&i!==0&&this.element.classList.remove(Vn)}this.label_.style.transform=n}this.rotation_=i}}class zu extends zi{constructor(t){t=t||{},super({element:document.createElement("div"),target:t.target});const e=t.className!==void 0?t.className:"ol-zoom",i=t.delta!==void 0?t.delta:1,n=t.zoomInClassName!==void 0?t.zoomInClassName:e+"-in",r=t.zoomOutClassName!==void 0?t.zoomOutClassName:e+"-out",o=t.zoomInLabel!==void 0?t.zoomInLabel:"+",a=t.zoomOutLabel!==void 0?t.zoomOutLabel:"–",l=t.zoomInTipLabel!==void 0?t.zoomInTipLabel:"Zoom in",c=t.zoomOutTipLabel!==void 0?t.zoomOutTipLabel:"Zoom out",h=document.createElement("button");h.className=n,h.setAttribute("type","button"),h.title=l,h.appendChild(typeof o=="string"?document.createTextNode(o):o),h.addEventListener(z.CLICK,this.handleClick_.bind(this,i),!1);const u=document.createElement("button");u.className=r,u.setAttribute("type","button"),u.title=c,u.appendChild(typeof a=="string"?document.createTextNode(a):a),u.addEventListener(z.CLICK,this.handleClick_.bind(this,-i),!1);const d=e+" "+ni+" "+bn,f=this.element;f.className=d,f.appendChild(h),f.appendChild(u),this.duration_=t.duration!==void 0?t.duration:250}handleClick_(t,e){e.preventDefault(),this.zoomByDelta_(t)}zoomByDelta_(t){const i=this.getMap().getView();if(!i)return;const n=i.getZoom();if(n!==void 0){const r=i.getConstrainedZoom(n+t);this.duration_>0?(i.getAnimating()&&i.cancelAnimations(),i.animate({zoom:r,duration:this.duration_,easing:ki})):i.setZoom(r)}}}function nl(s){s=s||{};const t=new Nt;return(s.zoom!==void 0?s.zoom:!0)&&t.push(new zu(s.zoomOptions)),(s.rotate!==void 0?s.rotate:!0)&&t.push(new Gu(s.rotateOptions)),(s.attribution!==void 0?s.attribution:!0)&&t.push(new Nu(s.attributionOptions)),t}class Wu extends Ni{constructor(t){super(),t=t||{},this.delta_=t.delta?t.delta:1,this.duration_=t.duration!==void 0?t.duration:250}handleEvent(t){let e=!1;if(t.type==st.DBLCLICK){const i=t.originalEvent,n=t.map,r=t.coordinate,o=i.shiftKey?-this.delta_:this.delta_,a=n.getView();_r(a,o,r,this.duration_),i.preventDefault(),e=!0}return!e}}class Xu extends vn{constructor(t){super({stopDown:wn}),t=t||{},this.kinetic_=t.kinetic,this.lastCentroid=null,this.lastPointersCount_,this.panning_=!1;const e=t.condition?t.condition:sr(Oa,$h);this.condition_=t.onFocusOnly?sr(Aa,e):e,this.noKinetic_=!1}handleDragEvent(t){const e=t.map;this.panning_||(this.panning_=!0,e.getView().beginInteraction());const i=this.targetPointers,n=e.getEventPixel(mr(i));if(i.length==this.lastPointersCount_){if(this.kinetic_&&this.kinetic_.update(n[0],n[1]),this.lastCentroid){const r=[this.lastCentroid[0]-n[0],n[1]-this.lastCentroid[1]],a=t.map.getView();fh(r,a.getResolution()),Er(r,a.getRotation()),a.adjustCenterInternal(r)}}else this.kinetic_&&this.kinetic_.begin();this.lastCentroid=n,this.lastPointersCount_=i.length,t.originalEvent.preventDefault()}handleUpEvent(t){const e=t.map,i=e.getView();if(this.targetPointers.length===0){if(!this.noKinetic_&&this.kinetic_&&this.kinetic_.end()){const n=this.kinetic_.getDistance(),r=this.kinetic_.getAngle(),o=i.getCenterInternal(),a=e.getPixelFromCoordinateInternal(o),l=e.getCoordinateFromPixelInternal([a[0]-n*Math.cos(r),a[1]-n*Math.sin(r)]);i.animateInternal({center:i.getConstrainedCenter(l),duration:500,easing:ki})}return this.panning_&&(this.panning_=!1,i.endInteraction()),!1}return this.kinetic_&&this.kinetic_.begin(),this.lastCentroid=null,!0}handleDownEvent(t){if(this.targetPointers.length>0&&this.condition_(t)){const i=t.map.getView();return this.lastCentroid=null,i.getAnimating()&&i.cancelAnimations(),this.kinetic_&&this.kinetic_.begin(),this.noKinetic_=this.targetPointers.length>1,!0}return!1}}class Yu extends vn{constructor(t){t=t||{},super({stopDown:wn}),this.condition_=t.condition?t.condition:Zh,this.lastAngle_=void 0,this.duration_=t.duration!==void 0?t.duration:250}handleDragEvent(t){if(!As(t))return;const e=t.map,i=e.getView();if(i.getConstraints().rotation===Ar)return;const n=e.getSize(),r=t.pixel,o=Math.atan2(n[1]/2-r[1],r[0]-n[0]/2);if(this.lastAngle_!==void 0){const a=o-this.lastAngle_;i.adjustRotationInternal(-a)}this.lastAngle_=o}handleUpEvent(t){return As(t)?(t.map.getView().endInteraction(this.duration_),!1):!0}handleDownEvent(t){return As(t)&&Pa(t)&&this.condition_(t)?(t.map.getView().beginInteraction(),this.lastAngle_=void 0,!0):!1}}class Vu extends ka{constructor(t){t=t||{};const e=t.condition?t.condition:Fa;super({condition:e,className:t.className||"ol-dragzoom",minArea:t.minArea}),this.duration_=t.duration!==void 0?t.duration:200,this.out_=t.out!==void 0?t.out:!1}onBoxEnd(t){const i=this.getMap().getView();let n=this.getGeometry();if(this.out_){const r=i.rotatedExtentForGeometry(n),o=i.getResolutionForExtentInternal(r),a=i.getResolution()/o;n=n.clone(),n.scale(a*a)}i.fitInternal(n,{duration:this.duration_,easing:ki})}}const qe={LEFT:"ArrowLeft",UP:"ArrowUp",RIGHT:"ArrowRight",DOWN:"ArrowDown"};class Bu extends Ni{constructor(t){super(),t=t||{},this.defaultCondition_=function(e){return Oa(e)&&Da(e)},this.condition_=t.condition!==void 0?t.condition:this.defaultCondition_,this.duration_=t.duration!==void 0?t.duration:100,this.pixelDelta_=t.pixelDelta!==void 0?t.pixelDelta:128}handleEvent(t){let e=!1;if(t.type==z.KEYDOWN){const i=t.originalEvent,n=i.key;if(this.condition_(t)&&(n==qe.DOWN||n==qe.LEFT||n==qe.RIGHT||n==qe.UP)){const o=t.map.getView(),a=o.getResolution()*this.pixelDelta_;let l=0,c=0;n==qe.DOWN?c=-a:n==qe.LEFT?l=-a:n==qe.RIGHT?l=a:c=a;const h=[l,c];Er(h,o.getRotation()),Vl(o,h,this.duration_),i.preventDefault(),e=!0}}return!e}}class Zu extends Ni{constructor(t){super(),t=t||{},this.condition_=t.condition?t.condition:function(e){return!Hh(e)&&Da(e)},this.delta_=t.delta?t.delta:1,this.duration_=t.duration!==void 0?t.duration:100}handleEvent(t){let e=!1;if(t.type==z.KEYDOWN||t.type==z.KEYPRESS){const i=t.originalEvent,n=i.key;if(this.condition_(t)&&(n==="+"||n==="-")){const r=t.map,o=n==="+"?this.delta_:-this.delta_,a=r.getView();_r(a,o,void 0,this.duration_),i.preventDefault(),e=!0}}return!e}}class Uu{constructor(t,e,i){this.decay_=t,this.minVelocity_=e,this.delay_=i,this.points_=[],this.angle_=0,this.initialVelocity_=0}begin(){this.points_.length=0,this.angle_=0,this.initialVelocity_=0}update(t,e){this.points_.push(t,e,Date.now())}end(){if(this.points_.length<6)return!1;const t=Date.now()-this.delay_,e=this.points_.length-3;if(this.points_[e+2]0&&this.points_[i+2]>t;)i-=3;const n=this.points_[e+2]-this.points_[i+2];if(n<1e3/60)return!1;const r=this.points_[e]-this.points_[i],o=this.points_[e+1]-this.points_[i+1];return this.angle_=Math.atan2(o,r),this.initialVelocity_=Math.sqrt(r*r+o*o)/n,this.initialVelocity_>this.minVelocity_}getDistance(){return(this.minVelocity_-this.initialVelocity_)/this.decay_}getAngle(){return this.angle_}}class Ku extends Ni{constructor(t){t=t||{},super(t),this.totalDelta_=0,this.lastDelta_=0,this.maxDelta_=t.maxDelta!==void 0?t.maxDelta:1,this.duration_=t.duration!==void 0?t.duration:250,this.timeout_=t.timeout!==void 0?t.timeout:80,this.useAnchor_=t.useAnchor!==void 0?t.useAnchor:!0,this.constrainResolution_=t.constrainResolution!==void 0?t.constrainResolution:!1;const e=t.condition?t.condition:Kh;this.condition_=t.onFocusOnly?sr(Aa,e):e,this.lastAnchor_=null,this.startTime_=void 0,this.timeoutId_,this.mode_=void 0,this.trackpadEventGap_=400,this.trackpadTimeoutId_,this.deltaPerZoom_=300}endInteraction_(){this.trackpadTimeoutId_=void 0;const t=this.getMap();if(!t)return;t.getView().endInteraction(void 0,this.lastDelta_?this.lastDelta_>0?1:-1:0,this.lastAnchor_)}handleEvent(t){if(!this.condition_(t)||t.type!==z.WHEEL)return!0;const i=t.map,n=t.originalEvent;n.preventDefault(),this.useAnchor_&&(this.lastAnchor_=t.coordinate);let r;if(t.type==z.WHEEL&&(r=n.deltaY,Yh&&n.deltaMode===WheelEvent.DOM_DELTA_PIXEL&&(r/=Sa),n.deltaMode===WheelEvent.DOM_DELTA_LINE&&(r*=40)),r===0)return!1;this.lastDelta_=r;const o=Date.now();this.startTime_===void 0&&(this.startTime_=o),(!this.mode_||o-this.startTime_>this.trackpadEventGap_)&&(this.mode_=Math.abs(r)<4?"trackpad":"wheel");const a=i.getView();if(this.mode_==="trackpad"&&!(a.getConstrainResolution()||this.constrainResolution_))return this.trackpadTimeoutId_?clearTimeout(this.trackpadTimeoutId_):(a.getAnimating()&&a.cancelAnimations(),a.beginInteraction()),this.trackpadTimeoutId_=setTimeout(this.endInteraction_.bind(this),this.timeout_),a.adjustZoom(-r/this.deltaPerZoom_,this.lastAnchor_),this.startTime_=o,!1;this.totalDelta_+=r;const l=Math.max(this.timeout_-(o-this.startTime_),0);return clearTimeout(this.timeoutId_),this.timeoutId_=setTimeout(this.handleWheelZoom_.bind(this,i),l),!1}handleWheelZoom_(t){const e=t.getView();e.getAnimating()&&e.cancelAnimations();let i=-ht(this.totalDelta_,-this.maxDelta_*this.deltaPerZoom_,this.maxDelta_*this.deltaPerZoom_)/this.deltaPerZoom_;(e.getConstrainResolution()||this.constrainResolution_)&&(i=i?i>0?1:-1:0),_r(e,i,this.lastAnchor_,this.duration_),this.mode_=void 0,this.totalDelta_=0,this.lastAnchor_=null,this.startTime_=void 0,this.timeoutId_=void 0}setMouseAnchor(t){this.useAnchor_=t,t||(this.lastAnchor_=null)}}class ju extends vn{constructor(t){t=t||{};const e=t;e.stopDown||(e.stopDown=wn),super(e),this.anchor_=null,this.lastAngle_=void 0,this.rotating_=!1,this.rotationDelta_=0,this.threshold_=t.threshold!==void 0?t.threshold:.3,this.duration_=t.duration!==void 0?t.duration:250}handleDragEvent(t){let e=0;const i=this.targetPointers[0],n=this.targetPointers[1],r=Math.atan2(n.clientY-i.clientY,n.clientX-i.clientX);if(this.lastAngle_!==void 0){const l=r-this.lastAngle_;this.rotationDelta_+=l,!this.rotating_&&Math.abs(this.rotationDelta_)>this.threshold_&&(this.rotating_=!0),e=l}this.lastAngle_=r;const o=t.map,a=o.getView();a.getConstraints().rotation!==Ar&&(this.anchor_=o.getCoordinateFromPixelInternal(o.getEventPixel(mr(this.targetPointers))),this.rotating_&&(o.render(),a.adjustRotationInternal(e,this.anchor_)))}handleUpEvent(t){return this.targetPointers.length<2?(t.map.getView().endInteraction(this.duration_),!1):!0}handleDownEvent(t){if(this.targetPointers.length>=2){const e=t.map;return this.anchor_=null,this.lastAngle_=void 0,this.rotating_=!1,this.rotationDelta_=0,this.handlingDownUpSequence||e.getView().beginInteraction(),!0}return!1}}class qu extends vn{constructor(t){t=t||{};const e=t;e.stopDown||(e.stopDown=wn),super(e),this.anchor_=null,this.duration_=t.duration!==void 0?t.duration:400,this.lastDistance_=void 0,this.lastScaleDelta_=1}handleDragEvent(t){let e=1;const i=this.targetPointers[0],n=this.targetPointers[1],r=i.clientX-n.clientX,o=i.clientY-n.clientY,a=Math.sqrt(r*r+o*o);this.lastDistance_!==void 0&&(e=this.lastDistance_/a),this.lastDistance_=a;const l=t.map,c=l.getView();e!=1&&(this.lastScaleDelta_=e),this.anchor_=l.getCoordinateFromPixelInternal(l.getEventPixel(mr(this.targetPointers))),l.render(),c.adjustResolutionInternal(e,this.anchor_)}handleUpEvent(t){if(this.targetPointers.length<2){const i=t.map.getView(),n=this.lastScaleDelta_>1?1:-1;return i.endInteraction(this.duration_,n),!1}return!0}handleDownEvent(t){if(this.targetPointers.length>=2){const e=t.map;return this.anchor_=null,this.lastDistance_=void 0,this.lastScaleDelta_=1,this.handlingDownUpSequence||e.getView().beginInteraction(),!0}return!1}}function sl(s){s=s||{};const t=new Nt,e=new Uu(-.005,.05,100);return(s.altShiftDragRotate!==void 0?s.altShiftDragRotate:!0)&&t.push(new Yu),(s.doubleClickZoom!==void 0?s.doubleClickZoom:!0)&&t.push(new Wu({delta:s.zoomDelta,duration:s.zoomDuration})),(s.dragPan!==void 0?s.dragPan:!0)&&t.push(new Xu({onFocusOnly:s.onFocusOnly,kinetic:e})),(s.pinchRotate!==void 0?s.pinchRotate:!0)&&t.push(new ju),(s.pinchZoom!==void 0?s.pinchZoom:!0)&&t.push(new qu({duration:s.zoomDuration})),(s.keyboard!==void 0?s.keyboard:!0)&&(t.push(new Bu),t.push(new Zu({delta:s.zoomDelta,duration:s.zoomDuration}))),(s.mouseWheelZoom!==void 0?s.mouseWheelZoom:!0)&&t.push(new Ku({onFocusOnly:s.onFocusOnly,duration:s.zoomDuration})),(s.shiftDragZoom!==void 0?s.shiftDragZoom:!0)&&t.push(new Vu({duration:s.zoomDuration})),t}function rl(s){if(s instanceof _s){s.setMapInternal(null);return}s instanceof ii&&s.getLayers().forEach(rl)}function ol(s,t){if(s instanceof _s){s.setMapInternal(t);return}if(s instanceof ii){const e=s.getLayers().getArray();for(let i=0,n=e.length;ithis.updateSize()),this.controls=e.controls||nl(),this.interactions=e.interactions||sl({onFocusOnly:!0}),this.overlays_=e.overlays,this.overlayIdIndex_={},this.renderer_=null,this.postRenderFunctions_=[],this.tileQueue_=new Du(this.getTilePriority.bind(this),this.handleTileChange_.bind(this)),this.addChangeListener(ct.LAYERGROUP,this.handleLayerGroupChanged_),this.addChangeListener(ct.VIEW,this.handleViewChanged_),this.addChangeListener(ct.SIZE,this.handleSizeChanged_),this.addChangeListener(ct.TARGET,this.handleTargetChanged_),this.setProperties(e.values);const i=this;t.view&&!(t.view instanceof Ut)&&t.view.then(function(n){i.setView(new Ut(n))}),this.controls.addEventListener(ft.ADD,n=>{n.element.setMap(this)}),this.controls.addEventListener(ft.REMOVE,n=>{n.element.setMap(null)}),this.interactions.addEventListener(ft.ADD,n=>{n.element.setMap(this)}),this.interactions.addEventListener(ft.REMOVE,n=>{n.element.setMap(null)}),this.overlays_.addEventListener(ft.ADD,n=>{this.addOverlayInternal_(n.element)}),this.overlays_.addEventListener(ft.REMOVE,n=>{const r=n.element.getId();r!==void 0&&delete this.overlayIdIndex_[r.toString()],n.element.setMap(null)}),this.controls.forEach(n=>{n.setMap(this)}),this.interactions.forEach(n=>{n.setMap(this)}),this.overlays_.forEach(this.addOverlayInternal_.bind(this))}addControl(t){this.getControls().push(t)}addInteraction(t){this.getInteractions().push(t)}addLayer(t){this.getLayerGroup().getLayers().push(t)}handleLayerAdd_(t){ol(t.layer,this)}addOverlay(t){this.getOverlays().push(t)}addOverlayInternal_(t){const e=t.getId();e!==void 0&&(this.overlayIdIndex_[e.toString()]=t),t.setMap(this)}disposeInternal(){this.controls.clear(),this.interactions.clear(),this.overlays_.clear(),this.resizeObserver_.disconnect(),this.setTarget(null),super.disposeInternal()}forEachFeatureAtPixel(t,e,i){if(!this.frameState_||!this.renderer_)return;const n=this.getCoordinateFromPixelInternal(t);i=i!==void 0?i:{};const r=i.hitTolerance!==void 0?i.hitTolerance:0,o=i.layerFilter!==void 0?i.layerFilter:ei,a=i.checkWrapped!==!1;return this.renderer_.forEachFeatureAtCoordinate(n,this.frameState_,r,a,e,null,o,null)}getFeaturesAtPixel(t,e){const i=[];return this.forEachFeatureAtPixel(t,function(n){i.push(n)},e),i}getAllLayers(){const t=[];function e(i){i.forEach(function(n){n instanceof ii?e(n.getLayers()):t.push(n)})}return e(this.getLayers()),t}hasFeatureAtPixel(t,e){if(!this.frameState_||!this.renderer_)return!1;const i=this.getCoordinateFromPixelInternal(t);e=e!==void 0?e:{};const n=e.layerFilter!==void 0?e.layerFilter:ei,r=e.hitTolerance!==void 0?e.hitTolerance:0,o=e.checkWrapped!==!1;return this.renderer_.hasFeatureAtCoordinate(i,this.frameState_,r,o,n,null)}getEventCoordinate(t){return this.getCoordinateFromPixel(this.getEventPixel(t))}getEventCoordinateInternal(t){return this.getCoordinateFromPixelInternal(this.getEventPixel(t))}getEventPixel(t){const i=this.viewport_.getBoundingClientRect(),n=this.getSize(),r=i.width/n[0],o=i.height/n[1],a="changedTouches"in t?t.changedTouches[0]:t;return[(a.clientX-i.left)/r,(a.clientY-i.top)/o]}getTarget(){return this.get(ct.TARGET)}getTargetElement(){return this.targetElement_}getCoordinateFromPixel(t){return nr(this.getCoordinateFromPixelInternal(t),this.getView().getProjection())}getCoordinateFromPixelInternal(t){const e=this.frameState_;return e?pt(e.pixelToCoordinateTransform,t.slice()):null}getControls(){return this.controls}getOverlays(){return this.overlays_}getOverlayById(t){const e=this.overlayIdIndex_[t.toString()];return e!==void 0?e:null}getInteractions(){return this.interactions}getLayerGroup(){return this.get(ct.LAYERGROUP)}setLayers(t){const e=this.getLayerGroup();if(t instanceof Nt){e.setLayers(t);return}const i=e.getLayers();i.clear(),i.extend(t)}getLayers(){return this.getLayerGroup().getLayers()}getLoadingOrNotReady(){const t=this.getLayerGroup().getLayerStatesArray();for(let e=0,i=t.length;e=0;r--){const o=n[r];if(o.getMap()!==this||!o.getActive()||!this.getTargetElement())continue;if(!o.handleEvent(t)||t.propagationStopped)break}}}handlePostRender(){const t=this.frameState_,e=this.tileQueue_;if(!e.isEmpty()){let n=this.maxTilesLoading_,r=n;if(t){const o=t.viewHints;if(o[wt.ANIMATING]||o[wt.INTERACTING]){const a=Date.now()-t.time>8;n=a?0:8,r=a?0:2}}e.getTilesLoading(){this.postRenderTimeoutHandle_=void 0,this.handlePostRender()},0))}setLayerGroup(t){const e=this.getLayerGroup();e&&this.handleLayerRemove_(new Oe("removelayer",e)),this.set(ct.LAYERGROUP,t)}setSize(t){this.set(ct.SIZE,t)}setTarget(t){this.set(ct.TARGET,t)}setView(t){if(!t||t instanceof Ut){this.set(ct.VIEW,t);return}this.set(ct.VIEW,new Ut);const e=this;t.then(function(i){e.setView(new Ut(i))})}updateSize(){const t=this.getTargetElement();let e;if(t){const n=getComputedStyle(t),r=t.offsetWidth-parseFloat(n.borderLeftWidth)-parseFloat(n.paddingLeft)-parseFloat(n.paddingRight)-parseFloat(n.borderRightWidth),o=t.offsetHeight-parseFloat(n.borderTopWidth)-parseFloat(n.paddingTop)-parseFloat(n.paddingBottom)-parseFloat(n.borderBottomWidth);!isNaN(r)&&!isNaN(o)&&(e=[r,o],!To(e)&&(t.offsetWidth||t.offsetHeight||t.getClientRects().length)&&ga("No map visible because the map container's width or height are 0."))}const i=this.getSize();e&&(!i||!We(e,i))&&(this.setSize(e),this.updateViewportSize_(e))}updateViewportSize_(t){const e=this.getView();e&&e.setViewportSize(t)}}function Hu(s){let t=null;s.keyboardEventTarget!==void 0&&(t=typeof s.keyboardEventTarget=="string"?document.getElementById(s.keyboardEventTarget):s.keyboardEventTarget);const e={},i=s.layers&&typeof s.layers.getLayers=="function"?s.layers:new ii({layers:s.layers});e[ct.LAYERGROUP]=i,e[ct.TARGET]=s.target,e[ct.VIEW]=s.view instanceof Ut?s.view:new Ut;let n;s.controls!==void 0&&(Array.isArray(s.controls)?n=new Nt(s.controls.slice()):($(typeof s.controls.getArray=="function","Expected `controls` to be an array or an `ol/Collection.js`"),n=s.controls));let r;s.interactions!==void 0&&(Array.isArray(s.interactions)?r=new Nt(s.interactions.slice()):($(typeof s.interactions.getArray=="function","Expected `interactions` to be an array or an `ol/Collection.js`"),r=s.interactions));let o;return s.overlays!==void 0?Array.isArray(s.overlays)?o=new Nt(s.overlays.slice()):($(typeof s.overlays.getArray=="function","Expected `overlays` to be an array or an `ol/Collection.js`"),o=s.overlays):o=new Nt,{controls:n,interactions:r,keyboardEventTarget:t,overlays:o,values:e}}class ll extends hs{constructor(t,e,i){super(),i=i||{},this.tileCoord=t,this.state=e,this.interimTile=null,this.key="",this.transition_=i.transition===void 0?250:i.transition,this.transitionStarts_={},this.interpolate=!!i.interpolate}changed(){this.dispatchEvent(z.CHANGE)}release(){this.state===P.ERROR&&this.setState(P.EMPTY)}getKey(){return this.key+"/"+this.tileCoord}getInterimTile(){let t=this.interimTile;if(!t)return this;do{if(t.getState()==P.LOADED)return this.transition_=0,t;t=t.interimTile}while(t);return this}refreshInterimChain(){let t=this.interimTile;if(!t)return;let e=this;do{if(t.getState()==P.LOADED){t.interimTile=null;break}t.getState()==P.LOADING?e=t:t.getState()==P.IDLE?e.interimTile=t.interimTile:e=t,t=e.interimTile}while(t)}getTileCoord(){return this.tileCoord}getState(){return this.state}setState(t){if(this.state!==P.ERROR&&this.state>t)throw new Error("Tile load sequence violation");this.state=t,this.changed()}load(){J()}getAlpha(t,e){if(!this.transition_)return 1;let i=this.transitionStarts_[t];if(!i)i=e,this.transitionStarts_[t]=i;else if(i===-1)return 1;const n=e-i+1e3/60;return n>=this.transition_?1:ia(n/this.transition_)}inTransition(t){return this.transition_?this.transitionStarts_[t]!==-1:!1}endTransition(t){this.transition_&&(this.transitionStarts_[t]=-1)}}class zr extends ll{constructor(t,e,i,n,r,o){super(t,e,o),this.crossOrigin_=n,this.src_=i,this.key=i,this.image_=new Image,n!==null&&(this.image_.crossOrigin=n),this.unlisten_=null,this.tileLoadFunction_=r}getImage(){return this.image_}setImage(t){this.image_=t,this.state=P.LOADED,this.unlistenImage_(),this.changed()}handleImageError_(){this.state=P.ERROR,this.unlistenImage_(),this.image_=$u(),this.changed()}handleImageLoad_(){const t=this.image_;t.naturalWidth&&t.naturalHeight?this.state=P.LOADED:this.state=P.EMPTY,this.unlistenImage_(),this.changed()}load(){this.state==P.ERROR&&(this.state=P.IDLE,this.image_=new Image,this.crossOrigin_!==null&&(this.image_.crossOrigin=this.crossOrigin_)),this.state==P.IDLE&&(this.state=P.LOADING,this.changed(),this.tileLoadFunction_(this,this.src_),this.unlisten_=Sc(this.image_,this.handleImageLoad_.bind(this),this.handleImageError_.bind(this)))}unlistenImage_(){this.unlisten_&&(this.unlisten_(),this.unlisten_=null)}}function $u(){const s=gt(1,1);return s.fillStyle="rgba(0,0,0,0)",s.fillRect(0,0,1,1),s.canvas}const Ju=.5,Qu=10,Go=.25;class td{constructor(t,e,i,n,r,o){this.sourceProj_=t,this.targetProj_=e;let a={};const l=ln(this.targetProj_,this.sourceProj_);this.transformInv_=function(y){const E=y[0]+"/"+y[1];return a[E]||(a[E]=l(y)),a[E]},this.maxSourceExtent_=n,this.errorThresholdSquared_=r*r,this.triangles_=[],this.wrapsXInSource_=!1,this.canWrapXInSource_=this.sourceProj_.canWrapX()&&!!n&&!!this.sourceProj_.getExtent()&&B(n)>=B(this.sourceProj_.getExtent()),this.sourceWorldWidth_=this.sourceProj_.getExtent()?B(this.sourceProj_.getExtent()):null,this.targetWorldWidth_=this.targetProj_.getExtent()?B(this.targetProj_.getExtent()):null;const c=Xe(i),h=us(i),u=Rn(i),d=cs(i),f=this.transformInv_(c),g=this.transformInv_(h),_=this.transformInv_(u),m=this.transformInv_(d),p=Qu+(o?Math.max(0,Math.ceil(Math.log2(Js(i)/(o*o*256*256)))):0);if(this.addQuad_(c,h,u,d,f,g,_,m,p),this.wrapsXInSource_){let y=1/0;this.triangles_.forEach(function(E,w,x){y=Math.min(y,E.source[0][0],E.source[1][0],E.source[2][0])}),this.triangles_.forEach(E=>{if(Math.max(E.source[0][0],E.source[1][0],E.source[2][0])-y>this.sourceWorldWidth_/2){const w=[[E.source[0][0],E.source[0][1]],[E.source[1][0],E.source[1][1]],[E.source[2][0],E.source[2][1]]];w[0][0]-y>this.sourceWorldWidth_/2&&(w[0][0]-=this.sourceWorldWidth_),w[1][0]-y>this.sourceWorldWidth_/2&&(w[1][0]-=this.sourceWorldWidth_),w[2][0]-y>this.sourceWorldWidth_/2&&(w[2][0]-=this.sourceWorldWidth_);const x=Math.min(w[0][0],w[1][0],w[2][0]);Math.max(w[0][0],w[1][0],w[2][0])-x.5&&u<1;let g=!1;if(c>0){if(this.targetProj_.isGlobal()&&this.targetWorldWidth_){const m=no([t,e,i,n]);g=B(m)/this.targetWorldWidth_>Go||g}!f&&this.sourceProj_.isGlobal()&&u&&(g=u>Go||g)}if(!g&&this.maxSourceExtent_&&isFinite(h[0])&&isFinite(h[1])&&isFinite(h[2])&&isFinite(h[3])&&!Pt(h,this.maxSourceExtent_))return;let _=0;if(!g&&(!isFinite(r[0])||!isFinite(r[1])||!isFinite(o[0])||!isFinite(o[1])||!isFinite(a[0])||!isFinite(a[1])||!isFinite(l[0])||!isFinite(l[1]))){if(c>0)g=!0;else if(_=(!isFinite(r[0])||!isFinite(r[1])?8:0)+(!isFinite(o[0])||!isFinite(o[1])?4:0)+(!isFinite(a[0])||!isFinite(a[1])?2:0)+(!isFinite(l[0])||!isFinite(l[1])?1:0),_!=1&&_!=2&&_!=4&&_!=8)return}if(c>0){if(!g){const m=[(t[0]+i[0])/2,(t[1]+i[1])/2],p=this.transformInv_(m);let y;f?y=(Qe(r[0],d)+Qe(a[0],d))/2-Qe(p[0],d):y=(r[0]+a[0])/2-p[0];const E=(r[1]+a[1])/2-p[1];g=y*y+E*E>this.errorThresholdSquared_}if(g){if(Math.abs(t[0]-i[0])<=Math.abs(t[1]-i[1])){const m=[(e[0]+i[0])/2,(e[1]+i[1])/2],p=this.transformInv_(m),y=[(n[0]+t[0])/2,(n[1]+t[1])/2],E=this.transformInv_(y);this.addQuad_(t,e,m,y,r,o,p,E,c-1),this.addQuad_(y,m,i,n,E,p,a,l,c-1)}else{const m=[(t[0]+e[0])/2,(t[1]+e[1])/2],p=this.transformInv_(m),y=[(i[0]+n[0])/2,(i[1]+n[1])/2],E=this.transformInv_(y);this.addQuad_(t,m,y,n,r,p,E,l,c-1),this.addQuad_(m,e,i,y,p,o,a,E,c-1)}return}}if(f){if(!this.canWrapXInSource_)return;this.wrapsXInSource_=!0}(_&11)==0&&this.addTriangle_(t,i,n,r,a,l),(_&14)==0&&this.addTriangle_(t,i,e,r,a,o),_&&((_&13)==0&&this.addTriangle_(e,n,t,o,l,r),(_&7)==0&&this.addTriangle_(e,n,i,o,l,a))}calculateSourceExtent(){const t=zt();return this.triangles_.forEach(function(e,i,n){const r=e.source;en(t,r[0]),en(t,r[1]),en(t,r[2])}),t}getTriangles(){return this.triangles_}}let Ys;const Ii=[];function zo(s,t,e,i,n){s.beginPath(),s.moveTo(0,0),s.lineTo(t,e),s.lineTo(i,n),s.closePath(),s.save(),s.clip(),s.fillRect(0,0,Math.max(t,i)+1,Math.max(e,n)),s.restore()}function Vs(s,t){return Math.abs(s[t*4]-210)>2||Math.abs(s[t*4+3]-.75*255)>2}function ed(){if(Ys===void 0){const s=gt(6,6,Ii);s.globalCompositeOperation="lighter",s.fillStyle="rgba(210, 0, 0, 0.75)",zo(s,4,5,4,0),zo(s,4,5,0,5);const t=s.getImageData(0,0,3,3).data;Ys=Vs(t,0)||Vs(t,4)||Vs(t,8),ps(s),Ii.push(s.canvas)}return Ys}function cr(s,t,e,i){const n=vr(e,t,s);let r=Hn(t,i,e);const o=t.getMetersPerUnit();o!==void 0&&(r*=o);const a=s.getMetersPerUnit();a!==void 0&&(r/=a);const l=s.getExtent();if(!l||Li(l,n)){const c=Hn(s,r,n)/r;isFinite(c)&&c>0&&(r/=c)}return r}function id(s,t,e,i){const n=Ge(e);let r=cr(s,t,n,i);return(!isFinite(r)||r<=0)&&ha(e,function(o){return r=cr(s,t,o,i),isFinite(r)&&r>0}),r}function nd(s,t,e,i,n,r,o,a,l,c,h,u,d,f){const g=gt(Math.round(e*s),Math.round(e*t),Ii);if(u||(g.imageSmoothingEnabled=!1),l.length===0)return g.canvas;g.scale(e,e);function _(x){return Math.round(x*e)/e}g.globalCompositeOperation="lighter";const m=zt();l.forEach(function(x,v,T){jl(m,x.extent)});let p;const y=e/i,E=(u?1:1+Math.pow(2,-24))/y;p=gt(Math.round(B(m)*y),Math.round(at(m)*y),Ii),u||(p.imageSmoothingEnabled=!1),l.forEach(function(x,v,T){if(x.image.width>0&&x.image.height>0){if(x.clipExtent){p.save();const A=(x.clipExtent[0]-m[0])*y,k=-(x.clipExtent[3]-m[3])*y,D=B(x.clipExtent)*y,G=at(x.clipExtent)*y;p.rect(u?A:Math.round(A),u?k:Math.round(k),u?D:Math.round(A+D)-Math.round(A),u?G:Math.round(k+G)-Math.round(k)),p.clip()}const R=(x.extent[0]-m[0])*y,I=-(x.extent[3]-m[3])*y,F=B(x.extent)*y,O=at(x.extent)*y;p.drawImage(x.image,c,c,x.image.width-2*c,x.image.height-2*c,u?R:Math.round(R),u?I:Math.round(I),u?F:Math.round(R+F)-Math.round(R),u?O:Math.round(I+O)-Math.round(I)),x.clipExtent&&p.restore()}});const w=Xe(o);return a.getTriangles().forEach(function(x,v,T){const R=x.source,I=x.target;let F=R[0][0],O=R[0][1],A=R[1][0],k=R[1][1],D=R[2][0],G=R[2][1];const b=_((I[0][0]-w[0])/r),K=_(-(I[0][1]-w[1])/r),W=_((I[1][0]-w[0])/r),nt=_(-(I[1][1]-w[1])/r),Y=_((I[2][0]-w[0])/r),j=_(-(I[2][1]-w[1])/r),Z=F,et=O;F=0,O=0,A-=Z,k-=et,D-=Z,G-=et;const S=[[A,k,0,0,W-b],[D,G,0,0,Y-b],[0,0,A,k,nt-K],[0,0,D,G,j-K]],Tt=uh(S);if(!Tt)return;if(g.save(),g.beginPath(),ed()||!u){g.moveTo(W,nt);const lt=4,qt=b-W,Ye=K-nt;for(let Rt=0;Rt{const F=e.getTileRangeForExtentAndZ(I,this.sourceZ_);for(let O=F.minX;O<=F.maxX;O++)for(let A=F.minY;A<=F.maxY;A++){const k=c(this.sourceZ_,O,A,a);if(k){const D=T*v;this.sourceTiles_.push({tile:k,offset:D})}}++T}),this.sourceTiles_.length===0&&(this.state=P.EMPTY)}}getImage(){return this.canvas_}reproject_(){const t=[];if(this.sourceTiles_.forEach(e=>{var n;const i=e.tile;if(i&&i.getState()==P.LOADED){const r=this.sourceTileGrid_.getTileCoordExtent(i.tileCoord);r[0]+=e.offset,r[2]+=e.offset;const o=(n=this.clipExtent_)==null?void 0:n.slice();o&&(o[0]+=e.offset,o[2]+=e.offset),t.push({extent:r,clipExtent:o,image:i.getImage()})}}),this.sourceTiles_.length=0,t.length===0)this.state=P.ERROR;else{const e=this.wrappedTileCoord_[0],i=this.targetTileGrid_.getTileSize(e),n=typeof i=="number"?i:i[0],r=typeof i=="number"?i:i[1],o=this.targetTileGrid_.getResolution(e),a=this.sourceTileGrid_.getResolution(this.sourceZ_),l=this.targetTileGrid_.getTileCoordExtent(this.wrappedTileCoord_);this.canvas_=nd(n,r,this.pixelRatio_,a,this.sourceTileGrid_.getExtent(),o,l,this.triangulation_,t,this.gutter_,this.renderEdges_,this.interpolate),this.state=P.LOADED}this.changed()}load(){if(this.state==P.IDLE){this.state=P.LOADING,this.changed();let t=0;this.sourcesListenerKeys_=[],this.sourceTiles_.forEach(({tile:e})=>{const i=e.getState();if(i==P.IDLE||i==P.LOADING){t++;const n=q(e,z.CHANGE,function(r){const o=e.getState();(o==P.LOADED||o==P.ERROR||o==P.EMPTY)&&(it(n),t--,t===0&&(this.unlistenSources_(),this.reproject_()))},this);this.sourcesListenerKeys_.push(n)}}),t===0?setTimeout(this.reproject_.bind(this),0):this.sourceTiles_.forEach(function({tile:e},i,n){e.getState()==P.IDLE&&e.load()})}}unlistenSources_(){this.sourcesListenerKeys_.forEach(it),this.sourcesListenerKeys_=null}release(){this.canvas_&&(ps(this.canvas_.getContext("2d")),Ii.push(this.canvas_),this.canvas_=null),super.release()}}class sd{constructor(t){this.highWaterMark=t!==void 0?t:2048,this.count_=0,this.entries_={},this.oldest_=null,this.newest_=null}canExpireCache(){return this.highWaterMark>0&&this.getCount()>this.highWaterMark}expireCache(t){for(;this.canExpireCache();)this.pop()}clear(){this.count_=0,this.entries_={},this.oldest_=null,this.newest_=null}containsKey(t){return this.entries_.hasOwnProperty(t)}forEach(t){let e=this.oldest_;for(;e;)t(e.value_,e.key_,this),e=e.newer}get(t,e){const i=this.entries_[t];return $(i!==void 0,"Tried to get a value for a key that does not exist in the cache"),i===this.newest_||(i===this.oldest_?(this.oldest_=this.oldest_.newer,this.oldest_.older=null):(i.newer.older=i.older,i.older.newer=i.newer),i.newer=null,i.older=this.newest_,this.newest_.newer=i,this.newest_=i),i.value_}remove(t){const e=this.entries_[t];return $(e!==void 0,"Tried to get a value for a key that does not exist in the cache"),e===this.newest_?(this.newest_=e.older,this.newest_&&(this.newest_.newer=null)):e===this.oldest_?(this.oldest_=e.newer,this.oldest_&&(this.oldest_.older=null)):(e.newer.older=e.older,e.older.newer=e.newer),delete this.entries_[t],--this.count_,e.value_}getCount(){return this.count_}getKeys(){const t=new Array(this.count_);let e=0,i;for(i=this.newest_;i;i=i.older)t[e++]=i.key_;return t}getValues(){const t=new Array(this.count_);let e=0,i;for(i=this.newest_;i;i=i.older)t[e++]=i.value_;return t}peekLast(){return this.oldest_.value_}peekLastKey(){return this.oldest_.key_}peekFirstKey(){return this.newest_.key_}peek(t){var e;return(e=this.entries_[t])==null?void 0:e.value_}pop(){const t=this.oldest_;return delete this.entries_[t.key_],t.newer&&(t.newer.older=null),this.oldest_=t.newer,this.oldest_||(this.newest_=null),--this.count_,t.value_}replace(t,e){this.get(t),this.entries_[t].value_=e}set(t,e){$(!(t in this.entries_),"Tried to set a value for a key that is used already");const i={key_:t,newer:null,older:this.newest_,value_:e};this.newest_?this.newest_.newer=i:this.oldest_=i,this.newest_=i,this.entries_[t]=i,++this.count_}setSize(t){this.highWaterMark=t}}function Wo(s,t,e,i){return i!==void 0?(i[0]=s,i[1]=t,i[2]=e,i):[s,t,e]}function vs(s,t,e){return s+"/"+t+"/"+e}function hl(s){return vs(s[0],s[1],s[2])}function rd(s){return s.split("/").map(Number)}function cl(s){return(s[1]<e||e>t.getMaxZoom())return!1;const r=t.getFullTileRange(e);return r?r.containsXY(i,n):!0}class ul extends sd{clear(){for(;this.getCount()>0;)this.pop().release();super.clear()}expireCache(t){for(;this.canExpireCache()&&!(this.peekLast().getKey()in t);)this.pop().release()}pruneExceptNewestZ(){if(this.getCount()===0)return;const t=this.peekFirstKey(),i=rd(t)[0];this.forEach(n=>{n.tileCoord[0]!==i&&(this.remove(hl(n.tileCoord)),n.release())})}}const Bs={TILELOADSTART:"tileloadstart",TILELOADEND:"tileloadend",TILELOADERROR:"tileloaderror"};class dl extends Qt{constructor(t){super(),this.projection=Mt(t.projection),this.attributions_=Xo(t.attributions),this.attributionsCollapsible_=t.attributionsCollapsible!==void 0?t.attributionsCollapsible:!0,this.loading=!1,this.state_=t.state!==void 0?t.state:"ready",this.wrapX_=t.wrapX!==void 0?t.wrapX:!1,this.interpolate_=!!t.interpolate,this.viewResolver=null,this.viewRejector=null;const e=this;this.viewPromise_=new Promise(function(i,n){e.viewResolver=i,e.viewRejector=n})}getAttributions(){return this.attributions_}getAttributionsCollapsible(){return this.attributionsCollapsible_}getProjection(){return this.projection}getResolutions(t){return null}getView(){return this.viewPromise_}getState(){return this.state_}getWrapX(){return this.wrapX_}getInterpolate(){return this.interpolate_}refresh(){this.changed()}setAttributions(t){this.attributions_=Xo(t),this.changed()}setState(t){this.state_=t,this.changed()}}function Xo(s){return s?Array.isArray(s)?function(t){return s}:typeof s=="function"?s:function(t){return[s]}:null}class Wr{constructor(t,e,i,n){this.minX=t,this.maxX=e,this.minY=i,this.maxY=n}contains(t){return this.containsXY(t[1],t[2])}containsTileRange(t){return this.minX<=t.minX&&t.maxX<=this.maxX&&this.minY<=t.minY&&t.maxY<=this.maxY}containsXY(t,e){return this.minX<=t&&t<=this.maxX&&this.minY<=e&&e<=this.maxY}equals(t){return this.minX==t.minX&&this.minY==t.minY&&this.maxX==t.maxX&&this.maxY==t.maxY}extend(t){t.minXthis.maxX&&(this.maxX=t.maxX),t.minYthis.maxY&&(this.maxY=t.maxY)}getHeight(){return this.maxY-this.minY+1}getSize(){return[this.getWidth(),this.getHeight()]}getWidth(){return this.maxX-this.minX+1}intersects(t){return this.minX<=t.maxX&&this.maxX>=t.minX&&this.minY<=t.maxY&&this.maxY>=t.minY}}function di(s,t,e,i,n){return n!==void 0?(n.minX=s,n.maxX=t,n.minY=e,n.maxY=i,n):new Wr(s,t,e,i)}const fi=[0,0,0],be=5;class Xr{constructor(t){this.minZoom=t.minZoom!==void 0?t.minZoom:0,this.resolutions_=t.resolutions,$(Nl(this.resolutions_,(n,r)=>r-n),"`resolutions` must be sorted in descending order");let e;if(!t.origins){for(let n=0,r=this.resolutions_.length-1;n{const o=new Wr(Math.min(0,n[0]),Math.max(n[0]-1,-1),Math.min(0,n[1]),Math.max(n[1]-1,-1));if(i){const a=this.getTileRangeForExtentAndZ(i,r);o.minX=Math.max(a.minX,o.minX),o.maxX=Math.min(a.maxX,o.maxX),o.minY=Math.max(a.minY,o.minY),o.maxY=Math.min(a.maxY,o.maxY)}return o}):i&&this.calculateTileRanges_(i)}forEachTileCoord(t,e,i){const n=this.getTileRangeForExtentAndZ(t,e);for(let r=n.minX,o=n.maxX;r<=o;++r)for(let a=n.minY,l=n.maxY;a<=l;++a)i([e,r,a])}forEachTileCoordParentTileRange(t,e,i,n){let r,o,a,l=null,c=t[0]-1;for(this.zoomFactor_===2?(o=t[1],a=t[2]):l=this.getTileCoordExtent(t,n);c>=this.minZoom;){if(o!==void 0&&a!==void 0?(o=Math.floor(o/2),a=Math.floor(a/2),r=di(o,o,a,a,i)):r=this.getTileRangeForExtentAndZ(l,c,i),e(c,r))return!0;--c}return!1}getExtent(){return this.extent_}getMaxZoom(){return this.maxZoom}getMinZoom(){return this.minZoom}getOrigin(t){return this.origin_?this.origin_:this.origins_[t]}getResolution(t){return this.resolutions_[t]}getResolutions(){return this.resolutions_}getTileCoordChildTileRange(t,e,i){if(t[0]this.maxZoom||e0?i:Math.max(r/e[0],n/e[1]);const o=t+1,a=new Array(o);for(let l=0;li.highWaterMark&&(i.highWaterMark=t)}useTile(t,e,i,n){}}class dd extends ae{constructor(t,e){super(t),this.tile=e}}function fd(s,t){const e=/\{z\}/g,i=/\{x\}/g,n=/\{y\}/g,r=/\{-y\}/g;return function(o,a,l){if(o)return s.replace(e,o[0].toString()).replace(i,o[1].toString()).replace(n,o[2].toString()).replace(r,function(){const c=o[0],h=t.getFullTileRange(c);if(!h)throw new Error("The {-y} placeholder requires a tile grid with extent");return(h.getHeight()-o[2]-1).toString()})}}function gd(s,t){const e=s.length,i=new Array(e);for(let n=0;nthis.getTileInternal(m,p,y,E,o),this.reprojectionErrorThreshold_,this.renderReprojectionEdges_,this.tileOptions);return _.key=u,c?(_.interimTile=c,_.refreshInterimChain(),a.replace(h,_)):a.set(h,_),_}getTileInternal(t,e,i,n,r){let o=null;const a=vs(t,e,i),l=this.getKey();if(!this.tileCache.containsKey(a))o=this.createTile_(t,e,i,n,r,l),this.tileCache.set(a,o);else if(o=this.tileCache.get(a),o.key!=l){const c=o;o=this.createTile_(t,e,i,n,r,l),c.getState()==P.IDLE?o.interimTile=c.interimTile:o.interimTile=c,o.refreshInterimChain(),this.tileCache.replace(a,o)}return o}setRenderReprojectionEdges(t){if(this.renderReprojectionEdges_!=t){this.renderReprojectionEdges_=t;for(const e in this.tileCacheForProjection)this.tileCacheForProjection[e].clear();this.changed()}}setTileGridForProjection(t,e){const i=Mt(t);if(i){const n=U(i);n in this.tileGridForProjection||(this.tileGridForProjection[n]=e)}}clear(){super.clear();for(const t in this.tileCacheForProjection)this.tileCacheForProjection[t].clear()}}function _d(s,t){s.getImage().src=t}class md extends Br{constructor(t){t=t||{};const e=t.projection!==void 0?t.projection:"EPSG:3857",i=t.tileGrid!==void 0?t.tileGrid:hd({extent:Yr(e),maxResolution:t.maxResolution,maxZoom:t.maxZoom,minZoom:t.minZoom,tileSize:t.tileSize});super({attributions:t.attributions,cacheSize:t.cacheSize,crossOrigin:t.crossOrigin,interpolate:t.interpolate,opaque:t.opaque,projection:e,reprojectionErrorThreshold:t.reprojectionErrorThreshold,tileGrid:i,tileLoadFunction:t.tileLoadFunction,tilePixelRatio:t.tilePixelRatio,tileUrlFunction:t.tileUrlFunction,url:t.url,urls:t.urls,wrapX:t.wrapX!==void 0?t.wrapX:!0,transition:t.transition,attributionsCollapsible:t.attributionsCollapsible,zDirection:t.zDirection}),this.gutter_=t.gutter!==void 0?t.gutter:0}getGutter(){return this.gutter_}}const pd='© OpenStreetMap contributors.';class yd extends md{constructor(t){t=t||{};let e;t.attributions!==void 0?e=t.attributions:e=[pd];const i=t.crossOrigin!==void 0?t.crossOrigin:"anonymous",n=t.url!==void 0?t.url:"https://tile.openstreetmap.org/{z}/{x}/{y}.png";super({attributions:e,attributionsCollapsible:!1,cacheSize:t.cacheSize,crossOrigin:i,interpolate:t.interpolate,maxZoom:t.maxZoom!==void 0?t.maxZoom:19,opaque:t.opaque!==void 0?t.opaque:!0,reprojectionErrorThreshold:t.reprojectionErrorThreshold,tileLoadFunction:t.tileLoadFunction,transition:t.transition,url:n,wrapX:t.wrapX,zDirection:t.zDirection})}}const Et={ELEMENT:"element",MAP:"map",OFFSET:"offset",POSITION:"position",POSITIONING:"positioning"};class Ed extends Qt{constructor(t){super(),this.on,this.once,this.un,this.options=t,this.id=t.id,this.insertFirst=t.insertFirst!==void 0?t.insertFirst:!0,this.stopEvent=t.stopEvent!==void 0?t.stopEvent:!0,this.element=document.createElement("div"),this.element.className=t.className!==void 0?t.className:"ol-overlay-container "+Oc,this.element.style.position="absolute",this.element.style.pointerEvents="auto",this.autoPan=t.autoPan===!0?{}:t.autoPan||void 0,this.rendered={transform_:"",visible:!0},this.mapPostrenderListenerKey=null,this.addChangeListener(Et.ELEMENT,this.handleElementChanged),this.addChangeListener(Et.MAP,this.handleMapChanged),this.addChangeListener(Et.OFFSET,this.handleOffsetChanged),this.addChangeListener(Et.POSITION,this.handlePositionChanged),this.addChangeListener(Et.POSITIONING,this.handlePositioningChanged),t.element!==void 0&&this.setElement(t.element),this.setOffset(t.offset!==void 0?t.offset:[0,0]),this.setPositioning(t.positioning||"top-left"),t.position!==void 0&&this.setPosition(t.position)}getElement(){return this.get(Et.ELEMENT)}getId(){return this.id}getMap(){return this.get(Et.MAP)||null}getOffset(){return this.get(Et.OFFSET)}getPosition(){return this.get(Et.POSITION)}getPositioning(){return this.get(Et.POSITIONING)}handleElementChanged(){Ya(this.element);const t=this.getElement();t&&this.element.appendChild(t)}handleMapChanged(){this.mapPostrenderListenerKey&&(es(this.element),it(this.mapPostrenderListenerKey),this.mapPostrenderListenerKey=null);const t=this.getMap();if(t){this.mapPostrenderListenerKey=q(t,te.POSTRENDER,this.render,this),this.updatePixelPosition();const e=this.stopEvent?t.getOverlayContainerStopEvent():t.getOverlayContainer();this.insertFirst?e.insertBefore(this.element,e.childNodes[0]||null):e.appendChild(this.element),this.performAutoPan()}}render(){this.updatePixelPosition()}handleOffsetChanged(){this.updatePixelPosition()}handlePositionChanged(){this.updatePixelPosition(),this.performAutoPan()}handlePositioningChanged(){this.updatePixelPosition()}setElement(t){this.set(Et.ELEMENT,t)}setMap(t){this.set(Et.MAP,t)}setOffset(t){this.set(Et.OFFSET,t)}setPosition(t){this.set(Et.POSITION,t)}performAutoPan(){this.autoPan&&this.panIntoView(this.autoPan)}panIntoView(t){const e=this.getMap();if(!e||!e.getTargetElement()||!this.get(Et.POSITION))return;const i=this.getRect(e.getTargetElement(),e.getSize()),n=this.getElement(),r=this.getRect(n,[Tc(n),Rc(n)]);t=t||{};const o=t.margin===void 0?20:t.margin;if(!Fe(i,r)){const a=r[0]-i[0],l=i[2]-r[2],c=r[1]-i[1],h=i[3]-r[3],u=[0,0];if(a<0?u[0]=a-o:l<0&&(u[0]=Math.abs(l)+o),c<0?u[1]=c-o:h<0&&(u[1]=Math.abs(h)+o),u[0]!==0||u[1]!==0){const d=e.getView().getCenterInternal(),f=e.getPixelFromCoordinateInternal(d);if(!f)return;const g=[f[0]+u[0],f[1]+u[1]],_=t.animation||{};e.getView().animateInternal({center:e.getCoordinateFromPixelInternal(g),duration:_.duration,easing:_.easing})}}}getRect(t,e){const i=t.getBoundingClientRect(),n=i.left+window.pageXOffset,r=i.top+window.pageYOffset;return[n,r,n+e[0],r+e[1]]}setPositioning(t){this.set(Et.POSITIONING,t)}setVisible(t){this.rendered.visible!==t&&(this.element.style.display=t?"":"none",this.rendered.visible=t)}updatePixelPosition(){const t=this.getMap(),e=this.getPosition();if(!t||!t.isRendered()||!e){this.setVisible(!1);return}const i=t.getPixelFromCoordinate(e),n=t.getSize();this.updateRenderedPosition(i,n)}updateRenderedPosition(t,e){const i=this.element.style,n=this.getOffset(),r=this.getPositioning();this.setVisible(!0);const o=Math.round(t[0]+n[0])+"px",a=Math.round(t[1]+n[1])+"px";let l="0%",c="0%";r=="bottom-right"||r=="center-right"||r=="top-right"?l="-100%":(r=="bottom-center"||r=="center-center"||r=="top-center")&&(l="-50%"),r=="bottom-left"||r=="bottom-center"||r=="bottom-right"?c="-100%":(r=="center-left"||r=="center-center"||r=="center-right")&&(c="-50%");const h=`translate(${l}, ${c}) translate(${o}, ${a})`;this.rendered.transform_!=h&&(this.rendered.transform_=h,i.transform=h)}getOptions(){return this.options}}const Zs=.75,Bn=.1;class xd extends zi{constructor(t){t=t||{},super({element:document.createElement("div"),render:t.render,target:t.target}),this.boundHandleRotationChanged_=this.handleRotationChanged_.bind(this),this.collapsed_=t.collapsed!==void 0?t.collapsed:!0,this.collapsible_=t.collapsible!==void 0?t.collapsible:!0,this.collapsible_||(this.collapsed_=!1),this.rotateWithView_=t.rotateWithView!==void 0?t.rotateWithView:!1,this.viewExtent_=void 0;const e=t.className!==void 0?t.className:"ol-overviewmap",i=t.tipLabel!==void 0?t.tipLabel:"Overview map",n=t.collapseLabel!==void 0?t.collapseLabel:"‹";typeof n=="string"?(this.collapseLabel_=document.createElement("span"),this.collapseLabel_.textContent=n):this.collapseLabel_=n;const r=t.label!==void 0?t.label:"›";typeof r=="string"?(this.label_=document.createElement("span"),this.label_.textContent=r):this.label_=r;const o=this.collapsible_&&!this.collapsed_?this.collapseLabel_:this.label_,a=document.createElement("button");a.setAttribute("type","button"),a.title=i,a.appendChild(o),a.addEventListener(z.CLICK,this.handleClick_.bind(this),!1),this.ovmapDiv_=document.createElement("div"),this.ovmapDiv_.className="ol-overviewmap-map",this.view_=t.view;const l=new al({view:t.view,controls:new Nt,interactions:new Nt});this.ovmap_=l,t.layers&&t.layers.forEach(function(y){l.addLayer(y)});const c=document.createElement("div");c.className="ol-overviewmap-box",c.style.boxSizing="border-box",this.boxOverlay_=new Ed({position:[0,0],positioning:"center-center",element:c}),this.ovmap_.addOverlay(this.boxOverlay_);const h=e+" "+ni+" "+bn+(this.collapsed_&&this.collapsible_?" "+is:"")+(this.collapsible_?"":" ol-uncollapsible"),u=this.element;u.className=h,u.appendChild(this.ovmapDiv_),u.appendChild(a);const d=this,f=this.boxOverlay_,g=this.boxOverlay_.getElement(),_=function(y){return{clientX:y.clientX,clientY:y.clientY}},m=function(y){const E=_(y),w=l.getEventCoordinateInternal(E);f.setPosition(w)},p=function(y){const E=l.getEventCoordinateInternal(y);d.getMap().getView().setCenterInternal(E),window.removeEventListener("mousemove",m),window.removeEventListener("mouseup",p)};g.addEventListener("mousedown",function(){window.addEventListener("mousemove",m),window.addEventListener("mouseup",p)})}setMap(t){const e=this.getMap();if(t!==e){if(e){const i=e.getView();i&&this.unbindView_(i),this.ovmap_.setTarget(null)}if(super.setMap(t),t){this.ovmap_.setTarget(this.ovmapDiv_),this.listenerKeys.push(q(t,ti.PROPERTYCHANGE,this.handleMapPropertyChange_,this));const i=t.getView();i&&(this.bindView_(i),i.isDef()&&(this.ovmap_.updateSize(),this.resetExtent_())),this.ovmap_.isRendered()||this.updateBoxAfterOvmapIsRendered_()}}}handleMapPropertyChange_(t){if(t.key===ct.VIEW){const e=t.oldValue;e&&this.unbindView_(e);const i=this.getMap().getView();this.bindView_(i)}else!this.ovmap_.isRendered()&&(t.key===ct.TARGET||t.key===ct.SIZE)&&this.ovmap_.updateSize()}bindView_(t){if(!this.view_){const e=new Ut({projection:t.getProjection()});this.ovmap_.setView(e)}t.addChangeListener(Dt.ROTATION,this.boundHandleRotationChanged_),this.handleRotationChanged_()}unbindView_(t){t.removeChangeListener(Dt.ROTATION,this.boundHandleRotationChanged_)}handleRotationChanged_(){this.rotateWithView_&&this.ovmap_.getView().setRotation(this.getMap().getView().getRotation())}validateExtent_(){const t=this.getMap(),e=this.ovmap_;if(!t.isRendered()||!e.isRendered())return;const i=t.getSize(),r=t.getView().calculateExtentInternal(i);if(this.viewExtent_&&Mi(r,this.viewExtent_))return;this.viewExtent_=r;const o=e.getSize(),l=e.getView().calculateExtentInternal(o),c=e.getPixelFromCoordinateInternal(Xe(r)),h=e.getPixelFromCoordinateInternal(Rn(r)),u=Math.abs(c[0]-h[0]),d=Math.abs(c[1]-h[1]),f=o[0],g=o[1];uf*Zs||d>g*Zs?this.resetExtent_():Fe(l,r)||this.recenter_()}resetExtent_(){const t=this.getMap(),e=this.ovmap_,i=t.getSize(),r=t.getView().calculateExtentInternal(i),o=e.getView(),a=Math.log(Zs/Bn)/Math.LN2,l=1/(Math.pow(2,a/2)*Bn);Jl(r,l),o.fitInternal(Jn(r))}recenter_(){const t=this.getMap(),e=this.ovmap_,i=t.getView();e.getView().setCenterInternal(i.getCenterInternal())}updateBox_(){const t=this.getMap(),e=this.ovmap_;if(!t.isRendered()||!e.isRendered())return;const i=t.getSize(),n=t.getView(),r=e.getView(),o=this.rotateWithView_?0:-n.getRotation(),a=this.boxOverlay_,l=this.boxOverlay_.getElement(),c=n.getCenterInternal(),h=n.getResolution(),u=r.getResolution(),d=i[0]*h/u,f=i[1]*h/u;if(a.setPosition(c),l){l.style.width=d+"px",l.style.height=f+"px";const g="rotate("+o+"rad)";l.style.transform=g}}updateBoxAfterOvmapIsRendered_(){this.ovmapPostrenderKey_||(this.ovmapPostrenderKey_=on(this.ovmap_,te.POSTRENDER,function(t){delete this.ovmapPostrenderKey_,this.updateBox_()},this))}handleClick_(t){t.preventDefault(),this.handleToggle_()}handleToggle_(){this.element.classList.toggle(is),this.collapsed_?ts(this.collapseLabel_,this.label_):ts(this.label_,this.collapseLabel_),this.collapsed_=!this.collapsed_;const t=this.ovmap_;if(!this.collapsed_){if(t.isRendered()){this.viewExtent_=void 0,t.render();return}t.updateSize(),this.resetExtent_(),this.updateBoxAfterOvmapIsRendered_()}}getCollapsible(){return this.collapsible_}setCollapsible(t){this.collapsible_!==t&&(this.collapsible_=t,this.element.classList.toggle("ol-uncollapsible"),!t&&this.collapsed_&&this.handleToggle_())}setCollapsed(t){!this.collapsible_||this.collapsed_===t||this.handleToggle_()}getCollapsed(){return this.collapsed_}getRotateWithView(){return this.rotateWithView_}setRotateWithView(t){this.rotateWithView_!==t&&(this.rotateWithView_=t,this.getMap().getView().getRotation()!==0&&(this.rotateWithView_?this.handleRotationChanged_():this.ovmap_.getView().setRotation(0),this.viewExtent_=void 0,this.validateExtent_(),this.updateBox_()))}getOverviewMap(){return this.ovmap_}render(t){this.validateExtent_(),this.updateBox_()}}const Us="units",wd=[1,2,5],$i=25.4/.28;class Cd extends zi{constructor(t){t=t||{};const e=document.createElement("div");e.style.pointerEvents="none",super({element:e,render:t.render,target:t.target}),this.on,this.once,this.un;const i=t.className!==void 0?t.className:t.bar?"ol-scale-bar":"ol-scale-line";this.innerElement_=document.createElement("div"),this.innerElement_.className=i+"-inner",this.element.className=i+" "+ni,this.element.appendChild(this.innerElement_),this.viewState_=null,this.minWidth_=t.minWidth!==void 0?t.minWidth:64,this.maxWidth_=t.maxWidth,this.renderedVisible_=!1,this.renderedWidth_=void 0,this.renderedHTML_="",this.addChangeListener(Us,this.handleUnitsChanged_),this.setUnits(t.units||"metric"),this.scaleBar_=t.bar||!1,this.scaleBarSteps_=t.steps||4,this.scaleBarText_=t.text||!1,this.dpi_=t.dpi||void 0}getUnits(){return this.get(Us)}handleUnitsChanged_(){this.updateElement_()}setUnits(t){this.set(Us,t)}setDpi(t){this.dpi_=t}updateElement_(){const t=this.viewState_;if(!t){this.renderedVisible_&&(this.element.style.display="none",this.renderedVisible_=!1);return}const e=t.center,i=t.projection,n=this.getUnits(),r=n=="degrees"?"degrees":"m";let o=Hn(i,t.resolution,e,r);const a=this.minWidth_*(this.dpi_||$i)/$i,l=this.maxWidth_!==void 0?this.maxWidth_*(this.dpi_||$i)/$i:void 0;let c=a*o,h="";if(n=="degrees"){const E=Ai.degrees;c*=E,c=l){d=_,f=m,g=p;break}else if(f>=a)break;_=d,m=f,p=g,++u}const y=this.scaleBar_?this.createScaleBar(f,d,h):d.toFixed(g<0?-g:0)+" "+h;this.renderedHTML_!=y&&(this.innerElement_.innerHTML=y,this.renderedHTML_=y),this.renderedWidth_!=f&&(this.innerElement_.style.width=f+"px",this.renderedWidth_=f),this.renderedVisible_||(this.element.style.display="",this.renderedVisible_=!0)}createScaleBar(t,e,i){const n=this.getScaleForResolution(),r=n<1?Math.round(1/n).toLocaleString()+" : 1":"1 : "+Math.round(n).toLocaleString(),o=this.scaleBarSteps_,a=t/o,l=[this.createMarker("absolute")];for(let h=0;h
`+this.createMarker("relative")+(h%2===0||o===2?this.createStepText(h,t,!1,e,i):"")+"")}return l.push(this.createStepText(o,t,!0,e,i)),(this.scaleBarText_?`
`+r+"
":"")+l.join("")}createMarker(t){return`
`}createStepText(t,e,i,n,r){const a=(t===0?0:Math.round(n/this.scaleBarSteps_*t*100)/100)+(t===0?"":" "+r),l=t===0?-3:e/this.scaleBarSteps_*-1,c=t===0?0:e/this.scaleBarSteps_*2;return`
`+a+"
"}getScaleForResolution(){const t=Hn(this.viewState_.projection,this.viewState_.resolution,this.viewState_.center,"m"),e=this.dpi_||$i,i=1e3/25.4;return t*i*e}render(t){const e=t.frameState;e?this.viewState_=e.viewState:this.viewState_=null,this.updateElement_()}}const M={BEGIN_GEOMETRY:0,BEGIN_PATH:1,CIRCLE:2,CLOSE_PATH:3,CUSTOM:4,DRAW_CHARS:5,DRAW_IMAGE:6,END_GEOMETRY:7,FILL:8,MOVE_TO_LINE_TO:9,SET_FILL_STYLE:10,SET_STROKE_STYLE:11,STROKE:12,ELLIPSE:13},gi=[M.FILL],ee=[M.STROKE],me=[M.BEGIN_PATH],Yo=[M.CLOSE_PATH];class pl{drawCustom(t,e,i,n,r){}drawGeometry(t){}setStyle(t){}drawCircle(t,e,i){}drawEllipse(t,e,i){}drawFeature(t,e,i){}drawGeometryCollection(t,e,i){}drawLineString(t,e,i){}drawMultiLineString(t,e,i){}drawMultiPoint(t,e,i){}drawMultiPolygon(t,e,i){}drawPoint(t,e,i){}drawPolygon(t,e,i){}drawText(t,e,i){}setFillStrokeStyle(t,e){}setImageStyle(t,e){}setTextStyle(t,e){}}class Mn extends pl{constructor(t,e,i,n){super(),this.tolerance=t,this.maxExtent=e,this.pixelRatio=n,this.maxLineWidth=0,this.resolution=i,this.beginGeometryInstruction1_=null,this.beginGeometryInstruction2_=null,this.bufferedMaxExtent_=null,this.instructions=[],this.coordinates=[],this.tmpCoordinate_=[],this.hitDetectionInstructions=[],this.state={}}applyPixelRatio(t){const e=this.pixelRatio;return e==1?t:t.map(function(i){return i*e})}appendFlatPointCoordinates(t,e){const i=this.getBufferedMaxExtent(),n=this.tmpCoordinate_,r=this.coordinates;let o=r.length;for(let a=0,l=t.length;al&&(this.instructions.push([M.CUSTOM,l,h,t,i,Ci,r]),this.hitDetectionInstructions.push([M.CUSTOM,l,h,t,n||i,Ci,r]));break;case"Point":c=t.getFlatCoordinates(),this.coordinates.push(c[0],c[1]),h=this.coordinates.length,this.instructions.push([M.CUSTOM,l,h,t,i,void 0,r]),this.hitDetectionInstructions.push([M.CUSTOM,l,h,t,n||i,void 0,r]);break}this.endGeometry(e)}beginGeometry(t,e,i){this.beginGeometryInstruction1_=[M.BEGIN_GEOMETRY,e,0,t,i],this.instructions.push(this.beginGeometryInstruction1_),this.beginGeometryInstruction2_=[M.BEGIN_GEOMETRY,e,0,t,i],this.hitDetectionInstructions.push(this.beginGeometryInstruction2_)}finish(){return{instructions:this.instructions,hitDetectionInstructions:this.hitDetectionInstructions,coordinates:this.coordinates}}reverseHitDetectionInstructions(){const t=this.hitDetectionInstructions;t.reverse();let e;const i=t.length;let n,r,o=-1;for(e=0;ethis.maxLineWidth&&(this.maxLineWidth=i.lineWidth,this.bufferedMaxExtent_=null)}else i.strokeStyle=void 0,i.lineCap=void 0,i.lineDash=null,i.lineDashOffset=void 0,i.lineJoin=void 0,i.lineWidth=void 0,i.miterLimit=void 0}createFill(t){const e=t.fillStyle,i=[M.SET_FILL_STYLE,e];return typeof e!="string"&&i.push(t.fillPatternScale),i}applyStroke(t){this.instructions.push(this.createStroke(t))}createStroke(t){return[M.SET_STROKE_STYLE,t.strokeStyle,t.lineWidth*this.pixelRatio,t.lineCap,t.lineJoin,t.miterLimit,this.applyPixelRatio(t.lineDash),t.lineDashOffset*this.pixelRatio]}updateFillStyle(t,e){const i=t.fillStyle;(typeof i!="string"||t.currentFillStyle!=i)&&(i!==void 0&&this.instructions.push(e.call(this,t)),t.currentFillStyle=i)}updateStrokeStyle(t,e){const i=t.strokeStyle,n=t.lineCap,r=t.lineDash,o=t.lineDashOffset,a=t.lineJoin,l=t.lineWidth,c=t.miterLimit;(t.currentStrokeStyle!=i||t.currentLineCap!=n||r!=t.currentLineDash&&!We(t.currentLineDash,r)||t.currentLineDashOffset!=o||t.currentLineJoin!=a||t.currentLineWidth!=l||t.currentMiterLimit!=c)&&(i!==void 0&&e.call(this,t),t.currentStrokeStyle=i,t.currentLineCap=n,t.currentLineDash=r,t.currentLineDashOffset=o,t.currentLineJoin=a,t.currentLineWidth=l,t.currentMiterLimit=c)}endGeometry(t){this.beginGeometryInstruction1_[2]=this.instructions.length,this.beginGeometryInstruction1_=null,this.beginGeometryInstruction2_[2]=this.hitDetectionInstructions.length,this.beginGeometryInstruction2_=null;const e=[M.END_GEOMETRY,t];this.instructions.push(e),this.hitDetectionInstructions.push(e)}getBufferedMaxExtent(){if(!this.bufferedMaxExtent_&&(this.bufferedMaxExtent_=sa(this.maxExtent),this.maxLineWidth>0)){const t=this.resolution*(this.maxLineWidth+1)/2;an(this.bufferedMaxExtent_,t,this.bufferedMaxExtent_)}return this.bufferedMaxExtent_}}class vd extends Mn{constructor(t,e,i,n){super(t,e,i,n),this.hitDetectionImage_=null,this.image_=null,this.imagePixelRatio_=void 0,this.anchorX_=void 0,this.anchorY_=void 0,this.height_=void 0,this.opacity_=void 0,this.originX_=void 0,this.originY_=void 0,this.rotateWithView_=void 0,this.rotation_=void 0,this.scale_=void 0,this.width_=void 0,this.declutterMode_=void 0,this.declutterImageWithText_=void 0}drawPoint(t,e,i){if(!this.image_||this.maxExtent&&!Li(this.maxExtent,t.getFlatCoordinates()))return;this.beginGeometry(t,e,i);const n=t.getFlatCoordinates(),r=t.getStride(),o=this.coordinates.length,a=this.appendFlatPointCoordinates(n,r);this.instructions.push([M.DRAW_IMAGE,o,a,this.image_,this.anchorX_*this.imagePixelRatio_,this.anchorY_*this.imagePixelRatio_,Math.ceil(this.height_*this.imagePixelRatio_),this.opacity_,this.originX_*this.imagePixelRatio_,this.originY_*this.imagePixelRatio_,this.rotateWithView_,this.rotation_,[this.scale_[0]*this.pixelRatio/this.imagePixelRatio_,this.scale_[1]*this.pixelRatio/this.imagePixelRatio_],Math.ceil(this.width_*this.imagePixelRatio_),this.declutterMode_,this.declutterImageWithText_]),this.hitDetectionInstructions.push([M.DRAW_IMAGE,o,a,this.hitDetectionImage_,this.anchorX_,this.anchorY_,this.height_,1,this.originX_,this.originY_,this.rotateWithView_,this.rotation_,this.scale_,this.width_,this.declutterMode_,this.declutterImageWithText_]),this.endGeometry(e)}drawMultiPoint(t,e,i){if(!this.image_)return;this.beginGeometry(t,e,i);const n=t.getFlatCoordinates(),r=[];for(let l=0,c=n.length;l=s){const g=(s-a+f)/f,_=Zt(c,u,g),m=Zt(h,d,g);l.push(_,m),r.push(l),l=[_,m],a==s&&(o+=n),a=0}else if(a0&&r.push(l),r}function Id(s,t,e,i,n){let r=e,o=e,a=0,l=0,c=e,h,u,d,f,g,_,m,p,y,E;for(u=e;us&&(l>a&&(a=l,r=c,o=u),l=0,c=u-n)),d=f,m=y,p=E),g=w,_=x}return l+=f,l>a?[c,u]:[r,o]}const ls={left:0,center:.5,right:1,top:0,middle:.5,hanging:.2,alphabetic:.8,ideographic:.8,bottom:1};class Sd extends Mn{constructor(t,e,i,n){super(t,e,i,n),this.labels_=null,this.text_="",this.textOffsetX_=0,this.textOffsetY_=0,this.textRotateWithView_=void 0,this.textRotation_=0,this.textFillState_=null,this.fillStates={},this.fillStates[Lt]={fillStyle:Lt},this.textStrokeState_=null,this.strokeStates={},this.textState_={},this.textStates={},this.textKey_="",this.fillKey_="",this.strokeKey_="",this.declutterMode_=void 0,this.declutterImageWithText_=void 0}finish(){const t=super.finish();return t.textStates=this.textStates,t.fillStates=this.fillStates,t.strokeStates=this.strokeStates,t}drawText(t,e,i){const n=this.textFillState_,r=this.textStrokeState_,o=this.textState_;if(this.text_===""||!o||!n&&!r)return;const a=this.coordinates;let l=a.length;const c=t.getType();let h=null,u=t.getStride();if(o.placement==="line"&&(c=="LineString"||c=="MultiLineString"||c=="Polygon"||c=="MultiPolygon")){if(!Pt(this.maxExtent,t.getExtent()))return;let d;if(h=t.getFlatCoordinates(),c=="LineString")d=[h.length];else if(c=="MultiLineString")d=t.getEnds();else if(c=="Polygon")d=t.getEnds().slice(0,1);else if(c=="MultiPolygon"){const m=t.getEndss();d=[];for(let p=0,y=m.length;p{const x=a[(y+w)*2]===h[w*u]&&a[(y+w)*2+1]===h[w*u+1];return x||--y,x})}this.saveTextStates_(),(o.backgroundFill||o.backgroundStroke)&&(this.setFillStrokeStyle(o.backgroundFill,o.backgroundStroke),o.backgroundFill&&this.updateFillStyle(this.state,this.createFill),o.backgroundStroke&&(this.updateStrokeStyle(this.state,this.applyStroke),this.hitDetectionInstructions.push(this.createStroke(this.state)))),this.beginGeometry(t,e,i);let g=o.padding;if(g!=Je&&(o.scale[0]<0||o.scale[1]<0)){let y=o.padding[0],E=o.padding[1],w=o.padding[2],x=o.padding[3];o.scale[0]<0&&(E=-E,x=-x),o.scale[1]<0&&(y=-y,w=-w),g=[y,E,w,x]}const _=this.pixelRatio;this.instructions.push([M.DRAW_IMAGE,l,f,null,NaN,NaN,NaN,1,0,0,this.textRotateWithView_,this.textRotation_,[1,1],NaN,this.declutterMode_,this.declutterImageWithText_,g==Je?Je:g.map(function(y){return y*_}),!!o.backgroundFill,!!o.backgroundStroke,this.text_,this.textKey_,this.strokeKey_,this.fillKey_,this.textOffsetX_,this.textOffsetY_,d]);const m=1/_,p=this.state.fillStyle;o.backgroundFill&&(this.state.fillStyle=Lt,this.hitDetectionInstructions.push(this.createFill(this.state))),this.hitDetectionInstructions.push([M.DRAW_IMAGE,l,f,null,NaN,NaN,NaN,1,0,0,this.textRotateWithView_,this.textRotation_,[m,m],NaN,this.declutterMode_,this.declutterImageWithText_,g,!!o.backgroundFill,!!o.backgroundStroke,this.text_,this.textKey_,this.strokeKey_,this.fillKey_?Lt:this.fillKey_,this.textOffsetX_,this.textOffsetY_,d]),o.backgroundFill&&(this.state.fillStyle=p,this.hitDetectionInstructions.push(this.createFill(this.state))),this.endGeometry(e)}}saveTextStates_(){const t=this.textStrokeState_,e=this.textState_,i=this.textFillState_,n=this.strokeKey_;t&&(n in this.strokeStates||(this.strokeStates[n]={strokeStyle:t.strokeStyle,lineCap:t.lineCap,lineDashOffset:t.lineDashOffset,lineWidth:t.lineWidth,lineJoin:t.lineJoin,miterLimit:t.miterLimit,lineDash:t.lineDash}));const r=this.textKey_;r in this.textStates||(this.textStates[r]={font:e.font,textAlign:e.textAlign||mn,justify:e.justify,textBaseline:e.textBaseline||ns,scale:e.scale});const o=this.fillKey_;i&&(o in this.fillStates||(this.fillStates[o]={fillStyle:i.fillStyle}))}drawChars_(t,e){const i=this.textStrokeState_,n=this.textState_,r=this.strokeKey_,o=this.textKey_,a=this.fillKey_;this.saveTextStates_();const l=this.pixelRatio,c=ls[n.textBaseline],h=this.textOffsetY_*l,u=this.text_,d=i?i.lineWidth*Math.abs(n.scale[0])/2:0;this.instructions.push([M.DRAW_CHARS,t,e,c,n.overflow,a,n.maxAngle,l,h,r,d*l,u,o,1,this.declutterMode_]),this.hitDetectionInstructions.push([M.DRAW_CHARS,t,e,c,n.overflow,a&&Lt,n.maxAngle,l,h,r,d*l,u,o,1/l,this.declutterMode_])}setTextStyle(t,e){let i,n,r;if(!t)this.text_="";else{const o=t.getFill();o?(n=this.textFillState_,n||(n={},this.textFillState_=n),n.fillStyle=se(o.getColor()||Lt)):(n=null,this.textFillState_=n);const a=t.getStroke();if(!a)r=null,this.textStrokeState_=r;else{r=this.textStrokeState_,r||(r={},this.textStrokeState_=r);const g=a.getLineDash(),_=a.getLineDashOffset(),m=a.getWidth(),p=a.getMiterLimit();r.lineCap=a.getLineCap()||Oi,r.lineDash=g?g.slice():ye,r.lineDashOffset=_===void 0?Ee:_,r.lineJoin=a.getLineJoin()||Fi,r.lineWidth=m===void 0?pn:m,r.miterLimit=p===void 0?gn:p,r.strokeStyle=se(a.getColor()||_n)}i=this.textState_;const l=t.getFont()||Ba;Dc(l);const c=t.getScaleArray();i.overflow=t.getOverflow(),i.font=l,i.maxAngle=t.getMaxAngle(),i.placement=t.getPlacement(),i.textAlign=t.getTextAlign(),i.repeat=t.getRepeat(),i.justify=t.getJustify(),i.textBaseline=t.getTextBaseline()||ns,i.backgroundFill=t.getBackgroundFill(),i.backgroundStroke=t.getBackgroundStroke(),i.padding=t.getPadding()||Je,i.scale=c===void 0?[1,1]:c;const h=t.getOffsetX(),u=t.getOffsetY(),d=t.getRotateWithView(),f=t.getRotation();this.text_=t.getText()||"",this.textOffsetX_=h===void 0?0:h,this.textOffsetY_=u===void 0?0:u,this.textRotateWithView_=d===void 0?!1:d,this.textRotation_=f===void 0?0:f,this.strokeKey_=r?(typeof r.strokeStyle=="string"?r.strokeStyle:U(r.strokeStyle))+r.lineCap+r.lineDashOffset+"|"+r.lineWidth+r.lineJoin+r.miterLimit+"["+r.lineDash.join()+"]":"",this.textKey_=i.font+i.scale+(i.textAlign||"?")+(i.repeat||"?")+(i.justify||"?")+(i.textBaseline||"?"),this.fillKey_=n&&n.fillStyle?typeof n.fillStyle=="string"?n.fillStyle:"|"+U(n.fillStyle):""}this.declutterMode_=t.getDeclutterMode(),this.declutterImageWithText_=e}}const bd={Circle:Ks,Default:Mn,Image:vd,LineString:Td,Polygon:Ks,Text:Sd,Ellipse:Ks};class Ld{constructor(t,e,i,n){this.tolerance_=t,this.maxExtent_=e,this.pixelRatio_=n,this.resolution_=i,this.buildersByZIndex_={}}finish(){const t={};for(const e in this.buildersByZIndex_){t[e]=t[e]||{};const i=this.buildersByZIndex_[e];for(const n in i){const r=i[n].finish();t[e][n]=r}}return t}getBuilder(t,e){const i=t!==void 0?t.toString():"0";let n=this.buildersByZIndex_[i];n===void 0&&(n={},this.buildersByZIndex_[i]=n);let r=n[e];if(r===void 0){const o=bd[e];r=new o(this.tolerance_,this.maxExtent_,this.resolution_,this.pixelRatio_),n[e]=r}return r}}class Md extends Cn{constructor(t){super(),this.ready=!0,this.boundHandleImageChange_=this.handleImageChange_.bind(this),this.layer_=t}getFeatures(t){return J()}getData(t){return null}prepareFrame(t){return J()}renderFrame(t,e){return J()}loadedTileCallback(t,e,i){t[e]||(t[e]={}),t[e][i.tileCoord.toString()]=i}createLoadedTileFinder(t,e,i){return(n,r)=>{const o=this.loadedTileCallback.bind(this,i,n);return t.forEachLoadedTile(e,n,r,o)}}forEachFeatureAtCoordinate(t,e,i,n,r){}getLayer(){return this.layer_}handleFontsChanged(){}handleImageChange_(t){const e=t.target;(e.getState()===V.LOADED||e.getState()===V.ERROR)&&this.renderIfReadyAndVisible()}loadImage(t){let e=t.getState();return e!=V.LOADED&&e!=V.ERROR&&t.addEventListener(z.CHANGE,this.boundHandleImageChange_),e==V.IDLE&&(t.load(),e=t.getState()),e==V.LOADED}renderIfReadyAndVisible(){const t=this.getLayer();t&&t.getVisible()&&t.getSourceState()==="ready"&&t.changed()}renderDeferred(t){}disposeInternal(){delete this.layer_,super.disposeInternal()}}class yl{constructor(){Qr(this,"pushMethodArgs_",(...t)=>(this.instructions_[this.zIndex+this.offset_].push(t),this));this.instructions_=[],this.zIndex=0,this.offset_=0,this.context_=new Proxy(Qn(),{get:(t,e)=>{if(typeof Qn()[e]=="function")return this.instructions_[this.zIndex+this.offset_]||(this.instructions_[this.zIndex+this.offset_]=[]),this.instructions_[this.zIndex+this.offset_].push(e),this.pushMethodArgs_},set:(t,e,i)=>(this.instructions_[this.zIndex+this.offset_]||(this.instructions_[this.zIndex+this.offset_]=[]),this.instructions_[this.zIndex+this.offset_].push(e,i),!0)})}pushFunction(t){this.instructions_[this.zIndex+this.offset_].push(t)}getContext(){return this.context_}draw(t){this.instructions_.forEach(e=>{for(let i=0,n=e.length;ib[2]}else O=w>I;const A=Math.PI,k=[],D=v+i===t;t=v,m=0,p=T,d=s[t],f=s[t+1];let G;if(D){y(),G=Math.atan2(f-_,d-g),O&&(G+=G>0?-A:A);const b=(I+w)/2,K=(F+x)/2;return k[0]=[b,K,(R-r)/2,G,n],k}n=n.replace(/\n/g," ");for(let b=0,K=n.length;b0?-A:A),G!==void 0){let S=W-G;if(S+=S>A?-2*A:S<-A?2*A:0,Math.abs(S)>o)return null}G=W;const nt=b;let Y=0;for(;b0&&s.push(` +`,""),s.push(t,""),s}class Dd{constructor(t,e,i,n,r){this.overlaps=i,this.pixelRatio=e,this.resolution=t,this.alignAndScaleFill_,this.instructions=n.instructions,this.coordinates=n.coordinates,this.coordinateCache_={},this.renderedTransform_=$t(),this.hitDetectionInstructions=n.hitDetectionInstructions,this.pixelCoordinates_=null,this.viewRotation_=0,this.fillStates=n.fillStates||{},this.strokeStates=n.strokeStates||{},this.textStates=n.textStates||{},this.widths_={},this.labels_={},this.zIndexContext_=r?new yl:null}getZIndexContext(){return this.zIndexContext_}createLabel(t,e,i,n){const r=t+e+i+n;if(this.labels_[r])return this.labels_[r];const o=n?this.strokeStates[n]:null,a=i?this.fillStates[i]:null,l=this.textStates[e],c=this.pixelRatio,h=[l.scale[0]*c,l.scale[1]*c],u=Array.isArray(t),d=l.justify?ls[l.justify]:js(Array.isArray(t)?t[0]:t,l.textAlign||mn),f=n&&o.lineWidth?o.lineWidth:0,g=u?t:t.split(` +`).reduce(Fd,[]),{width:_,height:m,widths:p,heights:y,lineWidths:E}=Nc(l,g),w=_+f,x=[],v=(w+2)*h[0],T=(m+f)*h[1],R={width:v<0?Math.floor(v):Math.ceil(v),height:T<0?Math.floor(T):Math.ceil(T),contextInstructions:x};(h[0]!=1||h[1]!=1)&&x.push("scale",h),n&&(x.push("strokeStyle",o.strokeStyle),x.push("lineWidth",f),x.push("lineCap",o.lineCap),x.push("lineJoin",o.lineJoin),x.push("miterLimit",o.miterLimit),x.push("setLineDash",[o.lineDash]),x.push("lineDashOffset",o.lineDashOffset)),i&&x.push("fillStyle",a.fillStyle),x.push("textBaseline","middle"),x.push("textAlign","center");const I=.5-d;let F=d*w+I*f;const O=[],A=[];let k=0,D=0,G=0,b=0,K;for(let W=0,nt=g.length;Wt?t-c:r,w=o+h>e?e-h:o,x=g[3]+E*d[0]+g[1],v=g[0]+w*d[1]+g[2],T=p-g[3],R=y-g[0];(_||u!==0)&&(Le[0]=T,Me[0]=T,Le[1]=R,ue[1]=R,ue[0]=T+x,de[0]=ue[0],de[1]=R+v,Me[1]=de[1]);let I;return u!==0?(I=we($t(),i,n,1,1,u,-i,-n),pt(I,Le),pt(I,ue),pt(I,de),pt(I,Me),Ce(Math.min(Le[0],ue[0],de[0],Me[0]),Math.min(Le[1],ue[1],de[1],Me[1]),Math.max(Le[0],ue[0],de[0],Me[0]),Math.max(Le[1],ue[1],de[1],Me[1]),_i)):Ce(Math.min(T,T+x),Math.min(R,R+v),Math.max(T,T+x),Math.max(R,R+v),_i),f&&(p=Math.round(p),y=Math.round(y)),{drawImageX:p,drawImageY:y,drawImageW:E,drawImageH:w,originX:c,originY:h,declutterBox:{minX:_i[0],minY:_i[1],maxX:_i[2],maxY:_i[3],value:m},canvasTransform:I,scale:d}}replayImageOrLabel_(t,e,i,n,r,o,a){const l=!!(o||a),c=n.declutterBox,h=a?a[2]*n.scale[0]/2:0;return c.minX-h<=e[0]&&c.maxX+h>=0&&c.minY-h<=e[1]&&c.maxY+h>=0&&(l&&this.replayTextBackground_(t,Le,ue,de,Me,o,a),Gc(t,n.canvasTransform,r,i,n.originX,n.originY,n.drawImageW,n.drawImageH,n.drawImageX,n.drawImageY,n.scale)),!0}fill_(t){const e=this.alignAndScaleFill_;if(e){const i=pt(this.renderedTransform_,[0,0]),n=512*this.pixelRatio;t.save(),t.translate(i[0]%n,i[1]%n),e!==1&&t.scale(e,e),t.rotate(this.viewRotation_)}t.fill(),e&&t.restore()}setStrokeStyle_(t,e){t.strokeStyle=e[1],t.lineWidth=e[2],t.lineCap=e[3],t.lineJoin=e[4],t.miterLimit=e[5],t.lineDashOffset=e[7],t.setLineDash(e[6])}drawLabelWithPointPlacement_(t,e,i,n){const r=this.textStates[e],o=this.createLabel(t,e,n,i),a=this.strokeStates[i],l=this.pixelRatio,c=js(Array.isArray(t)?t[0]:t,r.textAlign||mn),h=ls[r.textBaseline||ns],u=a&&a.lineWidth?a.lineWidth:0,d=o.width/l-2*r.scale[0],f=c*d+2*(.5-c)*u,g=h*o.height/l+2*(.5-h)*u;return{label:o,anchorX:f,anchorY:g}}execute_(t,e,i,n,r,o,a,l){const c=this.zIndexContext_;let h;this.pixelCoordinates_&&We(i,this.renderedTransform_)?h=this.pixelCoordinates_:(this.pixelCoordinates_||(this.pixelCoordinates_=[]),h=Ne(this.coordinates,0,this.coordinates.length,2,i,this.pixelCoordinates_),Bl(this.renderedTransform_,i));let u=0;const d=n.length;let f=0,g,_,m,p,y,E,w,x,v,T,R,I,F,O=0,A=0,k=null,D=null;const G=this.coordinateCache_,b=this.viewRotation_,K=Math.round(Math.atan2(-i[1],i[0])*1e12)/1e12,W={context:t,pixelRatio:this.pixelRatio,resolution:this.resolution,rotation:b},nt=this.instructions!=n||this.overlaps?0:200;let Y,j,Z,et;for(;unt&&(this.fill_(t),O=0),A>nt&&(t.stroke(),A=0),!O&&!A&&(t.beginPath(),y=NaN,E=NaN),++u;break;case M.CIRCLE:f=S[1];const yt=h[f],lt=h[f+1],qt=h[f+2],Ye=h[f+3],Rt=qt-yt,An=Ye-lt,Wi=Math.sqrt(Rt*Rt+An*An);t.moveTo(yt+Wi,lt),t.arc(yt,lt,Wi,0,2*Math.PI,!0),++u;break;case M.ELLIPSE:f=S[1],g=S[2];const Ve=h[f],Wt=h[f+1],Be=h[f+2],Ze=h[f+3],oi=h[f+4],Ue=h[f+5],ai=h[f+6],At=h[f+7];if(g-f===8){const _t=(oi-Ve)*.2761424,Xt=(Ue-Wt)*.2761424,mt=(ai-Be)*.2761424,St=(At-Ze)*.2761424;t.moveTo(Ve,Wt),t.bezierCurveTo(Ve-mt,Wt-St,Be-_t,Ze-Xt,Be,Ze),t.bezierCurveTo(Be+_t,Ze+Xt,oi-mt,Ue-St,oi,Ue),t.bezierCurveTo(oi+mt,Ue+St,ai+_t,At+Xt,ai,At),t.bezierCurveTo(ai-_t,At-Xt,Ve+mt,Wt+St,Ve,Wt)}++u;break;case M.CLOSE_PATH:t.closePath(),++u;break;case M.CUSTOM:f=S[1],g=S[2];const Ht=S[3],Ke=S[4],Re=S[5];W.geometry=Ht,W.feature=Y,u in G||(G[u]=[]);const Ie=G[u];Re?Re(h,f,g,2,Ie):(Ie[0]=h[f],Ie[1]=h[f+1],Ie.length=2),c&&(c.zIndex=S[6]),Ke(Ie,W),++u;break;case M.DRAW_IMAGE:f=S[1],g=S[2],v=S[3],_=S[4],m=S[5];let li=S[6];const Xi=S[7],hi=S[8],Ts=S[9],It=S[10];let Rs=S[11];const Il=S[12];let Pn=S[13];p=S[14]||"declutter";const Yi=S[15];if(!v&&S.length>=20){T=S[19],R=S[20],I=S[21],F=S[22];const _t=this.drawLabelWithPointPlacement_(T,R,I,F);v=_t.label,S[3]=v;const Xt=S[23];_=(_t.anchorX-Xt)*this.pixelRatio,S[4]=_;const mt=S[24];m=(_t.anchorY-mt)*this.pixelRatio,S[5]=m,li=v.height,S[6]=li,Pn=v.width,S[13]=Pn}let Is;S.length>25&&(Is=S[25]);let Ss,On,Fn;S.length>17?(Ss=S[16],On=S[17],Fn=S[18]):(Ss=Je,On=!1,Fn=!1),It&&K?Rs+=b:!It&&!K&&(Rs-=b);let Sl=0;for(;f!xl.includes(s));class Nd{constructor(t,e,i,n,r,o,a){this.maxExtent_=t,this.overlaps_=n,this.pixelRatio_=i,this.resolution_=e,this.renderBuffer_=o,this.executorsByZIndex_={},this.hitDetectionContext_=null,this.hitDetectionTransform_=$t(),this.renderedContext_=null,this.deferredZIndexContexts_={},this.createExecutors_(r,a)}clip(t,e){const i=this.getClipCoords(e);t.beginPath(),t.moveTo(i[0],i[1]),t.lineTo(i[2],i[3]),t.lineTo(i[4],i[5]),t.lineTo(i[6],i[7]),t.clip()}createExecutors_(t,e){for(const i in t){let n=this.executorsByZIndex_[i];n===void 0&&(n={},this.executorsByZIndex_[i]=n);const r=t[i];for(const o in r){const a=r[o];n[o]=new Dd(this.resolution_,this.pixelRatio_,this.overlaps_,a,e)}}}hasExecutors(t){for(const e in this.executorsByZIndex_){const i=this.executorsByZIndex_[e];for(let n=0,r=t.length;n0){if(!o||T==="none"||f!=="Image"&&f!=="Text"||o.includes(x)){const O=(d[I]-3)/4,A=n-O%a,k=n-(O/a|0),D=r(x,v,A*A+k*k);if(D)return D}h.clearRect(0,0,a,a);break}}const _=Object.keys(this.executorsByZIndex_).map(Number);_.sort(pe);let m,p,y,E,w;for(m=_.length-1;m>=0;--m){const x=_[m].toString();for(y=this.executorsByZIndex_[x],p=vi.length-1;p>=0;--p)if(f=vi[p],E=y[f],E!==void 0&&(w=E.executeHitDetection(h,l,i,g,u),w))return w}}getClipCoords(t){const e=this.maxExtent_;if(!e)return null;const i=e[0],n=e[1],r=e[2],o=e[3],a=[i,n,i,o,r,o,r,n];return Ne(a,0,8,2,t,a),a}isEmpty(){return bi(this.executorsByZIndex_)}execute(t,e,i,n,r,o,a){const l=Object.keys(this.executorsByZIndex_).map(Number);l.sort(pe),o=o||vi;const c=vi.length;let h,u,d,f,g;for(a&&l.reverse(),h=0,u=l.length;hp.execute(x,e,i,n,r,a)),w&&E.restore(),y){y.offset();const x=l[h]*c+d;this.deferredZIndexContexts_[x]||(this.deferredZIndexContexts_[x]=[]),this.deferredZIndexContexts_[x].push(y)}}}}this.renderedContext_=t}getDeferredZIndexContexts(){return this.deferredZIndexContexts_}getRenderedContext(){return this.renderedContext_}renderDeferred(){const t=this.deferredZIndexContexts_,e=Object.keys(t).map(Number).sort(pe);for(let i=0,n=e.length;i{r.draw(this.renderedContext_),r.clear()}),t[e[i]].length=0}}const qs={};function Gd(s){if(qs[s]!==void 0)return qs[s];const t=s*2+1,e=s*s,i=new Array(e+1);for(let r=0;r<=s;++r)for(let o=0;o<=s;++o){const a=r*r+o*o;if(a>e)break;let l=i[a];l||(l=[],i[a]=l),l.push(((s+r)*t+(s+o))*4+3),r>0&&l.push(((s-r)*t+(s+o))*4+3),o>0&&(l.push(((s+r)*t+(s-o))*4+3),r>0&&l.push(((s-r)*t+(s-o))*4+3))}const n=[];for(let r=0,o=i.length;ru*this.pixelRatio_),lineDashOffset:(o||Ee)*this.pixelRatio_,lineJoin:a!==void 0?a:Fi,lineWidth:(l!==void 0?l:pn)*this.pixelRatio_,miterLimit:c!==void 0?c:gn,strokeStyle:se(i||_n)}}}setImageStyle(t){let e;if(!t||!(e=t.getSize())){this.image_=null;return}const i=t.getPixelRatio(this.pixelRatio_),n=t.getAnchor(),r=t.getOrigin();this.image_=t.getImage(this.pixelRatio_),this.imageAnchorX_=n[0]*i,this.imageAnchorY_=n[1]*i,this.imageHeight_=e[1]*i,this.imageOpacity_=t.getOpacity(),this.imageOriginX_=r[0],this.imageOriginY_=r[1],this.imageRotateWithView_=t.getRotateWithView(),this.imageRotation_=t.getRotation();const o=t.getScaleArray();this.imageScale_=[o[0]*this.pixelRatio_/i,o[1]*this.pixelRatio_/i],this.imageWidth_=e[0]*i}setTextStyle(t){if(!t)this.text_="";else{const e=t.getFill();if(!e)this.textFillState_=null;else{const f=e.getColor();this.textFillState_={fillStyle:se(f||Lt)}}const i=t.getStroke();if(!i)this.textStrokeState_=null;else{const f=i.getColor(),g=i.getLineCap(),_=i.getLineDash(),m=i.getLineDashOffset(),p=i.getLineJoin(),y=i.getWidth(),E=i.getMiterLimit();this.textStrokeState_={lineCap:g!==void 0?g:Oi,lineDash:_||ye,lineDashOffset:m||Ee,lineJoin:p!==void 0?p:Fi,lineWidth:y!==void 0?y:pn,miterLimit:E!==void 0?E:gn,strokeStyle:se(f||_n)}}const n=t.getFont(),r=t.getOffsetX(),o=t.getOffsetY(),a=t.getRotateWithView(),l=t.getRotation(),c=t.getScaleArray(),h=t.getText(),u=t.getTextAlign(),d=t.getTextBaseline();this.textState_={font:n!==void 0?n:Ba,textAlign:u!==void 0?u:mn,textBaseline:d!==void 0?d:ns},this.text_=h!==void 0?Array.isArray(h)?h.reduce((f,g,_)=>f+=_%2?" ":g,""):h:"",this.textOffsetX_=r!==void 0?this.pixelRatio_*r:0,this.textOffsetY_=o!==void 0?this.pixelRatio_*o:0,this.textRotateWithView_=a!==void 0?a:!1,this.textRotation_=l!==void 0?l:0,this.textScale_=[this.pixelRatio_*c[0],this.pixelRatio_*c[1]]}}}const ie=.5;function Wd(s,t,e,i,n,r,o,a,l){const c=n,h=s[0]*ie,u=s[1]*ie,d=gt(h,u);d.imageSmoothingEnabled=!1;const f=d.canvas,g=new zd(d,ie,n,null,o,a,null),_=e.length,m=Math.floor((256*256*256-1)/_),p={};for(let E=1;E<=_;++E){const w=e[E-1],x=w.getStyleFunction()||i;if(!x)continue;let v=x(w,r);if(!v)continue;Array.isArray(v)||(v=[v]);const R=(E*m).toString(16).padStart(7,"#00000");for(let I=0,F=v.length;I0;return u&&Promise.all(l).then(()=>n(null)),Zd(s,t,e,i,r,o,a),u}function Zd(s,t,e,i,n,r,o){const a=e.getGeometryFunction()(t);if(!a)return;const l=a.simplifyTransformed(i,n);if(e.getRenderer())vl(s,l,e,t,o);else{const h=wl[l.getType()];h(s,l,e,t,o,r)}}function vl(s,t,e,i,n){if(t.getType()=="GeometryCollection"){const o=t.getGeometries();for(let a=0,l=o.length;a{if(this.frameState&&!this.hitDetectionImageData_&&!this.animatingOrInteracting_){const i=this.frameState.size.slice(),n=this.renderedCenter_,r=this.renderedResolution_,o=this.renderedRotation_,a=this.renderedProjection_,l=this.wrappedRenderedExtent_,c=this.getLayer(),h=[],u=i[0]*ie,d=i[1]*ie;h.push(this.getRenderTransform(n,r,o,ie,u,d,0).slice());const f=c.getSource(),g=a.getExtent();if(f.getWrapX()&&a.canWrapX()&&!Fe(g,l)){let _=l[0];const m=B(g);let p=0,y;for(;_g[2];)++p,y=m*p,h.push(this.getRenderTransform(n,r,o,ie,u,d,y).slice()),_-=m}this.hitDetectionImageData_=Wd(i,h,this.renderedFeatures_,c.getStyleFunction(),l,r,o,Uo(r,this.renderedPixelRatio_))}e(Xd(t,this.renderedFeatures_,this.hitDetectionImageData_))})}forEachFeatureAtCoordinate(t,e,i,n,r){if(!this.replayGroup_)return;const o=e.viewState.resolution,a=e.viewState.rotation,l=this.getLayer(),c={},h=function(g,_,m){const p=U(g),y=c[p];if(y){if(y!==!0&&mu=g.forEachFeatureAtCoordinate(t,o,a,i,h,f&&e.declutter[f]?e.declutter[f].all().map(_=>_.value):null)),u}handleFontsChanged(){const t=this.getLayer();t.getVisible()&&this.replayGroup_&&t.changed()}handleStyleImageChange_(t){this.renderIfReadyAndVisible()}prepareFrame(t){const e=this.getLayer(),i=e.getSource();if(!i)return!1;const n=t.viewHints[wt.ANIMATING],r=t.viewHints[wt.INTERACTING],o=e.getUpdateWhileAnimating(),a=e.getUpdateWhileInteracting();if(this.ready&&!o&&n||!a&&r)return this.animatingOrInteracting_=!0,!0;this.animatingOrInteracting_=!1;const l=t.extent,c=t.viewState,h=c.projection,u=c.resolution,d=t.pixelRatio,f=e.getRevision(),g=e.getRenderBuffer();let _=e.getRenderOrder();_===void 0&&(_=Vd);const m=c.center.slice(),p=an(l,g*u),y=p.slice(),E=[p.slice()],w=h.getExtent();if(i.getWrapX()&&h.canWrapX()&&!Fe(w,t.extent)){const D=B(w),G=Math.max(B(p)/2,D);p[0]=w[0]-G,p[2]=w[2]+G,fa(m,h);const b=ca(E[0],h);b[0]w[0]&&b[2]>w[2]&&E.push([b[0]-D,b[1],b[2]-D,b[3]])}if(this.ready&&this.renderedResolution_==u&&this.renderedRevision_==f&&this.renderedRenderOrder_==_&&this.renderedFrameDeclutter_===!!t.declutter&&Fe(this.wrappedRenderedExtent_,p))return We(this.renderedExtent_,y)||(this.hitDetectionImageData_=null,this.renderedExtent_=y),this.renderedCenter_=m,this.replayGroupChanged=!1,!0;this.replayGroup_=null;const x=new Ld(Cl(u,d),p,u,d);let v;for(let D=0,G=E.length;D{let b;const K=D.getStyleFunction()||e.getStyleFunction();if(K&&(b=K(D,u)),b){const W=this.renderFeature(D,T,b,x,v,this.getLayer().getDeclutter(),G);R=R&&!W}},F=pa(p),O=i.getFeaturesInExtent(F);_&&O.sort(_);for(let D=0,G=O.length;D=0;--n){const r=e[n];if(r!==this&&r instanceof Zr&&r.getStyle()&&r.getFeatures().getArray().lastIndexOf(t)!==-1){t.setStyle(r.getStyle());return}}const i=U(t);t.setStyle(Zn[i]),delete Zn[i]}removeFeatureLayerAssociation_(t){delete this.featureLayerAssociation_[U(t)]}handleEvent(t){if(!this.condition_(t))return!0;const e=this.addCondition_(t),i=this.removeCondition_(t),n=this.toggleCondition_(t),r=!e&&!i&&!n,o=t.map,a=this.getFeatures(),l=[],c=[];if(r){Di(this.featureLayerAssociation_),o.forEachFeatureAtPixel(t.pixel,(h,u)=>{if(!(!(h instanceof un)||!this.filter_(h,u)))return this.addFeatureLayerAssociation_(h,u),c.push(h),!this.multi_},{layerFilter:this.layerFilter_,hitTolerance:this.hitTolerance_});for(let h=a.getLength()-1;h>=0;--h){const u=a.item(h),d=c.indexOf(u);d>-1?c.splice(d,1):(a.remove(u),l.push(u))}c.length!==0&&a.extend(c)}else{o.forEachFeatureAtPixel(t.pixel,(h,u)=>{if(!(!(h instanceof un)||!this.filter_(h,u)))return(e||n)&&!a.getArray().includes(h)?(this.addFeatureLayerAssociation_(h,u),c.push(h)):(i||n)&&a.getArray().includes(h)&&(l.push(h),this.removeFeatureLayerAssociation_(h)),!this.multi_},{layerFilter:this.layerFilter_,hitTolerance:this.hitTolerance_});for(let h=l.length-1;h>=0;--h)a.remove(l[h]);a.extend(c)}return(c.length>0||l.length>0)&&this.dispatchEvent(new ef(tf.SELECT,c,l,t)),!0}}function nf(){const s=Xc();return rn(s.Polygon,s.LineString),rn(s.GeometryCollection,s.LineString),function(t){return t.getGeometry()?s[t.getGeometry().getType()]:null}}let Kt={colors:{blue:"#0099ff",white:"#ffffff",orange:"#ff5e00"},radius:{default:6},strokeWidth:{default:2}};Kt.default=new Gt({image:new si({radius:Kt.radius.default,fill:new ve({color:Kt.colors.blue}),stroke:new xe({color:Kt.colors.white,width:Kt.strokeWidth.default})})});Kt.selected=new Gt({image:new si({radius:Kt.radius.default,fill:new ve({color:Kt.colors.orange}),stroke:new xe({color:Kt.colors.white,width:Kt.strokeWidth.default})}),zIndex:1/0});const Un={PRELOAD:"preload",USE_INTERIM_TILES_ON_ERROR:"useInterimTilesOnError"};class sf extends _s{constructor(t){t=t||{};const e=Object.assign({},t);delete e.preload,delete e.useInterimTilesOnError,super(e),this.on,this.once,this.un,this.setPreload(t.preload!==void 0?t.preload:0),this.setUseInterimTilesOnError(t.useInterimTilesOnError!==void 0?t.useInterimTilesOnError:!0)}getPreload(){return this.get(Un.PRELOAD)}setPreload(t){this.set(Un.PRELOAD,t)}getUseInterimTilesOnError(){return this.get(Un.USE_INTERIM_TILES_ON_ERROR)}setUseInterimTilesOnError(t){this.set(Un.USE_INTERIM_TILES_ON_ERROR,t)}getData(t){return super.getData(t)}}class rf extends El{constructor(t){super(t),this.extentChanged=!0,this.renderedExtent_=null,this.renderedPixelRatio,this.renderedProjection=null,this.renderedRevision,this.renderedTiles=[],this.newTiles_=!1,this.tmpExtent=zt(),this.tmpTileRange_=new Wr(0,0,0,0)}isDrawableTile(t){const e=this.getLayer(),i=t.getState(),n=e.getUseInterimTilesOnError();return i==P.LOADED||i==P.EMPTY||i==P.ERROR&&!n}getTile(t,e,i,n){const r=n.pixelRatio,o=n.viewState.projection,a=this.getLayer();let c=a.getSource().getTile(t,e,i,r,o);return c.getState()==P.ERROR&&a.getUseInterimTilesOnError()&&a.getPreload()>0&&(this.newTiles_=!0),this.isDrawableTile(c)||(c=c.getInterimTile()),c}getData(t){const e=this.frameState;if(!e)return null;const i=this.getLayer(),n=pt(e.pixelToCoordinateTransform,t.slice()),r=i.getExtent();if(r&&!Li(r,n))return null;const o=e.pixelRatio,a=e.viewState.projection,l=e.viewState,c=i.getRenderSource(),h=c.getTileGridForProjection(l.projection),u=c.getTilePixelRatio(e.pixelRatio);for(let d=h.getZForResolution(l.resolution);d>=h.getMinZoom();--d){const f=h.getTileCoordForCoordAndZ(n,d),g=c.getTile(d,f[1],f[2],o,a);if(!(g instanceof zr||g instanceof ur)||g instanceof ur&&g.getState()===P.EMPTY)return null;if(g.getState()!==P.LOADED)continue;const _=h.getOrigin(d),m=Ft(h.getTileSize(d)),p=h.getResolution(d),y=Math.floor(u*((n[0]-_[0])/p-f[1]*m[0])),E=Math.floor(u*((_[1]-n[1])/p-f[2]*m[1])),w=Math.round(u*c.getGutterForProjection(l.projection));return this.getImageData(g.getImage(),y+w,E+w)}return null}loadedTileCallback(t,e,i){return this.isDrawableTile(i)?super.loadedTileCallback(t,e,i):!1}prepareFrame(t){return!!this.getLayer().getSource()}renderFrame(t,e){const i=t.layerStatesArray[t.layerIndex],n=t.viewState,r=n.projection,o=n.resolution,a=n.center,l=n.rotation,c=t.pixelRatio,h=this.getLayer(),u=h.getSource(),d=u.getRevision(),f=u.getTileGridForProjection(r),g=f.getZForResolution(o,u.zDirection),_=f.getResolution(g);let m=t.extent;const p=t.viewState.resolution,y=u.getTilePixelRatio(c);this.prepareContainer(t,e);const E=this.context.canvas.width,w=this.context.canvas.height,x=i.extent&&De(i.extent);x&&(m=nn(m,De(i.extent)));const v=_*E/2/y,T=_*w/2/y,R=[a[0]-v,a[1]-T,a[0]+v,a[1]+T],I=f.getTileRangeForExtentAndZ(m,g),F={};F[g]={};const O=this.createLoadedTileFinder(u,r,F),A=this.tmpExtent,k=this.tmpTileRange_;this.newTiles_=!1;const D=l?tr(n.center,p,l,t.size):void 0;for(let j=I.minX;j<=I.maxX;++j)for(let Z=I.minY;Z<=I.maxY;++Z){if(l&&!f.tileCoordIntersectsViewport([g,j,Z],D))continue;const et=this.getTile(g,j,Z,t);if(this.isDrawableTile(et)){const yt=U(this);if(et.getState()==P.LOADED){F[g][et.tileCoord.toString()]=et;let lt=et.inTransition(yt);lt&&i.opacity!==1&&(et.endTransition(yt),lt=!1),!this.newTiles_&&(lt||!this.renderedTiles.includes(et))&&(this.newTiles_=!0)}if(et.getAlpha(yt,t.time)===1)continue}const S=f.getTileCoordChildTileRange(et.tileCoord,k,A);let Tt=!1;S&&(Tt=O(g+1,S)),Tt||f.forEachTileCoordParentTileRange(et.tileCoord,O,k,A)}const G=_/o*c/y,b=this.getRenderContext(t);we(this.tempTransform,E/2,w/2,G,G,0,-E/2,-w/2),x&&this.clipUnrotated(b,t,x),u.getInterpolate()||(b.imageSmoothingEnabled=!1),this.preRender(b,t),this.renderedTiles.length=0;let K=Object.keys(F).map(Number);K.sort(pe);let W,nt,Y;i.opacity===1&&(!this.containerReused||u.getOpaque(t.viewState.projection))?K=K.reverse():(W=[],nt=[]);for(let j=K.length-1;j>=0;--j){const Z=K[j],et=u.getTilePixelSize(Z,c,r),Tt=f.getResolution(Z)/_,yt=et[0]*Tt*G,lt=et[1]*Tt*G,qt=f.getTileCoordForCoordAndZ(Xe(R),Z),Ye=f.getTileCoordExtent(qt),Rt=pt(this.tempTransform,[y*(Ye[0]-R[0])/_,y*(R[3]-Ye[3])/_]),An=y*u.getGutterForProjection(r),Wi=F[Z];for(const Ve in Wi){const Wt=Wi[Ve],Be=Wt.tileCoord,Ze=qt[1]-Be[1],oi=Math.round(Rt[0]-(Ze-1)*yt),Ue=qt[2]-Be[2],ai=Math.round(Rt[1]-(Ue-1)*lt),At=Math.round(Rt[0]-Ze*yt),Ht=Math.round(Rt[1]-Ue*lt),Ke=oi-At,Re=ai-Ht,Ie=g===Z,li=Ie&&Wt.getAlpha(U(this),t.time)!==1;let Xi=!1;if(!li)if(W){Y=[At,Ht,At+Ke,Ht,At+Ke,Ht+Re,At,Ht+Re];for(let hi=0,Ts=W.length;hi=0;return n[a?"CRS":"SRS"]=i.getCode(),a&&r.substr(0,2)=="ne"?o=[t[1],t[0],t[3],t[2]]:o=t,n.BBOX=o.join(","),Rl(s,n)}function af(s,t,e,i,n,r,o){r=Object.assign({REQUEST:"GetMap"},r);const a=t/e,l=[ao(B(s)/a,qo),ao(at(s)/a,qo)];if(e!=1)switch(o){case"geoserver":const h=90*e+.5|0;"FORMAT_OPTIONS"in r?r.FORMAT_OPTIONS+=";dpi:"+h:r.FORMAT_OPTIONS="dpi:"+h;break;case"mapserver":r.MAP_RESOLUTION=90*e;break;case"carmentaserver":case"qgis":r.DPI=90*e;break;default:throw new Error("Unknown `serverType` configured")}return of(n,s,l,i,r)}function Ho(s,t){return Object.assign({REQUEST:t,SERVICE:"WMS",VERSION:dr,FORMAT:"image/png",STYLES:"",TRANSPARENT:!0},s)}class lf extends Br{constructor(t){t=t||{};const e=Object.assign({},t.params),i="TRANSPARENT"in e?e.TRANSPARENT:!0;super({attributions:t.attributions,attributionsCollapsible:t.attributionsCollapsible,cacheSize:t.cacheSize,crossOrigin:t.crossOrigin,interpolate:t.interpolate,opaque:!i,projection:t.projection,reprojectionErrorThreshold:t.reprojectionErrorThreshold,tileClass:t.tileClass,tileGrid:t.tileGrid,tileLoadFunction:t.tileLoadFunction,url:t.url,urls:t.urls,wrapX:t.wrapX!==void 0?t.wrapX:!0,transition:t.transition,zDirection:t.zDirection}),this.gutter_=t.gutter!==void 0?t.gutter:0,this.params_=e,this.v13_=!0,this.serverType_=t.serverType,this.hidpi_=t.hidpi!==void 0?t.hidpi:!0,this.tmpExtent_=zt(),this.updateV13_(),this.setKey(this.getKeyForParams_())}getFeatureInfoUrl(t,e,i,n){const r=Mt(i),o=this.getProjection()||r;let a=this.getTileGrid();a||(a=this.getTileGridForProjection(o));const l=vr(t,r,o),c=cr(o,r,t,e),h=a.getZForResolution(c,this.zDirection),u=a.getResolution(h),d=a.getTileCoordForCoordAndZ(l,h);if(a.getResolutions().length<=d[0])return;let f=a.getTileCoordExtent(d,this.tmpExtent_);const g=this.gutter_;g!==0&&(f=an(f,u*g,f));const _={QUERY_LAYERS:this.params_.LAYERS};Object.assign(_,Ho(this.params_,"GetFeatureInfo"),n);const m=Math.floor((l[0]-f[0])/u),p=Math.floor((f[3]-l[1])/u);return _[this.v13_?"I":"X"]=m,_[this.v13_?"J":"Y"]=p,this.getRequestUrl_(d,f,1,o||r,_)}getLegendUrl(t,e){if(this.urls[0]===void 0)return;const i={SERVICE:"WMS",VERSION:dr,REQUEST:"GetLegendGraphic",FORMAT:"image/png"};if(e===void 0||e.LAYER===void 0){const n=this.params_.LAYERS;if(!(!Array.isArray(n)||n.length===1))return;i.LAYER=n}if(t!==void 0){const n=this.getProjection()?this.getProjection().getMetersPerUnit():1,r=28e-5;i.SCALE=t*n/r}return Object.assign(i,e),Rl(this.urls[0],i)}getGutter(){return this.gutter_}getParams(){return this.params_}getRequestUrl_(t,e,i,n,r){const o=this.urls;if(!o)return;let a;if(o.length==1)a=o[0];else{const l=Qe(cl(t),o.length);a=o[l]}return af(e,(this.tileGrid||this.getTileGridForProjection(n)).getResolution(t[0]),i,n,a,r,this.serverType_)}getTilePixelRatio(t){return!this.hidpi_||this.serverType_===void 0?1:t}getKeyForParams_(){let t=0;const e=[];for(const i in this.params_)e[t++]=i+"-"+this.params_[i];return e.join("/")}updateParams(t){Object.assign(this.params_,t),this.updateV13_(),this.setKey(this.getKeyForParams_())}updateV13_(){const t=this.params_.VERSION||dr;this.v13_=da(t,"1.3")>=0}tileUrlFunction(t,e,i){let n=this.getTileGrid();if(n||(n=this.getTileGridForProjection(i)),n.getResolutions().length<=t[0])return;e!=1&&(!this.hidpi_||this.serverType_===void 0)&&(e=1);const r=n.getResolution(t[0]);let o=n.getTileCoordExtent(t,this.tmpExtent_);const a=this.gutter_;a!==0&&(o=an(o,r*a,o));const l=Object.assign({},Ho(this.params_,"GetMap"));return this.getRequestUrl_(t,o,e,i,l)}}class $o{constructor(t){this.rbush_=new za(t),this.items_={}}insert(t,e){const i={minX:t[0],minY:t[1],maxX:t[2],maxY:t[3],value:e};this.rbush_.insert(i),this.items_[U(e)]=i}load(t,e){const i=new Array(e.length);for(let n=0,r=e.length;n1?o:2,r=r||new Array(o);for(let h=0;h{if(t===this.squaredTolerance_)return this.simplifiedGeometry_;this.simplifiedGeometry_=this.clone(),e&&this.simplifiedGeometry_.applyTransform(e);const i=this.simplifiedGeometry_.getFlatCoordinates();let n;switch(this.type_){case"LineString":i.length=Rr(i,0,this.simplifiedGeometry_.flatCoordinates_.length,this.simplifiedGeometry_.stride_,t,i,0),n=[i.length];break;case"MultiLineString":n=[],i.length=Ah(i,0,this.simplifiedGeometry_.ends_,this.simplifiedGeometry_.stride_,t,i,0,n);break;case"Polygon":n=[],i.length=Ca(i,0,this.simplifiedGeometry_.ends_,this.simplifiedGeometry_.stride_,Math.sqrt(t),i,0,n);break}return n&&(this.simplifiedGeometry_=new Bt(this.type_,i,n,2,this.properties_,this.id_)),this.squaredTolerance_=t,this.simplifiedGeometry_}),this}}Bt.prototype.getFlatCoordinates=Bt.prototype.getOrientedFlatCoordinates;const Vt={ADDFEATURE:"addfeature",CHANGEFEATURE:"changefeature",CLEAR:"clear",REMOVEFEATURE:"removefeature",FEATURESLOADSTART:"featuresloadstart",FEATURESLOADEND:"featuresloadend",FEATURESLOADERROR:"featuresloaderror"};function cf(s,t){return[[-1/0,-1/0,1/0,1/0]]}let uf=!1;function df(s,t,e,i,n,r,o){const a=new XMLHttpRequest;a.open("GET",typeof s=="function"?s(e,i,n):s,!0),t.getType()=="arraybuffer"&&(a.responseType="arraybuffer"),a.withCredentials=uf,a.onload=function(l){if(!a.status||a.status>=200&&a.status<300){const c=t.getType();try{let h;c=="text"||c=="json"?h=a.responseText:c=="xml"?h=a.responseXML||a.responseText:c=="arraybuffer"&&(h=a.response),h?r(t.readFeatures(h,{extent:e,featureProjection:n}),t.readProjection(h)):o()}catch{o()}}else o()},a.onerror=o,a.send()}function ta(s,t){return function(e,i,n,r,o){const a=this;df(s,t,e,i,n,function(l,c){a.addFeatures(l),r!==void 0&&r(l)},o||Si)}}class Ae extends ae{constructor(t,e,i){super(t),this.feature=e,this.features=i}}class ff extends dl{constructor(t){t=t||{},super({attributions:t.attributions,interpolate:!0,projection:void 0,state:"ready",wrapX:t.wrapX!==void 0?t.wrapX:!0}),this.on,this.once,this.un,this.loader_=Si,this.format_=t.format,this.overlaps_=t.overlaps===void 0?!0:t.overlaps,this.url_=t.url,t.loader!==void 0?this.loader_=t.loader:this.url_!==void 0&&($(this.format_,"`format` must be set when `url` is set"),this.loader_=ta(this.url_,this.format_)),this.strategy_=t.strategy!==void 0?t.strategy:cf;const e=t.useSpatialIndex!==void 0?t.useSpatialIndex:!0;this.featuresRtree_=e?new $o:null,this.loadedExtentsRtree_=new $o,this.loadingExtentsCount_=0,this.nullGeometryFeatures_={},this.idIndex_={},this.uidIndex_={},this.featureChangeKeys_={},this.featuresCollection_=null;let i,n;Array.isArray(t.features)?n=t.features:t.features&&(i=t.features,n=i.getArray()),!e&&i===void 0&&(i=new Nt(n)),n!==void 0&&this.addFeaturesInternal(n),i!==void 0&&this.bindFeaturesCollection_(i)}addFeature(t){this.addFeatureInternal(t),this.changed()}addFeatureInternal(t){const e=U(t);if(!this.addToIndex_(e,t)){this.featuresCollection_&&this.featuresCollection_.remove(t);return}this.setupChangeEvents_(e,t);const i=t.getGeometry();if(i){const n=i.getExtent();this.featuresRtree_&&this.featuresRtree_.insert(n,t)}else this.nullGeometryFeatures_[e]=t;this.dispatchEvent(new Ae(Vt.ADDFEATURE,t))}setupChangeEvents_(t,e){e instanceof Bt||(this.featureChangeKeys_[t]=[q(e,z.CHANGE,this.handleFeatureChange_,this),q(e,ti.PROPERTYCHANGE,this.handleFeatureChange_,this)])}addToIndex_(t,e){let i=!0;if(e.getId()!==void 0){const n=String(e.getId());if(!(n in this.idIndex_))this.idIndex_[n]=e;else if(e instanceof Bt){const r=this.idIndex_[n];r instanceof Bt?Array.isArray(r)?r.push(e):this.idIndex_[n]=[r,e]:i=!1}else i=!1}return i&&($(!(t in this.uidIndex_),"The passed `feature` was already added to the source"),this.uidIndex_[t]=e),i}addFeatures(t){this.addFeaturesInternal(t),this.changed()}addFeaturesInternal(t){const e=[],i=[],n=[];for(let r=0,o=t.length;r{e||(e=!0,this.addFeature(i.element),e=!1)}),t.addEventListener(ft.REMOVE,i=>{e||(e=!0,this.removeFeature(i.element),e=!1)}),this.featuresCollection_=t}clear(t){if(t){for(const i in this.featureChangeKeys_)this.featureChangeKeys_[i].forEach(it);this.featuresCollection_||(this.featureChangeKeys_={},this.idIndex_={},this.uidIndex_={})}else if(this.featuresRtree_){const i=n=>{this.removeFeatureInternal(n)};this.featuresRtree_.forEach(i);for(const n in this.nullGeometryFeatures_)this.removeFeatureInternal(this.nullGeometryFeatures_[n])}this.featuresCollection_&&this.featuresCollection_.clear(),this.featuresRtree_&&this.featuresRtree_.clear(),this.nullGeometryFeatures_={};const e=new Ae(Vt.CLEAR);this.dispatchEvent(e),this.changed()}forEachFeature(t){if(this.featuresRtree_)return this.featuresRtree_.forEach(t);this.featuresCollection_&&this.featuresCollection_.forEach(t)}forEachFeatureAtCoordinateDirect(t,e){const i=[t[0],t[1],t[0],t[1]];return this.forEachFeatureInExtent(i,function(n){const r=n.getGeometry();if(r instanceof Bt||r.intersectsCoordinate(t))return e(n)})}forEachFeatureInExtent(t,e){if(this.featuresRtree_)return this.featuresRtree_.forEachInExtent(t,e);this.featuresCollection_&&this.featuresCollection_.forEach(e)}forEachFeatureIntersectingExtent(t,e){return this.forEachFeatureInExtent(t,function(i){const n=i.getGeometry();if(n instanceof Bt||n.intersectsExtent(t)){const r=e(i);if(r)return r}})}getFeaturesCollection(){return this.featuresCollection_}getFeatures(){let t;return this.featuresCollection_?t=this.featuresCollection_.getArray().slice(0):this.featuresRtree_&&(t=this.featuresRtree_.getAll(),bi(this.nullGeometryFeatures_)||rn(t,Object.values(this.nullGeometryFeatures_))),t}getFeaturesAtCoordinate(t){const e=[];return this.forEachFeatureAtCoordinateDirect(t,function(i){e.push(i)}),e}getFeaturesInExtent(t,e){if(this.featuresRtree_){if(!(e&&e.canWrapX()&&this.getWrapX()))return this.featuresRtree_.getInExtent(t);const n=ua(t,e);return[].concat(...n.map(r=>this.featuresRtree_.getInExtent(r)))}return this.featuresCollection_?this.featuresCollection_.getArray().slice(0):[]}getClosestFeatureToCoordinate(t,e){const i=t[0],n=t[1];let r=null;const o=[NaN,NaN];let a=1/0;const l=[-1/0,-1/0,1/0,1/0];return e=e||ei,this.featuresRtree_.forEachInExtent(l,function(c){if(e(c)){const h=c.getGeometry(),u=a;if(a=h instanceof Bt?0:h.closestPointXY(i,n,o,a),a{--this.loadingExtentsCount_,this.dispatchEvent(new Ae(Vt.FEATURESLOADEND,void 0,h))},()=>{--this.loadingExtentsCount_,this.dispatchEvent(new Ae(Vt.FEATURESLOADERROR))}),n.insert(l,{extent:l.slice()}))}this.loading=this.loader_.length<4?!1:this.loadingExtentsCount_>0}refresh(){this.clear(!0),this.loadedExtentsRtree_.clear(),super.refresh()}removeLoadedExtent(t){const e=this.loadedExtentsRtree_;let i;e.forEachInExtent(t,function(n){if(Mi(n.extent,t))return i=n,!0}),i&&e.remove(i)}removeFeatures(t){const e=[];for(let i=0,n=t.length;i0&&this.changed()}removeFeature(t){if(!t)return;this.removeFeatureInternal(t)&&this.changed()}removeFeatureInternal(t){const e=U(t);if(!(e in this.uidIndex_))return;e in this.nullGeometryFeatures_?delete this.nullGeometryFeatures_[e]:this.featuresRtree_&&this.featuresRtree_.remove(t);const i=this.featureChangeKeys_[e];i==null||i.forEach(it),delete this.featureChangeKeys_[e];const n=t.getId();if(n!==void 0){const r=n.toString(),o=this.idIndex_[r];o===t?delete this.idIndex_[r]:Array.isArray(o)&&(o.splice(o.indexOf(t),1),o.length===1&&(this.idIndex_[r]=o[0]))}return delete this.uidIndex_[e],this.hasListener(Vt.REMOVEFEATURE)&&this.dispatchEvent(new Ae(Vt.REMOVEFEATURE,t)),t}removeFromIdIndex_(t){let e=!1;for(const i in this.idIndex_){const n=this.idIndex_[i];if(t instanceof Bt&&Array.isArray(n)&&n.includes(t))n.splice(n.indexOf(t),1);else if(this.idIndex_[i]===t){delete this.idIndex_[i],e=!0;break}}return e}setLoader(t){this.loader_=t}setUrl(t){$(this.format_,"`format` must be set when `url` is set"),this.url_=t,this.setLoader(ta(t,this.format_))}}class gf extends zr{constructor(t,e,i,n,r,o,a){super(e,i,n,r,o,a),this.zoomifyImage_=null,this.tileSize_=t}getImage(){if(this.zoomifyImage_)return this.zoomifyImage_;const t=super.getImage();if(this.state==P.LOADED){const e=this.tileSize_;if(t.width==e[0]&&t.height==e[1])return this.zoomifyImage_=t,t;const i=gt(e[0],e[1]);return i.drawImage(t,0,0),this.zoomifyImage_=i.canvas,i.canvas}return t}}class _f extends Br{constructor(t){const e=t.size,i=t.tierSizeCalculation!==void 0?t.tierSizeCalculation:"default",n=t.tilePixelRatio||1,r=e[0],o=e[1],a=[],l=t.tileSize||gs;let c=l*n;switch(i){case"default":for(;r>c||o>c;)a.push([Math.ceil(r/c),Math.ceil(o/c)]),c+=c;break;case"truncated":let v=r,T=o;for(;v>c||T>c;)a.push([Math.ceil(v/c),Math.ceil(T/c)]),v>>=1,T>>=1;break;default:throw new Error("Unknown `tierSizeCalculation` configured")}a.push([1,1]),a.reverse();const h=[n],u=[0];for(let v=1,T=a.length;v{_=l,this.changed()}),x.src=w}}class mf extends zi{constructor(t){t=t||{},super({element:document.createElement("div"),target:t.target}),this.extent=t.extent?t.extent:null;const e=t.className!==void 0?t.className:"ol-zoom-extent",i=t.label!==void 0?t.label:"E",n=t.tipLabel!==void 0?t.tipLabel:"Fit to extent",r=document.createElement("button");r.setAttribute("type","button"),r.title=n,r.appendChild(typeof i=="string"?document.createTextNode(i):i),r.addEventListener(z.CLICK,this.handleClick_.bind(this),!1);const o=e+" "+ni+" "+bn,a=this.element;a.className=o,a.appendChild(r)}handleClick_(t){t.preventDefault(),this.handleZoomToExtent()}handleZoomToExtent(){const e=this.getMap().getView(),i=this.extent?De(this.extent,e.getProjection()):e.getProjection().getExtent();e.fitInternal(Jn(i))}}let Hs=biigle.$require("events"),Rf=biigle.$require("handleErrorResponse"),If=biigle.$require("labelTrees.components.labelTrees"),Sf=biigle.$require("resource"),bf=biigle.$require("core.components.sidebar"),Lf=biigle.$require("core.components.sidebarTab"),pf=biigle.$require("utils.throttle");const yf=(s,t)=>{const e=s.__vccOpts||s;for(const[i,n]of t)e[i]=n;return e},Ef={emits:["select","disable-overlay-btn"],props:{lastAction:{type:Array},images:{type:Array,required:!0},preselected:{type:Array,default(){return[]}},interactive:{type:Boolean,default:!0},zoom:{type:Number},selectable:{type:Boolean,default:!1},overlays:{type:Array,default(){return[]}},overlayUrlTemplate:{type:String,default(){return""}},hideIds:{type:Set,default(){return new Set}}},data(){return{extents:{}}},computed:{imagesWithGps(){return this.images.filter(function(s){return s.lat!==null&&s.lng!==null})},features(){let s={};return this.preselected.forEach(function(t){s[t]=null}),this.imagesWithGps.map(function(t){return new un({id:t.id,preselected:s.hasOwnProperty(t.id),geometry:new fs(xh([t.lng,t.lat]))})})}},methods:{parseSelectedFeatures(s){return s.getArray().map(t=>t.get("id"))},createOverlayTile(s){let t=new yr({code:"zoomify-"+s.id,units:"m"}),e=new _f({url:this.overlayUrlTemplate.replaceAll(":id",s.id),size:[s.attrs.width,s.attrs.height],crossOrigin:"anonymous",zDirection:-1,projection:t}),i=[s.attrs.top_left_lng,s.attrs.top_left_lat,s.attrs.bottom_right_lng,s.attrs.bottom_right_lat],n=e.getTileGrid().getExtent(),r=uo(i,"EPSG:4326","EPSG:3857");return this.extents[s.id]=r,t.setGetPointResolution(a=>a*Math.max(B(r)/B(n),at(r)/at(n))),Eh(t,"EPSG:3857",([a,l])=>[r[0]+(a-n[0])*B(r)/B(n),r[1]+(l-n[1])*at(r)/at(n)],([a,l])=>[n[0]+(a-r[0])*B(n)/B(r),n[1]+(l-r[1])*at(n)/at(r)]),new Kn({source:e})},setLayerVisbility(s){s.layer.setVisible(!this.hideIds.has(s.layer.values_.id))}},watch:{lastAction(s){if(s[0]==="filter-map-changed")return;let t=s[1],e=this.extents[t];this.map.getView().fit(e,this.map.getSize())},features(s){this.source.clear(),this.source.addFeatures(s)}},created(){this.source=new ff},mounted(){this.source.addFeatures(this.features);let s=this.source.getExtent(),t=new Kn({source:new yd}),e=new Tl({source:this.source,style:Kt.default,updateWhileAnimating:!0,updateWhileInteracting:!0});this.overlayGroup=new ii({layers:[],name:"overlayGroup"}),this.overlayGroup.on("addlayer",i=>this.setLayerVisbility(i));for(let i=this.overlays.length-1;i>=0;i--)if(this.overlays[i].type=="webmap"){let n=new Kn({source:new lf({url:this.overlays[i].attrs.url,params:{LAYERS:this.overlays[i].attrs.layer,TILED:!0},serverType:"geoserver",transition:0})});if(n.set("id",this.overlays[i].id),this.overlayGroup.getLayers().push(n),Object.values(this.overlays[i].attrs).length>2){let r=[this.overlays[i].attrs.top_left_lng,this.overlays[i].attrs.top_left_lat,this.overlays[i].attrs.bottom_right_lng,this.overlays[i].attrs.bottom_right_lat],o=uo(r,"EPSG:4326","EPSG:3857");this.extents[this.overlays[i].id]=o}else Hs.$emit("disable-overlay-btn",this.overlays[i].id)}else{let n=this.createOverlayTile(this.overlays[i]);n.set("name",`geotiffTile_${this.overlays[i].id}`),n.set("id",this.overlays[i].id),this.overlayGroup.getLayers().push(n)}if(this.map=new al({target:this.$el,layers:[t,this.overlayGroup],view:new Ut({projection:"EPSG:3857",padding:[10,10,10,10]}),interactions:sl({altShiftDragRotate:!1,doubleClickZoom:this.interactive,keyboard:this.interactive,mouseWheelZoom:this.interactive,shiftDragZoom:!1,dragPan:this.interactive,pinchRotate:!1,pinchZoom:this.interactive}),controls:nl({zoom:this.interactive})}),this.map.addLayer(e),this.map.getView().fit(s,this.map.getSize()),this.zoom&&this.map.getView().setZoom(this.zoom),this.interactive&&(this.map.addControl(new Cd),this.map.addControl(new mf({extent:s,label:""})),this.map.addControl(new xd({collapsed:!1,collapsible:!1,layers:[new Kn({source:t.getSource()})],view:new Ut({zoom:1,maxZoom:1})}))),this.map.on("moveend",()=>pf(()=>Hs.emit("geo-map-action"),1e3)),this.selectable){let i=new Zr({style:Kt.selected});i.getFeatures().extend(this.features.filter(o=>o.get("preselected")));let n=i.getFeatures();this.map.addInteraction(i),i.on("select",()=>{this.$emit("select",this.parseSelectedFeatures(n))});let r=new ka({condition:qh});this.map.addInteraction(r),r.on("boxend",()=>{n.clear(),this.source.forEachFeatureIntersectingExtent(r.getGeometry().getExtent(),function(o){n.push(o)}),this.$emit("select",this.parseSelectedFeatures(n))})}Hs.on("sidebar.toggle",function(){this.map&&this.map.updateSize()}),this.$nextTick(function(){this.map.updateSize()})}},xf={class:"image-map"};function wf(s,t,e,i,n,r){return Fl(),Ol("div",xf)}const Mf=yf(Ef,[["render",wf]]);export{Hs as E,Mf as I,If as L,Sf as R,Lf as S,yf as _,bf as a,Rf as h}; diff --git a/src/public/assets/imageMap-zpCzvVRf.js b/src/public/assets/imageMap-zpCzvVRf.js deleted file mode 100644 index 858477e0..00000000 --- a/src/public/assets/imageMap-zpCzvVRf.js +++ /dev/null @@ -1,10 +0,0 @@ -var yl=Object.defineProperty;var El=(s,t,e)=>t in s?yl(s,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):s[t]=e;var Br=(s,t,e)=>El(s,typeof t!="symbol"?t+"":t,e);import{createElementBlock as xl,openBlock as wl}from"vue";class ae{constructor(t){this.propagationStopped,this.defaultPrevented,this.type=t,this.target=null}preventDefault(){this.defaultPrevented=!0}stopPropagation(){this.propagationStopped=!0}}const Je={PROPERTYCHANGE:"propertychange"};class or{constructor(){this.disposed=!1}dispose(){this.disposed||(this.disposed=!0,this.disposeInternal())}disposeInternal(){}}function Cl(s,t,e){let i,n;e=e||pe;let r=0,o=s.length,a=!1;for(;r>1),n=+e(s[i],t),n<0?r=i+1:(o=i,a=!n);return a?r:~r}function pe(s,t){return s>t?1:s0?n-1:n}return i-1}if(e>0){for(let n=1;n0||o===0)})}function Qe(){return!0}function yn(){return!1}function Ii(){}function Vo(s){let t=!1,e,i,n;return function(){const r=Array.prototype.slice.call(arguments);return(!t||this!==n||!ze(r,i))&&(t=!0,n=this,i=r,e=s.apply(this,arguments)),e}}function Rl(s){function t(){let e;try{e=s()}catch(i){return Promise.reject(i)}return e instanceof Promise?e:Promise.resolve(e)}return t()}function Oi(s){for(const t in s)delete s[t]}function Si(s){let t;for(t in s)return!1;return!t}class rs extends or{constructor(t){super(),this.eventTarget_=t,this.pendingRemovals_=null,this.dispatching_=null,this.listeners_=null}addEventListener(t,e){if(!t||!e)return;const i=this.listeners_||(this.listeners_={}),n=i[t]||(i[t]=[]);n.includes(e)||n.push(e)}dispatchEvent(t){const e=typeof t=="string",i=e?t:t.type,n=this.listeners_&&this.listeners_[i];if(!n)return;const r=e?new ae(t):t;r.target||(r.target=this.eventTarget_||this);const o=this.dispatching_||(this.dispatching_={}),a=this.pendingRemovals_||(this.pendingRemovals_={});i in o||(o[i]=0,a[i]=0),++o[i];let l;for(let c=0,h=n.length;c0:!1}removeEventListener(t,e){if(!this.listeners_)return;const i=this.listeners_[t];if(!i)return;const n=i.indexOf(e);n!==-1&&(this.pendingRemovals_&&t in this.pendingRemovals_?(i[n]=Ii,++this.pendingRemovals_[t]):(i.splice(n,1),i.length===0&&delete this.listeners_[t]))}}const N={CHANGE:"change",ERROR:"error",CONTEXTMENU:"contextmenu",CLICK:"click",DBLCLICK:"dblclick",KEYDOWN:"keydown",KEYPRESS:"keypress",LOAD:"load",TOUCHMOVE:"touchmove",WHEEL:"wheel"};function U(s,t,e,i,n){if(i&&i!==s&&(e=e.bind(i)),n){const o=e;e=function(){s.removeEventListener(t,e),o.apply(this,arguments)}}const r={target:s,type:t,listener:e};return s.addEventListener(t,e),r}function rn(s,t,e,i){return U(s,t,e,i,!0)}function it(s){s&&s.target&&(s.target.removeEventListener(s.type,s.listener),Oi(s))}class En extends rs{constructor(){super(),this.on=this.onInternal,this.once=this.onceInternal,this.un=this.unInternal,this.revision_=0}changed(){++this.revision_,this.dispatchEvent(N.CHANGE)}getRevision(){return this.revision_}onInternal(t,e){if(Array.isArray(t)){const i=t.length,n=new Array(i);for(let r=0;r0}}else if(t.type==st.POINTERDOWN){const i=this.handleDownEvent(t);this.handlingDownUpSequence=i,e=this.stopDown(i)}else t.type==st.POINTERMOVE&&this.handleMoveEvent(t);return!e}handleMoveEvent(t){}handleUpEvent(t){return!1}stopDown(t){return t}updateTrackedPointers_(t){t.activePointers&&(this.targetPointers=t.activePointers)}}function hr(s){const t=s.length;let e=0,i=0;for(let n=0;nMath.round(e*Ur[i])/Ur[i]).join(", ")+")"}const ct={UNKNOWN:0,INTERSECTING:1,ABOVE:2,RIGHT:4,BELOW:8,LEFT:16};function jr(s){const t=Ut();for(let e=0,i=s.length;en&&(l=l|ct.RIGHT),ar&&(l=l|ct.ABOVE),l===ct.UNKNOWN&&(l=ct.INTERSECTING),l}function Ut(){return[1/0,1/0,-1/0,-1/0]}function Ne(s,t,e,i,n){return n?(n[0]=s,n[1]=t,n[2]=e,n[3]=i,n):[s,t,e,i]}function os(s){return Ne(1/0,1/0,-1/0,-1/0,s)}function Ho(s,t){const e=s[0],i=s[1];return Ne(e,i,e,i,t)}function ur(s,t,e,i,n){const r=os(n);return qo(r,s,t,e,i)}function bi(s,t){return s[0]==t[0]&&s[2]==t[2]&&s[1]==t[1]&&s[3]==t[3]}function Dl(s,t){return t[0]s[2]&&(s[2]=t[2]),t[1]s[3]&&(s[3]=t[3]),s}function tn(s,t){t[0]s[2]&&(s[2]=t[0]),t[1]s[3]&&(s[3]=t[1])}function qo(s,t,e,i,n){for(;et[0]?i[0]=s[0]:i[0]=t[0],s[1]>t[1]?i[1]=s[1]:i[1]=t[1],s[2]=t[0]&&s[1]<=t[3]&&s[3]>=t[1]}function hs(s){return s[2]=o&&_<=l),!i&&r&ct.RIGHT&&!(n&ct.RIGHT)&&(m=f-(d-l)*g,i=m>=a&&m<=c),!i&&r&ct.BELOW&&!(n&ct.BELOW)&&(_=d-(f-a)/g,i=_>=o&&_<=l),!i&&r&ct.LEFT&&!(n&ct.LEFT)&&(m=f-(d-o)*g,i=m>=a&&m<=c)}return i}function Jo(s,t){const e=t.getExtent(),i=ti(s);if(t.canWrapX()&&(i[0]=e[2])){const n=tt(e),o=Math.floor((i[0]-e[0])/n)*n;s[0]-=o,s[2]-=o}return s}function Qo(s,t,e){if(t.canWrapX()){const i=t.getExtent();if(!isFinite(s[0])||!isFinite(s[2]))return[[i[0],s[1],i[2],s[3]]];Jo(s,t);const n=tt(i);if(tt(s)>n&&!e)return[[i[0],s[1],i[2],s[3]]];if(s[0]i[2])return[[s[0],s[1],i[2],s[3]],[i[0],s[1],s[2]-n,s[3]]]}return[s]}const Mi={radians:6370997/(2*Math.PI),degrees:2*Math.PI*6370997/360,ft:.3048,m:1,"us-ft":1200/3937};class ta{constructor(t){this.code_=t.code,this.units_=t.units,this.extent_=t.extent!==void 0?t.extent:null,this.worldExtent_=t.worldExtent!==void 0?t.worldExtent:null,this.axisOrientation_=t.axisOrientation!==void 0?t.axisOrientation:"enu",this.global_=t.global!==void 0?t.global:!1,this.canWrapX_=!!(this.global_&&this.extent_),this.getPointResolutionFunc_=t.getPointResolution,this.defaultTileGrid_=null,this.metersPerUnit_=t.metersPerUnit}canWrapX(){return this.canWrapX_}getCode(){return this.code_}getExtent(){return this.extent_}getUnits(){return this.units_}getMetersPerUnit(){return this.metersPerUnit_||Mi[this.units_]}getWorldExtent(){return this.worldExtent_}getAxisOrientation(){return this.axisOrientation_}isGlobal(){return this.global_}setGlobal(t){this.global_=t,this.canWrapX_=!!(t&&this.extent_)}getDefaultTileGrid(){return this.defaultTileGrid_}setDefaultTileGrid(t){this.defaultTileGrid_=t}setExtent(t){this.extent_=t,this.canWrapX_=!!(this.global_&&t)}setWorldExtent(t){this.worldExtent_=t}setGetPointResolution(t){this.getPointResolutionFunc_=t}getPointResolutionFunc(){return this.getPointResolutionFunc_}}const Cn=6378137,Ei=Math.PI*Cn,Wl=[-Ei,-Ei,Ei,Ei],Xl=[-180,-85,180,85],Mn=Cn*Math.log(Math.tan(Math.PI/2));class li extends ta{constructor(t){super({code:t,units:"m",extent:Wl,global:!0,worldExtent:Xl,getPointResolution:function(e,i){return e/Math.cosh(i[1]/Cn)}})}}const Hr=[new li("EPSG:3857"),new li("EPSG:102100"),new li("EPSG:102113"),new li("EPSG:900913"),new li("http://www.opengis.net/def/crs/EPSG/0/3857"),new li("http://www.opengis.net/gml/srs/epsg.xml#3857")];function Yl(s,t,e){const i=s.length;e=e>1?e:2,t===void 0&&(e>2?t=s.slice():t=new Array(i));for(let n=0;nMn?r=Mn:r<-Mn&&(r=-Mn),t[n+1]=r}return t}function Vl(s,t,e){const i=s.length;e=e>1?e:2,t===void 0&&(e>2?t=s.slice():t=new Array(i));for(let n=0;n1?(e=n,i=r):l>0&&(e+=o*l,i+=a*l)}return vi(s,t,e,i)}function vi(s,t,e,i){const n=e-s,r=i-t;return n*n+r*r}function ql(s){const t=s.length;for(let i=0;ir&&(r=l,n=a)}if(r===0)return null;const o=s[n];s[n]=s[i],s[i]=o;for(let a=i+1;a=0;i--){e[i]=s[i][t]/s[i][i];for(let n=i-1;n>=0;n--)s[n][t]-=s[n][i]*e[i]}return e}function Yn(s){return s*Math.PI/180}function Ti(s,t){const e=s%t;return e*t<0?e+t:e}function Vt(s,t,e){return s+e*(t-s)}function dr(s,t){const e=Math.pow(10,t);return Math.round(s*e)/e}function An(s,t){return Math.floor(dr(s,t))}function Pn(s,t){return Math.ceil(dr(s,t))}function $l(s,t){return s[0]+=+t[0],s[1]+=+t[1],s}function Bn(s,t){let e=!0;for(let i=s.length-1;i>=0;--i)if(s[i]!=t[i]){e=!1;break}return e}function fr(s,t){const e=Math.cos(t),i=Math.sin(t),n=s[0]*e-s[1]*i,r=s[1]*e+s[0]*i;return s[0]=n,s[1]=r,s}function Jl(s,t){return s[0]*=t,s[1]*=t,s}function ea(s,t){if(t.canWrapX()){const e=tt(t.getExtent()),i=Ql(s,t,e);i&&(s[0]-=i*e)}return s}function Ql(s,t,e){const i=t.getExtent();let n=0;return t.canWrapX()&&(s[0]i[2])&&(e=e||tt(i),n=Math.floor((s[0]-i[0])/e)),n}const th=63710088e-1;function Jr(s,t,e){e=e||th;const i=Yn(s[1]),n=Yn(t[1]),r=(n-i)/2,o=Yn(t[0]-s[0])/2,a=Math.sin(r)*Math.sin(r)+Math.sin(o)*Math.sin(o)*Math.cos(i)*Math.cos(n);return 2*e*Math.atan2(Math.sqrt(a),Math.sqrt(1-a))}function ia(...s){console.warn(...s)}let $s=!0;function na(s){$s=!1}function gr(s,t){if(t!==void 0){for(let e=0,i=s.length;e=-180&&s[0]<=180&&s[1]>=-90&&s[1]<=90&&($s=!1,ia("Call useGeographic() from ol/proj once to work with [longitude, latitude] coordinates.")),s}function oa(s,t){return s}function De(s,t){return s}function rh(){Qr(Hr),Qr($r),nh($r,Hr,Yl,Vl)}rh();function ke(s,t,e,i,n,r){r=r||[];let o=0;for(let a=t;a{if(!i)return this.getSimplifiedGeometry(e);const n=this.clone();return n.applyTransform(i),n.getSimplifiedGeometry(e)})}simplifyTransformed(t,e){return this.simplifyTransformedInternal(this.getRevision(),t,e)}clone(){return $()}closestPointXY(t,e,i,n){return $()}containsXY(t,e){const i=this.getClosestPoint([t,e]);return i[0]===t&&i[1]===e}getClosestPoint(t,e){return e=e||[NaN,NaN],this.closestPointXY(t[0],t[1],e,1/0),e}intersectsCoordinate(t){return this.containsXY(t[0],t[1])}computeExtent(t){return $()}getExtent(t){if(this.extentRevision_!=this.getRevision()){const e=this.computeExtent(this.extent_);(isNaN(e[0])||isNaN(e[1]))&&os(e),this.extentRevision_=this.getRevision()}return Nl(this.extent_,t)}rotate(t,e){$()}scale(t,e,i){$()}simplify(t){return this.getSimplifiedGeometry(t*t)}getSimplifiedGeometry(t){return $()}getType(){return $()}applyTransform(t){$()}intersectsExtent(t){return $()}translate(t,e){$()}transform(t,e){const i=jt(t),n=i.getUnits()=="tile-pixels"?function(r,o,a){const l=i.getExtent(),c=i.getWorldExtent(),h=bt(c)/bt(l);return we(to,c[0],c[3],h,-h,0,0,0),ke(r,0,r.length,a,to,o),Kn(i,e)(r,o,a)}:Kn(i,e);return this.applyTransform(n),this}}class pr extends lh{constructor(){super(),this.layout="XY",this.stride=2,this.flatCoordinates}computeExtent(t){return ur(this.flatCoordinates,0,this.flatCoordinates.length,this.stride,t)}getCoordinates(){return $()}getFirstCoordinate(){return this.flatCoordinates.slice(0,this.stride)}getFlatCoordinates(){return this.flatCoordinates}getLastCoordinate(){return this.flatCoordinates.slice(this.flatCoordinates.length-this.stride)}getLayout(){return this.layout}getSimplifiedGeometry(t){if(this.simplifiedGeometryRevision!==this.getRevision()&&(this.simplifiedGeometryMaxMinSquaredTolerance=0,this.simplifiedGeometryRevision=this.getRevision()),t<0||this.simplifiedGeometryMaxMinSquaredTolerance!==0&&t<=this.simplifiedGeometryMaxMinSquaredTolerance)return this;const e=this.getSimplifiedGeometryInternal(t);return e.getFlatCoordinates().length1)u=e;else if(d>0){for(let f=0;fn&&(n=c),r=a,o=l}return n}function uh(s,t,e,i,n){for(let r=0,o=e.length;r0;){const u=c.pop(),d=c.pop();let f=0;const g=s[d],_=s[d+1],m=s[u],y=s[u+1];for(let p=d+i;pf&&(h=p,f=x)}f>n&&(l[(h-t)/i]=1,d+i0&&_>f)&&(g<0&&m0&&m>g)){c=u,h=d;continue}r[o++]=c,r[o++]=h,a=c,l=h,c=u,h=d}return r[o++]=c,r[o++]=h,o}function ua(s,t,e,i,n,r,o,a){for(let l=0,c=e.length;lr&&(c-a)*(r-l)-(n-a)*(h-l)>0&&o++:h<=r&&(c-a)*(r-l)-(n-a)*(h-l)<0&&o--,a=c,l=h}return o!==0}function fa(s,t,e,i,n,r){if(e.length===0||!qe(s,t,e[0],i,n,r))return!1;for(let o=1,a=e.length;oy&&(c=(h+u)/2,fa(s,t,e,i,c,g)&&(m=c,y=p)),h=u}return isNaN(m)&&(m=n[r]),o?(o.push(m,g,y),o):[m,g,y]}function Eh(s,t,e,i,n){let r=[];for(let o=0,a=e.length;o=n[0]&&r[2]<=n[2]||r[1]>=n[1]&&r[3]<=n[3]?!0:xh(s,t,e,i,function(o,a){return zl(n,o,a)}):!1}function _a(s,t,e,i,n){return!!(ga(s,t,e,i,n)||qe(s,t,e,i,n[0],n[1])||qe(s,t,e,i,n[0],n[3])||qe(s,t,e,i,n[2],n[1])||qe(s,t,e,i,n[2],n[3]))}function wh(s,t,e,i,n){if(!_a(s,t,e[0],i,n))return!1;if(e.length===1)return!0;for(let r=1,o=e.length;r0}function vh(s,t,e,i,n){n=n!==void 0?n:!1;for(let r=0,o=e.length;r=this.minArea_}getGeometry(){return this.box_.getGeometry()}handleDragEvent(t){this.startPixel_&&(this.box_.setPixels(this.startPixel_,t.pixel),this.dispatchEvent(new On(Zi.BOXDRAG,t.coordinate,t)))}handleUpEvent(t){if(!this.startPixel_)return!1;this.box_.setMap(null);const e=this.boxEndCondition_(t,this.startPixel_,t.pixel);return e&&this.onBoxEnd(t),this.dispatchEvent(new On(e?Zi.BOXEND:Zi.BOXCANCEL,t.coordinate,t)),!1}handleDownEvent(t){return this.condition_(t)?(this.startPixel_=t.pixel,this.box_.setMap(t.map),this.box_.setPixels(this.startPixel_,this.startPixel_),this.dispatchEvent(new On(Zi.BOXSTART,t.coordinate,t)),!0):!1}onBoxEnd(t){}setActive(t){t||(this.box_.setMap(null),this.startPixel_&&(this.dispatchEvent(new On(Zi.BOXCANCEL,this.startPixel_,null)),this.startPixel_=null)),super.setActive(t)}}class ln extends Qt{constructor(t){if(super(),this.on,this.once,this.un,this.id_=void 0,this.geometryName_="geometry",this.style_=null,this.styleFunction_=void 0,this.geometryChangeKey_=null,this.addChangeListener(this.geometryName_,this.handleGeometryChanged_),t)if(typeof t.getSimplifiedGeometry=="function"){const e=t;this.setGeometry(e)}else{const e=t;this.setProperties(e)}}clone(){const t=new ln(this.hasProperties()?this.getProperties():null);t.setGeometryName(this.getGeometryName());const e=this.getGeometry();e&&t.setGeometry(e.clone());const i=this.getStyle();return i&&t.setStyle(i),t}getGeometry(){return this.get(this.geometryName_)}getId(){return this.id_}getGeometryName(){return this.geometryName_}getStyle(){return this.style_}getStyleFunction(){return this.styleFunction_}handleGeometryChange_(){this.changed()}handleGeometryChanged_(){this.geometryChangeKey_&&(it(this.geometryChangeKey_),this.geometryChangeKey_=null);const t=this.getGeometry();t&&(this.geometryChangeKey_=U(t,N.CHANGE,this.handleGeometryChange_,this)),this.changed()}setGeometry(t){this.set(this.geometryName_,t)}setStyle(t){this.style_=t,this.styleFunction_=t?kh(t):void 0,this.changed()}setId(t){this.id_=t,this.changed()}setGeometryName(t){this.removeChangeListener(this.geometryName_,this.handleGeometryChanged_),this.geometryName_=t,this.addChangeListener(this.geometryName_,this.handleGeometryChanged_),this.handleGeometryChanged_()}}function kh(s){if(typeof s=="function")return s;let t;return Array.isArray(s)?t=s:(H(typeof s.getZIndex=="function","Expected an `ol/style/Style` or an array of `ol/style/Style.js`"),t=[s]),function(){return t}}const dt={ADD:"add",REMOVE:"remove"},oo={LENGTH:"length"};class Dn extends ae{constructor(t,e,i){super(t),this.element=e,this.index=i}}class Ft extends Qt{constructor(t,e){if(super(),this.on,this.once,this.un,e=e||{},this.unique_=!!e.unique,this.array_=t||[],this.unique_)for(let i=0,n=this.array_.length;i0;)this.pop()}extend(t){for(let e=0,i=t.length;ethis.getLength())throw new Error("Index out of bounds: "+t);this.unique_&&this.assertUnique_(e),this.array_.splice(t,0,e),this.updateLength_(),this.dispatchEvent(new Dn(dt.ADD,e,t))}pop(){return this.removeAt(this.getLength()-1)}push(t){this.unique_&&this.assertUnique_(t);const e=this.getLength();return this.insertAt(e,t),this.getLength()}remove(t){const e=this.array_;for(let i=0,n=e.length;i=this.getLength())return;const e=this.array_[t];return this.array_.splice(t,1),this.updateLength_(),this.dispatchEvent(new Dn(dt.REMOVE,e,t)),e}setAt(t,e){const i=this.getLength();if(t>=i){this.insertAt(t,e);return}if(t<0)throw new Error("Index out of bounds: "+t);this.unique_&&this.assertUnique_(e,t);const n=this.array_[t];this.array_[t]=e,this.dispatchEvent(new Dn(dt.REMOVE,n,t)),this.dispatchEvent(new Dn(dt.ADD,e,t))}updateLength_(){this.set(oo.LENGTH,this.array_.length)}assertUnique_(t,e){for(let i=0,n=this.array_.length;if&&(d=(f+d)/2,f=d),g>_&&(g=(_+g)/2,_=g);let m=lt(i[0],d,f),y=lt(i[1],g,_);if(o&&e&&n){const p=30*n;m+=-p*Math.log(1+Math.max(0,d-i[0])/p)+p*Math.log(1+Math.max(0,i[0]-f)/p),y+=-p*Math.log(1+Math.max(0,g-i[1])/p)+p*Math.log(1+Math.max(0,i[1]-_)/p)}return[m,y]}}function Gh(s){return s}function vr(s,t,e,i){const n=tt(t)/e[0],r=bt(t)/e[1];return i?Math.min(s,Math.max(n,r)):Math.min(s,Math.min(n,r))}function Tr(s,t,e){let i=Math.min(s,t);const n=50;return i*=Math.log(1+n*Math.max(0,s/t-1))/n+1,e&&(i=Math.max(i,e),i/=Math.log(1+n*Math.max(0,e/s-1))/n+1),lt(i,e/2,t*2)}function zh(s,t,e,i){return t=t!==void 0?t:!0,function(n,r,o,a){if(n!==void 0){const l=s[0],c=s[s.length-1],h=e?vr(l,e,o,i):l;if(a)return t?Tr(n,h,c):lt(n,c,h);const u=Math.min(h,n),d=Math.floor(ar(s,u,r));return s[d]>h&&d1&&typeof arguments[e-1]=="function"&&(i=arguments[e-1],--e);let n=0;for(;n0}getInteracting(){return this.hints_[xt.INTERACTING]>0}cancelAnimations(){this.setHint(xt.ANIMATING,-this.hints_[xt.ANIMATING]);let t;for(let e=0,i=this.animations_.length;e=0;--i){const n=this.animations_[i];let r=!0;for(let o=0,a=n.length;o0?c/l.duration:1;h>=1?(l.complete=!0,h=1):r=!1;const u=l.easing(h);if(l.sourceCenter){const d=l.sourceCenter[0],f=l.sourceCenter[1],g=l.targetCenter[0],_=l.targetCenter[1];this.nextCenter_=l.targetCenter;const m=d+u*(g-d),y=f+u*(_-f);this.targetCenter_=[m,y]}if(l.sourceResolution&&l.targetResolution){const d=u===1?l.targetResolution:l.sourceResolution+u*(l.targetResolution-l.sourceResolution);if(l.anchor){const f=this.getViewportSize_(this.getRotation()),g=this.constraints_.resolution(d,0,f,!0);this.targetCenter_=this.calculateCenterZoom(g,l.anchor)}this.nextResolution_=l.targetResolution,this.targetResolution_=d,this.applyTargetState_(!0)}if(l.sourceRotation!==void 0&&l.targetRotation!==void 0){const d=u===1?Ti(l.targetRotation+Math.PI,2*Math.PI)-Math.PI:l.sourceRotation+u*(l.targetRotation-l.sourceRotation);if(l.anchor){const f=this.constraints_.rotation(d,!0);this.targetCenter_=this.calculateCenterRotate(f,l.anchor)}this.nextRotation_=l.targetRotation,this.targetRotation_=d}if(this.applyTargetState_(!0),e=!0,!l.complete)break}if(r){this.animations_[i]=null,this.setHint(xt.ANIMATING,-1),this.nextCenter_=null,this.nextResolution_=NaN,this.nextRotation_=NaN;const o=n[0].callback;o&&Fn(o,!0)}}this.animations_=this.animations_.filter(Boolean),e&&this.updateAnimationKey_===void 0&&(this.updateAnimationKey_=requestAnimationFrame(this.updateAnimations_.bind(this)))}calculateCenterRotate(t,e){let i;const n=this.getCenterInternal();return n!==void 0&&(i=[n[0]-e[0],n[1]-e[1]],fr(i,t-this.getRotation()),$l(i,e)),i}calculateCenterZoom(t,e){let i;const n=this.getCenterInternal(),r=this.getResolution();if(n!==void 0&&r!==void 0){const o=e[0]-t*(e[0]-n[0])/r,a=e[1]-t*(e[1]-n[1])/r;i=[o,a]}return i}getViewportSize_(t){const e=this.viewportSize_;if(t){const i=e[0],n=e[1];return[Math.abs(i*Math.cos(t))+Math.abs(n*Math.sin(t)),Math.abs(i*Math.sin(t))+Math.abs(n*Math.cos(t))]}return e}setViewportSize(t){this.viewportSize_=Array.isArray(t)?t.slice():[100,100],this.getAnimating()||this.resolveConstraints(0)}getCenter(){const t=this.getCenterInternal();return t&&Js(t,this.getProjection())}getCenterInternal(){return this.get(Ot.CENTER)}getConstraints(){return this.constraints_}getConstrainResolution(){return this.get("constrainResolution")}getHints(t){return t!==void 0?(t[0]=this.hints_[0],t[1]=this.hints_[1],t):this.hints_.slice()}calculateExtent(t){const e=this.calculateExtentInternal(t);return oa(e,this.getProjection())}calculateExtentInternal(t){t=t||this.getViewportSizeMinusPadding_();const e=this.getCenterInternal();H(e,"The view center is not defined");const i=this.getResolution();H(i!==void 0,"The view resolution is not defined");const n=this.getRotation();return H(n!==void 0,"The view rotation is not defined"),js(e,i,n,t)}getMaxResolution(){return this.maxResolution_}getMinResolution(){return this.minResolution_}getMaxZoom(){return this.getZoomForResolution(this.minResolution_)}setMaxZoom(t){this.applyOptions_(this.getUpdatedOptions_({maxZoom:t}))}getMinZoom(){return this.getZoomForResolution(this.maxResolution_)}setMinZoom(t){this.applyOptions_(this.getUpdatedOptions_({minZoom:t}))}setConstrainResolution(t){this.applyOptions_(this.getUpdatedOptions_({constrainResolution:t}))}getProjection(){return this.projection_}getResolution(){return this.get(Ot.RESOLUTION)}getResolutions(){return this.resolutions_}getResolutionForExtent(t,e){return this.getResolutionForExtentInternal(De(t,this.getProjection()),e)}getResolutionForExtentInternal(t,e){e=e||this.getViewportSizeMinusPadding_();const i=tt(t)/e[0],n=bt(t)/e[1];return Math.max(i,n)}getResolutionForValueFunction(t){t=t||2;const e=this.getConstrainedResolution(this.maxResolution_),i=this.minResolution_,n=Math.log(e/i)/Math.log(t);return function(r){return e/Math.pow(t,r*n)}}getRotation(){return this.get(Ot.ROTATION)}getValueForResolutionFunction(t){const e=Math.log(t||2),i=this.getConstrainedResolution(this.maxResolution_),n=this.minResolution_,r=Math.log(i/n)/e;return function(o){return Math.log(i/o)/e/r}}getViewportSizeMinusPadding_(t){let e=this.getViewportSize_(t);const i=this.padding_;return i&&(e=[e[0]-i[1]-i[3],e[1]-i[0]-i[2]]),e}getState(){const t=this.getProjection(),e=this.getResolution(),i=this.getRotation();let n=this.getCenterInternal();const r=this.padding_;if(r){const o=this.getViewportSizeMinusPadding_();n=bs(n,this.getViewportSize_(),[o[0]/2+r[3],o[1]/2+r[0]],e,i)}return{center:n.slice(0),projection:t!==void 0?t:null,resolution:e,nextCenter:this.nextCenter_,nextResolution:this.nextResolution_,nextRotation:this.nextRotation_,rotation:i,zoom:this.getZoom()}}getViewStateAndExtent(){return{viewState:this.getState(),extent:this.calculateExtent()}}getZoom(){let t;const e=this.getResolution();return e!==void 0&&(t=this.getZoomForResolution(e)),t}getZoomForResolution(t){let e=this.minZoom_||0,i,n;if(this.resolutions_){const r=ar(this.resolutions_,t,1);e=r,i=this.resolutions_[r],r==this.resolutions_.length-1?n=2:n=i/this.resolutions_[r+1]}else i=this.maxResolution_,n=this.zoomFactor_;return e+Math.log(i/t)/Math.log(n)}getResolutionForZoom(t){if(this.resolutions_){if(this.resolutions_.length<=1)return 0;const e=lt(Math.floor(t),0,this.resolutions_.length-2),i=this.resolutions_[e]/this.resolutions_[e+1];return this.resolutions_[e]/Math.pow(i,lt(t-e,0,1))}return this.maxResolution_/Math.pow(this.zoomFactor_,t-this.minZoom_)}fit(t,e){let i;if(H(Array.isArray(t)||typeof t.getSimplifiedGeometry=="function","Invalid extent or geometry provided as `geometry`"),Array.isArray(t)){H(!hs(t),"Cannot fit empty extent provided as `geometry`");const n=De(t,this.getProjection());i=jn(n)}else if(t.getType()==="Circle"){const n=De(t.getExtent(),this.getProjection());i=jn(n),i.rotate(this.getRotation(),ti(n))}else i=t;this.fitInternal(i,e)}rotatedExtentForGeometry(t){const e=this.getRotation(),i=Math.cos(e),n=Math.sin(-e),r=t.getFlatCoordinates(),o=t.getStride();let a=1/0,l=1/0,c=-1/0,h=-1/0;for(let u=0,d=r.length;u{this.dispatchEvent("sourceready")},0))),this.changed()}getFeatures(t){return this.renderer_?this.renderer_.getFeatures(t):Promise.resolve([])}getData(t){return!this.renderer_||!this.rendered?null:this.renderer_.getData(t)}isVisible(t){let e;const i=this.getMapInternal();!t&&i&&(t=i.getView()),t instanceof Bt?e={viewState:t.getState(),extent:t.calculateExtent()}:e=t,!e.layerStatesArray&&i&&(e.layerStatesArray=i.getLayerGroup().getLayerStatesArray());let n;e.layerStatesArray?n=e.layerStatesArray.find(o=>o.layer===this):n=this.getLayerState();const r=this.getExtent();return Ir(n,e.viewState)&&(!r||At(r,e.extent))}getAttributions(t){if(!this.isVisible(t))return[];let e;const i=this.getSource();if(i&&(e=i.getAttributions()),!e)return[];const n=t instanceof Bt?t.getViewStateAndExtent():t;let r=e(n);return Array.isArray(r)||(r=[r]),r}render(t,e){const i=this.getRenderer();return i.prepareFrame(t)?(this.rendered=!0,i.renderFrame(t,e)):null}unrender(){this.rendered=!1}getDeclutter(){}renderDeclutter(t,e){}renderDeferred(t){const e=this.getRenderer();e&&e.renderDeferred(t)}setMapInternal(t){t||this.unrender(),this.set(Q.MAP,t)}getMapInternal(){return this.get(Q.MAP)}setMap(t){this.mapPrecomposeKey_&&(it(this.mapPrecomposeKey_),this.mapPrecomposeKey_=null),t||this.changed(),this.mapRenderKey_&&(it(this.mapRenderKey_),this.mapRenderKey_=null),t&&(this.mapPrecomposeKey_=U(t,Kt.PRECOMPOSE,function(e){const n=e.frameState.layerStatesArray,r=this.getLayerState(!1);H(!n.some(function(o){return o.layer===r.layer}),"A layer can only be added to the map once. Use either `layer.setMap()` or `map.addLayer()`, not both."),n.push(r)},this),this.mapRenderKey_=U(this,N.CHANGE,t.render,t),this.changed())}setSource(t){this.set(Q.SOURCE,t)}getRenderer(){return this.renderer_||(this.renderer_=this.createRenderer()),this.renderer_}hasRenderer(){return!!this.renderer_}createRenderer(){return null}disposeInternal(){this.renderer_&&(this.renderer_.dispose(),delete this.renderer_),this.setSource(null),super.disposeInternal()}}function Ir(s,t){if(!s.visible)return!1;const e=t.resolution;if(e=s.maxResolution)return!1;const i=t.zoom;return i>s.minZoom&&i<=s.maxZoom}function Uh(s,t,e,i,n){Sa(s,t,e||0,i||s.length-1,n||jh)}function Sa(s,t,e,i,n){for(;i>e;){if(i-e>600){var r=i-e+1,o=t-e+1,a=Math.log(r),l=.5*Math.exp(2*a/3),c=.5*Math.sqrt(a*l*(r-l)/r)*(o-r/2<0?-1:1),h=Math.max(e,Math.floor(t-o*l/r+c)),u=Math.min(i,Math.floor(t+(r-o)*l/r+c));Sa(s,t,h,u,n)}var d=s[t],f=e,g=i;for(Ki(s,e,t),n(s[i],d)>0&&Ki(s,e,i);f0;)g--}n(s[e],d)===0?Ki(s,e,g):(g++,Ki(s,g,i)),g<=t&&(e=g+1),t<=g&&(i=g-1)}}function Ki(s,t,e){var i=s[t];s[t]=s[e],s[e]=i}function jh(s,t){return st?1:0}let La=class{constructor(t=9){this._maxEntries=Math.max(4,t),this._minEntries=Math.max(2,Math.ceil(this._maxEntries*.4)),this.clear()}all(){return this._all(this.data,[])}search(t){let e=this.data;const i=[];if(!Nn(t,e))return i;const n=this.toBBox,r=[];for(;e;){for(let o=0;o=0&&r[e].children.length>this._maxEntries;)this._split(r,e),e--;this._adjustParentBBoxes(n,r,e)}_split(t,e){const i=t[e],n=i.children.length,r=this._minEntries;this._chooseSplitAxis(i,r,n);const o=this._chooseSplitIndex(i,r,n),a=_i(i.children.splice(o,i.children.length-o));a.height=i.height,a.leaf=i.leaf,hi(i,this.toBBox),hi(a,this.toBBox),e?t[e-1].children.push(a):this._splitRoot(i,a)}_splitRoot(t,e){this.data=_i([t,e]),this.data.height=t.height+1,this.data.leaf=!1,hi(this.data,this.toBBox)}_chooseSplitIndex(t,e,i){let n,r=1/0,o=1/0;for(let a=e;a<=i-e;a++){const l=$i(t,0,a,this.toBBox),c=$i(t,a,i,this.toBBox),h=Qh(l,c),u=Ms(l)+Ms(c);h=e;c--){const h=t.children[c];Ji(a,t.leaf?r(h):h),l+=kn(a)}return l}_adjustParentBBoxes(t,e,i){for(let n=i;n>=0;n--)Ji(e[n],t)}_condense(t){for(let e=t.length-1,i;e>=0;e--)t[e].children.length===0?e>0?(i=t[e-1].children,i.splice(i.indexOf(t[e]),1)):this.clear():hi(t[e],this.toBBox)}};function Hh(s,t,e){if(!e)return t.indexOf(s);for(let i=0;i=s.minX&&t.maxY>=s.minY}function _i(s){return{children:s,height:1,leaf:!0,minX:1/0,minY:1/0,maxX:-1/0,maxY:-1/0}}function co(s,t,e,i,n){const r=[t,e];for(;r.length;){if(e=r.pop(),t=r.pop(),e-t<=i)continue;const o=t+Math.ceil((e-t)/i/2)*i;Uh(s,o,t,e,n),r.push(t,o,o,e)}}const V={IDLE:0,LOADING:1,LOADED:2,ERROR:3};function uo(s){return s[0]>0&&s[1]>0}function tc(s,t,e){return e===void 0&&(e=[0,0]),e[0]=s[0]*t+.5|0,e[1]=s[1]*t+.5|0,e}function kt(s,t){return Array.isArray(s)?s:(t===void 0?t=[s,s]:(t[0]=s,t[1]=s),t)}class ds{constructor(t){this.opacity_=t.opacity,this.rotateWithView_=t.rotateWithView,this.rotation_=t.rotation,this.scale_=t.scale,this.scaleArray_=kt(t.scale),this.displacement_=t.displacement,this.declutterMode_=t.declutterMode}clone(){const t=this.getScale();return new ds({opacity:this.getOpacity(),scale:Array.isArray(t)?t.slice():t,rotation:this.getRotation(),rotateWithView:this.getRotateWithView(),displacement:this.getDisplacement().slice(),declutterMode:this.getDeclutterMode()})}getOpacity(){return this.opacity_}getRotateWithView(){return this.rotateWithView_}getRotation(){return this.rotation_}getScale(){return this.scale_}getScaleArray(){return this.scaleArray_}getDisplacement(){return this.displacement_}getDeclutterMode(){return this.declutterMode_}getAnchor(){return $()}getImage(t){return $()}getHitDetectionImage(){return $()}getPixelRatio(t){return 1}getImageState(){return $()}getImageSize(){return $()}getOrigin(){return $()}getSize(){return $()}setDisplacement(t){this.displacement_=t}setOpacity(t){this.opacity_=t}setRotateWithView(t){this.rotateWithView_=t}setRotation(t){this.rotation_=t}setScale(t){this.scale_=t,this.scaleArray_=kt(t)}listenImageChange(t){$()}load(){$()}unlistenImageChange(t){$()}ready(){return Promise.resolve()}}const hn={name:"rgb",min:[0,0,0],max:[255,255,255],channel:["red","green","blue"],alias:["RGB"]},wt={name:"xyz",min:[0,0,0],channel:["X","Y","Z"],alias:["XYZ","ciexyz","cie1931"],whitepoint:{2:{A:[109.85,100,35.585],C:[98.074,100,118.232],D50:[96.422,100,82.521],D55:[95.682,100,92.149],D65:[95.045592705167,100,108.9057750759878],D75:[94.972,100,122.638],F2:[99.187,100,67.395],F7:[95.044,100,108.755],F11:[100.966,100,64.37],E:[100,100,100]},10:{A:[111.144,100,35.2],C:[97.285,100,116.145],D50:[96.72,100,81.427],D55:[95.799,100,90.926],D65:[94.811,100,107.304],D75:[94.416,100,120.641],F2:[103.28,100,69.026],F7:[95.792,100,107.687],F11:[103.866,100,65.627],E:[100,100,100]}}};wt.max=wt.whitepoint[2].D65;wt.rgb=function(s,t){t=t||wt.whitepoint[2].E;var e=s[0]/t[0],i=s[1]/t[1],n=s[2]/t[2],r,o,a;return r=e*3.240969941904521+i*-1.537383177570093+n*-.498610760293,o=e*-.96924363628087+i*1.87596750150772+n*.041555057407175,a=e*.055630079696993+i*-.20397695888897+n*1.056971514242878,r=r>.0031308?1.055*Math.pow(r,1/2.4)-.055:r=r*12.92,o=o>.0031308?1.055*Math.pow(o,1/2.4)-.055:o=o*12.92,a=a>.0031308?1.055*Math.pow(a,1/2.4)-.055:a=a*12.92,r=Math.min(Math.max(0,r),1),o=Math.min(Math.max(0,o),1),a=Math.min(Math.max(0,a),1),[r*255,o*255,a*255]};hn.xyz=function(s,t){var e=s[0]/255,i=s[1]/255,n=s[2]/255;e=e>.04045?Math.pow((e+.055)/1.055,2.4):e/12.92,i=i>.04045?Math.pow((i+.055)/1.055,2.4):i/12.92,n=n>.04045?Math.pow((n+.055)/1.055,2.4):n/12.92;var r=e*.41239079926595+i*.35758433938387+n*.18048078840183,o=e*.21263900587151+i*.71516867876775+n*.072192315360733,a=e*.019330818715591+i*.11919477979462+n*.95053215224966;return t=t||wt.whitepoint[2].E,[r*t[0],o*t[1],a*t[2]]};var Sr={name:"luv",min:[0,-134,-140],max:[100,224,122],channel:["lightness","u","v"],alias:["LUV","cieluv","cie1976"],xyz:function(s,t,e){var i,n,r,o,a,l,c,h,u,d,f,g,_;if(r=s[0],o=s[1],a=s[2],r===0)return[0,0,0];var m=.0011070564598794539;return t=t||"D65",e=e||2,u=wt.whitepoint[e][t][0],d=wt.whitepoint[e][t][1],f=wt.whitepoint[e][t][2],g=4*u/(u+15*d+3*f),_=9*d/(u+15*d+3*f),i=o/(13*r)+g||0,n=a/(13*r)+_||0,c=r>8?d*Math.pow((r+16)/116,3):d*r*m,l=c*9*i/(4*n)||0,h=c*(12-3*i-20*n)/(4*n)||0,[l,c,h]}};wt.luv=function(s,t,e){var i,n,r,o,a,l,c,h,u,d,f,g,_,m=.008856451679035631,y=903.2962962962961;t=t||"D65",e=e||2,u=wt.whitepoint[e][t][0],d=wt.whitepoint[e][t][1],f=wt.whitepoint[e][t][2],g=4*u/(u+15*d+3*f),_=9*d/(u+15*d+3*f),l=s[0],c=s[1],h=s[2],i=4*l/(l+15*c+3*h)||0,n=9*c/(l+15*c+3*h)||0;var p=c/d;return r=p<=m?y*p:116*Math.pow(p,1/3)-16,o=13*r*(i-g),a=13*r*(n-_),[r,o,a]};var ba={name:"lchuv",channel:["lightness","chroma","hue"],alias:["LCHuv","cielchuv"],min:[0,0,0],max:[100,100,360],luv:function(s){var t=s[0],e=s[1],i=s[2],n,r,o;return o=i/360*2*Math.PI,n=e*Math.cos(o),r=e*Math.sin(o),[t,n,r]},xyz:function(s){return Sr.xyz(ba.luv(s))}};Sr.lchuv=function(s){var t=s[0],e=s[1],i=s[2],n=Math.sqrt(e*e+i*i),r=Math.atan2(i,e),o=r*360/2/Math.PI;return o<0&&(o+=360),[t,n,o]};wt.lchuv=function(s){return Sr.lchuv(wt.luv(s))};const fo={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]};var go={red:0,orange:60,yellow:120,green:180,blue:240,purple:300};function ec(s){var h,u;var t,e=[],i=1,n;if(typeof s=="number")return{space:"rgb",values:[s>>>16,(s&65280)>>>8,s&255],alpha:1};if(typeof s=="number")return{space:"rgb",values:[s>>>16,(s&65280)>>>8,s&255],alpha:1};if(s=String(s).toLowerCase(),fo[s])e=fo[s].slice(),n="rgb";else if(s==="transparent")i=0,n="rgb",e=[0,0,0];else if(s[0]==="#"){var r=s.slice(1),o=r.length,a=o<=4;i=1,a?(e=[parseInt(r[0]+r[0],16),parseInt(r[1]+r[1],16),parseInt(r[2]+r[2],16)],o===4&&(i=parseInt(r[3]+r[3],16)/255)):(e=[parseInt(r[0]+r[1],16),parseInt(r[2]+r[3],16),parseInt(r[4]+r[5],16)],o===8&&(i=parseInt(r[6]+r[7],16)/255)),e[0]||(e[0]=0),e[1]||(e[1]=0),e[2]||(e[2]=0),n="rgb"}else if(t=/^((?:rgba?|hs[lvb]a?|hwba?|cmyk?|xy[zy]|gray|lab|lchu?v?|[ly]uv|lms|oklch|oklab|color))\s*\(([^\)]*)\)/.exec(s)){var l=t[1];n=l.replace(/a$/,"");var c=n==="cmyk"?4:n==="gray"?1:3;e=t[2].trim().split(/\s*[,\/]\s*|\s+/),n==="color"&&(n=e.shift()),e=e.map(function(d,f){if(d[d.length-1]==="%")return d=parseFloat(d)/100,f===3?d:n==="rgb"?d*255:n[0]==="h"||n[0]==="l"&&!f?d*100:n==="lab"?d*125:n==="lch"?f<2?d*150:d*360:n[0]==="o"&&!f?d:n==="oklab"?d*.4:n==="oklch"?f<2?d*.4:d*360:d;if(n[f]==="h"||f===2&&n[n.length-1]==="h"){if(go[d]!==void 0)return go[d];if(d.endsWith("deg"))return parseFloat(d);if(d.endsWith("turn"))return parseFloat(d)*360;if(d.endsWith("grad"))return parseFloat(d)*360/400;if(d.endsWith("rad"))return parseFloat(d)*180/Math.PI}return d==="none"?0:parseFloat(d)}),i=e.length>c?e.pop():1}else/[0-9](?:\s|\/|,)/.test(s)&&(e=s.match(/([0-9]+)/g).map(function(d){return parseFloat(d)}),n=((u=(h=s.match(/([a-z])/ig))==null?void 0:h.join(""))==null?void 0:u.toLowerCase())||"rgb");return{space:n,values:e,alpha:i}}var Ps={name:"hsl",min:[0,0,0],max:[360,100,100],channel:["hue","saturation","lightness"],alias:["HSL"],rgb:function(s){var t=s[0]/360,e=s[1]/100,i=s[2]/100,n,r,o,a,l,c=0;if(e===0)return l=i*255,[l,l,l];for(r=i<.5?i*(1+e):i+e-i*e,n=2*i-r,a=[0,0,0];c<3;)o=t+1/3*-(c-1),o<0?o++:o>1&&o--,l=6*o<1?n+(r-n)*6*o:2*o<1?r:3*o<2?n+(r-n)*(2/3-o)*6:n,a[c++]=l*255;return a}};hn.hsl=function(s){var t=s[0]/255,e=s[1]/255,i=s[2]/255,n=Math.min(t,e,i),r=Math.max(t,e,i),o=r-n,a,l,c;return r===n?a=0:t===r?a=(e-i)/o:e===r?a=2+(i-t)/o:i===r&&(a=4+(t-e)/o),a=Math.min(a*60,360),a<0&&(a+=360),c=(n+r)/2,r===n?l=0:c<=.5?l=o/(r+n):l=o/(2-r-n),[a,l*100,c*100]};function ic(s){Array.isArray(s)&&s.raw&&(s=String.raw(...arguments)),s instanceof Number&&(s=+s);var t,e=ec(s);if(!e.space)return[];const i=e.space[0]==="h"?Ps.min:hn.min,n=e.space[0]==="h"?Ps.max:hn.max;return t=Array(3),t[0]=Math.min(Math.max(e.values[0],i[0]),n[0]),t[1]=Math.min(Math.max(e.values[1],i[1]),n[1]),t[2]=Math.min(Math.max(e.values[2],i[2]),n[2]),e.space[0]==="h"&&(t=Ps.rgb(t)),t.push(Math.min(Math.max(e.alpha,0),1)),t}function nc(s){return typeof s=="string"?s:br(s)}const sc=1024,Ui={};let Os=0;function rc(s){if(s.length===4)return s;const t=s.slice();return t[3]=1,t}function _o(s){const t=wt.lchuv(hn.xyz(s));return t[3]=s[3],t}function oc(s){const t=wt.rgb(ba.xyz(s));return t[3]=s[3],t}function Lr(s){if(Ui.hasOwnProperty(s))return Ui[s];if(Os>=sc){let e=0;for(const i in Ui)e++&3||(delete Ui[i],--Os)}const t=ic(s);if(t.length!==4)throw new Error('Failed to parse "'+s+'" as color');for(const e of t)if(isNaN(e))throw new Error('Failed to parse "'+s+'" as color');return Ma(t),Ui[s]=t,++Os,t}function cn(s){return Array.isArray(s)?s:Lr(s)}function Ma(s){return s[0]=lt(s[0]+.5|0,0,255),s[1]=lt(s[1]+.5|0,0,255),s[2]=lt(s[2]+.5|0,0,255),s[3]=lt(s[3],0,1),s}function br(s){let t=s[0];t!=(t|0)&&(t=t+.5|0);let e=s[1];e!=(e|0)&&(e=e+.5|0);let i=s[2];i!=(i|0)&&(i=i+.5|0);const n=s[3]===void 0?1:Math.round(s[3]*1e3)/1e3;return"rgba("+t+","+e+","+i+","+n+")"}function ac(s){try{return Lr(s),!0}catch{return!1}}function mt(s,t,e,i){let n;return e&&e.length?n=e.shift():pa?n=new OffscreenCanvas(s||300,t||300):n=document.createElement("canvas"),s&&(n.width=s),t&&(n.height=t),n.getContext("2d",i)}let Ds;function Hn(){return Ds||(Ds=mt(1,1)),Ds}function fs(s){const t=s.canvas;t.width=1,t.height=1,s.clearRect(0,0,1,1)}function lc(s){let t=s.offsetWidth;const e=getComputedStyle(s);return t+=parseInt(e.marginLeft,10)+parseInt(e.marginRight,10),t}function hc(s){let t=s.offsetHeight;const e=getComputedStyle(s);return t+=parseInt(e.marginTop,10)+parseInt(e.marginBottom,10),t}function qn(s,t){const e=t.parentNode;e&&e.replaceChild(s,t)}function $n(s){return s&&s.parentNode?s.parentNode.removeChild(s):null}function Aa(s){for(;s.lastChild;)s.removeChild(s.lastChild)}function cc(s,t){const e=s.childNodes;for(let i=0;;++i){const n=e[i],r=t[i];if(!n&&!r)break;if(n!==r){if(!n){s.appendChild(r);continue}if(!r){s.removeChild(n),--i;continue}s.insertBefore(r,n)}}}function uc(s,t,e){const i=s;let n=!0,r=!1,o=!1;const a=[rn(i,N.LOAD,function(){o=!0,r||t()})];return i.src&&ya?(r=!0,i.decode().then(function(){n&&t()}).catch(function(l){n&&(o?t():e())})):a.push(rn(i,N.ERROR,e)),function(){n=!1,a.forEach(it)}}function dc(s,t){return new Promise((e,i)=>{function n(){o(),e(s)}function r(){o(),i(new Error("Image load error"))}function o(){s.removeEventListener("load",n),s.removeEventListener("error",r)}s.addEventListener("load",n),s.addEventListener("error",r)})}function fc(s,t){return t&&(s.src=t),s.src&&ya?new Promise((e,i)=>s.decode().then(()=>e(s)).catch(n=>s.complete&&s.width?e(s):i(n))):dc(s)}class gc{constructor(){this.cache_={},this.patternCache_={},this.cacheSize_=0,this.maxCacheSize_=32}clear(){this.cache_={},this.patternCache_={},this.cacheSize_=0}canExpireCache(){return this.cacheSize_>this.maxCacheSize_}expire(){if(this.canExpireCache()){let t=0;for(const e in this.cache_){const i=this.cache_[e];!(t++&3)&&!i.hasListener()&&(delete this.cache_[e],delete this.patternCache_[e],--this.cacheSize_)}}}get(t,e,i){const n=Fs(t,e,i);return n in this.cache_?this.cache_[n]:null}getPattern(t,e,i){const n=Fs(t,e,i);return n in this.patternCache_?this.patternCache_[n]:null}set(t,e,i,n,r){const o=Fs(t,e,i),a=o in this.cache_;this.cache_[o]=n,r&&(n.getImageState()===V.IDLE&&n.load(),n.getImageState()===V.LOADING?n.ready().then(()=>{this.patternCache_[o]=Hn().createPattern(n.getImage(1),"repeat")}):this.patternCache_[o]=Hn().createPattern(n.getImage(1),"repeat")),a||++this.cacheSize_}setSize(t){this.maxCacheSize_=t,this.expire()}}function Fs(s,t,e){const i=e?cn(e):"null";return t+":"+s+":"+i}const ne=new gc;let ji=null;class _c extends rs{constructor(t,e,i,n,r){super(),this.hitDetectionImage_=null,this.image_=t,this.crossOrigin_=i,this.canvas_={},this.color_=r,this.imageState_=n===void 0?V.IDLE:n,this.size_=t&&t.width&&t.height?[t.width,t.height]:null,this.src_=e,this.tainted_,this.ready_=null}initializeImage_(){this.image_=new Image,this.crossOrigin_!==null&&(this.image_.crossOrigin=this.crossOrigin_)}isTainted_(){if(this.tainted_===void 0&&this.imageState_===V.LOADED){ji||(ji=mt(1,1,void 0,{willReadFrequently:!0})),ji.drawImage(this.image_,0,0);try{ji.getImageData(0,0,1,1),this.tainted_=!1}catch{ji=null,this.tainted_=!0}}return this.tainted_===!0}dispatchChangeEvent_(){this.dispatchEvent(N.CHANGE)}handleImageError_(){this.imageState_=V.ERROR,this.dispatchChangeEvent_()}handleImageLoad_(){this.imageState_=V.LOADED,this.size_=[this.image_.width,this.image_.height],this.dispatchChangeEvent_()}getImage(t){return this.image_||this.initializeImage_(),this.replaceColor_(t),this.canvas_[t]?this.canvas_[t]:this.image_}getPixelRatio(t){return this.replaceColor_(t),this.canvas_[t]?t:1}getImageState(){return this.imageState_}getHitDetectionImage(){if(this.image_||this.initializeImage_(),!this.hitDetectionImage_)if(this.isTainted_()){const t=this.size_[0],e=this.size_[1],i=mt(t,e);i.fillRect(0,0,t,e),this.hitDetectionImage_=i.canvas}else this.hitDetectionImage_=this.image_;return this.hitDetectionImage_}getSize(){return this.size_}getSrc(){return this.src_}load(){if(this.imageState_===V.IDLE){this.image_||this.initializeImage_(),this.imageState_=V.LOADING;try{this.src_!==void 0&&(this.image_.src=this.src_)}catch{this.handleImageError_()}this.image_ instanceof HTMLImageElement&&fc(this.image_,this.src_).then(t=>{this.image_=t,this.handleImageLoad_()}).catch(this.handleImageError_.bind(this))}}replaceColor_(t){if(!this.color_||this.canvas_[t]||this.imageState_!==V.LOADED)return;const e=this.image_,i=document.createElement("canvas");i.width=Math.ceil(e.width*t),i.height=Math.ceil(e.height*t);const n=i.getContext("2d");n.scale(t,t),n.drawImage(e,0,0),n.globalCompositeOperation="multiply",n.fillStyle=nc(this.color_),n.fillRect(0,0,i.width/t,i.height/t),n.globalCompositeOperation="destination-in",n.drawImage(e,0,0),this.canvas_[t]=i}ready(){return this.ready_||(this.ready_=new Promise(t=>{this.imageState_===V.LOADED||this.imageState_===V.ERROR?t():this.addEventListener(N.CHANGE,function e(){(this.imageState_===V.LOADED||this.imageState_===V.ERROR)&&(this.removeEventListener(N.CHANGE,e),t())})})),this.ready_}}function Mr(s,t,e,i,n,r){let o=t===void 0?void 0:ne.get(t,e,n);return o||(o=new _c(s,s&&"src"in s?s.src||void 0:t,e,i,n),ne.set(t,e,n,o,r)),r&&o&&!ne.getPattern(t,e,n)&&ne.set(t,e,n,o,r),o}function se(s){return s?Array.isArray(s)?br(s):typeof s=="object"&&"src"in s?mc(s):s:null}function mc(s){if(!s.offset||!s.size)return ne.getPattern(s.src,"anonymous",s.color);const t=s.src+":"+s.offset,e=ne.getPattern(t,void 0,s.color);if(e)return e;const i=ne.get(s.src,"anonymous",null);if(i.getImageState()!==V.LOADED)return null;const n=mt(s.size[0],s.size[1]);return n.drawImage(i.getImage(1),s.offset[0],s.offset[1],s.size[0],s.size[1],0,0,s.size[0],s.size[1]),Mr(n.canvas,t,void 0,V.LOADED,s.color,!0),ne.getPattern(t,void 0,s.color)}const Gn="ol-hidden",pc="ol-selectable",ei="ol-unselectable",vn="ol-control",Jn="ol-collapsed",yc=new RegExp(["^\\s*(?=(?:(?:[-a-z]+\\s*){0,2}(italic|oblique))?)","(?=(?:(?:[-a-z]+\\s*){0,2}(small-caps))?)","(?=(?:(?:[-a-z]+\\s*){0,2}(bold(?:er)?|lighter|[1-9]00 ))?)","(?:(?:normal|\\1|\\2|\\3)\\s*){0,3}((?:xx?-)?","(?:small|large)|medium|smaller|larger|[\\.\\d]+(?:\\%|in|[cem]m|ex|p[ctx]))","(?:\\s*\\/\\s*(normal|[\\.\\d]+(?:\\%|in|[cem]m|ex|p[ctx])?))",`?\\s*([-,\\"\\'\\sa-z]+?)\\s*$`].join(""),"i"),mo=["style","variant","weight","size","lineHeight","family"],Pa=function(s){const t=s.match(yc);if(!t)return null;const e={lineHeight:"normal",size:"1.2em",style:"normal",weight:"normal",variant:"normal"};for(let i=0,n=mo.length;iMath.max(n,ts(s,r)),0);return e[t]=i,i}function wc(s,t){const e=[],i=[],n=[];let r=0,o=0,a=0,l=0;for(let c=0,h=t.length;c<=h;c+=2){const u=t[c];if(u===` -`||c===h){r=Math.max(r,o),n.push(o),o=0,a+=l,l=0;continue}const d=t[c+1]||s.font,f=ts(d,u);e.push(f),o+=f;const g=xc(d);i.push(g),l=Math.max(l,g)}return{width:r,height:a,widths:e,heights:i,lineWidths:n}}function Cc(s,t,e,i,n,r,o,a,l,c,h){s.save(),e!==1&&(s.globalAlpha===void 0?s.globalAlpha=u=>u.globalAlpha*=e:s.globalAlpha*=e),t&&s.transform.apply(s,t),i.contextInstructions?(s.translate(l,c),s.scale(h[0],h[1]),vc(i,s)):h[0]<0||h[1]<0?(s.translate(l,c),s.scale(h[0],h[1]),s.drawImage(i,n,r,o,a,0,0,o,a)):s.drawImage(i,n,r,o,a,l,c,o*h[0],a*h[1]),s.restore()}function vc(s,t){const e=s.contextInstructions;for(let i=0,n=e.length;ithis.imageState_=V.LOADED),this.render()}clone(){const t=this.getScale(),e=new gs({fill:this.getFill()?this.getFill().clone():void 0,points:this.getPoints(),radius:this.getRadius(),radius2:this.getRadius2(),angle:this.getAngle(),stroke:this.getStroke()?this.getStroke().clone():void 0,rotation:this.getRotation(),rotateWithView:this.getRotateWithView(),scale:Array.isArray(t)?t.slice():t,displacement:this.getDisplacement().slice(),declutterMode:this.getDeclutterMode()});return e.setOpacity(this.getOpacity()),e}getAnchor(){const t=this.size_,e=this.getDisplacement(),i=this.getScaleArray();return[t[0]/2-e[0]/i[0],t[1]/2+e[1]/i[1]]}getAngle(){return this.angle_}getFill(){return this.fill_}setFill(t){this.fill_=t,this.render()}getHitDetectionImage(){return this.hitDetectionCanvas_||(this.hitDetectionCanvas_=this.createHitDetectionCanvas_(this.renderOptions_)),this.hitDetectionCanvas_}getImage(t){let e=this.canvases_[t];if(!e){const i=this.renderOptions_,n=mt(i.size*t,i.size*t);this.draw_(i,n,t),e=n.canvas,this.canvases_[t]=e}return e}getPixelRatio(t){return t}getImageSize(){return this.size_}getImageState(){return this.imageState_}getOrigin(){return this.origin_}getPoints(){return this.points_}getRadius(){return this.radius_}getRadius2(){return this.radius2_}getSize(){return this.size_}getStroke(){return this.stroke_}setStroke(t){this.stroke_=t,this.render()}listenImageChange(t){}load(){}unlistenImageChange(t){}calculateLineJoinSize_(t,e,i){if(e===0||this.points_===1/0||t!=="bevel"&&t!=="miter")return e;let n=this.radius_,r=this.radius2_===void 0?n:this.radius2_;if(n{this.patternImage_=null}),e.getImageState()===V.IDLE&&e.load(),e.getImageState()===V.LOADING&&(this.patternImage_=e)}this.color_=t}loading(){return!!this.patternImage_}ready(){return this.patternImage_?this.patternImage_.ready():Promise.resolve()}}class xe{constructor(t){t=t||{},this.color_=t.color!==void 0?t.color:null,this.lineCap_=t.lineCap,this.lineDash_=t.lineDash!==void 0?t.lineDash:null,this.lineDashOffset_=t.lineDashOffset,this.lineJoin_=t.lineJoin,this.miterLimit_=t.miterLimit,this.width_=t.width}clone(){const t=this.getColor();return new xe({color:Array.isArray(t)?t.slice():t||void 0,lineCap:this.getLineCap(),lineDash:this.getLineDash()?this.getLineDash().slice():void 0,lineDashOffset:this.getLineDashOffset(),lineJoin:this.getLineJoin(),miterLimit:this.getMiterLimit(),width:this.getWidth()})}getColor(){return this.color_}getLineCap(){return this.lineCap_}getLineDash(){return this.lineDash_}getLineDashOffset(){return this.lineDashOffset_}getLineJoin(){return this.lineJoin_}getMiterLimit(){return this.miterLimit_}getWidth(){return this.width_}setColor(t){this.color_=t}setLineCap(t){this.lineCap_=t}setLineDash(t){this.lineDash_=t}setLineDashOffset(t){this.lineDashOffset_=t}setLineJoin(t){this.lineJoin_=t}setMiterLimit(t){this.miterLimit_=t}setWidth(t){this.width_=t}}class Nt{constructor(t){t=t||{},this.geometry_=null,this.geometryFunction_=yo,t.geometry!==void 0&&this.setGeometry(t.geometry),this.fill_=t.fill!==void 0?t.fill:null,this.image_=t.image!==void 0?t.image:null,this.renderer_=t.renderer!==void 0?t.renderer:null,this.hitDetectionRenderer_=t.hitDetectionRenderer!==void 0?t.hitDetectionRenderer:null,this.stroke_=t.stroke!==void 0?t.stroke:null,this.text_=t.text!==void 0?t.text:null,this.zIndex_=t.zIndex}clone(){let t=this.getGeometry();return t&&typeof t=="object"&&(t=t.clone()),new Nt({geometry:t??void 0,fill:this.getFill()?this.getFill().clone():void 0,image:this.getImage()?this.getImage().clone():void 0,renderer:this.getRenderer()??void 0,stroke:this.getStroke()?this.getStroke().clone():void 0,text:this.getText()?this.getText().clone():void 0,zIndex:this.getZIndex()})}getRenderer(){return this.renderer_}setRenderer(t){this.renderer_=t}setHitDetectionRenderer(t){this.hitDetectionRenderer_=t}getHitDetectionRenderer(){return this.hitDetectionRenderer_}getGeometry(){return this.geometry_}getGeometryFunction(){return this.geometryFunction_}getFill(){return this.fill_}setFill(t){this.fill_=t}getImage(){return this.image_}setImage(t){this.image_=t}getStroke(){return this.stroke_}setStroke(t){this.stroke_=t}getText(){return this.text_}setText(t){this.text_=t}getZIndex(){return this.zIndex_}setGeometry(t){typeof t=="function"?this.geometryFunction_=t:typeof t=="string"?this.geometryFunction_=function(e){return e.get(t)}:t?t!==void 0&&(this.geometryFunction_=function(){return t}):this.geometryFunction_=yo,this.geometry_=t}setZIndex(t){this.zIndex_=t}}function Tc(s){let t;if(typeof s=="function")t=s;else{let e;Array.isArray(s)?e=s:(H(typeof s.getZIndex=="function","Expected an `Style` or an array of `Style`"),e=[s]),t=function(){return e}}return t}let ks=null;function Fa(s,t){if(!ks){const e=new Ce({color:"rgba(255,255,255,0.4)"}),i=new xe({color:"#3399CC",width:1.25});ks=[new Nt({image:new ii({fill:e,stroke:i,radius:5}),fill:e,stroke:i})]}return ks}function Rc(){const s={},t=[255,255,255,1],e=[0,153,255,1],i=3;return s.Polygon=[new Nt({fill:new Ce({color:[255,255,255,.5]})})],s.MultiPolygon=s.Polygon,s.LineString=[new Nt({stroke:new xe({color:t,width:i+2})}),new Nt({stroke:new xe({color:e,width:i})})],s.MultiLineString=s.LineString,s.Circle=s.Polygon.concat(s.LineString),s.Point=[new Nt({image:new ii({radius:i*2,fill:new Ce({color:e}),stroke:new xe({color:t,width:i/2})}),zIndex:1/0})],s.MultiPoint=s.Point,s.GeometryCollection=s.Polygon.concat(s.LineString,s.Point),s}function yo(s){return s.getGeometry()}function Eo(s,t,e,i){return e!==void 0&&i!==void 0?[e/s,i/t]:e!==void 0?e/s:i!==void 0?i/t:1}class _s extends ds{constructor(t){t=t||{};const e=t.opacity!==void 0?t.opacity:1,i=t.rotation!==void 0?t.rotation:0,n=t.scale!==void 0?t.scale:1,r=t.rotateWithView!==void 0?t.rotateWithView:!1;super({opacity:e,rotation:i,scale:n,displacement:t.displacement!==void 0?t.displacement:[0,0],rotateWithView:r,declutterMode:t.declutterMode}),this.anchor_=t.anchor!==void 0?t.anchor:[.5,.5],this.normalizedAnchor_=null,this.anchorOrigin_=t.anchorOrigin!==void 0?t.anchorOrigin:"top-left",this.anchorXUnits_=t.anchorXUnits!==void 0?t.anchorXUnits:"fraction",this.anchorYUnits_=t.anchorYUnits!==void 0?t.anchorYUnits:"fraction",this.crossOrigin_=t.crossOrigin!==void 0?t.crossOrigin:null;const o=t.img!==void 0?t.img:null;let a=t.src;H(!(a!==void 0&&o),"`image` and `src` cannot be provided at the same time"),(a===void 0||a.length===0)&&o&&(a=o.src||Z(o)),H(a!==void 0&&a.length>0,"A defined and non-empty `src` or `image` must be provided"),H(!((t.width!==void 0||t.height!==void 0)&&t.scale!==void 0),"`width` or `height` cannot be provided together with `scale`");let l;if(t.src!==void 0?l=V.IDLE:o!==void 0&&("complete"in o?o.complete?l=o.src?V.LOADED:V.IDLE:l=V.LOADING:l=V.LOADED),this.color_=t.color!==void 0?cn(t.color):null,this.iconImage_=Mr(o,a,this.crossOrigin_,l,this.color_),this.offset_=t.offset!==void 0?t.offset:[0,0],this.offsetOrigin_=t.offsetOrigin!==void 0?t.offsetOrigin:"top-left",this.origin_=null,this.size_=t.size!==void 0?t.size:null,t.width!==void 0||t.height!==void 0){let c,h;if(t.size)[c,h]=t.size;else{const u=this.getImage(1);if(u.width&&u.height)c=u.width,h=u.height;else if(u instanceof HTMLImageElement){this.initialOptions_=t;const d=()=>{if(this.unlistenImageChange(d),!this.initialOptions_)return;const f=this.iconImage_.getSize();this.setScale(Eo(f[0],f[1],t.width,t.height))};this.listenImageChange(d);return}}c!==void 0&&this.setScale(Eo(c,h,t.width,t.height))}}clone(){let t,e,i;return this.initialOptions_?(e=this.initialOptions_.width,i=this.initialOptions_.height):(t=this.getScale(),t=Array.isArray(t)?t.slice():t),new _s({anchor:this.anchor_.slice(),anchorOrigin:this.anchorOrigin_,anchorXUnits:this.anchorXUnits_,anchorYUnits:this.anchorYUnits_,color:this.color_&&this.color_.slice?this.color_.slice():this.color_||void 0,crossOrigin:this.crossOrigin_,offset:this.offset_.slice(),offsetOrigin:this.offsetOrigin_,opacity:this.getOpacity(),rotateWithView:this.getRotateWithView(),rotation:this.getRotation(),scale:t,width:e,height:i,size:this.size_!==null?this.size_.slice():void 0,src:this.getSrc(),displacement:this.getDisplacement().slice(),declutterMode:this.getDeclutterMode()})}getAnchor(){let t=this.normalizedAnchor_;if(!t){t=this.anchor_;const n=this.getSize();if(this.anchorXUnits_=="fraction"||this.anchorYUnits_=="fraction"){if(!n)return null;t=this.anchor_.slice(),this.anchorXUnits_=="fraction"&&(t[0]*=n[0]),this.anchorYUnits_=="fraction"&&(t[1]*=n[1])}if(this.anchorOrigin_!="top-left"){if(!n)return null;t===this.anchor_&&(t=this.anchor_.slice()),(this.anchorOrigin_=="top-right"||this.anchorOrigin_=="bottom-right")&&(t[0]=-t[0]+n[0]),(this.anchorOrigin_=="bottom-left"||this.anchorOrigin_=="bottom-right")&&(t[1]=-t[1]+n[1])}this.normalizedAnchor_=t}const e=this.getDisplacement(),i=this.getScaleArray();return[t[0]-e[0]/i[0],t[1]+e[1]/i[1]]}setAnchor(t){this.anchor_=t,this.normalizedAnchor_=null}getColor(){return this.color_}getImage(t){return this.iconImage_.getImage(t)}getPixelRatio(t){return this.iconImage_.getPixelRatio(t)}getImageSize(){return this.iconImage_.getSize()}getImageState(){return this.iconImage_.getImageState()}getHitDetectionImage(){return this.iconImage_.getHitDetectionImage()}getOrigin(){if(this.origin_)return this.origin_;let t=this.offset_;if(this.offsetOrigin_!="top-left"){const e=this.getSize(),i=this.iconImage_.getSize();if(!e||!i)return null;t=t.slice(),(this.offsetOrigin_=="top-right"||this.offsetOrigin_=="bottom-right")&&(t[0]=i[0]-e[0]-t[0]),(this.offsetOrigin_=="bottom-left"||this.offsetOrigin_=="bottom-right")&&(t[1]=i[1]-e[1]-t[1])}return this.origin_=t,this.origin_}getSrc(){return this.iconImage_.getSrc()}getSize(){return this.size_?this.size_:this.iconImage_.getSize()}getWidth(){const t=this.getScaleArray();if(this.size_)return this.size_[0]*t[0];if(this.iconImage_.getImageState()==V.LOADED)return this.iconImage_.getSize()[0]*t[0]}getHeight(){const t=this.getScaleArray();if(this.size_)return this.size_[1]*t[1];if(this.iconImage_.getImageState()==V.LOADED)return this.iconImage_.getSize()[1]*t[1]}setScale(t){delete this.initialOptions_,super.setScale(t)}listenImageChange(t){this.iconImage_.addEventListener(N.CHANGE,t)}load(){this.iconImage_.load()}unlistenImageChange(t){this.iconImage_.removeEventListener(N.CHANGE,t)}ready(){return this.iconImage_.ready()}}const Ic="#333";class Ar{constructor(t){t=t||{},this.font_=t.font,this.rotation_=t.rotation,this.rotateWithView_=t.rotateWithView,this.scale_=t.scale,this.scaleArray_=kt(t.scale!==void 0?t.scale:1),this.text_=t.text,this.textAlign_=t.textAlign,this.justify_=t.justify,this.repeat_=t.repeat,this.textBaseline_=t.textBaseline,this.fill_=t.fill!==void 0?t.fill:new Ce({color:Ic}),this.maxAngle_=t.maxAngle!==void 0?t.maxAngle:Math.PI/4,this.placement_=t.placement!==void 0?t.placement:"point",this.overflow_=!!t.overflow,this.stroke_=t.stroke!==void 0?t.stroke:null,this.offsetX_=t.offsetX!==void 0?t.offsetX:0,this.offsetY_=t.offsetY!==void 0?t.offsetY:0,this.backgroundFill_=t.backgroundFill?t.backgroundFill:null,this.backgroundStroke_=t.backgroundStroke?t.backgroundStroke:null,this.padding_=t.padding===void 0?null:t.padding,this.declutterMode_=t.declutterMode}clone(){const t=this.getScale();return new Ar({font:this.getFont(),placement:this.getPlacement(),repeat:this.getRepeat(),maxAngle:this.getMaxAngle(),overflow:this.getOverflow(),rotation:this.getRotation(),rotateWithView:this.getRotateWithView(),scale:Array.isArray(t)?t.slice():t,text:this.getText(),textAlign:this.getTextAlign(),justify:this.getJustify(),textBaseline:this.getTextBaseline(),fill:this.getFill()?this.getFill().clone():void 0,stroke:this.getStroke()?this.getStroke().clone():void 0,offsetX:this.getOffsetX(),offsetY:this.getOffsetY(),backgroundFill:this.getBackgroundFill()?this.getBackgroundFill().clone():void 0,backgroundStroke:this.getBackgroundStroke()?this.getBackgroundStroke().clone():void 0,padding:this.getPadding()||void 0,declutterMode:this.getDeclutterMode()})}getOverflow(){return this.overflow_}getFont(){return this.font_}getMaxAngle(){return this.maxAngle_}getPlacement(){return this.placement_}getRepeat(){return this.repeat_}getOffsetX(){return this.offsetX_}getOffsetY(){return this.offsetY_}getFill(){return this.fill_}getRotateWithView(){return this.rotateWithView_}getRotation(){return this.rotation_}getScale(){return this.scale_}getScaleArray(){return this.scaleArray_}getStroke(){return this.stroke_}getText(){return this.text_}getTextAlign(){return this.textAlign_}getJustify(){return this.justify_}getTextBaseline(){return this.textBaseline_}getBackgroundFill(){return this.backgroundFill_}getBackgroundStroke(){return this.backgroundStroke_}getPadding(){return this.padding_}getDeclutterMode(){return this.declutterMode_}setOverflow(t){this.overflow_=t}setFont(t){this.font_=t}setMaxAngle(t){this.maxAngle_=t}setOffsetX(t){this.offsetX_=t}setOffsetY(t){this.offsetY_=t}setPlacement(t){this.placement_=t}setRepeat(t){this.repeat_=t}setRotateWithView(t){this.rotateWithView_=t}setFill(t){this.fill_=t}setRotation(t){this.rotation_=t}setScale(t){this.scale_=t,this.scaleArray_=kt(t!==void 0?t:1)}setStroke(t){this.stroke_=t}setText(t){this.text_=t}setTextAlign(t){this.textAlign_=t}setJustify(t){this.justify_=t}setTextBaseline(t){this.textBaseline_=t}setBackgroundFill(t){this.backgroundFill_=t}setBackgroundStroke(t){this.backgroundStroke_=t}setPadding(t){this.padding_=t}}let ni=0;const ki=0,ot=1<",GreaterThanOrEqualTo:">=",LessThan:"<",LessThanOrEqualTo:"<=",Multiply:"*",Divide:"/",Add:"+",Subtract:"-",Clamp:"clamp",Mod:"%",Pow:"^",Abs:"abs",Floor:"floor",Ceil:"ceil",Round:"round",Sin:"sin",Cos:"cos",Atan:"atan",Sqrt:"sqrt",Match:"match",Between:"between",Interpolate:"interpolate",Coalesce:"coalesce",Case:"case",In:"in",Number:"number",String:"string",Array:"array",Color:"color",Id:"id",Band:"band",Palette:"palette",ToString:"to-string"},Ac={[C.Get]:F(([s,t])=>t!==void 0?Mc(t.value):Et,X(1,2),Pc),[C.Var]:F(([s])=>s.type,X(1,1),Oc),[C.Id]:F(b|Dt,Hi,Dc),[C.Concat]:F(Dt,X(2,1/0),j(Et)),[C.GeometryType]:F(Dt,Hi,Fc),[C.Resolution]:F(b,Hi),[C.Zoom]:F(b,Hi),[C.Time]:F(b,Hi),[C.Any]:F(ot,X(2,1/0),j(ot)),[C.All]:F(ot,X(2,1/0),j(ot)),[C.Not]:F(ot,X(1,1),j(ot)),[C.Equal]:F(ot,X(2,2),j(Et),Ie),[C.NotEqual]:F(ot,X(2,2),j(Et),Ie),[C.GreaterThan]:F(ot,X(2,2),j(Et),Ie),[C.GreaterThanOrEqualTo]:F(ot,X(2,2),j(Et),Ie),[C.LessThan]:F(ot,X(2,2),j(Et),Ie),[C.LessThanOrEqualTo]:F(ot,X(2,2),j(Et),Ie),[C.Multiply]:F(s=>{let t=b|ut;for(let e=0;e{let t=Et;for(let e=1;e{let t=Et;for(let e=2;e{let t=ut|b;for(let e=3;e{let t=Et;for(let e=1;es.length===2?re|nn:s.length===3||s.length===4?re|ut:re,X(1,1/0),j(b)),[C.Color]:F(ut,X(1,4),j(b)),[C.Band]:F(b,X(1,3),j(b)),[C.Palette]:F(ut,X(2,2),Xc),[C.ToString]:F(Dt,X(1,1),j(ot|b|Dt|ut))};function Pc(s,t){const e=J(s[1],t);if(!(e instanceof Fe))throw new Error("Expected a literal argument for get operation");if(typeof e.value!="string")throw new Error("Expected a string argument for get operation");if(t.properties.add(e.value),s.length===3){const i=J(s[2],t);return[e,i]}return[e]}function Oc(s,t,e,i){const n=s[1];if(typeof n!="string")throw new Error("Expected a string argument for var operation");if(t.variables.add(n),!("variables"in t.style)||t.style.variables[n]===void 0)return[new Fe(Et,n)];const r=t.style.variables[n],o=J(r,t);if(o.value=n,i&&!oe(i,o.type))throw new Error(`The variable ${n} has type ${Ct(o.type)} but the following type was expected: ${Ct(i)}`);return[o]}function Dc(s,t){t.featureId=!0}function Fc(s,t){t.geometryType=!0}function Hi(s,t){const e=s[0];if(s.length!==1)throw new Error(`Expected no arguments for ${e} operation`);return[]}function X(s,t){return function(e,i){const n=e[0],r=e.length-1;if(s===t){if(r!==s){const o=s===1?"":"s";throw new Error(`Expected ${s} argument${o} for ${n}, got ${r}`)}}else if(rt){const o=t===1/0?`${s} or more`:`${s} to ${t}`;throw new Error(`Expected ${o} arguments for ${n}, got ${r}`)}}}function j(s){return function(t,e){const i=t[0],n=t.length-1,r=new Array(n);for(let o=0;oi.featureId;case C.GeometryType:return i=>i.geometryType;case C.Concat:{const i=s.args.map(n=>Jt(n));return n=>"".concat(...i.map(r=>r(n).toString()))}case C.Resolution:return i=>i.resolution;case C.Any:case C.All:case C.Between:case C.In:case C.Not:return Kc(s);case C.Equal:case C.NotEqual:case C.LessThan:case C.LessThanOrEqualTo:case C.GreaterThan:case C.GreaterThanOrEqualTo:return Zc(s);case C.Multiply:case C.Divide:case C.Add:case C.Subtract:case C.Clamp:case C.Mod:case C.Pow:case C.Abs:case C.Floor:case C.Ceil:case C.Round:case C.Sin:case C.Cos:case C.Atan:case C.Sqrt:return Uc(s);case C.Case:return jc(s);case C.Match:return Hc(s);case C.Interpolate:return qc(s);case C.ToString:return $c(s);default:throw new Error(`Unsupported operator ${e}`)}}function Vc(s,t){const e=s.operator,i=s.args.length,n=new Array(i);for(let r=0;r{for(let o=0;o{for(let o=0;on.properties[i];case C.Var:return n=>n.variables[i];default:throw new Error(`Unsupported accessor operator ${s.operator}`)}}function Zc(s,t){const e=s.operator,i=Jt(s.args[0]),n=Jt(s.args[1]);switch(e){case C.Equal:return r=>i(r)===n(r);case C.NotEqual:return r=>i(r)!==n(r);case C.LessThan:return r=>i(r)i(r)<=n(r);case C.GreaterThan:return r=>i(r)>n(r);case C.GreaterThanOrEqualTo:return r=>i(r)>=n(r);default:throw new Error(`Unsupported comparison operator ${e}`)}}function Kc(s,t){const e=s.operator,i=s.args.length,n=new Array(i);for(let r=0;r{for(let o=0;o{for(let o=0;o{const o=n[0](r),a=n[1](r),l=n[2](r);return o>=a&&o<=l};case C.In:return r=>{const o=n[0](r);for(let a=1;a!n[0](r);default:throw new Error(`Unsupported logical operator ${e}`)}}function Uc(s,t){const e=s.operator,i=s.args.length,n=new Array(i);for(let r=0;r{let o=1;for(let a=0;an[0](r)/n[1](r);case C.Add:return r=>{let o=0;for(let a=0;an[0](r)-n[1](r);case C.Clamp:return r=>{const o=n[0](r),a=n[1](r);if(ol?l:o};case C.Mod:return r=>n[0](r)%n[1](r);case C.Pow:return r=>Math.pow(n[0](r),n[1](r));case C.Abs:return r=>Math.abs(n[0](r));case C.Floor:return r=>Math.floor(n[0](r));case C.Ceil:return r=>Math.ceil(n[0](r));case C.Round:return r=>Math.round(n[0](r));case C.Sin:return r=>Math.sin(n[0](r));case C.Cos:return r=>Math.cos(n[0](r));case C.Atan:return i===2?r=>Math.atan2(n[0](r),n[1](r)):r=>Math.atan(n[0](r));case C.Sqrt:return r=>Math.sqrt(n[0](r));default:throw new Error(`Unsupported numeric operator ${e}`)}}function jc(s,t){const e=s.args.length,i=new Array(e);for(let n=0;n{for(let r=0;r{const r=i[0](n);for(let o=1;o{const r=i[0](n),o=i[1](n);let a,l;for(let c=2;c=o)return c===2?u:d?Jc(r,o,a,l,h,u):Qi(r,o,a,l,h,u);a=h,l=u}return l}}function $c(s,t){const e=s.operator,i=s.args.length,n=new Array(i);for(let r=0;r{const o=n[0](r);return s.args[0].type===ut?br(o):o.toString()};default:throw new Error(`Unsupported convert operator ${e}`)}}function Qi(s,t,e,i,n,r){const o=n-e;if(o===0)return i;const a=t-e,l=s===1?a/o:(Math.pow(s,a)-1)/(Math.pow(s,o)-1);return i+l*(r-i)}function Jc(s,t,e,i,n,r){if(n-e===0)return i;const a=_o(i),l=_o(r);let c=l[2]-a[2];c>180?c-=360:c<-180&&(c+=360);const h=[Qi(s,t,e,a[0],n,l[0]),Qi(s,t,e,a[1],n,l[1]),a[2]+Qi(s,t,e,0,n,c),Qi(s,t,e,i[3],n,r[3])];return Ma(oc(h))}function Qc(s){return!0}function tu(s){const t=Na(),e=eu(s,t),i=za();return function(n,r){if(i.properties=n.getPropertiesInternal(),i.resolution=r,t.featureId){const o=n.getId();o!==void 0?i.featureId=o:i.featureId=null}return t.geometryType&&(i.geometryType=Ga(n.getGeometry())),e(i)}}function wo(s){const t=Na(),e=s.length,i=new Array(e);for(let o=0;o4)throw new Error(`Expected a color with 3 or 4 values for ${t}`);return e}function Va(s,t){const e=Tn(s,t);if(e.length!==2)throw new Error(`Expected an array of two numbers for ${t}`);return e}function du(s,t){return typeof s=="number"?s:Va(s,t)}const Ro={RENDER_ORDER:"renderOrder"};class Ba extends us{constructor(t){t=t||{};const e=Object.assign({},t);delete e.style,delete e.renderBuffer,delete e.updateWhileAnimating,delete e.updateWhileInteracting,super(e),this.declutter_=t.declutter?String(t.declutter):void 0,this.renderBuffer_=t.renderBuffer!==void 0?t.renderBuffer:100,this.style_=null,this.styleFunction_=void 0,this.setStyle(t.style),this.updateWhileAnimating_=t.updateWhileAnimating!==void 0?t.updateWhileAnimating:!1,this.updateWhileInteracting_=t.updateWhileInteracting!==void 0?t.updateWhileInteracting:!1}getDeclutter(){return this.declutter_}getFeatures(t){return super.getFeatures(t)}getRenderBuffer(){return this.renderBuffer_}getRenderOrder(){return this.get(Ro.RENDER_ORDER)}getStyle(){return this.style_}getStyleFunction(){return this.styleFunction_}getUpdateWhileAnimating(){return this.updateWhileAnimating_}getUpdateWhileInteracting(){return this.updateWhileInteracting_}renderDeclutter(t,e){const i=this.getDeclutter();i in t.declutter||(t.declutter[i]=new La(9)),this.getRenderer().renderDeclutter(t,e)}setRenderOrder(t){this.set(Ro.RENDER_ORDER,t)}setStyle(t){this.style_=t===void 0?Fa:t;const e=fu(t);this.styleFunction_=t===null?void 0:Tc(e),this.changed()}}function fu(s){if(s===void 0)return Fa;if(!s)return null;if(typeof s=="function"||s instanceof Nt)return s;if(!Array.isArray(s))return wo([s]);if(s.length===0)return[];const t=s.length,e=s[0];if(e instanceof Nt){const n=new Array(t);for(let r=0;r=0;--x){const S=_[x],I=S.layer;if(I.hasRenderer()&&Ir(S,h)&&a.call(l,I)){const v=I.getRenderer(),T=I.getSource();if(v&&T){const k=T.getWrapX()?f:t,O=u.bind(null,S.managed);p[0]=k[0]+g[w][0],p[1]=k[1]+g[w][1],c=v.forEachFeatureAtCoordinate(p,e,i,O,y)}if(c)return c}}if(y.length===0)return;const E=1/y.length;return y.forEach((w,x)=>w.distanceSq+=x*E),y.sort((w,x)=>w.distanceSq-x.distanceSq),y.some(w=>c=w.callback(w.feature,w.layer,w.geometry)),c}hasFeatureAtCoordinate(t,e,i,n,r,o){return this.forEachFeatureAtCoordinate(t,e,i,n,Qe,this,r,o)!==void 0}getMap(){return this.map_}renderFrame(t){$()}scheduleExpireIconCache(t){ne.canExpireCache()&&t.postRenderFunctions.push(_u)}}function _u(s,t){ne.expire()}class Za extends ae{constructor(t,e,i,n){super(t),this.inversePixelTransform=e,this.frameState=i,this.context=n}}class mu extends gu{constructor(t){super(t),this.fontChangeListenerKey_=U(ge,Je.PROPERTYCHANGE,t.redrawText.bind(t)),this.element_=document.createElement("div");const e=this.element_.style;e.position="absolute",e.width="100%",e.height="100%",e.zIndex="0",this.element_.className=ei+" ol-layers";const i=t.getViewport();i.insertBefore(this.element_,i.firstChild||null),this.children_=[],this.renderedVisible_=!0}dispatchRenderEvent(t,e){const i=this.getMap();if(i.hasListener(t)){const n=new Za(t,void 0,e);i.dispatchEvent(n)}}disposeInternal(){it(this.fontChangeListenerKey_),this.element_.parentNode.removeChild(this.element_),super.disposeInternal()}renderFrame(t){if(!t){this.renderedVisible_&&(this.element_.style.display="none",this.renderedVisible_=!1);return}this.calculateMatrices2D(t),this.dispatchRenderEvent(Kt.PRECOMPOSE,t);const e=t.layerStatesArray.sort(function(a,l){return a.zIndex-l.zIndex});e.some(a=>a.layer instanceof Ba&&a.layer.getDeclutter())&&(t.declutter={});const n=t.viewState;this.children_.length=0;const r=[];let o=null;for(let a=0,l=e.length;a=0;--i){const n=e[i],r=n.layer;r.getDeclutter()&&r.renderDeclutter(t,n)}e.forEach(i=>i.layer.renderDeferred(t))}}}class Pe extends ae{constructor(t,e){super(t),this.layer=e}}const Ns={LAYERS:"layers"};class Ni extends Ia{constructor(t){t=t||{};const e=Object.assign({},t);delete e.layers;let i=t.layers;super(e),this.on,this.once,this.un,this.layersListenerKeys_=[],this.listenerKeys_={},this.addChangeListener(Ns.LAYERS,this.handleLayersChanged_),i?Array.isArray(i)?i=new Ft(i.slice(),{unique:!0}):H(typeof i.getArray=="function","Expected `layers` to be an array or a `Collection`"):i=new Ft(void 0,{unique:!0}),this.setLayers(i)}handleLayerChange_(){this.changed()}handleLayersChanged_(){this.layersListenerKeys_.forEach(it),this.layersListenerKeys_.length=0;const t=this.getLayers();this.layersListenerKeys_.push(U(t,dt.ADD,this.handleLayersAdd_,this),U(t,dt.REMOVE,this.handleLayersRemove_,this));for(const i in this.listenerKeys_)this.listenerKeys_[i].forEach(it);Oi(this.listenerKeys_);const e=t.getArray();for(let i=0,n=e.length;i{this.clickTimeoutId_=void 0;const i=new Ae(st.SINGLECLICK,this.map_,t);this.dispatchEvent(i)},250)}updateActivePointers_(t){const e=t,i=e.pointerId;if(e.type==st.POINTERUP||e.type==st.POINTERCANCEL){delete this.trackedTouches_[i];for(const n in this.trackedTouches_)if(this.trackedTouches_[n].target!==e.target){delete this.trackedTouches_[n];break}}else(e.type==st.POINTERDOWN||e.type==st.POINTERMOVE)&&(this.trackedTouches_[i]=e);this.activePointers_=Object.values(this.trackedTouches_)}handlePointerUp_(t){this.updateActivePointers_(t);const e=new Ae(st.POINTERUP,this.map_,t,void 0,void 0,this.activePointers_);this.dispatchEvent(e),this.emulateClicks_&&!e.defaultPrevented&&!this.dragging_&&this.isMouseActionButton_(t)&&this.emulateClick_(this.down_),this.activePointers_.length===0&&(this.dragListenerKeys_.forEach(it),this.dragListenerKeys_.length=0,this.dragging_=!1,this.down_=null)}isMouseActionButton_(t){return t.button===0}handlePointerDown_(t){this.emulateClicks_=this.activePointers_.length===0,this.updateActivePointers_(t);const e=new Ae(st.POINTERDOWN,this.map_,t,void 0,void 0,this.activePointers_);if(this.dispatchEvent(e),this.down_=new PointerEvent(t.type,t),Object.defineProperty(this.down_,"target",{writable:!1,value:t.target}),this.dragListenerKeys_.length===0){const i=this.map_.getOwnerDocument();this.dragListenerKeys_.push(U(i,st.POINTERMOVE,this.handlePointerMove_,this),U(i,st.POINTERUP,this.handlePointerUp_,this),U(this.element_,st.POINTERCANCEL,this.handlePointerUp_,this)),this.element_.getRootNode&&this.element_.getRootNode()!==i&&this.dragListenerKeys_.push(U(this.element_.getRootNode(),st.POINTERUP,this.handlePointerUp_,this))}}handlePointerMove_(t){if(this.isMoving_(t)){this.updateActivePointers_(t),this.dragging_=!0;const e=new Ae(st.POINTERDRAG,this.map_,t,this.dragging_,void 0,this.activePointers_);this.dispatchEvent(e)}}relayMoveEvent_(t){this.originalPointerMoveEvent_=t;const e=!!(this.down_&&this.isMoving_(t));this.dispatchEvent(new Ae(st.POINTERMOVE,this.map_,t,e))}handleTouchMove_(t){const e=this.originalPointerMoveEvent_;(!e||e.defaultPrevented)&&(typeof t.cancelable!="boolean"||t.cancelable===!0)&&t.preventDefault()}isMoving_(t){return this.dragging_||Math.abs(t.clientX-this.down_.clientX)>this.moveTolerance_||Math.abs(t.clientY-this.down_.clientY)>this.moveTolerance_}disposeInternal(){this.relayedListenerKey_&&(it(this.relayedListenerKey_),this.relayedListenerKey_=null),this.element_.removeEventListener(N.TOUCHMOVE,this.boundHandleTouchMove_),this.pointerdownListenerKey_&&(it(this.pointerdownListenerKey_),this.pointerdownListenerKey_=null),this.dragListenerKeys_.forEach(it),this.dragListenerKeys_.length=0,this.element_=null,super.disposeInternal()}}const te={POSTRENDER:"postrender",MOVESTART:"movestart",MOVEEND:"moveend",LOADSTART:"loadstart",LOADEND:"loadend"},ht={LAYERGROUP:"layergroup",SIZE:"size",TARGET:"target",VIEW:"view"},ns=1/0;class yu{constructor(t,e){this.priorityFunction_=t,this.keyFunction_=e,this.elements_=[],this.priorities_=[],this.queuedElements_={}}clear(){this.elements_.length=0,this.priorities_.length=0,Oi(this.queuedElements_)}dequeue(){const t=this.elements_,e=this.priorities_,i=t[0];t.length==1?(t.length=0,e.length=0):(t[0]=t.pop(),e[0]=e.pop(),this.siftUp_(0));const n=this.keyFunction_(i);return delete this.queuedElements_[n],i}enqueue(t){H(!(this.keyFunction_(t)in this.queuedElements_),"Tried to enqueue an `element` that was already added to the queue");const e=this.priorityFunction_(t);return e!=ns?(this.elements_.push(t),this.priorities_.push(e),this.queuedElements_[this.keyFunction_(t)]=!0,this.siftDown_(0,this.elements_.length-1),!0):!1}getCount(){return this.elements_.length}getLeftChildIndex_(t){return t*2+1}getRightChildIndex_(t){return t*2+2}getParentIndex_(t){return t-1>>1}heapify_(){let t;for(t=(this.elements_.length>>1)-1;t>=0;t--)this.siftUp_(t)}isEmpty(){return this.elements_.length===0}isKeyQueued(t){return t in this.queuedElements_}isQueued(t){return this.isKeyQueued(this.keyFunction_(t))}siftUp_(t){const e=this.elements_,i=this.priorities_,n=e.length,r=e[t],o=i[t],a=t;for(;t>1;){const l=this.getLeftChildIndex_(t),c=this.getRightChildIndex_(t),h=ct;){const a=this.getParentIndex_(e);if(n[a]>o)i[e]=i[a],n[e]=n[a],e=a;else break}i[e]=r,n[e]=o}reprioritize(){const t=this.priorityFunction_,e=this.elements_,i=this.priorities_;let n=0;const r=e.length;let o,a,l;for(a=0;a0;)r=this.dequeue()[0],o=r.getKey(),n=r.getState(),n===A.IDLE&&!(o in this.tilesLoadingKeys_)&&(this.tilesLoadingKeys_[o]=!0,++this.tilesLoading_,++i,r.load())}}function xu(s,t,e,i,n){if(!s||!(e in s.wantedTiles)||!s.wantedTiles[e][t.getKey()])return ns;const r=s.viewState.center,o=i[0]-r[0],a=i[1]-r[1];return 65536*Math.log(n)+Math.sqrt(o*o+a*a)/n}class Gi extends Qt{constructor(t){super();const e=t.element;e&&!t.target&&!e.style.pointerEvents&&(e.style.pointerEvents="auto"),this.element=e||null,this.target_=null,this.map_=null,this.listenerKeys=[],t.render&&(this.render=t.render),t.target&&this.setTarget(t.target)}disposeInternal(){$n(this.element),super.disposeInternal()}getMap(){return this.map_}setMap(t){this.map_&&$n(this.element);for(let e=0,i=this.listenerKeys.length;en.getAttributions(t)))),i=!this.getMap().getAllLayers().some(n=>n.getSource()&&n.getSource().getAttributionsCollapsible()===!1);return this.overrideCollapsible_||this.setCollapsible(i),e}async updateElement_(t){if(!t){this.renderedVisible_&&(this.element.style.display="none",this.renderedVisible_=!1);return}const e=await Promise.all(this.collectSourceAttributions_(t).map(n=>Rl(()=>n))),i=e.length>0;if(this.renderedVisible_!=i&&(this.element.style.display=i?"":"none",this.renderedVisible_=i),!ze(e,this.renderedAttributions_)){Aa(this.ulElement_);for(let n=0,r=e.length;n0&&i%(2*Math.PI)!==0?e.animate({rotation:0,duration:this.duration_,easing:Di}):e.setRotation(0))}render(t){const e=t.frameState;if(!e)return;const i=e.viewState.rotation;if(i!=this.rotation_){const n="rotate("+i+"rad)";if(this.autoHide_){const r=this.element.classList.contains(Gn);!r&&i===0?this.element.classList.add(Gn):r&&i!==0&&this.element.classList.remove(Gn)}this.label_.style.transform=n}this.rotation_=i}}class vu extends Gi{constructor(t){t=t||{},super({element:document.createElement("div"),target:t.target});const e=t.className!==void 0?t.className:"ol-zoom",i=t.delta!==void 0?t.delta:1,n=t.zoomInClassName!==void 0?t.zoomInClassName:e+"-in",r=t.zoomOutClassName!==void 0?t.zoomOutClassName:e+"-out",o=t.zoomInLabel!==void 0?t.zoomInLabel:"+",a=t.zoomOutLabel!==void 0?t.zoomOutLabel:"–",l=t.zoomInTipLabel!==void 0?t.zoomInTipLabel:"Zoom in",c=t.zoomOutTipLabel!==void 0?t.zoomOutTipLabel:"Zoom out",h=document.createElement("button");h.className=n,h.setAttribute("type","button"),h.title=l,h.appendChild(typeof o=="string"?document.createTextNode(o):o),h.addEventListener(N.CLICK,this.handleClick_.bind(this,i),!1);const u=document.createElement("button");u.className=r,u.setAttribute("type","button"),u.title=c,u.appendChild(typeof a=="string"?document.createTextNode(a):a),u.addEventListener(N.CLICK,this.handleClick_.bind(this,-i),!1);const d=e+" "+ei+" "+vn,f=this.element;f.className=d,f.appendChild(h),f.appendChild(u),this.duration_=t.duration!==void 0?t.duration:250}handleClick_(t,e){e.preventDefault(),this.zoomByDelta_(t)}zoomByDelta_(t){const i=this.getMap().getView();if(!i)return;const n=i.getZoom();if(n!==void 0){const r=i.getConstrainedZoom(n+t);this.duration_>0?(i.getAnimating()&&i.cancelAnimations(),i.animate({zoom:r,duration:this.duration_,easing:Di})):i.setZoom(r)}}}function Ka(s){s=s||{};const t=new Ft;return(s.zoom!==void 0?s.zoom:!0)&&t.push(new vu(s.zoomOptions)),(s.rotate!==void 0?s.rotate:!0)&&t.push(new Cu(s.rotateOptions)),(s.attribution!==void 0?s.attribution:!0)&&t.push(new wu(s.attributionOptions)),t}class Tu extends Fi{constructor(t){super(),t=t||{},this.delta_=t.delta?t.delta:1,this.duration_=t.duration!==void 0?t.duration:250}handleEvent(t){let e=!1;if(t.type==st.DBLCLICK){const i=t.originalEvent,n=t.map,r=t.coordinate,o=i.shiftKey?-this.delta_:this.delta_,a=n.getView();lr(a,o,r,this.duration_),i.preventDefault(),e=!0}return!e}}class Ru extends xn{constructor(t){super({stopDown:yn}),t=t||{},this.kinetic_=t.kinetic,this.lastCentroid=null,this.lastPointersCount_,this.panning_=!1;const e=t.condition?t.condition:Qs(Ca,Fh);this.condition_=t.onFocusOnly?Qs(xa,e):e,this.noKinetic_=!1}handleDragEvent(t){const e=t.map;this.panning_||(this.panning_=!0,e.getView().beginInteraction());const i=this.targetPointers,n=e.getEventPixel(hr(i));if(i.length==this.lastPointersCount_){if(this.kinetic_&&this.kinetic_.update(n[0],n[1]),this.lastCentroid){const r=[this.lastCentroid[0]-n[0],n[1]-this.lastCentroid[1]],a=t.map.getView();Jl(r,a.getResolution()),fr(r,a.getRotation()),a.adjustCenterInternal(r)}}else this.kinetic_&&this.kinetic_.begin();this.lastCentroid=n,this.lastPointersCount_=i.length,t.originalEvent.preventDefault()}handleUpEvent(t){const e=t.map,i=e.getView();if(this.targetPointers.length===0){if(!this.noKinetic_&&this.kinetic_&&this.kinetic_.end()){const n=this.kinetic_.getDistance(),r=this.kinetic_.getAngle(),o=i.getCenterInternal(),a=e.getPixelFromCoordinateInternal(o),l=e.getCoordinateFromPixelInternal([a[0]-n*Math.cos(r),a[1]-n*Math.sin(r)]);i.animateInternal({center:i.getConstrainedCenter(l),duration:500,easing:Di})}return this.panning_&&(this.panning_=!1,i.endInteraction()),!1}return this.kinetic_&&this.kinetic_.begin(),this.lastCentroid=null,!0}handleDownEvent(t){if(this.targetPointers.length>0&&this.condition_(t)){const i=t.map.getView();return this.lastCentroid=null,i.getAnimating()&&i.cancelAnimations(),this.kinetic_&&this.kinetic_.begin(),this.noKinetic_=this.targetPointers.length>1,!0}return!1}}class Iu extends xn{constructor(t){t=t||{},super({stopDown:yn}),this.condition_=t.condition?t.condition:bh,this.lastAngle_=void 0,this.duration_=t.duration!==void 0?t.duration:250}handleDragEvent(t){if(!Ss(t))return;const e=t.map,i=e.getView();if(i.getConstraints().rotation===Rr)return;const n=e.getSize(),r=t.pixel,o=Math.atan2(n[1]/2-r[1],r[0]-n[0]/2);if(this.lastAngle_!==void 0){const a=o-this.lastAngle_;i.adjustRotationInternal(-a)}this.lastAngle_=o}handleUpEvent(t){return Ss(t)?(t.map.getView().endInteraction(this.duration_),!1):!0}handleDownEvent(t){return Ss(t)&&wa(t)&&this.condition_(t)?(t.map.getView().beginInteraction(),this.lastAngle_=void 0,!0):!1}}class Su extends Ra{constructor(t){t=t||{};const e=t.condition?t.condition:va;super({condition:e,className:t.className||"ol-dragzoom",minArea:t.minArea}),this.duration_=t.duration!==void 0?t.duration:200,this.out_=t.out!==void 0?t.out:!1}onBoxEnd(t){const i=this.getMap().getView();let n=this.getGeometry();if(this.out_){const r=i.rotatedExtentForGeometry(n),o=i.getResolutionForExtentInternal(r),a=i.getResolution()/o;n=n.clone(),n.scale(a*a)}i.fitInternal(n,{duration:this.duration_,easing:Di})}}const je={LEFT:"ArrowLeft",UP:"ArrowUp",RIGHT:"ArrowRight",DOWN:"ArrowDown"};class Lu extends Fi{constructor(t){super(),t=t||{},this.defaultCondition_=function(e){return Ca(e)&&Ta(e)},this.condition_=t.condition!==void 0?t.condition:this.defaultCondition_,this.duration_=t.duration!==void 0?t.duration:100,this.pixelDelta_=t.pixelDelta!==void 0?t.pixelDelta:128}handleEvent(t){let e=!1;if(t.type==N.KEYDOWN){const i=t.originalEvent,n=i.key;if(this.condition_(t)&&(n==je.DOWN||n==je.LEFT||n==je.RIGHT||n==je.UP)){const o=t.map.getView(),a=o.getResolution()*this.pixelDelta_;let l=0,c=0;n==je.DOWN?c=-a:n==je.LEFT?l=-a:n==je.RIGHT?l=a:c=a;const h=[l,c];fr(h,o.getRotation()),Ml(o,h,this.duration_),i.preventDefault(),e=!0}}return!e}}class bu extends Fi{constructor(t){super(),t=t||{},this.condition_=t.condition?t.condition:function(e){return!Dh(e)&&Ta(e)},this.delta_=t.delta?t.delta:1,this.duration_=t.duration!==void 0?t.duration:100}handleEvent(t){let e=!1;if(t.type==N.KEYDOWN||t.type==N.KEYPRESS){const i=t.originalEvent,n=i.key;if(this.condition_(t)&&(n==="+"||n==="-")){const r=t.map,o=n==="+"?this.delta_:-this.delta_,a=r.getView();lr(a,o,void 0,this.duration_),i.preventDefault(),e=!0}}return!e}}class Mu{constructor(t,e,i){this.decay_=t,this.minVelocity_=e,this.delay_=i,this.points_=[],this.angle_=0,this.initialVelocity_=0}begin(){this.points_.length=0,this.angle_=0,this.initialVelocity_=0}update(t,e){this.points_.push(t,e,Date.now())}end(){if(this.points_.length<6)return!1;const t=Date.now()-this.delay_,e=this.points_.length-3;if(this.points_[e+2]0&&this.points_[i+2]>t;)i-=3;const n=this.points_[e+2]-this.points_[i+2];if(n<1e3/60)return!1;const r=this.points_[e]-this.points_[i],o=this.points_[e+1]-this.points_[i+1];return this.angle_=Math.atan2(o,r),this.initialVelocity_=Math.sqrt(r*r+o*o)/n,this.initialVelocity_>this.minVelocity_}getDistance(){return(this.minVelocity_-this.initialVelocity_)/this.decay_}getAngle(){return this.angle_}}class Au extends Fi{constructor(t){t=t||{},super(t),this.totalDelta_=0,this.lastDelta_=0,this.maxDelta_=t.maxDelta!==void 0?t.maxDelta:1,this.duration_=t.duration!==void 0?t.duration:250,this.timeout_=t.timeout!==void 0?t.timeout:80,this.useAnchor_=t.useAnchor!==void 0?t.useAnchor:!0,this.constrainResolution_=t.constrainResolution!==void 0?t.constrainResolution:!1;const e=t.condition?t.condition:Ah;this.condition_=t.onFocusOnly?Qs(xa,e):e,this.lastAnchor_=null,this.startTime_=void 0,this.timeoutId_,this.mode_=void 0,this.trackpadEventGap_=400,this.trackpadTimeoutId_,this.deltaPerZoom_=300}endInteraction_(){this.trackpadTimeoutId_=void 0;const t=this.getMap();if(!t)return;t.getView().endInteraction(void 0,this.lastDelta_?this.lastDelta_>0?1:-1:0,this.lastAnchor_)}handleEvent(t){if(!this.condition_(t)||t.type!==N.WHEEL)return!0;const i=t.map,n=t.originalEvent;n.preventDefault(),this.useAnchor_&&(this.lastAnchor_=t.coordinate);let r;if(t.type==N.WHEEL&&(r=n.deltaY,Ih&&n.deltaMode===WheelEvent.DOM_DELTA_PIXEL&&(r/=ma),n.deltaMode===WheelEvent.DOM_DELTA_LINE&&(r*=40)),r===0)return!1;this.lastDelta_=r;const o=Date.now();this.startTime_===void 0&&(this.startTime_=o),(!this.mode_||o-this.startTime_>this.trackpadEventGap_)&&(this.mode_=Math.abs(r)<4?"trackpad":"wheel");const a=i.getView();if(this.mode_==="trackpad"&&!(a.getConstrainResolution()||this.constrainResolution_))return this.trackpadTimeoutId_?clearTimeout(this.trackpadTimeoutId_):(a.getAnimating()&&a.cancelAnimations(),a.beginInteraction()),this.trackpadTimeoutId_=setTimeout(this.endInteraction_.bind(this),this.timeout_),a.adjustZoom(-r/this.deltaPerZoom_,this.lastAnchor_),this.startTime_=o,!1;this.totalDelta_+=r;const l=Math.max(this.timeout_-(o-this.startTime_),0);return clearTimeout(this.timeoutId_),this.timeoutId_=setTimeout(this.handleWheelZoom_.bind(this,i),l),!1}handleWheelZoom_(t){const e=t.getView();e.getAnimating()&&e.cancelAnimations();let i=-lt(this.totalDelta_,-this.maxDelta_*this.deltaPerZoom_,this.maxDelta_*this.deltaPerZoom_)/this.deltaPerZoom_;(e.getConstrainResolution()||this.constrainResolution_)&&(i=i?i>0?1:-1:0),lr(e,i,this.lastAnchor_,this.duration_),this.mode_=void 0,this.totalDelta_=0,this.lastAnchor_=null,this.startTime_=void 0,this.timeoutId_=void 0}setMouseAnchor(t){this.useAnchor_=t,t||(this.lastAnchor_=null)}}class Pu extends xn{constructor(t){t=t||{};const e=t;e.stopDown||(e.stopDown=yn),super(e),this.anchor_=null,this.lastAngle_=void 0,this.rotating_=!1,this.rotationDelta_=0,this.threshold_=t.threshold!==void 0?t.threshold:.3,this.duration_=t.duration!==void 0?t.duration:250}handleDragEvent(t){let e=0;const i=this.targetPointers[0],n=this.targetPointers[1],r=Math.atan2(n.clientY-i.clientY,n.clientX-i.clientX);if(this.lastAngle_!==void 0){const l=r-this.lastAngle_;this.rotationDelta_+=l,!this.rotating_&&Math.abs(this.rotationDelta_)>this.threshold_&&(this.rotating_=!0),e=l}this.lastAngle_=r;const o=t.map,a=o.getView();a.getConstraints().rotation!==Rr&&(this.anchor_=o.getCoordinateFromPixelInternal(o.getEventPixel(hr(this.targetPointers))),this.rotating_&&(o.render(),a.adjustRotationInternal(e,this.anchor_)))}handleUpEvent(t){return this.targetPointers.length<2?(t.map.getView().endInteraction(this.duration_),!1):!0}handleDownEvent(t){if(this.targetPointers.length>=2){const e=t.map;return this.anchor_=null,this.lastAngle_=void 0,this.rotating_=!1,this.rotationDelta_=0,this.handlingDownUpSequence||e.getView().beginInteraction(),!0}return!1}}class Ou extends xn{constructor(t){t=t||{};const e=t;e.stopDown||(e.stopDown=yn),super(e),this.anchor_=null,this.duration_=t.duration!==void 0?t.duration:400,this.lastDistance_=void 0,this.lastScaleDelta_=1}handleDragEvent(t){let e=1;const i=this.targetPointers[0],n=this.targetPointers[1],r=i.clientX-n.clientX,o=i.clientY-n.clientY,a=Math.sqrt(r*r+o*o);this.lastDistance_!==void 0&&(e=this.lastDistance_/a),this.lastDistance_=a;const l=t.map,c=l.getView();e!=1&&(this.lastScaleDelta_=e),this.anchor_=l.getCoordinateFromPixelInternal(l.getEventPixel(hr(this.targetPointers))),l.render(),c.adjustResolutionInternal(e,this.anchor_)}handleUpEvent(t){if(this.targetPointers.length<2){const i=t.map.getView(),n=this.lastScaleDelta_>1?1:-1;return i.endInteraction(this.duration_,n),!1}return!0}handleDownEvent(t){if(this.targetPointers.length>=2){const e=t.map;return this.anchor_=null,this.lastDistance_=void 0,this.lastScaleDelta_=1,this.handlingDownUpSequence||e.getView().beginInteraction(),!0}return!1}}function Ua(s){s=s||{};const t=new Ft,e=new Mu(-.005,.05,100);return(s.altShiftDragRotate!==void 0?s.altShiftDragRotate:!0)&&t.push(new Iu),(s.doubleClickZoom!==void 0?s.doubleClickZoom:!0)&&t.push(new Tu({delta:s.zoomDelta,duration:s.zoomDuration})),(s.dragPan!==void 0?s.dragPan:!0)&&t.push(new Ru({onFocusOnly:s.onFocusOnly,kinetic:e})),(s.pinchRotate!==void 0?s.pinchRotate:!0)&&t.push(new Pu),(s.pinchZoom!==void 0?s.pinchZoom:!0)&&t.push(new Ou({duration:s.zoomDuration})),(s.keyboard!==void 0?s.keyboard:!0)&&(t.push(new Lu),t.push(new bu({delta:s.zoomDelta,duration:s.zoomDuration}))),(s.mouseWheelZoom!==void 0?s.mouseWheelZoom:!0)&&t.push(new Au({onFocusOnly:s.onFocusOnly,duration:s.zoomDuration})),(s.shiftDragZoom!==void 0?s.shiftDragZoom:!0)&&t.push(new Su({duration:s.zoomDuration})),t}function ja(s){if(s instanceof us){s.setMapInternal(null);return}s instanceof Ni&&s.getLayers().forEach(ja)}function Ha(s,t){if(s instanceof us){s.setMapInternal(t);return}if(s instanceof Ni){const e=s.getLayers().getArray();for(let i=0,n=e.length;ithis.updateSize()),this.controls=e.controls||Ka(),this.interactions=e.interactions||Ua({onFocusOnly:!0}),this.overlays_=e.overlays,this.overlayIdIndex_={},this.renderer_=null,this.postRenderFunctions_=[],this.tileQueue_=new Eu(this.getTilePriority.bind(this),this.handleTileChange_.bind(this)),this.addChangeListener(ht.LAYERGROUP,this.handleLayerGroupChanged_),this.addChangeListener(ht.VIEW,this.handleViewChanged_),this.addChangeListener(ht.SIZE,this.handleSizeChanged_),this.addChangeListener(ht.TARGET,this.handleTargetChanged_),this.setProperties(e.values);const i=this;t.view&&!(t.view instanceof Bt)&&t.view.then(function(n){i.setView(new Bt(n))}),this.controls.addEventListener(dt.ADD,n=>{n.element.setMap(this)}),this.controls.addEventListener(dt.REMOVE,n=>{n.element.setMap(null)}),this.interactions.addEventListener(dt.ADD,n=>{n.element.setMap(this)}),this.interactions.addEventListener(dt.REMOVE,n=>{n.element.setMap(null)}),this.overlays_.addEventListener(dt.ADD,n=>{this.addOverlayInternal_(n.element)}),this.overlays_.addEventListener(dt.REMOVE,n=>{const r=n.element.getId();r!==void 0&&delete this.overlayIdIndex_[r.toString()],n.element.setMap(null)}),this.controls.forEach(n=>{n.setMap(this)}),this.interactions.forEach(n=>{n.setMap(this)}),this.overlays_.forEach(this.addOverlayInternal_.bind(this))}addControl(t){this.getControls().push(t)}addInteraction(t){this.getInteractions().push(t)}addLayer(t){this.getLayerGroup().getLayers().push(t)}handleLayerAdd_(t){Ha(t.layer,this)}addOverlay(t){this.getOverlays().push(t)}addOverlayInternal_(t){const e=t.getId();e!==void 0&&(this.overlayIdIndex_[e.toString()]=t),t.setMap(this)}disposeInternal(){this.controls.clear(),this.interactions.clear(),this.overlays_.clear(),this.resizeObserver_.disconnect(),this.setTarget(null),super.disposeInternal()}forEachFeatureAtPixel(t,e,i){if(!this.frameState_||!this.renderer_)return;const n=this.getCoordinateFromPixelInternal(t);i=i!==void 0?i:{};const r=i.hitTolerance!==void 0?i.hitTolerance:0,o=i.layerFilter!==void 0?i.layerFilter:Qe,a=i.checkWrapped!==!1;return this.renderer_.forEachFeatureAtCoordinate(n,this.frameState_,r,a,e,null,o,null)}getFeaturesAtPixel(t,e){const i=[];return this.forEachFeatureAtPixel(t,function(n){i.push(n)},e),i}getAllLayers(){const t=[];function e(i){i.forEach(function(n){n instanceof Ni?e(n.getLayers()):t.push(n)})}return e(this.getLayers()),t}hasFeatureAtPixel(t,e){if(!this.frameState_||!this.renderer_)return!1;const i=this.getCoordinateFromPixelInternal(t);e=e!==void 0?e:{};const n=e.layerFilter!==void 0?e.layerFilter:Qe,r=e.hitTolerance!==void 0?e.hitTolerance:0,o=e.checkWrapped!==!1;return this.renderer_.hasFeatureAtCoordinate(i,this.frameState_,r,o,n,null)}getEventCoordinate(t){return this.getCoordinateFromPixel(this.getEventPixel(t))}getEventCoordinateInternal(t){return this.getCoordinateFromPixelInternal(this.getEventPixel(t))}getEventPixel(t){const i=this.viewport_.getBoundingClientRect(),n=this.getSize(),r=i.width/n[0],o=i.height/n[1],a="changedTouches"in t?t.changedTouches[0]:t;return[(a.clientX-i.left)/r,(a.clientY-i.top)/o]}getTarget(){return this.get(ht.TARGET)}getTargetElement(){return this.targetElement_}getCoordinateFromPixel(t){return Js(this.getCoordinateFromPixelInternal(t),this.getView().getProjection())}getCoordinateFromPixelInternal(t){const e=this.frameState_;return e?_t(e.pixelToCoordinateTransform,t.slice()):null}getControls(){return this.controls}getOverlays(){return this.overlays_}getOverlayById(t){const e=this.overlayIdIndex_[t.toString()];return e!==void 0?e:null}getInteractions(){return this.interactions}getLayerGroup(){return this.get(ht.LAYERGROUP)}setLayers(t){const e=this.getLayerGroup();if(t instanceof Ft){e.setLayers(t);return}const i=e.getLayers();i.clear(),i.extend(t)}getLayers(){return this.getLayerGroup().getLayers()}getLoadingOrNotReady(){const t=this.getLayerGroup().getLayerStatesArray();for(let e=0,i=t.length;e=0;r--){const o=n[r];if(o.getMap()!==this||!o.getActive()||!this.getTargetElement())continue;if(!o.handleEvent(t)||t.propagationStopped)break}}}handlePostRender(){const t=this.frameState_,e=this.tileQueue_;if(!e.isEmpty()){let n=this.maxTilesLoading_,r=n;if(t){const o=t.viewHints;if(o[xt.ANIMATING]||o[xt.INTERACTING]){const a=Date.now()-t.time>8;n=a?0:8,r=a?0:2}}e.getTilesLoading(){this.postRenderTimeoutHandle_=void 0,this.handlePostRender()},0))}setLayerGroup(t){const e=this.getLayerGroup();e&&this.handleLayerRemove_(new Pe("removelayer",e)),this.set(ht.LAYERGROUP,t)}setSize(t){this.set(ht.SIZE,t)}setTarget(t){this.set(ht.TARGET,t)}setView(t){if(!t||t instanceof Bt){this.set(ht.VIEW,t);return}this.set(ht.VIEW,new Bt);const e=this;t.then(function(i){e.setView(new Bt(i))})}updateSize(){const t=this.getTargetElement();let e;if(t){const n=getComputedStyle(t),r=t.offsetWidth-parseFloat(n.borderLeftWidth)-parseFloat(n.paddingLeft)-parseFloat(n.paddingRight)-parseFloat(n.borderRightWidth),o=t.offsetHeight-parseFloat(n.borderTopWidth)-parseFloat(n.paddingTop)-parseFloat(n.paddingBottom)-parseFloat(n.borderBottomWidth);!isNaN(r)&&!isNaN(o)&&(e=[r,o],!uo(e)&&(t.offsetWidth||t.offsetHeight||t.getClientRects().length)&&ia("No map visible because the map container's width or height are 0."))}const i=this.getSize();e&&(!i||!ze(e,i))&&(this.setSize(e),this.updateViewportSize_(e))}updateViewportSize_(t){const e=this.getView();e&&e.setViewportSize(t)}}function Du(s){let t=null;s.keyboardEventTarget!==void 0&&(t=typeof s.keyboardEventTarget=="string"?document.getElementById(s.keyboardEventTarget):s.keyboardEventTarget);const e={},i=s.layers&&typeof s.layers.getLayers=="function"?s.layers:new Ni({layers:s.layers});e[ht.LAYERGROUP]=i,e[ht.TARGET]=s.target,e[ht.VIEW]=s.view instanceof Bt?s.view:new Bt;let n;s.controls!==void 0&&(Array.isArray(s.controls)?n=new Ft(s.controls.slice()):(H(typeof s.controls.getArray=="function","Expected `controls` to be an array or an `ol/Collection.js`"),n=s.controls));let r;s.interactions!==void 0&&(Array.isArray(s.interactions)?r=new Ft(s.interactions.slice()):(H(typeof s.interactions.getArray=="function","Expected `interactions` to be an array or an `ol/Collection.js`"),r=s.interactions));let o;return s.overlays!==void 0?Array.isArray(s.overlays)?o=new Ft(s.overlays.slice()):(H(typeof s.overlays.getArray=="function","Expected `overlays` to be an array or an `ol/Collection.js`"),o=s.overlays):o=new Ft,{controls:n,interactions:r,keyboardEventTarget:t,overlays:o,values:e}}class $a extends rs{constructor(t,e,i){super(),i=i||{},this.tileCoord=t,this.state=e,this.interimTile=null,this.key="",this.transition_=i.transition===void 0?250:i.transition,this.transitionStarts_={},this.interpolate=!!i.interpolate}changed(){this.dispatchEvent(N.CHANGE)}release(){this.state===A.ERROR&&this.setState(A.EMPTY)}getKey(){return this.key+"/"+this.tileCoord}getInterimTile(){let t=this.interimTile;if(!t)return this;do{if(t.getState()==A.LOADED)return this.transition_=0,t;t=t.interimTile}while(t);return this}refreshInterimChain(){let t=this.interimTile;if(!t)return;let e=this;do{if(t.getState()==A.LOADED){t.interimTile=null;break}t.getState()==A.LOADING?e=t:t.getState()==A.IDLE?e.interimTile=t.interimTile:e=t,t=e.interimTile}while(t)}getTileCoord(){return this.tileCoord}getState(){return this.state}setState(t){if(this.state!==A.ERROR&&this.state>t)throw new Error("Tile load sequence violation");this.state=t,this.changed()}load(){$()}getAlpha(t,e){if(!this.transition_)return 1;let i=this.transitionStarts_[t];if(!i)i=e,this.transitionStarts_[t]=i;else if(i===-1)return 1;const n=e-i+1e3/60;return n>=this.transition_?1:Bo(n/this.transition_)}inTransition(t){return this.transition_?this.transitionStarts_[t]!==-1:!1}endTransition(t){this.transition_&&(this.transitionStarts_[t]=-1)}}class Ja extends $a{constructor(t,e,i,n,r,o){super(t,e,o),this.crossOrigin_=n,this.src_=i,this.key=i,this.image_=new Image,n!==null&&(this.image_.crossOrigin=n),this.unlisten_=null,this.tileLoadFunction_=r}getImage(){return this.image_}setImage(t){this.image_=t,this.state=A.LOADED,this.unlistenImage_(),this.changed()}handleImageError_(){this.state=A.ERROR,this.unlistenImage_(),this.image_=Fu(),this.changed()}handleImageLoad_(){const t=this.image_;t.naturalWidth&&t.naturalHeight?this.state=A.LOADED:this.state=A.EMPTY,this.unlistenImage_(),this.changed()}load(){this.state==A.ERROR&&(this.state=A.IDLE,this.image_=new Image,this.crossOrigin_!==null&&(this.image_.crossOrigin=this.crossOrigin_)),this.state==A.IDLE&&(this.state=A.LOADING,this.changed(),this.tileLoadFunction_(this,this.src_),this.unlisten_=uc(this.image_,this.handleImageLoad_.bind(this),this.handleImageError_.bind(this)))}unlistenImage_(){this.unlisten_&&(this.unlisten_(),this.unlisten_=null)}}function Fu(){const s=mt(1,1);return s.fillStyle="rgba(0,0,0,0)",s.fillRect(0,0,1,1),s.canvas}const ku=.5,Nu=10,Io=.25;class Gu{constructor(t,e,i,n,r,o){this.sourceProj_=t,this.targetProj_=e;let a={};const l=Kn(this.targetProj_,this.sourceProj_);this.transformInv_=function(p){const E=p[0]+"/"+p[1];return a[E]||(a[E]=l(p)),a[E]},this.maxSourceExtent_=n,this.errorThresholdSquared_=r*r,this.triangles_=[],this.wrapsXInSource_=!1,this.canWrapXInSource_=this.sourceProj_.canWrapX()&&!!n&&!!this.sourceProj_.getExtent()&&tt(n)>=tt(this.sourceProj_.getExtent()),this.sourceWorldWidth_=this.sourceProj_.getExtent()?tt(this.sourceProj_.getExtent()):null,this.targetWorldWidth_=this.targetProj_.getExtent()?tt(this.targetProj_.getExtent()):null;const c=We(i),h=ls(i),u=wn(i),d=as(i),f=this.transformInv_(c),g=this.transformInv_(h),_=this.transformInv_(u),m=this.transformInv_(d),y=Nu+(o?Math.max(0,Math.ceil(Math.log2(Us(i)/(o*o*256*256)))):0);if(this.addQuad_(c,h,u,d,f,g,_,m,y),this.wrapsXInSource_){let p=1/0;this.triangles_.forEach(function(E,w,x){p=Math.min(p,E.source[0][0],E.source[1][0],E.source[2][0])}),this.triangles_.forEach(E=>{if(Math.max(E.source[0][0],E.source[1][0],E.source[2][0])-p>this.sourceWorldWidth_/2){const w=[[E.source[0][0],E.source[0][1]],[E.source[1][0],E.source[1][1]],[E.source[2][0],E.source[2][1]]];w[0][0]-p>this.sourceWorldWidth_/2&&(w[0][0]-=this.sourceWorldWidth_),w[1][0]-p>this.sourceWorldWidth_/2&&(w[1][0]-=this.sourceWorldWidth_),w[2][0]-p>this.sourceWorldWidth_/2&&(w[2][0]-=this.sourceWorldWidth_);const x=Math.min(w[0][0],w[1][0],w[2][0]);Math.max(w[0][0],w[1][0],w[2][0])-x.5&&u<1;let g=!1;if(c>0){if(this.targetProj_.isGlobal()&&this.targetWorldWidth_){const m=jr([t,e,i,n]);g=tt(m)/this.targetWorldWidth_>Io||g}!f&&this.sourceProj_.isGlobal()&&u&&(g=u>Io||g)}if(!g&&this.maxSourceExtent_&&isFinite(h[0])&&isFinite(h[1])&&isFinite(h[2])&&isFinite(h[3])&&!At(h,this.maxSourceExtent_))return;let _=0;if(!g&&(!isFinite(r[0])||!isFinite(r[1])||!isFinite(o[0])||!isFinite(o[1])||!isFinite(a[0])||!isFinite(a[1])||!isFinite(l[0])||!isFinite(l[1]))){if(c>0)g=!0;else if(_=(!isFinite(r[0])||!isFinite(r[1])?8:0)+(!isFinite(o[0])||!isFinite(o[1])?4:0)+(!isFinite(a[0])||!isFinite(a[1])?2:0)+(!isFinite(l[0])||!isFinite(l[1])?1:0),_!=1&&_!=2&&_!=4&&_!=8)return}if(c>0){if(!g){const m=[(t[0]+i[0])/2,(t[1]+i[1])/2],y=this.transformInv_(m);let p;f?p=(Ti(r[0],d)+Ti(a[0],d))/2-Ti(y[0],d):p=(r[0]+a[0])/2-y[0];const E=(r[1]+a[1])/2-y[1];g=p*p+E*E>this.errorThresholdSquared_}if(g){if(Math.abs(t[0]-i[0])<=Math.abs(t[1]-i[1])){const m=[(e[0]+i[0])/2,(e[1]+i[1])/2],y=this.transformInv_(m),p=[(n[0]+t[0])/2,(n[1]+t[1])/2],E=this.transformInv_(p);this.addQuad_(t,e,m,p,r,o,y,E,c-1),this.addQuad_(p,m,i,n,E,y,a,l,c-1)}else{const m=[(t[0]+e[0])/2,(t[1]+e[1])/2],y=this.transformInv_(m),p=[(i[0]+n[0])/2,(i[1]+n[1])/2],E=this.transformInv_(p);this.addQuad_(t,m,p,n,r,y,E,l,c-1),this.addQuad_(m,e,i,p,y,o,a,E,c-1)}return}}if(f){if(!this.canWrapXInSource_)return;this.wrapsXInSource_=!0}_&11||this.addTriangle_(t,i,n,r,a,l),_&14||this.addTriangle_(t,i,e,r,a,o),_&&(_&13||this.addTriangle_(e,n,t,o,l,r),_&7||this.addTriangle_(e,n,i,o,l,a))}calculateSourceExtent(){const t=Ut();return this.triangles_.forEach(function(e,i,n){const r=e.source;tn(t,r[0]),tn(t,r[1]),tn(t,r[2])}),t}getTriangles(){return this.triangles_}}let Gs;const Ri=[];function So(s,t,e,i,n){s.beginPath(),s.moveTo(0,0),s.lineTo(t,e),s.lineTo(i,n),s.closePath(),s.save(),s.clip(),s.fillRect(0,0,Math.max(t,i)+1,Math.max(e,n)),s.restore()}function zs(s,t){return Math.abs(s[t*4]-210)>2||Math.abs(s[t*4+3]-.75*255)>2}function zu(){if(Gs===void 0){const s=mt(6,6,Ri);s.globalCompositeOperation="lighter",s.fillStyle="rgba(210, 0, 0, 0.75)",So(s,4,5,4,0),So(s,4,5,0,5);const t=s.getImageData(0,0,3,3).data;Gs=zs(t,0)||zs(t,4)||zs(t,8),fs(s),Ri.push(s.canvas)}return Gs}function Lo(s,t,e,i){const n=ra(e,t,s);let r=Zn(t,i,e);const o=t.getMetersPerUnit();o!==void 0&&(r*=o);const a=s.getMetersPerUnit();a!==void 0&&(r/=a);const l=s.getExtent();if(!l||Li(l,n)){const c=Zn(s,r,n)/r;isFinite(c)&&c>0&&(r/=c)}return r}function Wu(s,t,e,i){const n=ti(e);let r=Lo(s,t,n,i);return(!isFinite(r)||r<=0)&&$o(e,function(o){return r=Lo(s,t,o,i),isFinite(r)&&r>0}),r}function Xu(s,t,e,i,n,r,o,a,l,c,h,u,d,f){const g=mt(Math.round(e*s),Math.round(e*t),Ri);if(u||(g.imageSmoothingEnabled=!1),l.length===0)return g.canvas;g.scale(e,e);function _(x){return Math.round(x*e)/e}g.globalCompositeOperation="lighter";const m=Ut();l.forEach(function(x,S,I){Dl(m,x.extent)});let y;const p=e/i,E=(u?1:1+Math.pow(2,-24))/p;y=mt(Math.round(tt(m)*p),Math.round(bt(m)*p),Ri),u||(y.imageSmoothingEnabled=!1),l.forEach(function(x,S,I){if(x.image.width>0&&x.image.height>0){if(x.clipExtent){y.save();const P=(x.clipExtent[0]-m[0])*p,G=-(x.clipExtent[3]-m[3])*p,D=tt(x.clipExtent)*p,z=bt(x.clipExtent)*p;y.rect(u?P:Math.round(P),u?G:Math.round(G),u?D:Math.round(P+D)-Math.round(P),u?z:Math.round(G+z)-Math.round(G)),y.clip()}const v=(x.extent[0]-m[0])*p,T=-(x.extent[3]-m[3])*p,k=tt(x.extent)*p,O=bt(x.extent)*p;y.drawImage(x.image,c,c,x.image.width-2*c,x.image.height-2*c,u?v:Math.round(v),u?T:Math.round(T),u?k:Math.round(v+k)-Math.round(v),u?O:Math.round(T+O)-Math.round(T)),x.clipExtent&&y.restore()}});const w=We(o);return a.getTriangles().forEach(function(x,S,I){const v=x.source,T=x.target;let k=v[0][0],O=v[0][1],P=v[1][0],G=v[1][1],D=v[2][0],z=v[2][1];const L=_((T[0][0]-w[0])/r),q=_(-(T[0][1]-w[1])/r),W=_((T[1][0]-w[0])/r),nt=_(-(T[1][1]-w[1])/r),Y=_((T[2][0]-w[0])/r),K=_(-(T[2][1]-w[1])/r),B=k,et=O;k=0,O=0,P-=B,G-=et,D-=B,z-=et;const R=[[P,G,0,0,W-L],[D,z,0,0,Y-L],[0,0,P,G,nt-q],[0,0,D,z,K-q]],vt=ql(R);if(!vt)return;if(g.save(),g.beginPath(),zu()||!u){g.moveTo(W,nt);const at=4,Ht=L-W,Xe=q-nt;for(let Tt=0;Tt{const k=e.getTileRangeForExtentAndZ(T,this.sourceZ_);for(let O=k.minX;O<=k.maxX;O++)for(let P=k.minY;P<=k.maxY;P++){const G=c(this.sourceZ_,O,P,a);if(G){const D=I*S;this.sourceTiles_.push({tile:G,offset:D})}}++I}),this.sourceTiles_.length===0&&(this.state=A.EMPTY)}}getImage(){return this.canvas_}reproject_(){const t=[];if(this.sourceTiles_.forEach(e=>{var n;const i=e.tile;if(i&&i.getState()==A.LOADED){const r=this.sourceTileGrid_.getTileCoordExtent(i.tileCoord);r[0]+=e.offset,r[2]+=e.offset;const o=(n=this.clipExtent_)==null?void 0:n.slice();o&&(o[0]+=e.offset,o[2]+=e.offset),t.push({extent:r,clipExtent:o,image:i.getImage()})}}),this.sourceTiles_.length=0,t.length===0)this.state=A.ERROR;else{const e=this.wrappedTileCoord_[0],i=this.targetTileGrid_.getTileSize(e),n=typeof i=="number"?i:i[0],r=typeof i=="number"?i:i[1],o=this.targetTileGrid_.getResolution(e),a=this.sourceTileGrid_.getResolution(this.sourceZ_),l=this.targetTileGrid_.getTileCoordExtent(this.wrappedTileCoord_);this.canvas_=Xu(n,r,this.pixelRatio_,a,this.sourceTileGrid_.getExtent(),o,l,this.triangulation_,t,this.gutter_,this.renderEdges_,this.interpolate),this.state=A.LOADED}this.changed()}load(){if(this.state==A.IDLE){this.state=A.LOADING,this.changed();let t=0;this.sourcesListenerKeys_=[],this.sourceTiles_.forEach(({tile:e})=>{const i=e.getState();if(i==A.IDLE||i==A.LOADING){t++;const n=U(e,N.CHANGE,function(r){const o=e.getState();(o==A.LOADED||o==A.ERROR||o==A.EMPTY)&&(it(n),t--,t===0&&(this.unlistenSources_(),this.reproject_()))},this);this.sourcesListenerKeys_.push(n)}}),t===0?setTimeout(this.reproject_.bind(this),0):this.sourceTiles_.forEach(function({tile:e},i,n){e.getState()==A.IDLE&&e.load()})}}unlistenSources_(){this.sourcesListenerKeys_.forEach(it),this.sourcesListenerKeys_=null}release(){this.canvas_&&(fs(this.canvas_.getContext("2d")),Ri.push(this.canvas_),this.canvas_=null),super.release()}}class Yu{constructor(t){this.highWaterMark=t!==void 0?t:2048,this.count_=0,this.entries_={},this.oldest_=null,this.newest_=null}canExpireCache(){return this.highWaterMark>0&&this.getCount()>this.highWaterMark}expireCache(t){for(;this.canExpireCache();)this.pop()}clear(){this.count_=0,this.entries_={},this.oldest_=null,this.newest_=null}containsKey(t){return this.entries_.hasOwnProperty(t)}forEach(t){let e=this.oldest_;for(;e;)t(e.value_,e.key_,this),e=e.newer}get(t,e){const i=this.entries_[t];return H(i!==void 0,"Tried to get a value for a key that does not exist in the cache"),i===this.newest_||(i===this.oldest_?(this.oldest_=this.oldest_.newer,this.oldest_.older=null):(i.newer.older=i.older,i.older.newer=i.newer),i.newer=null,i.older=this.newest_,this.newest_.newer=i,this.newest_=i),i.value_}remove(t){const e=this.entries_[t];return H(e!==void 0,"Tried to get a value for a key that does not exist in the cache"),e===this.newest_?(this.newest_=e.older,this.newest_&&(this.newest_.newer=null)):e===this.oldest_?(this.oldest_=e.newer,this.oldest_&&(this.oldest_.older=null)):(e.newer.older=e.older,e.older.newer=e.newer),delete this.entries_[t],--this.count_,e.value_}getCount(){return this.count_}getKeys(){const t=new Array(this.count_);let e=0,i;for(i=this.newest_;i;i=i.older)t[e++]=i.key_;return t}getValues(){const t=new Array(this.count_);let e=0,i;for(i=this.newest_;i;i=i.older)t[e++]=i.value_;return t}peekLast(){return this.oldest_.value_}peekLastKey(){return this.oldest_.key_}peekFirstKey(){return this.newest_.key_}peek(t){var e;return(e=this.entries_[t])==null?void 0:e.value_}pop(){const t=this.oldest_;return delete this.entries_[t.key_],t.newer&&(t.newer.older=null),this.oldest_=t.newer,this.oldest_||(this.newest_=null),--this.count_,t.value_}replace(t,e){this.get(t),this.entries_[t].value_=e}set(t,e){H(!(t in this.entries_),"Tried to set a value for a key that is used already");const i={key_:t,newer:null,older:this.newest_,value_:e};this.newest_?this.newest_.newer=i:this.oldest_=i,this.newest_=i,this.entries_[t]=i,++this.count_}setSize(t){this.highWaterMark=t}}function bo(s,t,e,i){return i!==void 0?(i[0]=s,i[1]=t,i[2]=e,i):[s,t,e]}function Es(s,t,e){return s+"/"+t+"/"+e}function Qa(s){return Es(s[0],s[1],s[2])}function Vu(s){return s.split("/").map(Number)}function Bu(s){return(s[1]<e||e>t.getMaxZoom())return!1;const r=t.getFullTileRange(e);return r?r.containsXY(i,n):!0}class tl extends Yu{clear(){for(;this.getCount()>0;)this.pop().release();super.clear()}expireCache(t){for(;this.canExpireCache()&&!(this.peekLast().getKey()in t);)this.pop().release()}pruneExceptNewestZ(){if(this.getCount()===0)return;const t=this.peekFirstKey(),i=Vu(t)[0];this.forEach(n=>{n.tileCoord[0]!==i&&(this.remove(Qa(n.tileCoord)),n.release())})}}const Ws={TILELOADSTART:"tileloadstart",TILELOADEND:"tileloadend",TILELOADERROR:"tileloaderror"};class el extends Qt{constructor(t){super(),this.projection=jt(t.projection),this.attributions_=Mo(t.attributions),this.attributionsCollapsible_=t.attributionsCollapsible!==void 0?t.attributionsCollapsible:!0,this.loading=!1,this.state_=t.state!==void 0?t.state:"ready",this.wrapX_=t.wrapX!==void 0?t.wrapX:!1,this.interpolate_=!!t.interpolate,this.viewResolver=null,this.viewRejector=null;const e=this;this.viewPromise_=new Promise(function(i,n){e.viewResolver=i,e.viewRejector=n})}getAttributions(){return this.attributions_}getAttributionsCollapsible(){return this.attributionsCollapsible_}getProjection(){return this.projection}getResolutions(t){return null}getView(){return this.viewPromise_}getState(){return this.state_}getWrapX(){return this.wrapX_}getInterpolate(){return this.interpolate_}refresh(){this.changed()}setAttributions(t){this.attributions_=Mo(t),this.changed()}setState(t){this.state_=t,this.changed()}}function Mo(s){return s?Array.isArray(s)?function(t){return s}:typeof s=="function"?s:function(t){return[s]}:null}class Or{constructor(t,e,i,n){this.minX=t,this.maxX=e,this.minY=i,this.maxY=n}contains(t){return this.containsXY(t[1],t[2])}containsTileRange(t){return this.minX<=t.minX&&t.maxX<=this.maxX&&this.minY<=t.minY&&t.maxY<=this.maxY}containsXY(t,e){return this.minX<=t&&t<=this.maxX&&this.minY<=e&&e<=this.maxY}equals(t){return this.minX==t.minX&&this.minY==t.minY&&this.maxX==t.maxX&&this.maxY==t.maxY}extend(t){t.minXthis.maxX&&(this.maxX=t.maxX),t.minYthis.maxY&&(this.maxY=t.maxY)}getHeight(){return this.maxY-this.minY+1}getSize(){return[this.getWidth(),this.getHeight()]}getWidth(){return this.maxX-this.minX+1}intersects(t){return this.minX<=t.maxX&&this.maxX>=t.minX&&this.minY<=t.maxY&&this.maxY>=t.minY}}function ci(s,t,e,i,n){return n!==void 0?(n.minX=s,n.maxX=t,n.minY=e,n.maxY=i,n):new Or(s,t,e,i)}const ui=[0,0,0],Se=5;class il{constructor(t){this.minZoom=t.minZoom!==void 0?t.minZoom:0,this.resolutions_=t.resolutions,H(Tl(this.resolutions_,(n,r)=>r-n),"`resolutions` must be sorted in descending order");let e;if(!t.origins){for(let n=0,r=this.resolutions_.length-1;n{const o=new Or(Math.min(0,n[0]),Math.max(n[0]-1,-1),Math.min(0,n[1]),Math.max(n[1]-1,-1));if(i){const a=this.getTileRangeForExtentAndZ(i,r);o.minX=Math.max(a.minX,o.minX),o.maxX=Math.min(a.maxX,o.maxX),o.minY=Math.max(a.minY,o.minY),o.maxY=Math.min(a.maxY,o.maxY)}return o}):i&&this.calculateTileRanges_(i)}forEachTileCoord(t,e,i){const n=this.getTileRangeForExtentAndZ(t,e);for(let r=n.minX,o=n.maxX;r<=o;++r)for(let a=n.minY,l=n.maxY;a<=l;++a)i([e,r,a])}forEachTileCoordParentTileRange(t,e,i,n){let r,o,a,l=null,c=t[0]-1;for(this.zoomFactor_===2?(o=t[1],a=t[2]):l=this.getTileCoordExtent(t,n);c>=this.minZoom;){if(o!==void 0&&a!==void 0?(o=Math.floor(o/2),a=Math.floor(a/2),r=ci(o,o,a,a,i)):r=this.getTileRangeForExtentAndZ(l,c,i),e(c,r))return!0;--c}return!1}getExtent(){return this.extent_}getMaxZoom(){return this.maxZoom}getMinZoom(){return this.minZoom}getOrigin(t){return this.origin_?this.origin_:this.origins_[t]}getResolution(t){return this.resolutions_[t]}getResolutions(){return this.resolutions_}getTileCoordChildTileRange(t,e,i){if(t[0]this.maxZoom||e0?i:Math.max(r/e[0],n/e[1]);const o=t+1,a=new Array(o);for(let l=0;li.highWaterMark&&(i.highWaterMark=t)}useTile(t,e,i,n){}}class $u extends ae{constructor(t,e){super(t),this.tile=e}}function Ju(s,t){const e=/\{z\}/g,i=/\{x\}/g,n=/\{y\}/g,r=/\{-y\}/g;return function(o,a,l){if(o)return s.replace(e,o[0].toString()).replace(i,o[1].toString()).replace(n,o[2].toString()).replace(r,function(){const c=o[0],h=t.getFullTileRange(c);if(!h)throw new Error("The {-y} placeholder requires a tile grid with extent");return(h.getHeight()-o[2]-1).toString()})}}function Qu(s,t){const e=s.length,i=new Array(e);for(let n=0;nthis.getTileInternal(m,y,p,E,o),this.reprojectionErrorThreshold_,this.renderReprojectionEdges_,this.tileOptions);return _.key=u,c?(_.interimTile=c,_.refreshInterimChain(),a.replace(h,_)):a.set(h,_),_}getTileInternal(t,e,i,n,r){let o=null;const a=Es(t,e,i),l=this.getKey();if(!this.tileCache.containsKey(a))o=this.createTile_(t,e,i,n,r,l),this.tileCache.set(a,o);else if(o=this.tileCache.get(a),o.key!=l){const c=o;o=this.createTile_(t,e,i,n,r,l),c.getState()==A.IDLE?o.interimTile=c.interimTile:o.interimTile=c,o.refreshInterimChain(),this.tileCache.replace(a,o)}return o}setRenderReprojectionEdges(t){if(this.renderReprojectionEdges_!=t){this.renderReprojectionEdges_=t;for(const e in this.tileCacheForProjection)this.tileCacheForProjection[e].clear();this.changed()}}setTileGridForProjection(t,e){const i=jt(t);if(i){const n=Z(i);n in this.tileGridForProjection||(this.tileGridForProjection[n]=e)}}clear(){super.clear();for(const t in this.tileCacheForProjection)this.tileCacheForProjection[t].clear()}}function nd(s,t){s.getImage().src=t}class sd extends id{constructor(t){t=t||{};const e=t.projection!==void 0?t.projection:"EPSG:3857",i=t.tileGrid!==void 0?t.tileGrid:ju({extent:Dr(e),maxResolution:t.maxResolution,maxZoom:t.maxZoom,minZoom:t.minZoom,tileSize:t.tileSize});super({attributions:t.attributions,cacheSize:t.cacheSize,crossOrigin:t.crossOrigin,interpolate:t.interpolate,opaque:t.opaque,projection:e,reprojectionErrorThreshold:t.reprojectionErrorThreshold,tileGrid:i,tileLoadFunction:t.tileLoadFunction,tilePixelRatio:t.tilePixelRatio,tileUrlFunction:t.tileUrlFunction,url:t.url,urls:t.urls,wrapX:t.wrapX!==void 0?t.wrapX:!0,transition:t.transition,attributionsCollapsible:t.attributionsCollapsible,zDirection:t.zDirection}),this.gutter_=t.gutter!==void 0?t.gutter:0}getGutter(){return this.gutter_}}const rd='© OpenStreetMap contributors.';class od extends sd{constructor(t){t=t||{};let e;t.attributions!==void 0?e=t.attributions:e=[rd];const i=t.crossOrigin!==void 0?t.crossOrigin:"anonymous",n=t.url!==void 0?t.url:"https://tile.openstreetmap.org/{z}/{x}/{y}.png";super({attributions:e,attributionsCollapsible:!1,cacheSize:t.cacheSize,crossOrigin:i,interpolate:t.interpolate,maxZoom:t.maxZoom!==void 0?t.maxZoom:19,opaque:t.opaque!==void 0?t.opaque:!0,reprojectionErrorThreshold:t.reprojectionErrorThreshold,tileLoadFunction:t.tileLoadFunction,transition:t.transition,url:n,wrapX:t.wrapX,zDirection:t.zDirection})}}const yt={ELEMENT:"element",MAP:"map",OFFSET:"offset",POSITION:"position",POSITIONING:"positioning"};class ad extends Qt{constructor(t){super(),this.on,this.once,this.un,this.options=t,this.id=t.id,this.insertFirst=t.insertFirst!==void 0?t.insertFirst:!0,this.stopEvent=t.stopEvent!==void 0?t.stopEvent:!0,this.element=document.createElement("div"),this.element.className=t.className!==void 0?t.className:"ol-overlay-container "+pc,this.element.style.position="absolute",this.element.style.pointerEvents="auto",this.autoPan=t.autoPan===!0?{}:t.autoPan||void 0,this.rendered={transform_:"",visible:!0},this.mapPostrenderListenerKey=null,this.addChangeListener(yt.ELEMENT,this.handleElementChanged),this.addChangeListener(yt.MAP,this.handleMapChanged),this.addChangeListener(yt.OFFSET,this.handleOffsetChanged),this.addChangeListener(yt.POSITION,this.handlePositionChanged),this.addChangeListener(yt.POSITIONING,this.handlePositioningChanged),t.element!==void 0&&this.setElement(t.element),this.setOffset(t.offset!==void 0?t.offset:[0,0]),this.setPositioning(t.positioning||"top-left"),t.position!==void 0&&this.setPosition(t.position)}getElement(){return this.get(yt.ELEMENT)}getId(){return this.id}getMap(){return this.get(yt.MAP)||null}getOffset(){return this.get(yt.OFFSET)}getPosition(){return this.get(yt.POSITION)}getPositioning(){return this.get(yt.POSITIONING)}handleElementChanged(){Aa(this.element);const t=this.getElement();t&&this.element.appendChild(t)}handleMapChanged(){this.mapPostrenderListenerKey&&($n(this.element),it(this.mapPostrenderListenerKey),this.mapPostrenderListenerKey=null);const t=this.getMap();if(t){this.mapPostrenderListenerKey=U(t,te.POSTRENDER,this.render,this),this.updatePixelPosition();const e=this.stopEvent?t.getOverlayContainerStopEvent():t.getOverlayContainer();this.insertFirst?e.insertBefore(this.element,e.childNodes[0]||null):e.appendChild(this.element),this.performAutoPan()}}render(){this.updatePixelPosition()}handleOffsetChanged(){this.updatePixelPosition()}handlePositionChanged(){this.updatePixelPosition(),this.performAutoPan()}handlePositioningChanged(){this.updatePixelPosition()}setElement(t){this.set(yt.ELEMENT,t)}setMap(t){this.set(yt.MAP,t)}setOffset(t){this.set(yt.OFFSET,t)}setPosition(t){this.set(yt.POSITION,t)}performAutoPan(){this.autoPan&&this.panIntoView(this.autoPan)}panIntoView(t){const e=this.getMap();if(!e||!e.getTargetElement()||!this.get(yt.POSITION))return;const i=this.getRect(e.getTargetElement(),e.getSize()),n=this.getElement(),r=this.getRect(n,[lc(n),hc(n)]);t=t||{};const o=t.margin===void 0?20:t.margin;if(!Oe(i,r)){const a=r[0]-i[0],l=i[2]-r[2],c=r[1]-i[1],h=i[3]-r[3],u=[0,0];if(a<0?u[0]=a-o:l<0&&(u[0]=Math.abs(l)+o),c<0?u[1]=c-o:h<0&&(u[1]=Math.abs(h)+o),u[0]!==0||u[1]!==0){const d=e.getView().getCenterInternal(),f=e.getPixelFromCoordinateInternal(d);if(!f)return;const g=[f[0]+u[0],f[1]+u[1]],_=t.animation||{};e.getView().animateInternal({center:e.getCoordinateFromPixelInternal(g),duration:_.duration,easing:_.easing})}}}getRect(t,e){const i=t.getBoundingClientRect(),n=i.left+window.pageXOffset,r=i.top+window.pageYOffset;return[n,r,n+e[0],r+e[1]]}setPositioning(t){this.set(yt.POSITIONING,t)}setVisible(t){this.rendered.visible!==t&&(this.element.style.display=t?"":"none",this.rendered.visible=t)}updatePixelPosition(){const t=this.getMap(),e=this.getPosition();if(!t||!t.isRendered()||!e){this.setVisible(!1);return}const i=t.getPixelFromCoordinate(e),n=t.getSize();this.updateRenderedPosition(i,n)}updateRenderedPosition(t,e){const i=this.element.style,n=this.getOffset(),r=this.getPositioning();this.setVisible(!0);const o=Math.round(t[0]+n[0])+"px",a=Math.round(t[1]+n[1])+"px";let l="0%",c="0%";r=="bottom-right"||r=="center-right"||r=="top-right"?l="-100%":(r=="bottom-center"||r=="center-center"||r=="top-center")&&(l="-50%"),r=="bottom-left"||r=="bottom-center"||r=="bottom-right"?c="-100%":(r=="center-left"||r=="center-center"||r=="center-right")&&(c="-50%");const h=`translate(${l}, ${c}) translate(${o}, ${a})`;this.rendered.transform_!=h&&(this.rendered.transform_=h,i.transform=h)}getOptions(){return this.options}}const Xs=.75,zn=.1;class ld extends Gi{constructor(t){t=t||{},super({element:document.createElement("div"),render:t.render,target:t.target}),this.boundHandleRotationChanged_=this.handleRotationChanged_.bind(this),this.collapsed_=t.collapsed!==void 0?t.collapsed:!0,this.collapsible_=t.collapsible!==void 0?t.collapsible:!0,this.collapsible_||(this.collapsed_=!1),this.rotateWithView_=t.rotateWithView!==void 0?t.rotateWithView:!1,this.viewExtent_=void 0;const e=t.className!==void 0?t.className:"ol-overviewmap",i=t.tipLabel!==void 0?t.tipLabel:"Overview map",n=t.collapseLabel!==void 0?t.collapseLabel:"‹";typeof n=="string"?(this.collapseLabel_=document.createElement("span"),this.collapseLabel_.textContent=n):this.collapseLabel_=n;const r=t.label!==void 0?t.label:"›";typeof r=="string"?(this.label_=document.createElement("span"),this.label_.textContent=r):this.label_=r;const o=this.collapsible_&&!this.collapsed_?this.collapseLabel_:this.label_,a=document.createElement("button");a.setAttribute("type","button"),a.title=i,a.appendChild(o),a.addEventListener(N.CLICK,this.handleClick_.bind(this),!1),this.ovmapDiv_=document.createElement("div"),this.ovmapDiv_.className="ol-overviewmap-map",this.view_=t.view;const l=new qa({view:t.view,controls:new Ft,interactions:new Ft});this.ovmap_=l,t.layers&&t.layers.forEach(function(p){l.addLayer(p)});const c=document.createElement("div");c.className="ol-overviewmap-box",c.style.boxSizing="border-box",this.boxOverlay_=new ad({position:[0,0],positioning:"center-center",element:c}),this.ovmap_.addOverlay(this.boxOverlay_);const h=e+" "+ei+" "+vn+(this.collapsed_&&this.collapsible_?" "+Jn:"")+(this.collapsible_?"":" ol-uncollapsible"),u=this.element;u.className=h,u.appendChild(this.ovmapDiv_),u.appendChild(a);const d=this,f=this.boxOverlay_,g=this.boxOverlay_.getElement(),_=function(p){return{clientX:p.clientX,clientY:p.clientY}},m=function(p){const E=_(p),w=l.getEventCoordinateInternal(E);f.setPosition(w)},y=function(p){const E=l.getEventCoordinateInternal(p);d.getMap().getView().setCenterInternal(E),window.removeEventListener("mousemove",m),window.removeEventListener("mouseup",y)};g.addEventListener("mousedown",function(){window.addEventListener("mousemove",m),window.addEventListener("mouseup",y)})}setMap(t){const e=this.getMap();if(t!==e){if(e){const i=e.getView();i&&this.unbindView_(i),this.ovmap_.setTarget(null)}if(super.setMap(t),t){this.ovmap_.setTarget(this.ovmapDiv_),this.listenerKeys.push(U(t,Je.PROPERTYCHANGE,this.handleMapPropertyChange_,this));const i=t.getView();i&&(this.bindView_(i),i.isDef()&&(this.ovmap_.updateSize(),this.resetExtent_())),this.ovmap_.isRendered()||this.updateBoxAfterOvmapIsRendered_()}}}handleMapPropertyChange_(t){if(t.key===ht.VIEW){const e=t.oldValue;e&&this.unbindView_(e);const i=this.getMap().getView();this.bindView_(i)}else!this.ovmap_.isRendered()&&(t.key===ht.TARGET||t.key===ht.SIZE)&&this.ovmap_.updateSize()}bindView_(t){if(!this.view_){const e=new Bt({projection:t.getProjection()});this.ovmap_.setView(e)}t.addChangeListener(Ot.ROTATION,this.boundHandleRotationChanged_),this.handleRotationChanged_()}unbindView_(t){t.removeChangeListener(Ot.ROTATION,this.boundHandleRotationChanged_)}handleRotationChanged_(){this.rotateWithView_&&this.ovmap_.getView().setRotation(this.getMap().getView().getRotation())}validateExtent_(){const t=this.getMap(),e=this.ovmap_;if(!t.isRendered()||!e.isRendered())return;const i=t.getSize(),r=t.getView().calculateExtentInternal(i);if(this.viewExtent_&&bi(r,this.viewExtent_))return;this.viewExtent_=r;const o=e.getSize(),l=e.getView().calculateExtentInternal(o),c=e.getPixelFromCoordinateInternal(We(r)),h=e.getPixelFromCoordinateInternal(wn(r)),u=Math.abs(c[0]-h[0]),d=Math.abs(c[1]-h[1]),f=o[0],g=o[1];uf*Xs||d>g*Xs?this.resetExtent_():Oe(l,r)||this.recenter_()}resetExtent_(){const t=this.getMap(),e=this.ovmap_,i=t.getSize(),r=t.getView().calculateExtentInternal(i),o=e.getView(),a=Math.log(Xs/zn)/Math.LN2,l=1/(Math.pow(2,a/2)*zn);Gl(r,l),o.fitInternal(jn(r))}recenter_(){const t=this.getMap(),e=this.ovmap_,i=t.getView();e.getView().setCenterInternal(i.getCenterInternal())}updateBox_(){const t=this.getMap(),e=this.ovmap_;if(!t.isRendered()||!e.isRendered())return;const i=t.getSize(),n=t.getView(),r=e.getView(),o=this.rotateWithView_?0:-n.getRotation(),a=this.boxOverlay_,l=this.boxOverlay_.getElement(),c=n.getCenterInternal(),h=n.getResolution(),u=r.getResolution(),d=i[0]*h/u,f=i[1]*h/u;if(a.setPosition(c),l){l.style.width=d+"px",l.style.height=f+"px";const g="rotate("+o+"rad)";l.style.transform=g}}updateBoxAfterOvmapIsRendered_(){this.ovmapPostrenderKey_||(this.ovmapPostrenderKey_=rn(this.ovmap_,te.POSTRENDER,function(t){delete this.ovmapPostrenderKey_,this.updateBox_()},this))}handleClick_(t){t.preventDefault(),this.handleToggle_()}handleToggle_(){this.element.classList.toggle(Jn),this.collapsed_?qn(this.collapseLabel_,this.label_):qn(this.label_,this.collapseLabel_),this.collapsed_=!this.collapsed_;const t=this.ovmap_;if(!this.collapsed_){if(t.isRendered()){this.viewExtent_=void 0,t.render();return}t.updateSize(),this.resetExtent_(),this.updateBoxAfterOvmapIsRendered_()}}getCollapsible(){return this.collapsible_}setCollapsible(t){this.collapsible_!==t&&(this.collapsible_=t,this.element.classList.toggle("ol-uncollapsible"),!t&&this.collapsed_&&this.handleToggle_())}setCollapsed(t){!this.collapsible_||this.collapsed_===t||this.handleToggle_()}getCollapsed(){return this.collapsed_}getRotateWithView(){return this.rotateWithView_}setRotateWithView(t){this.rotateWithView_!==t&&(this.rotateWithView_=t,this.getMap().getView().getRotation()!==0&&(this.rotateWithView_?this.handleRotationChanged_():this.ovmap_.getView().setRotation(0),this.viewExtent_=void 0,this.validateExtent_(),this.updateBox_()))}getOverviewMap(){return this.ovmap_}render(t){this.validateExtent_(),this.updateBox_()}}const Ys="units",hd=[1,2,5],qi=25.4/.28;class cd extends Gi{constructor(t){t=t||{};const e=document.createElement("div");e.style.pointerEvents="none",super({element:e,render:t.render,target:t.target}),this.on,this.once,this.un;const i=t.className!==void 0?t.className:t.bar?"ol-scale-bar":"ol-scale-line";this.innerElement_=document.createElement("div"),this.innerElement_.className=i+"-inner",this.element.className=i+" "+ei,this.element.appendChild(this.innerElement_),this.viewState_=null,this.minWidth_=t.minWidth!==void 0?t.minWidth:64,this.maxWidth_=t.maxWidth,this.renderedVisible_=!1,this.renderedWidth_=void 0,this.renderedHTML_="",this.addChangeListener(Ys,this.handleUnitsChanged_),this.setUnits(t.units||"metric"),this.scaleBar_=t.bar||!1,this.scaleBarSteps_=t.steps||4,this.scaleBarText_=t.text||!1,this.dpi_=t.dpi||void 0}getUnits(){return this.get(Ys)}handleUnitsChanged_(){this.updateElement_()}setUnits(t){this.set(Ys,t)}setDpi(t){this.dpi_=t}updateElement_(){const t=this.viewState_;if(!t){this.renderedVisible_&&(this.element.style.display="none",this.renderedVisible_=!1);return}const e=t.center,i=t.projection,n=this.getUnits(),r=n=="degrees"?"degrees":"m";let o=Zn(i,t.resolution,e,r);const a=this.minWidth_*(this.dpi_||qi)/qi,l=this.maxWidth_!==void 0?this.maxWidth_*(this.dpi_||qi)/qi:void 0;let c=a*o,h="";if(n=="degrees"){const E=Mi.degrees;c*=E,c=l){d=_,f=m,g=y;break}else if(f>=a)break;_=d,m=f,y=g,++u}const p=this.scaleBar_?this.createScaleBar(f,d,h):d.toFixed(g<0?-g:0)+" "+h;this.renderedHTML_!=p&&(this.innerElement_.innerHTML=p,this.renderedHTML_=p),this.renderedWidth_!=f&&(this.innerElement_.style.width=f+"px",this.renderedWidth_=f),this.renderedVisible_||(this.element.style.display="",this.renderedVisible_=!0)}createScaleBar(t,e,i){const n=this.getScaleForResolution(),r=n<1?Math.round(1/n).toLocaleString()+" : 1":"1 : "+Math.round(n).toLocaleString(),o=this.scaleBarSteps_,a=t/o,l=[this.createMarker("absolute")];for(let h=0;h
`+this.createMarker("relative")+(h%2===0||o===2?this.createStepText(h,t,!1,e,i):"")+"")}return l.push(this.createStepText(o,t,!0,e,i)),(this.scaleBarText_?`
`+r+"
":"")+l.join("")}createMarker(t){return`
`}createStepText(t,e,i,n,r){const a=(t===0?0:Math.round(n/this.scaleBarSteps_*t*100)/100)+(t===0?"":" "+r),l=t===0?-3:e/this.scaleBarSteps_*-1,c=t===0?0:e/this.scaleBarSteps_*2;return`
`+a+"
"}getScaleForResolution(){const t=Zn(this.viewState_.projection,this.viewState_.resolution,this.viewState_.center,"m"),e=this.dpi_||qi,i=1e3/25.4;return t*i*e}render(t){const e=t.frameState;e?this.viewState_=e.viewState:this.viewState_=null,this.updateElement_()}}const M={BEGIN_GEOMETRY:0,BEGIN_PATH:1,CIRCLE:2,CLOSE_PATH:3,CUSTOM:4,DRAW_CHARS:5,DRAW_IMAGE:6,END_GEOMETRY:7,FILL:8,MOVE_TO_LINE_TO:9,SET_FILL_STYLE:10,SET_STROKE_STYLE:11,STROKE:12,ELLIPSE:13},di=[M.FILL],ee=[M.STROKE],me=[M.BEGIN_PATH],Ao=[M.CLOSE_PATH];class rl{drawCustom(t,e,i,n,r){}drawGeometry(t){}setStyle(t){}drawCircle(t,e,i){}drawEllipse(t,e,i){}drawFeature(t,e,i){}drawGeometryCollection(t,e,i){}drawLineString(t,e,i){}drawMultiLineString(t,e,i){}drawMultiPoint(t,e,i){}drawMultiPolygon(t,e,i){}drawPoint(t,e,i){}drawPolygon(t,e,i){}drawText(t,e,i){}setFillStrokeStyle(t,e){}setImageStyle(t,e){}setTextStyle(t,e){}}class Rn extends rl{constructor(t,e,i,n){super(),this.tolerance=t,this.maxExtent=e,this.pixelRatio=n,this.maxLineWidth=0,this.resolution=i,this.beginGeometryInstruction1_=null,this.beginGeometryInstruction2_=null,this.bufferedMaxExtent_=null,this.instructions=[],this.coordinates=[],this.tmpCoordinate_=[],this.hitDetectionInstructions=[],this.state={}}applyPixelRatio(t){const e=this.pixelRatio;return e==1?t:t.map(function(i){return i*e})}appendFlatPointCoordinates(t,e){const i=this.getBufferedMaxExtent(),n=this.tmpCoordinate_,r=this.coordinates;let o=r.length;for(let a=0,l=t.length;al&&(this.instructions.push([M.CUSTOM,l,h,t,i,xi,r]),this.hitDetectionInstructions.push([M.CUSTOM,l,h,t,n||i,xi,r]));break;case"Point":c=t.getFlatCoordinates(),this.coordinates.push(c[0],c[1]),h=this.coordinates.length,this.instructions.push([M.CUSTOM,l,h,t,i,void 0,r]),this.hitDetectionInstructions.push([M.CUSTOM,l,h,t,n||i,void 0,r]);break}this.endGeometry(e)}beginGeometry(t,e,i){this.beginGeometryInstruction1_=[M.BEGIN_GEOMETRY,e,0,t,i],this.instructions.push(this.beginGeometryInstruction1_),this.beginGeometryInstruction2_=[M.BEGIN_GEOMETRY,e,0,t,i],this.hitDetectionInstructions.push(this.beginGeometryInstruction2_)}finish(){return{instructions:this.instructions,hitDetectionInstructions:this.hitDetectionInstructions,coordinates:this.coordinates}}reverseHitDetectionInstructions(){const t=this.hitDetectionInstructions;t.reverse();let e;const i=t.length;let n,r,o=-1;for(e=0;ethis.maxLineWidth&&(this.maxLineWidth=i.lineWidth,this.bufferedMaxExtent_=null)}else i.strokeStyle=void 0,i.lineCap=void 0,i.lineDash=null,i.lineDashOffset=void 0,i.lineJoin=void 0,i.lineWidth=void 0,i.miterLimit=void 0}createFill(t){const e=t.fillStyle,i=[M.SET_FILL_STYLE,e];return typeof e!="string"&&i.push(t.fillPatternScale),i}applyStroke(t){this.instructions.push(this.createStroke(t))}createStroke(t){return[M.SET_STROKE_STYLE,t.strokeStyle,t.lineWidth*this.pixelRatio,t.lineCap,t.lineJoin,t.miterLimit,this.applyPixelRatio(t.lineDash),t.lineDashOffset*this.pixelRatio]}updateFillStyle(t,e){const i=t.fillStyle;(typeof i!="string"||t.currentFillStyle!=i)&&(i!==void 0&&this.instructions.push(e.call(this,t)),t.currentFillStyle=i)}updateStrokeStyle(t,e){const i=t.strokeStyle,n=t.lineCap,r=t.lineDash,o=t.lineDashOffset,a=t.lineJoin,l=t.lineWidth,c=t.miterLimit;(t.currentStrokeStyle!=i||t.currentLineCap!=n||r!=t.currentLineDash&&!ze(t.currentLineDash,r)||t.currentLineDashOffset!=o||t.currentLineJoin!=a||t.currentLineWidth!=l||t.currentMiterLimit!=c)&&(i!==void 0&&e.call(this,t),t.currentStrokeStyle=i,t.currentLineCap=n,t.currentLineDash=r,t.currentLineDashOffset=o,t.currentLineJoin=a,t.currentLineWidth=l,t.currentMiterLimit=c)}endGeometry(t){this.beginGeometryInstruction1_[2]=this.instructions.length,this.beginGeometryInstruction1_=null,this.beginGeometryInstruction2_[2]=this.hitDetectionInstructions.length,this.beginGeometryInstruction2_=null;const e=[M.END_GEOMETRY,t];this.instructions.push(e),this.hitDetectionInstructions.push(e)}getBufferedMaxExtent(){if(!this.bufferedMaxExtent_&&(this.bufferedMaxExtent_=Ko(this.maxExtent),this.maxLineWidth>0)){const t=this.resolution*(this.maxLineWidth+1)/2;cr(this.bufferedMaxExtent_,t,this.bufferedMaxExtent_)}return this.bufferedMaxExtent_}}class ud extends Rn{constructor(t,e,i,n){super(t,e,i,n),this.hitDetectionImage_=null,this.image_=null,this.imagePixelRatio_=void 0,this.anchorX_=void 0,this.anchorY_=void 0,this.height_=void 0,this.opacity_=void 0,this.originX_=void 0,this.originY_=void 0,this.rotateWithView_=void 0,this.rotation_=void 0,this.scale_=void 0,this.width_=void 0,this.declutterMode_=void 0,this.declutterImageWithText_=void 0}drawPoint(t,e,i){if(!this.image_||this.maxExtent&&!Li(this.maxExtent,t.getFlatCoordinates()))return;this.beginGeometry(t,e,i);const n=t.getFlatCoordinates(),r=t.getStride(),o=this.coordinates.length,a=this.appendFlatPointCoordinates(n,r);this.instructions.push([M.DRAW_IMAGE,o,a,this.image_,this.anchorX_*this.imagePixelRatio_,this.anchorY_*this.imagePixelRatio_,Math.ceil(this.height_*this.imagePixelRatio_),this.opacity_,this.originX_*this.imagePixelRatio_,this.originY_*this.imagePixelRatio_,this.rotateWithView_,this.rotation_,[this.scale_[0]*this.pixelRatio/this.imagePixelRatio_,this.scale_[1]*this.pixelRatio/this.imagePixelRatio_],Math.ceil(this.width_*this.imagePixelRatio_),this.declutterMode_,this.declutterImageWithText_]),this.hitDetectionInstructions.push([M.DRAW_IMAGE,o,a,this.hitDetectionImage_,this.anchorX_,this.anchorY_,this.height_,1,this.originX_,this.originY_,this.rotateWithView_,this.rotation_,this.scale_,this.width_,this.declutterMode_,this.declutterImageWithText_]),this.endGeometry(e)}drawMultiPoint(t,e,i){if(!this.image_)return;this.beginGeometry(t,e,i);const n=t.getFlatCoordinates(),r=[];for(let l=0,c=n.length;l=s){const g=(s-a+f)/f,_=Vt(c,u,g),m=Vt(h,d,g);l.push(_,m),r.push(l),l=[_,m],a==s&&(o+=n),a=0}else if(a0&&r.push(l),r}function gd(s,t,e,i,n){let r=e,o=e,a=0,l=0,c=e,h,u,d,f,g,_,m,y,p,E;for(u=e;us&&(l>a&&(a=l,r=c,o=u),l=0,c=u-n)),d=f,m=p,y=E),g=w,_=x}return l+=f,l>a?[c,u]:[r,o]}const ss={left:0,center:.5,right:1,top:0,middle:.5,hanging:.2,alphabetic:.8,ideographic:.8,bottom:1};class _d extends Rn{constructor(t,e,i,n){super(t,e,i,n),this.labels_=null,this.text_="",this.textOffsetX_=0,this.textOffsetY_=0,this.textRotateWithView_=void 0,this.textRotation_=0,this.textFillState_=null,this.fillStates={},this.fillStates[Lt]={fillStyle:Lt},this.textStrokeState_=null,this.strokeStates={},this.textState_={},this.textStates={},this.textKey_="",this.fillKey_="",this.strokeKey_="",this.declutterMode_=void 0,this.declutterImageWithText_=void 0}finish(){const t=super.finish();return t.textStates=this.textStates,t.fillStates=this.fillStates,t.strokeStates=this.strokeStates,t}drawText(t,e,i){const n=this.textFillState_,r=this.textStrokeState_,o=this.textState_;if(this.text_===""||!o||!n&&!r)return;const a=this.coordinates;let l=a.length;const c=t.getType();let h=null,u=t.getStride();if(o.placement==="line"&&(c=="LineString"||c=="MultiLineString"||c=="Polygon"||c=="MultiPolygon")){if(!At(this.maxExtent,t.getExtent()))return;let d;if(h=t.getFlatCoordinates(),c=="LineString")d=[h.length];else if(c=="MultiLineString")d=t.getEnds();else if(c=="Polygon")d=t.getEnds().slice(0,1);else if(c=="MultiPolygon"){const m=t.getEndss();d=[];for(let y=0,p=m.length;y{const x=a[(p+w)*2]===h[w*u]&&a[(p+w)*2+1]===h[w*u+1];return x||--p,x})}this.saveTextStates_(),(o.backgroundFill||o.backgroundStroke)&&(this.setFillStrokeStyle(o.backgroundFill,o.backgroundStroke),o.backgroundFill&&this.updateFillStyle(this.state,this.createFill),o.backgroundStroke&&(this.updateStrokeStyle(this.state,this.applyStroke),this.hitDetectionInstructions.push(this.createStroke(this.state)))),this.beginGeometry(t,e,i);let g=o.padding;if(g!=$e&&(o.scale[0]<0||o.scale[1]<0)){let p=o.padding[0],E=o.padding[1],w=o.padding[2],x=o.padding[3];o.scale[0]<0&&(E=-E,x=-x),o.scale[1]<0&&(p=-p,w=-w),g=[p,E,w,x]}const _=this.pixelRatio;this.instructions.push([M.DRAW_IMAGE,l,f,null,NaN,NaN,NaN,1,0,0,this.textRotateWithView_,this.textRotation_,[1,1],NaN,this.declutterMode_,this.declutterImageWithText_,g==$e?$e:g.map(function(p){return p*_}),!!o.backgroundFill,!!o.backgroundStroke,this.text_,this.textKey_,this.strokeKey_,this.fillKey_,this.textOffsetX_,this.textOffsetY_,d]);const m=1/_,y=this.state.fillStyle;o.backgroundFill&&(this.state.fillStyle=Lt,this.hitDetectionInstructions.push(this.createFill(this.state))),this.hitDetectionInstructions.push([M.DRAW_IMAGE,l,f,null,NaN,NaN,NaN,1,0,0,this.textRotateWithView_,this.textRotation_,[m,m],NaN,this.declutterMode_,this.declutterImageWithText_,g,!!o.backgroundFill,!!o.backgroundStroke,this.text_,this.textKey_,this.strokeKey_,this.fillKey_?Lt:this.fillKey_,this.textOffsetX_,this.textOffsetY_,d]),o.backgroundFill&&(this.state.fillStyle=y,this.hitDetectionInstructions.push(this.createFill(this.state))),this.endGeometry(e)}}saveTextStates_(){const t=this.textStrokeState_,e=this.textState_,i=this.textFillState_,n=this.strokeKey_;t&&(n in this.strokeStates||(this.strokeStates[n]={strokeStyle:t.strokeStyle,lineCap:t.lineCap,lineDashOffset:t.lineDashOffset,lineWidth:t.lineWidth,lineJoin:t.lineJoin,miterLimit:t.miterLimit,lineDash:t.lineDash}));const r=this.textKey_;r in this.textStates||(this.textStates[r]={font:e.font,textAlign:e.textAlign||fn,justify:e.justify,textBaseline:e.textBaseline||Qn,scale:e.scale});const o=this.fillKey_;i&&(o in this.fillStates||(this.fillStates[o]={fillStyle:i.fillStyle}))}drawChars_(t,e){const i=this.textStrokeState_,n=this.textState_,r=this.strokeKey_,o=this.textKey_,a=this.fillKey_;this.saveTextStates_();const l=this.pixelRatio,c=ss[n.textBaseline],h=this.textOffsetY_*l,u=this.text_,d=i?i.lineWidth*Math.abs(n.scale[0])/2:0;this.instructions.push([M.DRAW_CHARS,t,e,c,n.overflow,a,n.maxAngle,l,h,r,d*l,u,o,1,this.declutterMode_]),this.hitDetectionInstructions.push([M.DRAW_CHARS,t,e,c,n.overflow,a&&Lt,n.maxAngle,l,h,r,d*l,u,o,1/l,this.declutterMode_])}setTextStyle(t,e){let i,n,r;if(!t)this.text_="";else{const o=t.getFill();o?(n=this.textFillState_,n||(n={},this.textFillState_=n),n.fillStyle=se(o.getColor()||Lt)):(n=null,this.textFillState_=n);const a=t.getStroke();if(!a)r=null,this.textStrokeState_=r;else{r=this.textStrokeState_,r||(r={},this.textStrokeState_=r);const g=a.getLineDash(),_=a.getLineDashOffset(),m=a.getWidth(),y=a.getMiterLimit();r.lineCap=a.getLineCap()||Ai,r.lineDash=g?g.slice():ye,r.lineDashOffset=_===void 0?Ee:_,r.lineJoin=a.getLineJoin()||Pi,r.lineWidth=m===void 0?gn:m,r.miterLimit=y===void 0?un:y,r.strokeStyle=se(a.getColor()||dn)}i=this.textState_;const l=t.getFont()||Oa;Ec(l);const c=t.getScaleArray();i.overflow=t.getOverflow(),i.font=l,i.maxAngle=t.getMaxAngle(),i.placement=t.getPlacement(),i.textAlign=t.getTextAlign(),i.repeat=t.getRepeat(),i.justify=t.getJustify(),i.textBaseline=t.getTextBaseline()||Qn,i.backgroundFill=t.getBackgroundFill(),i.backgroundStroke=t.getBackgroundStroke(),i.padding=t.getPadding()||$e,i.scale=c===void 0?[1,1]:c;const h=t.getOffsetX(),u=t.getOffsetY(),d=t.getRotateWithView(),f=t.getRotation();this.text_=t.getText()||"",this.textOffsetX_=h===void 0?0:h,this.textOffsetY_=u===void 0?0:u,this.textRotateWithView_=d===void 0?!1:d,this.textRotation_=f===void 0?0:f,this.strokeKey_=r?(typeof r.strokeStyle=="string"?r.strokeStyle:Z(r.strokeStyle))+r.lineCap+r.lineDashOffset+"|"+r.lineWidth+r.lineJoin+r.miterLimit+"["+r.lineDash.join()+"]":"",this.textKey_=i.font+i.scale+(i.textAlign||"?")+(i.repeat||"?")+(i.justify||"?")+(i.textBaseline||"?"),this.fillKey_=n&&n.fillStyle?typeof n.fillStyle=="string"?n.fillStyle:"|"+Z(n.fillStyle):""}this.declutterMode_=t.getDeclutterMode(),this.declutterImageWithText_=e}}const md={Circle:Vs,Default:Rn,Image:ud,LineString:dd,Polygon:Vs,Text:_d,Ellipse:Vs};class pd{constructor(t,e,i,n){this.tolerance_=t,this.maxExtent_=e,this.pixelRatio_=n,this.resolution_=i,this.buildersByZIndex_={}}finish(){const t={};for(const e in this.buildersByZIndex_){t[e]=t[e]||{};const i=this.buildersByZIndex_[e];for(const n in i){const r=i[n].finish();t[e][n]=r}}return t}getBuilder(t,e){const i=t!==void 0?t.toString():"0";let n=this.buildersByZIndex_[i];n===void 0&&(n={},this.buildersByZIndex_[i]=n);let r=n[e];if(r===void 0){const o=md[e];r=new o(this.tolerance_,this.maxExtent_,this.resolution_,this.pixelRatio_),n[e]=r}return r}}class yd extends En{constructor(t){super(),this.ready=!0,this.boundHandleImageChange_=this.handleImageChange_.bind(this),this.layer_=t}getFeatures(t){return $()}getData(t){return null}prepareFrame(t){return $()}renderFrame(t,e){return $()}loadedTileCallback(t,e,i){t[e]||(t[e]={}),t[e][i.tileCoord.toString()]=i}createLoadedTileFinder(t,e,i){return(n,r)=>{const o=this.loadedTileCallback.bind(this,i,n);return t.forEachLoadedTile(e,n,r,o)}}forEachFeatureAtCoordinate(t,e,i,n,r){}getLayer(){return this.layer_}handleFontsChanged(){}handleImageChange_(t){const e=t.target;(e.getState()===V.LOADED||e.getState()===V.ERROR)&&this.renderIfReadyAndVisible()}loadImage(t){let e=t.getState();return e!=V.LOADED&&e!=V.ERROR&&t.addEventListener(N.CHANGE,this.boundHandleImageChange_),e==V.IDLE&&(t.load(),e=t.getState()),e==V.LOADED}renderIfReadyAndVisible(){const t=this.getLayer();t&&t.getVisible()&&t.getSourceState()==="ready"&&t.changed()}renderDeferred(t){}disposeInternal(){delete this.layer_,super.disposeInternal()}}class ol{constructor(){Br(this,"pushMethodArgs_",(...t)=>(this.instructions_[this.zIndex+this.offset_].push(t),this));this.instructions_=[],this.zIndex=0,this.offset_=0,this.context_=new Proxy(Hn(),{get:(t,e)=>{if(typeof Hn()[e]=="function")return this.instructions_[this.zIndex+this.offset_]||(this.instructions_[this.zIndex+this.offset_]=[]),this.instructions_[this.zIndex+this.offset_].push(e),this.pushMethodArgs_},set:(t,e,i)=>(this.instructions_[this.zIndex+this.offset_]||(this.instructions_[this.zIndex+this.offset_]=[]),this.instructions_[this.zIndex+this.offset_].push(e,i),!0)})}pushFunction(t){this.instructions_[this.zIndex+this.offset_].push(t)}getContext(){return this.context_}draw(t){this.instructions_.forEach(e=>{for(let i=0,n=e.length;iL[2]}else O=w>T;const P=Math.PI,G=[],D=S+i===t;t=S,m=0,y=I,d=s[t],f=s[t+1];let z;if(D){p(),z=Math.atan2(f-_,d-g),O&&(z+=z>0?-P:P);const L=(T+w)/2,q=(k+x)/2;return G[0]=[L,q,(v-r)/2,z,n],G}n=n.replace(/\n/g," ");for(let L=0,q=n.length;L0?-P:P),z!==void 0){let R=W-z;if(R+=R>P?-2*P:R<-P?2*P:0,Math.abs(R)>o)return null}z=W;const nt=L;let Y=0;for(;L0&&s.push(` -`,""),s.push(t,""),s}class vd{constructor(t,e,i,n,r){this.overlaps=i,this.pixelRatio=e,this.resolution=t,this.alignAndScaleFill_,this.instructions=n.instructions,this.coordinates=n.coordinates,this.coordinateCache_={},this.renderedTransform_=$t(),this.hitDetectionInstructions=n.hitDetectionInstructions,this.pixelCoordinates_=null,this.viewRotation_=0,this.fillStates=n.fillStates||{},this.strokeStates=n.strokeStates||{},this.textStates=n.textStates||{},this.widths_={},this.labels_={},this.zIndexContext_=r?new ol:null}getZIndexContext(){return this.zIndexContext_}createLabel(t,e,i,n){const r=t+e+i+n;if(this.labels_[r])return this.labels_[r];const o=n?this.strokeStates[n]:null,a=i?this.fillStates[i]:null,l=this.textStates[e],c=this.pixelRatio,h=[l.scale[0]*c,l.scale[1]*c],u=Array.isArray(t),d=l.justify?ss[l.justify]:Bs(Array.isArray(t)?t[0]:t,l.textAlign||fn),f=n&&o.lineWidth?o.lineWidth:0,g=u?t:t.split(` -`).reduce(Cd,[]),{width:_,height:m,widths:y,heights:p,lineWidths:E}=wc(l,g),w=_+f,x=[],S=(w+2)*h[0],I=(m+f)*h[1],v={width:S<0?Math.floor(S):Math.ceil(S),height:I<0?Math.floor(I):Math.ceil(I),contextInstructions:x};(h[0]!=1||h[1]!=1)&&x.push("scale",h),n&&(x.push("strokeStyle",o.strokeStyle),x.push("lineWidth",f),x.push("lineCap",o.lineCap),x.push("lineJoin",o.lineJoin),x.push("miterLimit",o.miterLimit),x.push("setLineDash",[o.lineDash]),x.push("lineDashOffset",o.lineDashOffset)),i&&x.push("fillStyle",a.fillStyle),x.push("textBaseline","middle"),x.push("textAlign","center");const T=.5-d;let k=d*w+T*f;const O=[],P=[];let G=0,D=0,z=0,L=0,q;for(let W=0,nt=g.length;Wt?t-c:r,w=o+h>e?e-h:o,x=g[3]+E*d[0]+g[1],S=g[0]+w*d[1]+g[2],I=y-g[3],v=p-g[0];(_||u!==0)&&(Le[0]=I,be[0]=I,Le[1]=v,ue[1]=v,ue[0]=I+x,de[0]=ue[0],de[1]=v+S,be[1]=de[1]);let T;return u!==0?(T=we($t(),i,n,1,1,u,-i,-n),_t(T,Le),_t(T,ue),_t(T,de),_t(T,be),Ne(Math.min(Le[0],ue[0],de[0],be[0]),Math.min(Le[1],ue[1],de[1],be[1]),Math.max(Le[0],ue[0],de[0],be[0]),Math.max(Le[1],ue[1],de[1],be[1]),fi)):Ne(Math.min(I,I+x),Math.min(v,v+S),Math.max(I,I+x),Math.max(v,v+S),fi),f&&(y=Math.round(y),p=Math.round(p)),{drawImageX:y,drawImageY:p,drawImageW:E,drawImageH:w,originX:c,originY:h,declutterBox:{minX:fi[0],minY:fi[1],maxX:fi[2],maxY:fi[3],value:m},canvasTransform:T,scale:d}}replayImageOrLabel_(t,e,i,n,r,o,a){const l=!!(o||a),c=n.declutterBox,h=a?a[2]*n.scale[0]/2:0;return c.minX-h<=e[0]&&c.maxX+h>=0&&c.minY-h<=e[1]&&c.maxY+h>=0&&(l&&this.replayTextBackground_(t,Le,ue,de,be,o,a),Cc(t,n.canvasTransform,r,i,n.originX,n.originY,n.drawImageW,n.drawImageH,n.drawImageX,n.drawImageY,n.scale)),!0}fill_(t){const e=this.alignAndScaleFill_;if(e){const i=_t(this.renderedTransform_,[0,0]),n=512*this.pixelRatio;t.save(),t.translate(i[0]%n,i[1]%n),e!==1&&t.scale(e,e),t.rotate(this.viewRotation_)}t.fill(),e&&t.restore()}setStrokeStyle_(t,e){t.strokeStyle=e[1],t.lineWidth=e[2],t.lineCap=e[3],t.lineJoin=e[4],t.miterLimit=e[5],t.lineDashOffset=e[7],t.setLineDash(e[6])}drawLabelWithPointPlacement_(t,e,i,n){const r=this.textStates[e],o=this.createLabel(t,e,n,i),a=this.strokeStates[i],l=this.pixelRatio,c=Bs(Array.isArray(t)?t[0]:t,r.textAlign||fn),h=ss[r.textBaseline||Qn],u=a&&a.lineWidth?a.lineWidth:0,d=o.width/l-2*r.scale[0],f=c*d+2*(.5-c)*u,g=h*o.height/l+2*(.5-h)*u;return{label:o,anchorX:f,anchorY:g}}execute_(t,e,i,n,r,o,a,l){const c=this.zIndexContext_;let h;this.pixelCoordinates_&&ze(i,this.renderedTransform_)?h=this.pixelCoordinates_:(this.pixelCoordinates_||(this.pixelCoordinates_=[]),h=ke(this.coordinates,0,this.coordinates.length,2,i,this.pixelCoordinates_),Al(this.renderedTransform_,i));let u=0;const d=n.length;let f=0,g,_,m,y,p,E,w,x,S,I,v,T,k,O=0,P=0,G=null,D=null;const z=this.coordinateCache_,L=this.viewRotation_,q=Math.round(Math.atan2(-i[1],i[0])*1e12)/1e12,W={context:t,pixelRatio:this.pixelRatio,resolution:this.resolution,rotation:L},nt=this.instructions!=n||this.overlaps?0:200;let Y,K,B,et;for(;unt&&(this.fill_(t),O=0),P>nt&&(t.stroke(),P=0),!O&&!P&&(t.beginPath(),p=NaN,E=NaN),++u;break;case M.CIRCLE:f=R[1];const pt=h[f],at=h[f+1],Ht=h[f+2],Xe=h[f+3],Tt=Ht-pt,In=Xe-at,zi=Math.sqrt(Tt*Tt+In*In);t.moveTo(pt+zi,at),t.arc(pt,at,zi,0,2*Math.PI,!0),++u;break;case M.ELLIPSE:f=R[1],g=R[2];const Ye=h[f],Gt=h[f+1],Ve=h[f+2],Be=h[f+3],si=h[f+4],Ze=h[f+5],ri=h[f+6],Mt=h[f+7];if(g-f===8){const ft=(si-Ye)*.2761424,zt=(Ze-Gt)*.2761424,gt=(ri-Ve)*.2761424,It=(Mt-Be)*.2761424;t.moveTo(Ye,Gt),t.bezierCurveTo(Ye-gt,Gt-It,Ve-ft,Be-zt,Ve,Be),t.bezierCurveTo(Ve+ft,Be+zt,si-gt,Ze-It,si,Ze),t.bezierCurveTo(si+gt,Ze+It,ri+ft,Mt+zt,ri,Mt),t.bezierCurveTo(ri-ft,Mt-zt,Ye+gt,Gt+It,Ye,Gt)}++u;break;case M.CLOSE_PATH:t.closePath(),++u;break;case M.CUSTOM:f=R[1],g=R[2];const qt=R[3],Ke=R[4],Te=R[5];W.geometry=qt,W.feature=Y,u in z||(z[u]=[]);const Re=z[u];Te?Te(h,f,g,2,Re):(Re[0]=h[f],Re[1]=h[f+1],Re.length=2),c&&(c.zIndex=R[6]),Ke(Re,W),++u;break;case M.DRAW_IMAGE:f=R[1],g=R[2],S=R[3],_=R[4],m=R[5];let oi=R[6];const Wi=R[7],ai=R[8],xs=R[9],Rt=R[10];let ws=R[11];const fl=R[12];let Sn=R[13];y=R[14]||"declutter";const Xi=R[15];if(!S&&R.length>=20){I=R[19],v=R[20],T=R[21],k=R[22];const ft=this.drawLabelWithPointPlacement_(I,v,T,k);S=ft.label,R[3]=S;const zt=R[23];_=(ft.anchorX-zt)*this.pixelRatio,R[4]=_;const gt=R[24];m=(ft.anchorY-gt)*this.pixelRatio,R[5]=m,oi=S.height,R[6]=oi,Sn=S.width,R[13]=Sn}let Cs;R.length>25&&(Cs=R[25]);let vs,Ln,bn;R.length>17?(vs=R[16],Ln=R[17],bn=R[18]):(vs=$e,Ln=!1,bn=!1),Rt&&q?ws+=L:!Rt&&!q&&(ws-=L);let gl=0;for(;f!ll.includes(s));class Rd{constructor(t,e,i,n,r,o,a){this.maxExtent_=t,this.overlaps_=n,this.pixelRatio_=i,this.resolution_=e,this.renderBuffer_=o,this.executorsByZIndex_={},this.hitDetectionContext_=null,this.hitDetectionTransform_=$t(),this.renderedContext_=null,this.deferredZIndexContexts_={},this.createExecutors_(r,a)}clip(t,e){const i=this.getClipCoords(e);t.beginPath(),t.moveTo(i[0],i[1]),t.lineTo(i[2],i[3]),t.lineTo(i[4],i[5]),t.lineTo(i[6],i[7]),t.clip()}createExecutors_(t,e){for(const i in t){let n=this.executorsByZIndex_[i];n===void 0&&(n={},this.executorsByZIndex_[i]=n);const r=t[i];for(const o in r){const a=r[o];n[o]=new vd(this.resolution_,this.pixelRatio_,this.overlaps_,a,e)}}}hasExecutors(t){for(const e in this.executorsByZIndex_){const i=this.executorsByZIndex_[e];for(let n=0,r=t.length;n0){if(!o||I==="none"||f!=="Image"&&f!=="Text"||o.includes(x)){const O=(d[T]-3)/4,P=n-O%a,G=n-(O/a|0),D=r(x,S,P*P+G*G);if(D)return D}h.clearRect(0,0,a,a);break}}const _=Object.keys(this.executorsByZIndex_).map(Number);_.sort(pe);let m,y,p,E,w;for(m=_.length-1;m>=0;--m){const x=_[m].toString();for(p=this.executorsByZIndex_[x],y=wi.length-1;y>=0;--y)if(f=wi[y],E=p[f],E!==void 0&&(w=E.executeHitDetection(h,l,i,g,u),w))return w}}getClipCoords(t){const e=this.maxExtent_;if(!e)return null;const i=e[0],n=e[1],r=e[2],o=e[3],a=[i,n,i,o,r,o,r,n];return ke(a,0,8,2,t,a),a}isEmpty(){return Si(this.executorsByZIndex_)}execute(t,e,i,n,r,o,a){const l=Object.keys(this.executorsByZIndex_).map(Number);l.sort(pe),o=o||wi;const c=wi.length;let h,u,d,f,g;for(a&&l.reverse(),h=0,u=l.length;hy.execute(x,e,i,n,r,a)),w&&E.restore(),p){p.offset();const x=l[h]*c+d;this.deferredZIndexContexts_[x]||(this.deferredZIndexContexts_[x]=[]),this.deferredZIndexContexts_[x].push(p)}}}}this.renderedContext_=t}getDeferredZIndexContexts(){return this.deferredZIndexContexts_}getRenderedContext(){return this.renderedContext_}renderDeferred(){const t=this.deferredZIndexContexts_,e=Object.keys(t).map(Number).sort(pe);for(let i=0,n=e.length;i{r.draw(this.renderedContext_),r.clear()}),t[e[i]].length=0}}const Zs={};function Id(s){if(Zs[s]!==void 0)return Zs[s];const t=s*2+1,e=s*s,i=new Array(e+1);for(let r=0;r<=s;++r)for(let o=0;o<=s;++o){const a=r*r+o*o;if(a>e)break;let l=i[a];l||(l=[],i[a]=l),l.push(((s+r)*t+(s+o))*4+3),r>0&&l.push(((s-r)*t+(s+o))*4+3),o>0&&(l.push(((s+r)*t+(s-o))*4+3),r>0&&l.push(((s-r)*t+(s-o))*4+3))}const n=[];for(let r=0,o=i.length;ru*this.pixelRatio_),lineDashOffset:(o||Ee)*this.pixelRatio_,lineJoin:a!==void 0?a:Pi,lineWidth:(l!==void 0?l:gn)*this.pixelRatio_,miterLimit:c!==void 0?c:un,strokeStyle:se(i||dn)}}}setImageStyle(t){let e;if(!t||!(e=t.getSize())){this.image_=null;return}const i=t.getPixelRatio(this.pixelRatio_),n=t.getAnchor(),r=t.getOrigin();this.image_=t.getImage(this.pixelRatio_),this.imageAnchorX_=n[0]*i,this.imageAnchorY_=n[1]*i,this.imageHeight_=e[1]*i,this.imageOpacity_=t.getOpacity(),this.imageOriginX_=r[0],this.imageOriginY_=r[1],this.imageRotateWithView_=t.getRotateWithView(),this.imageRotation_=t.getRotation();const o=t.getScaleArray();this.imageScale_=[o[0]*this.pixelRatio_/i,o[1]*this.pixelRatio_/i],this.imageWidth_=e[0]*i}setTextStyle(t){if(!t)this.text_="";else{const e=t.getFill();if(!e)this.textFillState_=null;else{const f=e.getColor();this.textFillState_={fillStyle:se(f||Lt)}}const i=t.getStroke();if(!i)this.textStrokeState_=null;else{const f=i.getColor(),g=i.getLineCap(),_=i.getLineDash(),m=i.getLineDashOffset(),y=i.getLineJoin(),p=i.getWidth(),E=i.getMiterLimit();this.textStrokeState_={lineCap:g!==void 0?g:Ai,lineDash:_||ye,lineDashOffset:m||Ee,lineJoin:y!==void 0?y:Pi,lineWidth:p!==void 0?p:gn,miterLimit:E!==void 0?E:un,strokeStyle:se(f||dn)}}const n=t.getFont(),r=t.getOffsetX(),o=t.getOffsetY(),a=t.getRotateWithView(),l=t.getRotation(),c=t.getScaleArray(),h=t.getText(),u=t.getTextAlign(),d=t.getTextBaseline();this.textState_={font:n!==void 0?n:Oa,textAlign:u!==void 0?u:fn,textBaseline:d!==void 0?d:Qn},this.text_=h!==void 0?Array.isArray(h)?h.reduce((f,g,_)=>f+=_%2?" ":g,""):h:"",this.textOffsetX_=r!==void 0?this.pixelRatio_*r:0,this.textOffsetY_=o!==void 0?this.pixelRatio_*o:0,this.textRotateWithView_=a!==void 0?a:!1,this.textRotation_=l!==void 0?l:0,this.textScale_=[this.pixelRatio_*c[0],this.pixelRatio_*c[1]]}}}const ie=.5;function Ld(s,t,e,i,n,r,o,a,l){const c=n,h=s[0]*ie,u=s[1]*ie,d=mt(h,u);d.imageSmoothingEnabled=!1;const f=d.canvas,g=new Sd(d,ie,n,null,o,a,null),_=e.length,m=Math.floor((256*256*256-1)/_),y={};for(let E=1;E<=_;++E){const w=e[E-1],x=w.getStyleFunction()||i;if(!x)continue;let S=x(w,r);if(!S)continue;Array.isArray(S)||(S=[S]);const v=(E*m).toString(16).padStart(7,"#00000");for(let T=0,k=S.length;T0;return u&&Promise.all(l).then(()=>n(null)),Od(s,t,e,i,r,o,a),u}function Od(s,t,e,i,n,r,o){const a=e.getGeometryFunction()(t);if(!a)return;const l=a.simplifyTransformed(i,n);if(e.getRenderer())ul(s,l,e,t,o);else{const h=hl[l.getType()];h(s,l,e,t,o,r)}}function ul(s,t,e,i,n){if(t.getType()=="GeometryCollection"){const o=t.getGeometries();for(let a=0,l=o.length;a{if(this.frameState&&!this.hitDetectionImageData_&&!this.animatingOrInteracting_){const i=this.frameState.size.slice(),n=this.renderedCenter_,r=this.renderedResolution_,o=this.renderedRotation_,a=this.renderedProjection_,l=this.wrappedRenderedExtent_,c=this.getLayer(),h=[],u=i[0]*ie,d=i[1]*ie;h.push(this.getRenderTransform(n,r,o,ie,u,d,0).slice());const f=c.getSource(),g=a.getExtent();if(f.getWrapX()&&a.canWrapX()&&!Oe(g,l)){let _=l[0];const m=tt(g);let y=0,p;for(;_g[2];)++y,p=m*y,h.push(this.getRenderTransform(n,r,o,ie,u,d,p).slice()),_-=m}this.hitDetectionImageData_=Ld(i,h,this.renderedFeatures_,c.getStyleFunction(),l,r,o,Fo(r,this.renderedPixelRatio_))}e(bd(t,this.renderedFeatures_,this.hitDetectionImageData_))})}forEachFeatureAtCoordinate(t,e,i,n,r){if(!this.replayGroup_)return;const o=e.viewState.resolution,a=e.viewState.rotation,l=this.getLayer(),c={},h=function(g,_,m){const y=Z(g),p=c[y];if(p){if(p!==!0&&mu=g.forEachFeatureAtCoordinate(t,o,a,i,h,f&&e.declutter[f]?e.declutter[f].all().map(_=>_.value):null)),u}handleFontsChanged(){const t=this.getLayer();t.getVisible()&&this.replayGroup_&&t.changed()}handleStyleImageChange_(t){this.renderIfReadyAndVisible()}prepareFrame(t){const e=this.getLayer(),i=e.getSource();if(!i)return!1;const n=t.viewHints[xt.ANIMATING],r=t.viewHints[xt.INTERACTING],o=e.getUpdateWhileAnimating(),a=e.getUpdateWhileInteracting();if(this.ready&&!o&&n||!a&&r)return this.animatingOrInteracting_=!0,!0;this.animatingOrInteracting_=!1;const l=t.extent,c=t.viewState,h=c.projection,u=c.resolution,d=t.pixelRatio,f=e.getRevision(),g=e.getRenderBuffer();let _=e.getRenderOrder();_===void 0&&(_=Ad);const m=c.center.slice(),y=cr(l,g*u),p=y.slice(),E=[y.slice()],w=h.getExtent();if(i.getWrapX()&&h.canWrapX()&&!Oe(w,t.extent)){const D=tt(w),z=Math.max(tt(y)/2,D);y[0]=w[0]-z,y[2]=w[2]+z,ea(m,h);const L=Jo(E[0],h);L[0]w[0]&&L[2]>w[2]&&E.push([L[0]-D,L[1],L[2]-D,L[3]])}if(this.ready&&this.renderedResolution_==u&&this.renderedRevision_==f&&this.renderedRenderOrder_==_&&this.renderedFrameDeclutter_===!!t.declutter&&Oe(this.wrappedRenderedExtent_,y))return ze(this.renderedExtent_,p)||(this.hitDetectionImageData_=null,this.renderedExtent_=p),this.renderedCenter_=m,this.replayGroupChanged=!1,!0;this.replayGroup_=null;const x=new pd(cl(u,d),y,u,d);let S;for(let D=0,z=E.length;D{let L;const q=D.getStyleFunction()||e.getStyleFunction();if(q&&(L=q(D,u)),L){const W=this.renderFeature(D,I,L,x,S,this.getLayer().getDeclutter(),z);v=v&&!W}},k=oa(y),O=i.getFeaturesInExtent(k);_&&O.sort(_);for(let D=0,z=O.length;D=0;--n){const r=e[n];if(r!==this&&r instanceof kr&&r.getStyle()&&r.getFeatures().getArray().lastIndexOf(t)!==-1){t.setStyle(r.getStyle());return}}const i=Z(t);t.setStyle(Wn[i]),delete Wn[i]}removeFeatureLayerAssociation_(t){delete this.featureLayerAssociation_[Z(t)]}handleEvent(t){if(!this.condition_(t))return!0;const e=this.addCondition_(t),i=this.removeCondition_(t),n=this.toggleCondition_(t),r=!e&&!i&&!n,o=t.map,a=this.getFeatures(),l=[],c=[];if(r){Oi(this.featureLayerAssociation_),o.forEachFeatureAtPixel(t.pixel,(h,u)=>{if(!(!(h instanceof ln)||!this.filter_(h,u)))return this.addFeatureLayerAssociation_(h,u),c.push(h),!this.multi_},{layerFilter:this.layerFilter_,hitTolerance:this.hitTolerance_});for(let h=a.getLength()-1;h>=0;--h){const u=a.item(h),d=c.indexOf(u);d>-1?c.splice(d,1):(a.remove(u),l.push(u))}c.length!==0&&a.extend(c)}else{o.forEachFeatureAtPixel(t.pixel,(h,u)=>{if(!(!(h instanceof ln)||!this.filter_(h,u)))return(e||n)&&!a.getArray().includes(h)?(this.addFeatureLayerAssociation_(h,u),c.push(h)):(i||n)&&a.getArray().includes(h)&&(l.push(h),this.removeFeatureLayerAssociation_(h)),!this.multi_},{layerFilter:this.layerFilter_,hitTolerance:this.hitTolerance_});for(let h=l.length-1;h>=0;--h)a.remove(l[h]);a.extend(c)}return(c.length>0||l.length>0)&&this.dispatchEvent(new Vd(Yd.SELECT,c,l,t)),!0}}function Bd(){const s=Rc();return sn(s.Polygon,s.LineString),sn(s.GeometryCollection,s.LineString),function(t){return t.getGeometry()?s[t.getGeometry().getType()]:null}}let Zt={colors:{blue:"#0099ff",white:"#ffffff",orange:"#ff5e00"},radius:{default:6},strokeWidth:{default:2}};Zt.default=new Nt({image:new ii({radius:Zt.radius.default,fill:new Ce({color:Zt.colors.blue}),stroke:new xe({color:Zt.colors.white,width:Zt.strokeWidth.default})})});Zt.selected=new Nt({image:new ii({radius:Zt.radius.default,fill:new Ce({color:Zt.colors.orange}),stroke:new xe({color:Zt.colors.white,width:Zt.strokeWidth.default})}),zIndex:1/0});const Xn={PRELOAD:"preload",USE_INTERIM_TILES_ON_ERROR:"useInterimTilesOnError"};class Zd extends us{constructor(t){t=t||{};const e=Object.assign({},t);delete e.preload,delete e.useInterimTilesOnError,super(e),this.on,this.once,this.un,this.setPreload(t.preload!==void 0?t.preload:0),this.setUseInterimTilesOnError(t.useInterimTilesOnError!==void 0?t.useInterimTilesOnError:!0)}getPreload(){return this.get(Xn.PRELOAD)}setPreload(t){this.set(Xn.PRELOAD,t)}getUseInterimTilesOnError(){return this.get(Xn.USE_INTERIM_TILES_ON_ERROR)}setUseInterimTilesOnError(t){this.set(Xn.USE_INTERIM_TILES_ON_ERROR,t)}getData(t){return super.getData(t)}}class Kd extends al{constructor(t){super(t),this.extentChanged=!0,this.renderedExtent_=null,this.renderedPixelRatio,this.renderedProjection=null,this.renderedRevision,this.renderedTiles=[],this.newTiles_=!1,this.tmpExtent=Ut(),this.tmpTileRange_=new Or(0,0,0,0)}isDrawableTile(t){const e=this.getLayer(),i=t.getState(),n=e.getUseInterimTilesOnError();return i==A.LOADED||i==A.EMPTY||i==A.ERROR&&!n}getTile(t,e,i,n){const r=n.pixelRatio,o=n.viewState.projection,a=this.getLayer();let c=a.getSource().getTile(t,e,i,r,o);return c.getState()==A.ERROR&&a.getUseInterimTilesOnError()&&a.getPreload()>0&&(this.newTiles_=!0),this.isDrawableTile(c)||(c=c.getInterimTile()),c}getData(t){const e=this.frameState;if(!e)return null;const i=this.getLayer(),n=_t(e.pixelToCoordinateTransform,t.slice()),r=i.getExtent();if(r&&!Li(r,n))return null;const o=e.pixelRatio,a=e.viewState.projection,l=e.viewState,c=i.getRenderSource(),h=c.getTileGridForProjection(l.projection),u=c.getTilePixelRatio(e.pixelRatio);for(let d=h.getZForResolution(l.resolution);d>=h.getMinZoom();--d){const f=h.getTileCoordForCoordAndZ(n,d),g=c.getTile(d,f[1],f[2],o,a);if(!(g instanceof Ja||g instanceof rr)||g instanceof rr&&g.getState()===A.EMPTY)return null;if(g.getState()!==A.LOADED)continue;const _=h.getOrigin(d),m=kt(h.getTileSize(d)),y=h.getResolution(d),p=Math.floor(u*((n[0]-_[0])/y-f[1]*m[0])),E=Math.floor(u*((_[1]-n[1])/y-f[2]*m[1])),w=Math.round(u*c.getGutterForProjection(l.projection));return this.getImageData(g.getImage(),p+w,E+w)}return null}loadedTileCallback(t,e,i){return this.isDrawableTile(i)?super.loadedTileCallback(t,e,i):!1}prepareFrame(t){return!!this.getLayer().getSource()}renderFrame(t,e){const i=t.layerStatesArray[t.layerIndex],n=t.viewState,r=n.projection,o=n.resolution,a=n.center,l=n.rotation,c=t.pixelRatio,h=this.getLayer(),u=h.getSource(),d=u.getRevision(),f=u.getTileGridForProjection(r),g=f.getZForResolution(o,u.zDirection),_=f.getResolution(g);let m=t.extent;const y=t.viewState.resolution,p=u.getTilePixelRatio(c);this.prepareContainer(t,e);const E=this.context.canvas.width,w=this.context.canvas.height,x=i.extent&&De(i.extent);x&&(m=en(m,De(i.extent)));const S=_*E/2/p,I=_*w/2/p,v=[a[0]-S,a[1]-I,a[0]+S,a[1]+I],T=f.getTileRangeForExtentAndZ(m,g),k={};k[g]={};const O=this.createLoadedTileFinder(u,r,k),P=this.tmpExtent,G=this.tmpTileRange_;this.newTiles_=!1;const D=l?Hs(n.center,y,l,t.size):void 0;for(let K=T.minX;K<=T.maxX;++K)for(let B=T.minY;B<=T.maxY;++B){if(l&&!f.tileCoordIntersectsViewport([g,K,B],D))continue;const et=this.getTile(g,K,B,t);if(this.isDrawableTile(et)){const pt=Z(this);if(et.getState()==A.LOADED){k[g][et.tileCoord.toString()]=et;let at=et.inTransition(pt);at&&i.opacity!==1&&(et.endTransition(pt),at=!1),!this.newTiles_&&(at||!this.renderedTiles.includes(et))&&(this.newTiles_=!0)}if(et.getAlpha(pt,t.time)===1)continue}const R=f.getTileCoordChildTileRange(et.tileCoord,G,P);let vt=!1;R&&(vt=O(g+1,R)),vt||f.forEachTileCoordParentTileRange(et.tileCoord,O,G,P)}const z=_/o*c/p,L=this.getRenderContext(t);we(this.tempTransform,E/2,w/2,z,z,0,-E/2,-w/2),x&&this.clipUnrotated(L,t,x),u.getInterpolate()||(L.imageSmoothingEnabled=!1),this.preRender(L,t),this.renderedTiles.length=0;let q=Object.keys(k).map(Number);q.sort(pe);let W,nt,Y;i.opacity===1&&(!this.containerReused||u.getOpaque(t.viewState.projection))?q=q.reverse():(W=[],nt=[]);for(let K=q.length-1;K>=0;--K){const B=q[K],et=u.getTilePixelSize(B,c,r),vt=f.getResolution(B)/_,pt=et[0]*vt*z,at=et[1]*vt*z,Ht=f.getTileCoordForCoordAndZ(We(v),B),Xe=f.getTileCoordExtent(Ht),Tt=_t(this.tempTransform,[p*(Xe[0]-v[0])/_,p*(v[3]-Xe[3])/_]),In=p*u.getGutterForProjection(r),zi=k[B];for(const Ye in zi){const Gt=zi[Ye],Ve=Gt.tileCoord,Be=Ht[1]-Ve[1],si=Math.round(Tt[0]-(Be-1)*pt),Ze=Ht[2]-Ve[2],ri=Math.round(Tt[1]-(Ze-1)*at),Mt=Math.round(Tt[0]-Be*pt),qt=Math.round(Tt[1]-Ze*at),Ke=si-Mt,Te=ri-qt,Re=g===B,oi=Re&&Gt.getAlpha(Z(this),t.time)!==1;let Wi=!1;if(!oi)if(W){Y=[Mt,qt,Mt+Ke,qt,Mt+Ke,qt+Te,Mt,qt+Te];for(let ai=0,xs=W.length;ai1?o:2,r=r||new Array(o);for(let h=0;h{if(t===this.squaredTolerance_)return this.simplifiedGeometry_;this.simplifiedGeometry_=this.clone(),e&&this.simplifiedGeometry_.applyTransform(e);const i=this.simplifiedGeometry_.getFlatCoordinates();let n;switch(this.type_){case"LineString":i.length=yr(i,0,this.simplifiedGeometry_.flatCoordinates_.length,this.simplifiedGeometry_.stride_,t,i,0),n=[i.length];break;case"MultiLineString":n=[],i.length=_h(i,0,this.simplifiedGeometry_.ends_,this.simplifiedGeometry_.stride_,t,i,0,n);break;case"Polygon":n=[],i.length=ua(i,0,this.simplifiedGeometry_.ends_,this.simplifiedGeometry_.stride_,Math.sqrt(t),i,0,n);break}return n&&(this.simplifiedGeometry_=new Yt(this.type_,i,n,2,this.properties_,this.id_)),this.squaredTolerance_=t,this.simplifiedGeometry_}),this}}Yt.prototype.getFlatCoordinates=Yt.prototype.getOrientedFlatCoordinates;const Xt={ADDFEATURE:"addfeature",CHANGEFEATURE:"changefeature",CLEAR:"clear",REMOVEFEATURE:"removefeature",FEATURESLOADSTART:"featuresloadstart",FEATURESLOADEND:"featuresloadend",FEATURESLOADERROR:"featuresloaderror"};function jd(s,t){return[[-1/0,-1/0,1/0,1/0]]}let Hd=!1;function qd(s,t,e,i,n,r,o){const a=new XMLHttpRequest;a.open("GET",typeof s=="function"?s(e,i,n):s,!0),t.getType()=="arraybuffer"&&(a.responseType="arraybuffer"),a.withCredentials=Hd,a.onload=function(l){if(!a.status||a.status>=200&&a.status<300){const c=t.getType();try{let h;c=="text"||c=="json"?h=a.responseText:c=="xml"?h=a.responseXML||a.responseText:c=="arraybuffer"&&(h=a.response),h?r(t.readFeatures(h,{extent:e,featureProjection:n}),t.readProjection(h)):o()}catch{o()}}else o()},a.onerror=o,a.send()}function Yo(s,t){return function(e,i,n,r,o){const a=this;qd(s,t,e,i,n,function(l,c){a.addFeatures(l),r!==void 0&&r(l)},o||Ii)}}class Me extends ae{constructor(t,e,i){super(t),this.feature=e,this.features=i}}class $d extends el{constructor(t){t=t||{},super({attributions:t.attributions,interpolate:!0,projection:void 0,state:"ready",wrapX:t.wrapX!==void 0?t.wrapX:!0}),this.on,this.once,this.un,this.loader_=Ii,this.format_=t.format,this.overlaps_=t.overlaps===void 0?!0:t.overlaps,this.url_=t.url,t.loader!==void 0?this.loader_=t.loader:this.url_!==void 0&&(H(this.format_,"`format` must be set when `url` is set"),this.loader_=Yo(this.url_,this.format_)),this.strategy_=t.strategy!==void 0?t.strategy:jd;const e=t.useSpatialIndex!==void 0?t.useSpatialIndex:!0;this.featuresRtree_=e?new zo:null,this.loadedExtentsRtree_=new zo,this.loadingExtentsCount_=0,this.nullGeometryFeatures_={},this.idIndex_={},this.uidIndex_={},this.featureChangeKeys_={},this.featuresCollection_=null;let i,n;Array.isArray(t.features)?n=t.features:t.features&&(i=t.features,n=i.getArray()),!e&&i===void 0&&(i=new Ft(n)),n!==void 0&&this.addFeaturesInternal(n),i!==void 0&&this.bindFeaturesCollection_(i)}addFeature(t){this.addFeatureInternal(t),this.changed()}addFeatureInternal(t){const e=Z(t);if(!this.addToIndex_(e,t)){this.featuresCollection_&&this.featuresCollection_.remove(t);return}this.setupChangeEvents_(e,t);const i=t.getGeometry();if(i){const n=i.getExtent();this.featuresRtree_&&this.featuresRtree_.insert(n,t)}else this.nullGeometryFeatures_[e]=t;this.dispatchEvent(new Me(Xt.ADDFEATURE,t))}setupChangeEvents_(t,e){e instanceof Yt||(this.featureChangeKeys_[t]=[U(e,N.CHANGE,this.handleFeatureChange_,this),U(e,Je.PROPERTYCHANGE,this.handleFeatureChange_,this)])}addToIndex_(t,e){let i=!0;if(e.getId()!==void 0){const n=String(e.getId());if(!(n in this.idIndex_))this.idIndex_[n]=e;else if(e instanceof Yt){const r=this.idIndex_[n];r instanceof Yt?Array.isArray(r)?r.push(e):this.idIndex_[n]=[r,e]:i=!1}else i=!1}return i&&(H(!(t in this.uidIndex_),"The passed `feature` was already added to the source"),this.uidIndex_[t]=e),i}addFeatures(t){this.addFeaturesInternal(t),this.changed()}addFeaturesInternal(t){const e=[],i=[],n=[];for(let r=0,o=t.length;r{e||(e=!0,this.addFeature(i.element),e=!1)}),t.addEventListener(dt.REMOVE,i=>{e||(e=!0,this.removeFeature(i.element),e=!1)}),this.featuresCollection_=t}clear(t){if(t){for(const i in this.featureChangeKeys_)this.featureChangeKeys_[i].forEach(it);this.featuresCollection_||(this.featureChangeKeys_={},this.idIndex_={},this.uidIndex_={})}else if(this.featuresRtree_){const i=n=>{this.removeFeatureInternal(n)};this.featuresRtree_.forEach(i);for(const n in this.nullGeometryFeatures_)this.removeFeatureInternal(this.nullGeometryFeatures_[n])}this.featuresCollection_&&this.featuresCollection_.clear(),this.featuresRtree_&&this.featuresRtree_.clear(),this.nullGeometryFeatures_={};const e=new Me(Xt.CLEAR);this.dispatchEvent(e),this.changed()}forEachFeature(t){if(this.featuresRtree_)return this.featuresRtree_.forEach(t);this.featuresCollection_&&this.featuresCollection_.forEach(t)}forEachFeatureAtCoordinateDirect(t,e){const i=[t[0],t[1],t[0],t[1]];return this.forEachFeatureInExtent(i,function(n){const r=n.getGeometry();if(r instanceof Yt||r.intersectsCoordinate(t))return e(n)})}forEachFeatureInExtent(t,e){if(this.featuresRtree_)return this.featuresRtree_.forEachInExtent(t,e);this.featuresCollection_&&this.featuresCollection_.forEach(e)}forEachFeatureIntersectingExtent(t,e){return this.forEachFeatureInExtent(t,function(i){const n=i.getGeometry();if(n instanceof Yt||n.intersectsExtent(t)){const r=e(i);if(r)return r}})}getFeaturesCollection(){return this.featuresCollection_}getFeatures(){let t;return this.featuresCollection_?t=this.featuresCollection_.getArray().slice(0):this.featuresRtree_&&(t=this.featuresRtree_.getAll(),Si(this.nullGeometryFeatures_)||sn(t,Object.values(this.nullGeometryFeatures_))),t}getFeaturesAtCoordinate(t){const e=[];return this.forEachFeatureAtCoordinateDirect(t,function(i){e.push(i)}),e}getFeaturesInExtent(t,e){if(this.featuresRtree_){if(!(e&&e.canWrapX()&&this.getWrapX()))return this.featuresRtree_.getInExtent(t);const n=Qo(t,e);return[].concat(...n.map(r=>this.featuresRtree_.getInExtent(r)))}return this.featuresCollection_?this.featuresCollection_.getArray().slice(0):[]}getClosestFeatureToCoordinate(t,e){const i=t[0],n=t[1];let r=null;const o=[NaN,NaN];let a=1/0;const l=[-1/0,-1/0,1/0,1/0];return e=e||Qe,this.featuresRtree_.forEachInExtent(l,function(c){if(e(c)){const h=c.getGeometry(),u=a;if(a=h instanceof Yt?0:h.closestPointXY(i,n,o,a),a{--this.loadingExtentsCount_,this.dispatchEvent(new Me(Xt.FEATURESLOADEND,void 0,h))},()=>{--this.loadingExtentsCount_,this.dispatchEvent(new Me(Xt.FEATURESLOADERROR))}),n.insert(l,{extent:l.slice()}))}this.loading=this.loader_.length<4?!1:this.loadingExtentsCount_>0}refresh(){this.clear(!0),this.loadedExtentsRtree_.clear(),super.refresh()}removeLoadedExtent(t){const e=this.loadedExtentsRtree_;let i;e.forEachInExtent(t,function(n){if(bi(n.extent,t))return i=n,!0}),i&&e.remove(i)}removeFeatures(t){const e=[];for(let i=0,n=t.length;i0&&this.changed()}removeFeature(t){if(!t)return;this.removeFeatureInternal(t)&&this.changed()}removeFeatureInternal(t){const e=Z(t);if(!(e in this.uidIndex_))return;e in this.nullGeometryFeatures_?delete this.nullGeometryFeatures_[e]:this.featuresRtree_&&this.featuresRtree_.remove(t);const i=this.featureChangeKeys_[e];i==null||i.forEach(it),delete this.featureChangeKeys_[e];const n=t.getId();if(n!==void 0){const r=n.toString(),o=this.idIndex_[r];o===t?delete this.idIndex_[r]:Array.isArray(o)&&(o.splice(o.indexOf(t),1),o.length===1&&(this.idIndex_[r]=o[0]))}return delete this.uidIndex_[e],this.hasListener(Xt.REMOVEFEATURE)&&this.dispatchEvent(new Me(Xt.REMOVEFEATURE,t)),t}removeFromIdIndex_(t){let e=!1;for(const i in this.idIndex_){const n=this.idIndex_[i];if(t instanceof Yt&&Array.isArray(n)&&n.includes(t))n.splice(n.indexOf(t),1);else if(this.idIndex_[i]===t){delete this.idIndex_[i],e=!0;break}}return e}setLoader(t){this.loader_=t}setUrl(t){H(this.format_,"`format` must be set when `url` is set"),this.url_=t,this.setLoader(Yo(t,this.format_))}}class Jd extends Gi{constructor(t){t=t||{},super({element:document.createElement("div"),target:t.target}),this.extent=t.extent?t.extent:null;const e=t.className!==void 0?t.className:"ol-zoom-extent",i=t.label!==void 0?t.label:"E",n=t.tipLabel!==void 0?t.tipLabel:"Fit to extent",r=document.createElement("button");r.setAttribute("type","button"),r.title=n,r.appendChild(typeof i=="string"?document.createTextNode(i):i),r.addEventListener(N.CLICK,this.handleClick_.bind(this),!1);const o=e+" "+ei+" "+vn,a=this.element;a.className=o,a.appendChild(r)}handleClick_(t){t.preventDefault(),this.handleZoomToExtent()}handleZoomToExtent(){const e=this.getMap().getView(),i=this.extent?De(this.extent,e.getProjection()):e.getProjection().getExtent();e.fitInternal(jn(i))}}let Qd=biigle.$require("events"),lf=biigle.$require("handleErrorResponse"),hf=biigle.$require("labelTrees.components.labelTrees"),cf=biigle.$require("resource"),uf=biigle.$require("core.components.sidebar"),df=biigle.$require("core.components.sidebarTab");const tf=(s,t)=>{const e=s.__vccOpts||s;for(const[i,n]of t)e[i]=n;return e},ef={emits:["select"],props:{images:{type:Array,required:!0},preselected:{type:Array,default(){return[]}},interactive:{type:Boolean,default:!0},zoom:{type:Number},selectable:{type:Boolean,default:!1}},data(){return{}},computed:{imagesWithGps(){return this.images.filter(function(s){return s.lat!==null&&s.lng!==null})},features(){let s={};return this.preselected.forEach(function(t){s[t]=null}),this.imagesWithGps.map(function(t){return new ln({id:t.id,preselected:s.hasOwnProperty(t.id),geometry:new cs(sh([t.lng,t.lat]))})})}},methods:{parseSelectedFeatures(s){return s.getArray().map(t=>t.get("id"))}},watch:{features(s){this.source.clear(),this.source.addFeatures(s)}},created(){this.source=new $d},mounted(){this.source.addFeatures(this.features);let s=this.source.getExtent(),t=new Go({source:new od}),e=new dl({source:this.source,style:Zt.default,updateWhileAnimating:!0,updateWhileInteracting:!0}),i=new qa({target:this.$el,layers:[t,e],view:new Bt({padding:[10,10,10,10]}),interactions:Ua({altShiftDragRotate:!1,doubleClickZoom:this.interactive,keyboard:this.interactive,mouseWheelZoom:this.interactive,shiftDragZoom:!1,dragPan:this.interactive,pinchRotate:!1,pinchZoom:this.interactive}),controls:Ka({zoom:this.interactive})});if(i.getView().fit(s,{padding:[10,10,10,10]}),this.zoom&&i.getView().setZoom(this.zoom),this.interactive&&(i.addControl(new cd),i.addControl(new Jd({extent:s,label:""})),i.addControl(new ld({collapsed:!1,collapsible:!1,layers:[new Go({source:t.getSource()})],view:new Bt({zoom:1,maxZoom:1})}))),this.selectable){let n=new kr({style:Zt.selected});n.getFeatures().extend(this.features.filter(a=>a.get("preselected")));let r=n.getFeatures();i.addInteraction(n),n.on("select",()=>{this.$emit("select",this.parseSelectedFeatures(r))});let o=new Ra({condition:Oh});i.addInteraction(o),o.on("boxend",()=>{r.clear(),this.source.forEachFeatureIntersectingExtent(o.getGeometry().getExtent(),function(a){r.push(a)}),this.$emit("select",this.parseSelectedFeatures(r))})}Qd.on("sidebar.toggle",function(){i.updateSize()}),this.$nextTick(function(){i.updateSize()})}},nf={class:"image-map"};function sf(s,t,e,i,n,r){return wl(),xl("div",nf)}const ff=tf(ef,[["render",sf]]);export{Qd as E,ff as I,hf as L,cf as R,df as S,tf as _,uf as a,lf as h}; diff --git a/src/public/assets/main-DZ-6XyOZ.js b/src/public/assets/main-BAAD5r19.js similarity index 97% rename from src/public/assets/main-DZ-6XyOZ.js rename to src/public/assets/main-BAAD5r19.js index ac0d6460..1464e917 100644 --- a/src/public/assets/main-DZ-6XyOZ.js +++ b/src/public/assets/main-BAAD5r19.js @@ -1 +1 @@ -import{I as l,E as t,R as d,L as n,S as o,a as g,h as m}from"./imageMap-zpCzvVRf.js";import"vue";const h={data(){return{images:[]}},components:{imageMap:l},created(){let e=biigle.$require("geo.image");this.images=[e]}},c={data(){return{number:0,loading:!1}},created(){this.number=biigle.$require("geo.images").length,t.on("loading.start",()=>{this.loading=!0}),t.on("loading.stop",()=>{this.loading=!1}),t.on("imageMap.update",e=>this.number=e)}},u=d("api/v1/projects{/pid}/images/filter/annotation-label{/lid}"),r={components:{imageMap:l,sidebar:g,sidebarTab:o,labelTrees:n},data:function(){return{selectedLabels:[],filteredImageCache:{},allImages:[],labelTrees:[]}},computed:{filteredImages(){let e=[];if(this.selectedLabels.length>0){let i=this.filteredImageCache[this.selectedLabels[0]];Array.prototype.push.apply(e,i);for(let s=this.selectedLabels.length-1;s>=0;s--){i=this.filteredImageCache[this.selectedLabels[s]];for(let a=i.length-1;a>=0;a--)e.indexOf(i[a])===-1&&e.push(i[a])}}return e},images(){return this.selectedLabels.length>0?this.allImages.filter(e=>this.filteredImages.indexOf(e.id)!==-1):this.allImages},imageCount(){return this.images.length}},methods:{addSelectedLabel(e){this.selectedLabels.indexOf(e.id)===-1&&this.selectedLabels.push(e.id)},handleSelectedLabel(e){this.filteredImageCache.hasOwnProperty(e.id)?this.addSelectedLabel(e):(t.emit("loading.start"),this.getImageFilterApi(e.id).then(i=>{this.filteredImageCache[e.id]=i.data,this.addSelectedLabel(e)},i=>{this.handleDeselectedLabel(e),m(i)}).finally(function(){t.emit("loading.stop")}))},handleDeselectedLabel(e){let i=this.selectedLabels.indexOf(e.id);i!==-1&&this.selectedLabels.splice(i,1)},handleClearedLabels(){this.selectedLabels.splice(0)},handleSidebarToggle(){this.$nextTick(function(){t.emit("sidebar.toggle")})}},watch:{imageCount(e){t.emit("imageMap.update",e)}},created(){this.allImages=biigle.$require("geo.images"),this.labelTrees=biigle.$require("geo.labelTrees")}},p={extends:r,data(){return{projectId:null}},methods:{getImageFilterApi(e){return u.get({pid:this.projectId,lid:e},{})}},created(){this.projectId=biigle.$require("geo.project.id")}},b=d("api/v1/volumes{/vid}/files/filter/annotation-label{/lid}"),f={extends:r,data(){return{volumeId:null}},methods:{getImageFilterApi(e){return b.get({vid:this.volumeId,lid:e},{})}},created(){this.volumeId=biigle.$require("geo.volume.id")}};biigle.$mount("volume-geo-map",f);biigle.$mount("project-geo-map",p);biigle.$mount("geo-image-location-panel",h);biigle.$mount("geo-navbar",c); +import{I as l,E as t,R as d,L as n,S as o,a as g,h as m}from"./imageMap-mzZ_8F5g.js";import"vue";const h={data(){return{images:[]}},components:{imageMap:l},created(){let e=biigle.$require("geo.image");this.images=[e]}},c={data(){return{number:0,loading:!1}},created(){this.number=biigle.$require("geo.images").length,t.on("loading.start",()=>{this.loading=!0}),t.on("loading.stop",()=>{this.loading=!1}),t.on("imageMap.update",e=>this.number=e)}},u=d("api/v1/projects{/pid}/images/filter/annotation-label{/lid}"),r={components:{imageMap:l,sidebar:g,sidebarTab:o,labelTrees:n},data:function(){return{selectedLabels:[],filteredImageCache:{},allImages:[],labelTrees:[]}},computed:{filteredImages(){let e=[];if(this.selectedLabels.length>0){let i=this.filteredImageCache[this.selectedLabels[0]];Array.prototype.push.apply(e,i);for(let s=this.selectedLabels.length-1;s>=0;s--){i=this.filteredImageCache[this.selectedLabels[s]];for(let a=i.length-1;a>=0;a--)e.indexOf(i[a])===-1&&e.push(i[a])}}return e},images(){return this.selectedLabels.length>0?this.allImages.filter(e=>this.filteredImages.indexOf(e.id)!==-1):this.allImages},imageCount(){return this.images.length}},methods:{addSelectedLabel(e){this.selectedLabels.indexOf(e.id)===-1&&this.selectedLabels.push(e.id)},handleSelectedLabel(e){this.filteredImageCache.hasOwnProperty(e.id)?this.addSelectedLabel(e):(t.emit("loading.start"),this.getImageFilterApi(e.id).then(i=>{this.filteredImageCache[e.id]=i.data,this.addSelectedLabel(e)},i=>{this.handleDeselectedLabel(e),m(i)}).finally(function(){t.emit("loading.stop")}))},handleDeselectedLabel(e){let i=this.selectedLabels.indexOf(e.id);i!==-1&&this.selectedLabels.splice(i,1)},handleClearedLabels(){this.selectedLabels.splice(0)},handleSidebarToggle(){this.$nextTick(function(){t.emit("sidebar.toggle")})}},watch:{imageCount(e){t.emit("imageMap.update",e)}},created(){this.allImages=biigle.$require("geo.images"),this.labelTrees=biigle.$require("geo.labelTrees")}},p={extends:r,data(){return{projectId:null}},methods:{getImageFilterApi(e){return u.get({pid:this.projectId,lid:e},{})}},created(){this.projectId=biigle.$require("geo.project.id")}},b=d("api/v1/volumes{/vid}/files/filter/annotation-label{/lid}"),f={extends:r,data(){return{volumeId:null}},methods:{getImageFilterApi(e){return b.get({vid:this.volumeId,lid:e},{})}},created(){this.volumeId=biigle.$require("geo.volume.id")}};biigle.$mount("volume-geo-map",f);biigle.$mount("project-geo-map",p);biigle.$mount("geo-image-location-panel",h);biigle.$mount("geo-navbar",c); diff --git a/src/public/assets/main-BiON8o25.css b/src/public/assets/main-BiON8o25.css deleted file mode 100644 index ddb95e87..00000000 --- a/src/public/assets/main-BiON8o25.css +++ /dev/null @@ -1 +0,0 @@ -.image-map[data-v-dc3e2d09]{height:450px}p[data-v-dc3e2d09]{padding-top:10px}.filter-select[data-v-66e670c7]{display:block;margin-top:-15px}.filter-select>.position[data-v-66e670c7]{position:relative;margin-top:15px} diff --git a/src/public/assets/main-xdd0Il5X.js b/src/public/assets/main-xdd0Il5X.js deleted file mode 100644 index 8b32841e..00000000 --- a/src/public/assets/main-xdd0Il5X.js +++ /dev/null @@ -1,2 +0,0 @@ -import{_ as b,I as v}from"./imageMap-zpCzvVRf.js";import{resolveComponent as r,createBlock as m,openBlock as n,withCtx as p,createCommentVNode as h,createTextVNode as i,createElementVNode as s,createElementBlock as I}from"vue";let M=biigle.$require("volumes.components.filterListComponent"),k=biigle.$require("core.mixins.loader"),_=biigle.$require("resource"),g=biigle.$require("volumes.stores.filters"),C=biigle.$require("uiv.modal");const w=_("api/v1/volumes{/id}/coordinates",{}),x={emits:["on","close-modal"],mixins:[k],components:{modal:C,imageMap:v},props:{volumeId:{type:Number,required:!0}},data(){return{show:!1,images:[],disabled:!0,imageIds:[]}},methods:{callback(t){t==="ok"?this.$emit("on",this.imageIds):this.$emit("close-modal")},handleSelectedImages(t){t.length>0?(this.imageIds=[...t.sort()],this.disabled=!1):(this.imageIds=[],this.disabled=!0)}},created(){this.startLoading(),this.show=!0,w.get({id:this.volumeId}).then(t=>this.images=t.body,this.handleErrorResponse).finally(this.finishLoading)}},y=["disabled"];function q(t,e,u,f,o,l){const d=r("image-map"),c=r("modal");return n(),m(c,{modelValue:o.show,"onUpdate:modelValue":e[2]||(e[2]=a=>o.show=a),title:"Map Filter",size:"lg",backdrop:!1,onHide:l.callback},{footer:p(()=>[s("div",null,[s("button",{class:"btn btn-default",onClick:e[0]||(e[0]=a=>l.callback("dismiss"))},"Cancel"),e[3]||(e[3]=i()),s("button",{class:"btn btn-default",onClick:e[1]||(e[1]=a=>l.callback("ok")),disabled:o.disabled||null},"Add rule",8,y)])]),default:p(()=>[o.images.length?(n(),m(d,{key:0,images:o.images,selectable:!0,onSelect:l.handleSelectedImages},null,8,["images","onSelect"])):h("",!0),e[4]||(e[4]=i()),e[5]||(e[5]=s("p",{class:"text-muted"},[s("em",null,"Hint:"),i(" Select image locations on the volume map by drawing an encompassing rectangle. To do this, press and hold "),s("kbd",null,"Ctrl"),i(` as well as the left mouse button and move the cursor on the map. - `)],-1)),e[6]||(e[6]=i())]),_:1},8,["modelValue","onHide"])}const $=b(x,[["render",q],["__scopeId","data-v-dc3e2d09"]]),S={emits:["select"],components:{geoMapModal:$},props:{volumeId:{type:Number,required:!0}},data(){return{selectedItem:[],showModal:!1}},methods:{submit(t){this.hideModal(),this.selectedItem=t,this.$emit("select",this.selectedItem)},hideModal(){this.showModal=!1}}},V={class:"filter-select"};function A(t,e,u,f,o,l){const d=r("geo-map-modal");return n(),I("div",V,[o.showModal?(n(),m(d,{key:0,volumeId:u.volumeId,onOn:l.submit,onCloseModal:l.hideModal},null,8,["volumeId","onOn","onCloseModal"])):h("",!0),e[1]||(e[1]=i()),s("button",{type:"submit",class:"btn btn-default pull-right position",onClick:e[0]||(e[0]=c=>o.showModal=!0)},"Add rule")])}const L=b(S,[["render",A],["__scopeId","data-v-66e670c7"]]);Array.isArray(g)&&g.push({id:"location",types:["image"],label:"geo selection",help:"All images that were (not) selected on the world map.",listComponent:{extends:M,data(){return{name:"geo selection"}}},selectComponent:{extends:L},getSequence(t,e){return Promise.resolve({data:e})}}); diff --git a/src/public/assets/volumes-CYbfqU7S.css b/src/public/assets/volumes-CYbfqU7S.css new file mode 100644 index 00000000..bd71b191 --- /dev/null +++ b/src/public/assets/volumes-CYbfqU7S.css @@ -0,0 +1 @@ +.image-map[data-v-083304c1]{height:450px}p[data-v-083304c1]{padding-top:10px}.content[data-v-083304c1]{display:grid;grid-template-columns:auto minmax(30px,auto);grid-auto-rows:max-content;grid-gap:1rem;padding:1rem;box-sizing:border-box}.cell[data-v-083304c1]{border-radius:4px;background-color:none}.cell-map[data-v-083304c1]{grid-column:1;grid-row-start:1;grid-row-end:2}.cell-edit[data-v-083304c1]{grid-column:2;grid-row:1;min-width:min(min-content,200px);max-width:200px}.cell-content[data-v-083304c1]{grid-row:2;grid-column-start:1;grid-column-end:2}.list-group-item.active[data-v-083304c1]{background-color:#353535;color:#fff}.list-group-item[data-v-083304c1]:hover:disabled{background-color:transparent}.layer-button[data-v-083304c1]{position:absolute;top:20px;right:20px;display:block;background-color:var(--body-bg);text-decoration:none;font-size:1.5em;border:none;color:#aaa;padding:15px;z-index:9}.layer-button[data-v-083304c1]:active{color:#fff;transform:scale(.9)}.overlays-wrapper[data-v-083304c1]{max-height:320px;overflow-y:scroll}.layers[data-v-083304c1]{display:none}.layers.active[data-v-083304c1]{display:block}.custom[data-v-083304c1]{display:flex;flex-direction:row;justify-content:space-between;gap:10px}.custom>.ellipsis[data-v-083304c1]{order:1;flex:1;min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.filter-select[data-v-f9127000]{display:block;margin-top:-15px}.filter-select>.position[data-v-f9127000]{position:relative;margin-top:15px}tr[data-v-b12f96ee]:has(.handle:active){background-color:#7c7c7c}td[data-v-b12f96ee]:nth-child(1){width:30px}td[data-v-b12f96ee]:nth-child(2){width:35px}td[data-v-b12f96ee]:nth-child(3){width:200px}td[data-v-b12f96ee]:nth-child(4){min-width:90px}td[data-v-b12f96ee]:nth-child(5){min-width:80px}td[data-v-b12f96ee]:nth-child(6){min-width:65px}td[data-v-b12f96ee]:not(.start){text-align:center}.truncate[data-v-b12f96ee]{text-overflow:ellipsis;display:inline-block;white-space:nowrap;overflow:hidden;width:200px}.close[data-v-b12f96ee]{float:none}.table-responsive[data-v-128dcc04]{display:grid;grid-template-columns:repeat(auto-fit,minmax(0,1fr));max-height:300px;overflow-x:scroll;overflow-y:scroll}table[data-v-128dcc04]{table-layout:auto;margin-bottom:0}th[data-v-128dcc04]{white-space:normal;word-wrap:break-word}caption[data-v-128dcc04]{text-align:center} diff --git a/src/public/assets/volumes-DZMJLBmT.js b/src/public/assets/volumes-DZMJLBmT.js new file mode 100644 index 00000000..64cd09a9 --- /dev/null +++ b/src/public/assets/volumes-DZMJLBmT.js @@ -0,0 +1,15 @@ +import{_ as he,I as sn,h as Wr}from"./imageMap-mzZ_8F5g.js";import ln,{resolveComponent as Ne,createBlock as Ze,openBlock as Lt,withCtx as Vr,createElementVNode as V,createTextVNode as nt,createCommentVNode as ke,createElementBlock as Xt,normalizeClass as qe,Fragment as un,renderList as fn,toDisplayString as mr,renderSlot as Xr,setBlockTracking as Dr,createVNode as dn}from"vue";let cn=biigle.$require("core.mixins.editor"),vn=biigle.$require("volumes.components.filterListComponent"),Cr=biigle.$require("messages").handleErrorResponse;biigle.$require("messages");let Yr=biigle.$require("core.mixins.loader"),hn=biigle.$require("uiv.tab"),pn=biigle.$require("uiv.tabs"),Ar=biigle.$require("volumes.stores.filters"),zr=biigle.$require("resource"),gn=biigle.$require("uiv.modal"),mn=biigle.$require("echo"),Rr=biigle.$require("events");const yn=zr("api/v1/volumes{/id}/coordinates",{}),ie=zr("api/v1/geo-overlays{/id}",{},{updateGeoOverlays:{method:"PUT",url:"api/v1/volumes{/id}/geo-overlays"},deleteGeoOverlay:{method:"DELETE",url:"api/v1/geo-overlays/{id}"},saveGeoTiff:{method:"POST",url:"api/v1/volumes{/id}/geo-overlays/geotiff"},saveWebMap:{method:"POST",url:"api/v1/volumes{/id}/geo-overlays/webmap"},getOverlays:{method:"GET",url:"api/v1/volumes{/id}/geo-overlays"}}),bn={emits:["on","close-modal"],mixins:[Yr],components:{modal:gn,imageMap:sn},props:{volumeId:{type:Number,required:!0}},data(){return{show:!1,showLayers:!1,images:[],disabled:!0,imageIds:[],geoOverlays:[],overlayUrlTemplate:"",lastAction:[],disabledIds:[],hideIds:new Set}},computed:{showOverlay(){return this.images.length&&!this.loading}},methods:{callback(n){n==="ok"?this.$emit("on",this.imageIds):this.$emit("close-modal")},handleSelectedImages(n){n.length>0?(this.imageIds=[...n.sort()],this.disabled=!1):(this.imageIds=[],this.disabled=!0)},setLastAction(n){this.lastAction=["selectedOverlay",n]},changeLastAction(){if(this.lastAction[0]==="filter-map-changed")return;let n=this.lastAction[1];this.lastAction=["filter-map-changed",n]},addToDisabledIds(n){this.disabledIds.push(n)},isDisabled(n){return this.disabledIds.includes(n)||this.hideIds.has(n)}},created(){Rr.on("disable-overlay-btn",n=>this.addToDisabledIds(n)),Rr.on("geo-map-action",()=>this.changeLastAction()),this.startLoading(),this.show=!0,yn.get({id:this.volumeId}).then(n=>this.images=n.body,this.handleErrorResponse),ie.getOverlays({id:this.volumeId}).then(n=>{this.overlayUrlTemplate=n.body.urlTemplate,this.geoOverlays=n.body.geoOverlays,this.hideIds=new Set(this.geoOverlays.filter(e=>!e.browsing_layer).map(e=>e.id))},this.handleErrorResponse).finally(this.finishLoading)}},Sn={class:"content"},En={class:"cell cell-map"},xn={class:"cell cell-edit"},On={key:0},In={key:1,class:"overlays-wrapper"},Tn={key:0},Pn=["id","onClick","disabled"],Dn=["title","textContent"];function Cn(n,e,o,s,r,l){const t=Ne("image-map"),a=Ne("modal");return Lt(),Ze(a,{modelValue:r.show,"onUpdate:modelValue":e[2]||(e[2]=i=>r.show=i),title:"Map Filter",size:"lg",backdrop:!1,onHide:l.callback},{default:Vr(()=>[V("div",Sn,[V("div",En,[l.showOverlay?(Lt(),Ze(t,{key:0,images:r.images,selectable:!0,onSelect:l.handleSelectedImages,overlays:r.geoOverlays,"overlay-url-template":r.overlayUrlTemplate,"last-action":r.lastAction,"hide-ids":r.hideIds},null,8,["images","onSelect","overlays","overlay-url-template","last-action","hide-ids"])):ke("",!0)]),e[14]||(e[14]=nt()),V("div",xn,[r.geoOverlays.length===0?(Lt(),Xt("div",On,[V("button",{class:"layer-button",onClick:e[0]||(e[0]=i=>r.showLayers=!r.showLayers),title:"Show available geo-overlays"},e[3]||(e[3]=[V("i",{class:"fas fa-layer-group"},null,-1)])),e[5]||(e[5]=nt()),V("div",{class:qe(["layers",{active:r.showLayers}])},e[4]||(e[4]=[V("h4",null,"Geo Overlays",-1),nt(),V("p",{class:"text-danger"},"Currently no overlays uploaded / selected.",-1),nt(),V("p",{class:"text-muted"},[V("em",null,"Hint:"),nt(` In the volume-edit section, you can upload a geo-overlay and mark it as + browsing-layer to make it available here. + `)],-1)]),2)])):(Lt(),Xt("div",In,[V("button",{class:"layer-button",onClick:e[1]||(e[1]=i=>r.showLayers=!r.showLayers),title:"Show available geo-overlays"},e[6]||(e[6]=[V("i",{class:"fas fa-layer-group"},null,-1)])),e[13]||(e[13]=nt()),V("div",{class:qe(["layers",{active:r.showLayers}])},[e[9]||(e[9]=V("h4",null,"Geo Overlays",-1)),e[10]||(e[10]=nt()),e[11]||(e[11]=V("p",{class:"text-muted"},[V("em",null,"Hint:"),nt(" Select an overlay from the list below to show on map.")],-1)),e[12]||(e[12]=nt()),r.geoOverlays.length!==0?(Lt(),Xt("div",Tn,[e[7]||(e[7]=V("p",{class:"help-block"},"Geo Overlays",-1)),e[8]||(e[8]=nt()),(Lt(!0),Xt(un,null,fn(r.geoOverlays,i=>(Lt(),Xt("div",{key:i.id},[V("button",{id:i.id,class:"list-group-item custom",onClick:u=>l.setLastAction(i.id),disabled:l.isDisabled(i.id)},[V("span",{class:"ellipsis",title:i.name,textContent:mr(i.name)},null,8,Dn)],8,Pn)]))),128))])):ke("",!0)],2)]))]),e[15]||(e[15]=nt()),e[16]||(e[16]=V("div",{class:"cell cell-content"},[V("p",{class:"text-muted"},[V("em",null,"Hint:"),nt(` Select image locations on the volume map by drawing an encompassing rectangle. To do + this, press and hold `),V("kbd",null,"Ctrl"),nt(" ("),V("kbd",null,"Cmd ⌘"),nt(` on Mac) as well as the left mouse + button and move the cursor on the map. + `)])],-1))])]),_:1},8,["modelValue","onHide"])}const An=he(bn,[["render",Cn],["__scopeId","data-v-083304c1"]]),Rn={emits:["select"],components:{geoMapModal:An},props:{volumeId:{type:Number,required:!0}},data(){return{selectedItem:[],showModal:!1}},methods:{submit(n){this.hideModal(),this.selectedItem=n,this.$emit("select",this.selectedItem)},hideModal(){this.showModal=!1}}},Mn={class:"filter-select"};function wn(n,e,o,s,r,l){const t=Ne("geo-map-modal");return Lt(),Xt("div",Mn,[r.showModal?(Lt(),Ze(t,{key:0,volumeId:o.volumeId,onOn:l.submit,onCloseModal:l.hideModal},null,8,["volumeId","onOn","onCloseModal"])):ke("",!0),e[1]||(e[1]=nt()),V("button",{type:"submit",class:"btn btn-default pull-right position",onClick:e[0]||(e[0]=a=>r.showModal=!0)},"Add rule")])}const Nn=he(Rn,[["render",wn],["__scopeId","data-v-f9127000"]]);Array.isArray(Ar)&&Ar.push({id:"location",types:["image"],label:"geo selection",help:"All images that were (not) selected on the world map.",listComponent:{extends:vn,data(){return{name:"geo selection"}}},selectComponent:{extends:Nn},getSequence(n,e){return Promise.resolve({data:e})}});const Ln={props:{volumeId:{type:Number,required:!0},jobError:{type:String,default:""},overlayCount:{type:Number,default:0}},data(){return{error:""}},emits:["success","upload"],methods:{handleError(n){let e=n.body.errors&&(n.body.errors.geotiff||n.body.errors.fileExists||n.body.errors.invalidColorSpace||n.body.errors.noPCSKEY||n.body.errors.failedTransformation||n.body.errors.missingModelTiePoints||n.body.errors.missingModelType||n.body.errors.wrongModelType||n.body.errors.affineTransformation||n.body.errors.userDefined||n.body.errors.unDefined||n.body.errors.transformError||n.body.errors.failedUpload);e?this.error=Array.isArray(e)?e[0]:e:n.status===422?this.error="The file is invalid. It must be a valid geotiff, use a 'projected' coordinate reference system or the EPSG code 4326.":this.error="An unknown error occured. Please retry later.",this.$emit("upload",!1)},submitGeoTiff(){document.getElementById("geoTiffInput").click()},upload(n){return ie.saveGeoTiff({id:this.volumeId},n)},uploadGeoTiff(n){this.$emit("upload",!0);let e=new FormData;e.append("geotiff",n.target.files[0]),e.append("layer_index",this.overlayCount),this.upload(e).catch(this.handleError)}},watch:{jobError(){this.error=this.jobError}}};function jn(n,e,o,s,r,l){return Xr(n.$slots,"default",{submitGeoTiff:l.submitGeoTiff,uploadGeoTiff:l.uploadGeoTiff,error:r.error})}const Fn=he(Ln,[["render",jn]]),$n={data(){return{error:!1,success:!1}},props:{volumeId:{type:Number,required:!0},overlayCount:{type:Number,default:0}},emits:["success","upload"],methods:{handleSuccess(n){this.error=!1,this.success=!0,this.$emit("success",n.data)},handleError(n){let e=n.body.errors&&(n.body.errors.url||n.body.errors.tooManyLayers||n.body.errors.invalidWMS||n.body.errors.noValidLayer||n.body.errors.uniqueUrl);e?this.error=Array.isArray(e)?e[0]:e:n.status===422?this.error="The url or WMS resource is invalid.":this.error="An unknown error occured. Please retry later."},submitWebMap(n){this.$emit("upload",!0);let e=new FormData;this.urlIsInvalid(n.target[0].value)||(e.append("url",n.target[0].value),e.append("layer_index",this.overlayCount),ie.saveWebMap({id:this.volumeId},e).then(this.handleSuccess,this.handleError).finally(()=>this.$emit("upload",!1)))},urlIsInvalid(n){const o=new URL(n).searchParams.get("layers");return o&&o.match(/\s|\,/g)?(this.error="The url must not contain more than one layer.",this.$emit("upload",!1),!0):!1}}};function Gn(n,e,o,s,r,l){return Xr(n.$slots,"default",{submitWebMap:l.submitWebMap,error:r.error})}const Un=he($n,[["render",Gn]]),Bn={data(){return{browsingLayer:!0}},props:{overlay:{type:Object,required:!0},volumeId:{type:Number,required:!0},index:{type:Number,required:!0}},computed:{title(){return"Delete overlay "+this.overlay.name}},methods:{remove(){confirm(`Are you sure you want to delete the overlay ${this.overlay.name}?`)&&this.$emit("remove",this.overlay)},updateShowLayer(){let n=[{id:this.overlay.id,name:this.overlay.name,volume_id:this.volumeId,browsing_layer:!this.browsingLayer}];ie.updateGeoOverlays({id:this.volumeId},{updated_overlays:n}).then(()=>this.browsingLayer=!this.browsingLayer).catch(Wr)}},mounted(){this.browsingLayer=this.overlay.browsing_layer}},Kn={scope:"row",class:"start"},Hn={class:"text-muted"},Wn={class:"start"},Vn=["title","textContent"],Xn={class:"power-toggle"};function Yn(n,e,o,s,r,l){return Lt(),Xt("tr",null,[e[5]||(e[5]=V("td",{class:"handle start"},[V("i",{class:"fas fa-grip-lines"})],-1)),e[6]||(e[6]=nt()),V("td",Kn,[V("span",Hn,[e[2]||(e[2]=nt("#")),V("span",null,mr(o.index+1),1)])]),e[7]||(e[7]=nt()),V("td",Wn,[V("span",{class:"truncate",title:o.overlay.name,textContent:mr(o.overlay.name)},null,8,Vn)]),e[8]||(e[8]=nt()),V("td",null,[V("span",Xn,[V("button",{class:qe(["btn btn-default btn-sm",{"active btn-info":r.browsingLayer}]),onClick:e[0]||(e[0]=(...t)=>l.updateShowLayer&&l.updateShowLayer(...t)),title:"Add overlay to geo-selection filter"},e[3]||(e[3]=[V("i",{class:"fa fa-fw fa-power-off"},null,-1)]),2)])]),e[9]||(e[9]=nt()),V("td",null,[e[1]||(Dr(-1,!0),(e[1]=V("button",{type:"button",class:"close",title:l.title,onClick:l.remove},[e[4]||(e[4]=V("span",{"aria-hidden":"true"},"×",-1))],8,["title","onClick"])).cacheIndex=1,Dr(1),e[1])])])}const zn=he(Bn,[["render",Yn],["__scopeId","data-v-b12f96ee"]]);function Jn(n){return n&&n.__esModule&&Object.prototype.hasOwnProperty.call(n,"default")?n.default:n}function Qn(n){if(Object.prototype.hasOwnProperty.call(n,"__esModule"))return n;var e=n.default;if(typeof e=="function"){var o=function s(){return this instanceof s?Reflect.construct(e,arguments,this.constructor):e.apply(this,arguments)};o.prototype=e.prototype}else o={};return Object.defineProperty(o,"__esModule",{value:!0}),Object.keys(n).forEach(function(s){var r=Object.getOwnPropertyDescriptor(n,s);Object.defineProperty(o,s,r.get?r:{enumerable:!0,get:function(){return n[s]}})}),o}var Ve={exports:{}};/**! + * Sortable 1.14.0 + * @author RubaXa + * @author owenm + * @license MIT + */function Mr(n,e){var o=Object.keys(n);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(n);e&&(s=s.filter(function(r){return Object.getOwnPropertyDescriptor(n,r).enumerable})),o.push.apply(o,s)}return o}function Vt(n){for(var e=1;e=0)&&(o[r]=n[r]);return o}function qn(n,e){if(n==null)return{};var o=kn(n,e),s,r;if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(n);for(r=0;r=0)&&Object.prototype.propertyIsEnumerable.call(n,s)&&(o[s]=n[s])}return o}function _n(n){return to(n)||eo(n)||ro(n)||no()}function to(n){if(Array.isArray(n))return yr(n)}function eo(n){if(typeof Symbol<"u"&&n[Symbol.iterator]!=null||n["@@iterator"]!=null)return Array.from(n)}function ro(n,e){if(n){if(typeof n=="string")return yr(n,e);var o=Object.prototype.toString.call(n).slice(8,-1);if(o==="Object"&&n.constructor&&(o=n.constructor.name),o==="Map"||o==="Set")return Array.from(n);if(o==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(o))return yr(n,e)}}function yr(n,e){(e==null||e>n.length)&&(e=n.length);for(var o=0,s=new Array(e);o"&&(e=e.substring(1)),n)try{if(n.matches)return n.matches(e);if(n.msMatchesSelector)return n.msMatchesSelector(e);if(n.webkitMatchesSelector)return n.webkitMatchesSelector(e)}catch{return!1}return!1}}function io(n){return n.host&&n!==document&&n.host.nodeType?n.host:n.parentNode}function Bt(n,e,o,s){if(n){o=o||document;do{if(e!=null&&(e[0]===">"?n.parentNode===o&&_e(n,e):_e(n,e))||s&&n===o)return n;if(n===o)break}while(n=io(n))}return null}var Nr=/\s+/g;function ut(n,e,o){if(n&&e)if(n.classList)n.classList[o?"add":"remove"](e);else{var s=(" "+n.className+" ").replace(Nr," ").replace(" "+e+" "," ");n.className=(s+(o?" "+e:"")).replace(Nr," ")}}function F(n,e,o){var s=n&&n.style;if(s){if(o===void 0)return document.defaultView&&document.defaultView.getComputedStyle?o=document.defaultView.getComputedStyle(n,""):n.currentStyle&&(o=n.currentStyle),e===void 0?o:o[e];!(e in s)&&e.indexOf("webkit")===-1&&(e="-webkit-"+e),s[e]=o+(typeof o=="string"?"":"px")}}function ae(n,e){var o="";if(typeof n=="string")o=n;else do{var s=F(n,"transform");s&&s!=="none"&&(o=s+" "+o)}while(!e&&(n=n.parentNode));var r=window.DOMMatrix||window.WebKitCSSMatrix||window.CSSMatrix||window.MSCSSMatrix;return r&&new r(o)}function Zr(n,e,o){if(n){var s=n.getElementsByTagName(e),r=0,l=s.length;if(o)for(;r=l,!t)return s;if(s===Wt())break;s=_t(s,!1)}return!1}function ve(n,e,o,s){for(var r=0,l=0,t=n.children;l2&&arguments[2]!==void 0?arguments[2]:{},r=s.evt,l=qn(s,ho);je.pluginEvent.bind(K)(e,o,Vt({dragEl:A,parentEl:ct,ghostEl:J,rootEl:it,nextEl:oe,lastDownEl:Ye,cloneEl:vt,cloneHidden:qt,dragStarted:Te,putSortable:Ot,activeSortable:K.active,originalEvent:r,oldIndex:ce,oldDraggableIndex:Re,newIndex:Nt,newDraggableIndex:kt,hideGhostForTarget:rn,unhideGhostForTarget:nn,cloneNowHidden:function(){qt=!0},cloneNowShown:function(){qt=!1},dispatchSortableEvent:function(a){Dt({sortable:o,name:a,originalEvent:r})}},l))};function Dt(n){Ie(Vt({putSortable:Ot,cloneEl:vt,targetEl:A,rootEl:it,oldIndex:ce,oldDraggableIndex:Re,newIndex:Nt,newDraggableIndex:kt},n))}var A,ct,J,it,oe,Ye,vt,qt,ce,Nt,Re,kt,Ge,Ot,de=!1,tr=!1,er=[],re,Gt,fr,dr,$r,Gr,Te,ue,Me,we=!1,Ue=!1,ze,It,cr=[],br=!1,rr=[],or=typeof document<"u",Be=Jr,Ur=Le||zt?"cssFloat":"float",po=or&&!ao&&!Jr&&"draggable"in document.createElement("div"),_r=function(){if(or){if(zt)return!1;var n=document.createElement("x");return n.style.cssText="pointer-events:auto",n.style.pointerEvents==="auto"}}(),tn=function(e,o){var s=F(e),r=parseInt(s.width)-parseInt(s.paddingLeft)-parseInt(s.paddingRight)-parseInt(s.borderLeftWidth)-parseInt(s.borderRightWidth),l=ve(e,0,o),t=ve(e,1,o),a=l&&F(l),i=t&&F(t),u=a&&parseInt(a.marginLeft)+parseInt(a.marginRight)+st(l).width,d=i&&parseInt(i.marginLeft)+parseInt(i.marginRight)+st(t).width;if(s.display==="flex")return s.flexDirection==="column"||s.flexDirection==="column-reverse"?"vertical":"horizontal";if(s.display==="grid")return s.gridTemplateColumns.split(" ").length<=1?"vertical":"horizontal";if(l&&a.float&&a.float!=="none"){var f=a.float==="left"?"left":"right";return t&&(i.clear==="both"||i.clear===f)?"vertical":"horizontal"}return l&&(a.display==="block"||a.display==="flex"||a.display==="table"||a.display==="grid"||u>=r&&s[Ur]==="none"||t&&s[Ur]==="none"&&u+d>r)?"vertical":"horizontal"},go=function(e,o,s){var r=s?e.left:e.top,l=s?e.right:e.bottom,t=s?e.width:e.height,a=s?o.left:o.top,i=s?o.right:o.bottom,u=s?o.width:o.height;return r===a||l===i||r+t/2===a+u/2},mo=function(e,o){var s;return er.some(function(r){var l=r[Tt].options.emptyInsertThreshold;if(!(!l||Or(r))){var t=st(r),a=e>=t.left-l&&e<=t.right+l,i=o>=t.top-l&&o<=t.bottom+l;if(a&&i)return s=r}}),s},en=function(e){function o(l,t){return function(a,i,u,d){var f=a.options.group.name&&i.options.group.name&&a.options.group.name===i.options.group.name;if(l==null&&(t||f))return!0;if(l==null||l===!1)return!1;if(t&&l==="clone")return l;if(typeof l=="function")return o(l(a,i,u,d),t)(a,i,u,d);var c=(t?a:i).options.group.name;return l===!0||typeof l=="string"&&l===c||l.join&&l.indexOf(c)>-1}}var s={},r=e.group;(!r||Xe(r)!="object")&&(r={name:r}),s.name=r.name,s.checkPull=o(r.pull,!0),s.checkPut=o(r.put),s.revertClone=r.revertClone,e.group=s},rn=function(){!_r&&J&&F(J,"display","none")},nn=function(){!_r&&J&&F(J,"display","")};or&&document.addEventListener("click",function(n){if(tr)return n.preventDefault(),n.stopPropagation&&n.stopPropagation(),n.stopImmediatePropagation&&n.stopImmediatePropagation(),tr=!1,!1},!0);var ne=function(e){if(A){e=e.touches?e.touches[0]:e;var o=mo(e.clientX,e.clientY);if(o){var s={};for(var r in e)e.hasOwnProperty(r)&&(s[r]=e[r]);s.target=s.rootEl=o,s.preventDefault=void 0,s.stopPropagation=void 0,o[Tt]._onDragOver(s)}}},yo=function(e){A&&A.parentNode[Tt]._isOutsideThisEl(e.target)};function K(n,e){if(!(n&&n.nodeType&&n.nodeType===1))throw"Sortable: `el` must be an HTMLElement, not ".concat({}.toString.call(n));this.el=n,this.options=e=Ft({},e),n[Tt]=this;var o={group:null,sort:!0,disabled:!1,store:null,handle:null,draggable:/^[uo]l$/i.test(n.nodeName)?">li":">*",swapThreshold:1,invertSwap:!1,invertedSwapThreshold:null,removeCloneOnHide:!0,direction:function(){return tn(n,this.options)},ghostClass:"sortable-ghost",chosenClass:"sortable-chosen",dragClass:"sortable-drag",ignore:"a, img",filter:null,preventOnFilter:!0,animation:0,easing:null,setData:function(t,a){t.setData("Text",a.textContent)},dropBubble:!1,dragoverBubble:!1,dataIdAttr:"data-id",delay:0,delayOnTouchOnly:!1,touchStartThreshold:(Number.parseInt?Number:window).parseInt(window.devicePixelRatio,10)||1,forceFallback:!1,fallbackClass:"sortable-fallback",fallbackOnBody:!1,fallbackTolerance:0,fallbackOffset:{x:0,y:0},supportPointer:K.supportPointer!==!1&&"PointerEvent"in window&&!Ce,emptyInsertThreshold:5};je.initializePlugins(this,n,o);for(var s in o)!(s in e)&&(e[s]=o[s]);en(e);for(var r in this)r.charAt(0)==="_"&&typeof this[r]=="function"&&(this[r]=this[r].bind(this));this.nativeDraggable=e.forceFallback?!1:po,this.nativeDraggable&&(this.options.touchStartThreshold=1),e.supportPointer?k(n,"pointerdown",this._onTapStart):(k(n,"mousedown",this._onTapStart),k(n,"touchstart",this._onTapStart)),this.nativeDraggable&&(k(n,"dragover",this),k(n,"dragenter",this)),er.push(this.el),e.store&&e.store.get&&this.sort(e.store.get(this)||[]),Ft(this,fo())}K.prototype={constructor:K,_isOutsideThisEl:function(e){!this.el.contains(e)&&e!==this.el&&(ue=null)},_getDirection:function(e,o){return typeof this.options.direction=="function"?this.options.direction.call(this,e,o,A):this.options.direction},_onTapStart:function(e){if(e.cancelable){var o=this,s=this.el,r=this.options,l=r.preventOnFilter,t=e.type,a=e.touches&&e.touches[0]||e.pointerType&&e.pointerType==="touch"&&e,i=(a||e).target,u=e.target.shadowRoot&&(e.path&&e.path[0]||e.composedPath&&e.composedPath()[0])||i,d=r.filter;if(Po(s),!A&&!(/mousedown|pointerdown/.test(t)&&e.button!==0||r.disabled)&&!u.isContentEditable&&!(!this.nativeDraggable&&Ce&&i&&i.tagName.toUpperCase()==="SELECT")&&(i=Bt(i,r.draggable,s,!1),!(i&&i.animated)&&Ye!==i)){if(ce=ht(i),Re=ht(i,r.draggable),typeof d=="function"){if(d.call(this,e,i,this)){Dt({sortable:o,rootEl:u,name:"filter",targetEl:i,toEl:s,fromEl:s}),At("filter",o,{evt:e}),l&&e.cancelable&&e.preventDefault();return}}else if(d&&(d=d.split(",").some(function(f){if(f=Bt(u,f.trim(),s,!1),f)return Dt({sortable:o,rootEl:f,name:"filter",targetEl:i,fromEl:s,toEl:s}),At("filter",o,{evt:e}),!0}),d)){l&&e.cancelable&&e.preventDefault();return}r.handle&&!Bt(u,r.handle,s,!1)||this._prepareDragStart(e,a,i)}}},_prepareDragStart:function(e,o,s){var r=this,l=r.el,t=r.options,a=l.ownerDocument,i;if(s&&!A&&s.parentNode===l){var u=st(s);if(it=l,A=s,ct=A.parentNode,oe=A.nextSibling,Ye=s,Ge=t.group,K.dragged=A,re={target:A,clientX:(o||e).clientX,clientY:(o||e).clientY},$r=re.clientX-u.left,Gr=re.clientY-u.top,this._lastX=(o||e).clientX,this._lastY=(o||e).clientY,A.style["will-change"]="all",i=function(){if(At("delayEnded",r,{evt:e}),K.eventCanceled){r._onDrop();return}r._disableDelayedDragEvents(),!wr&&r.nativeDraggable&&(A.draggable=!0),r._triggerDragStart(e,o),Dt({sortable:r,name:"choose",originalEvent:e}),ut(A,t.chosenClass,!0)},t.ignore.split(",").forEach(function(d){Zr(A,d.trim(),vr)}),k(a,"dragover",ne),k(a,"mousemove",ne),k(a,"touchmove",ne),k(a,"mouseup",r._onDrop),k(a,"touchend",r._onDrop),k(a,"touchcancel",r._onDrop),wr&&this.nativeDraggable&&(this.options.touchStartThreshold=4,A.draggable=!0),At("delayStart",this,{evt:e}),t.delay&&(!t.delayOnTouchOnly||o)&&(!this.nativeDraggable||!(Le||zt))){if(K.eventCanceled){this._onDrop();return}k(a,"mouseup",r._disableDelayedDrag),k(a,"touchend",r._disableDelayedDrag),k(a,"touchcancel",r._disableDelayedDrag),k(a,"mousemove",r._delayedDragTouchMoveHandler),k(a,"touchmove",r._delayedDragTouchMoveHandler),t.supportPointer&&k(a,"pointermove",r._delayedDragTouchMoveHandler),r._dragStartTimer=setTimeout(i,t.delay)}else i()}},_delayedDragTouchMoveHandler:function(e){var o=e.touches?e.touches[0]:e;Math.max(Math.abs(o.clientX-this._lastX),Math.abs(o.clientY-this._lastY))>=Math.floor(this.options.touchStartThreshold/(this.nativeDraggable&&window.devicePixelRatio||1))&&this._disableDelayedDrag()},_disableDelayedDrag:function(){A&&vr(A),clearTimeout(this._dragStartTimer),this._disableDelayedDragEvents()},_disableDelayedDragEvents:function(){var e=this.el.ownerDocument;Z(e,"mouseup",this._disableDelayedDrag),Z(e,"touchend",this._disableDelayedDrag),Z(e,"touchcancel",this._disableDelayedDrag),Z(e,"mousemove",this._delayedDragTouchMoveHandler),Z(e,"touchmove",this._delayedDragTouchMoveHandler),Z(e,"pointermove",this._delayedDragTouchMoveHandler)},_triggerDragStart:function(e,o){o=o||e.pointerType=="touch"&&e,!this.nativeDraggable||o?this.options.supportPointer?k(document,"pointermove",this._onTouchMove):o?k(document,"touchmove",this._onTouchMove):k(document,"mousemove",this._onTouchMove):(k(A,"dragend",this),k(it,"dragstart",this._onDragStart));try{document.selection?Je(function(){document.selection.empty()}):window.getSelection().removeAllRanges()}catch{}},_dragStarted:function(e,o){if(de=!1,it&&A){At("dragStarted",this,{evt:o}),this.nativeDraggable&&k(document,"dragover",yo);var s=this.options;!e&&ut(A,s.dragClass,!1),ut(A,s.ghostClass,!0),K.active=this,e&&this._appendGhost(),Dt({sortable:this,name:"start",originalEvent:o})}else this._nulling()},_emulateDragOver:function(){if(Gt){this._lastX=Gt.clientX,this._lastY=Gt.clientY,rn();for(var e=document.elementFromPoint(Gt.clientX,Gt.clientY),o=e;e&&e.shadowRoot&&(e=e.shadowRoot.elementFromPoint(Gt.clientX,Gt.clientY),e!==o);)o=e;if(A.parentNode[Tt]._isOutsideThisEl(e),o)do{if(o[Tt]){var s=void 0;if(s=o[Tt]._onDragOver({clientX:Gt.clientX,clientY:Gt.clientY,target:e,rootEl:o}),s&&!this.options.dragoverBubble)break}e=o}while(o=o.parentNode);nn()}},_onTouchMove:function(e){if(re){var o=this.options,s=o.fallbackTolerance,r=o.fallbackOffset,l=e.touches?e.touches[0]:e,t=J&&ae(J,!0),a=J&&t&&t.a,i=J&&t&&t.d,u=Be&&It&&jr(It),d=(l.clientX-re.clientX+r.x)/(a||1)+(u?u[0]-cr[0]:0)/(a||1),f=(l.clientY-re.clientY+r.y)/(i||1)+(u?u[1]-cr[1]:0)/(i||1);if(!K.active&&!de){if(s&&Math.max(Math.abs(l.clientX-this._lastX),Math.abs(l.clientY-this._lastY))=0&&(Dt({rootEl:ct,name:"add",toEl:ct,fromEl:it,originalEvent:e}),Dt({sortable:this,name:"remove",toEl:ct,originalEvent:e}),Dt({rootEl:ct,name:"sort",toEl:ct,fromEl:it,originalEvent:e}),Dt({sortable:this,name:"sort",toEl:ct,originalEvent:e})),Ot&&Ot.save()):Nt!==ce&&Nt>=0&&(Dt({sortable:this,name:"update",toEl:ct,originalEvent:e}),Dt({sortable:this,name:"sort",toEl:ct,originalEvent:e})),K.active&&((Nt==null||Nt===-1)&&(Nt=ce,kt=Re),Dt({sortable:this,name:"end",toEl:ct,originalEvent:e}),this.save()))),this._nulling()},_nulling:function(){At("nulling",this),it=A=ct=J=oe=vt=Ye=qt=re=Gt=Te=Nt=kt=ce=Re=ue=Me=Ot=Ge=K.dragged=K.ghost=K.clone=K.active=null,rr.forEach(function(e){e.checked=!0}),rr.length=fr=dr=0},handleEvent:function(e){switch(e.type){case"drop":case"dragend":this._onDrop(e);break;case"dragenter":case"dragover":A&&(this._onDragOver(e),bo(e));break;case"selectstart":e.preventDefault();break}},toArray:function(){for(var e=[],o,s=this.el.children,r=0,l=s.length,t=this.options;rs.right+r||n.clientX<=s.right&&n.clientY>s.bottom&&n.clientX>=s.left:n.clientX>s.right&&n.clientY>s.top||n.clientX<=s.right&&n.clientY>s.bottom+r}function Oo(n,e,o,s,r,l,t,a){var i=s?n.clientY:n.clientX,u=s?o.height:o.width,d=s?o.top:o.left,f=s?o.bottom:o.right,c=!1;if(!t){if(a&&zed+u*l/2:if-ze)return-Me}else if(i>d+u*(1-r)/2&&if-u*l/2)?i>d+u/2?1:-1:0}function Io(n){return ht(A)1&&(z.forEach(function(a){l.addAnimationState({target:a,rect:Rt?st(a):t}),lr(a),a.fromRect=t,s.removeAnimationState(a)}),Rt=!1,Mo(!this.options.removeCloneOnHide,r))},dragOverCompleted:function(o){var s=o.sortable,r=o.isOwner,l=o.insertion,t=o.activeSortable,a=o.parentEl,i=o.putSortable,u=this.options;if(l){if(r&&t._hideClone(),xe=!1,u.animation&&z.length>1&&(Rt||!r&&!t.options.sort&&!i)){var d=st(rt,!1,!0,!0);z.forEach(function(c){c!==rt&&(Fr(c,d),a.appendChild(c))}),Rt=!0}if(!r)if(Rt||We(),z.length>1){var f=He;t._showClone(s),t.options.animation&&!He&&f&&wt.forEach(function(c){t.addAnimationState({target:c,rect:Oe}),c.fromRect=Oe,c.thisAnimationDuration=null})}else t._showClone(s)}},dragOverAnimationCapture:function(o){var s=o.dragRect,r=o.isOwner,l=o.activeSortable;if(z.forEach(function(a){a.thisAnimationDuration=null}),l.options.animation&&!r&&l.multiDrag.isMultiDrag){Oe=Ft({},s);var t=ae(rt,!0);Oe.top-=t.f,Oe.left-=t.e}},dragOverAnimationComplete:function(){Rt&&(Rt=!1,We())},drop:function(o){var s=o.originalEvent,r=o.rootEl,l=o.parentEl,t=o.sortable,a=o.dispatchSortableEvent,i=o.oldIndex,u=o.putSortable,d=u||this.sortable;if(s){var f=this.options,c=l.children;if(!fe)if(f.multiDragKey&&!this.multiDragKeyDown&&this._deselectMultiDrag(),ut(rt,f.selectedClass,!~z.indexOf(rt)),~z.indexOf(rt))z.splice(z.indexOf(rt),1),Ee=null,Ie({sortable:t,rootEl:r,name:"deselect",targetEl:rt});else{if(z.push(rt),Ie({sortable:t,rootEl:r,name:"select",targetEl:rt}),s.shiftKey&&Ee&&t.el.contains(Ee)){var v=ht(Ee),h=ht(rt);if(~v&&~h&&v!==h){var p,g;for(h>v?(g=v,p=h):(g=h,p=v+1);g1){var b=st(rt),S=ht(rt,":not(."+this.options.selectedClass+")");if(!xe&&f.animation&&(rt.thisAnimationDuration=null),d.captureAnimationState(),!xe&&(f.animation&&(rt.fromRect=b,z.forEach(function(x){if(x.thisAnimationDuration=null,x!==rt){var P=Rt?st(x):b;x.fromRect=P,d.addAnimationState({target:x,rect:P})}})),We(),z.forEach(function(x){c[S]?l.insertBefore(x,c[S]):l.appendChild(x),S++}),i===ht(rt))){var T=!1;z.forEach(function(x){if(x.sortableIndex!==ht(x)){T=!0;return}}),T&&a("update")}z.forEach(function(x){lr(x)}),d.animateAll()}Ut=d}(r===l||u&&u.lastPutMode!=="clone")&&wt.forEach(function(x){x.parentNode&&x.parentNode.removeChild(x)})}},nullingGlobal:function(){this.isMultiDrag=fe=!1,wt.length=0},destroyGlobal:function(){this._deselectMultiDrag(),Z(document,"pointerup",this._deselectMultiDrag),Z(document,"mouseup",this._deselectMultiDrag),Z(document,"touchend",this._deselectMultiDrag),Z(document,"keydown",this._checkKeyDown),Z(document,"keyup",this._checkKeyUp)},_deselectMultiDrag:function(o){if(!(typeof fe<"u"&&fe)&&Ut===this.sortable&&!(o&&Bt(o.target,this.options.draggable,this.sortable.el,!1))&&!(o&&o.button!==0))for(;z.length;){var s=z[0];ut(s,this.options.selectedClass,!1),z.shift(),Ie({sortable:this.sortable,rootEl:this.sortable.el,name:"deselect",targetEl:s})}},_checkKeyDown:function(o){o.key===this.options.multiDragKey&&(this.multiDragKeyDown=!0)},_checkKeyUp:function(o){o.key===this.options.multiDragKey&&(this.multiDragKeyDown=!1)}},Ft(n,{pluginName:"multiDrag",utils:{select:function(o){var s=o.parentNode[Tt];!s||!s.options.multiDrag||~z.indexOf(o)||(Ut&&Ut!==s&&(Ut.multiDrag._deselectMultiDrag(),Ut=s),ut(o,s.options.selectedClass,!0),z.push(o))},deselect:function(o){var s=o.parentNode[Tt],r=z.indexOf(o);!s||!s.options.multiDrag||!~r||(ut(o,s.options.selectedClass,!1),z.splice(r,1))}},eventProperties:function(){var o=this,s=[],r=[];return z.forEach(function(l){s.push({multiDragElement:l,index:l.sortableIndex});var t;Rt&&l!==rt?t=-1:Rt?t=ht(l,":not(."+o.options.selectedClass+")"):t=ht(l),r.push({multiDragElement:l,index:t})}),{items:_n(z),clones:[].concat(wt),oldIndicies:s,newIndicies:r}},optionListeners:{multiDragKey:function(o){return o=o.toLowerCase(),o==="ctrl"?o="Control":o.length>1&&(o=o.charAt(0).toUpperCase()+o.substr(1)),o}}})}function Mo(n,e){z.forEach(function(o,s){var r=e.children[o.sortableIndex+(n?Number(s):0)];r?e.insertBefore(o,r):e.appendChild(o)})}function Kr(n,e){wt.forEach(function(o,s){var r=e.children[o.sortableIndex+(n?Number(s):0)];r?e.insertBefore(o,r):e.appendChild(o)})}function We(){z.forEach(function(n){n!==rt&&n.parentNode&&n.parentNode.removeChild(n)})}K.mount(new Do);K.mount(Pr,Tr);const wo=Object.freeze(Object.defineProperty({__proto__:null,MultiDrag:Ro,Sortable:K,Swap:Co,default:K},Symbol.toStringTag,{value:"Module"})),No=Qn(wo);var Lo=Ve.exports,Hr;function jo(){return Hr||(Hr=1,function(n,e){(function(s,r){n.exports=r(ln,No)})(typeof self<"u"?self:Lo,function(o,s){return function(r){var l={};function t(a){if(l[a])return l[a].exports;var i=l[a]={i:a,l:!1,exports:{}};return r[a].call(i.exports,i,i.exports,t),i.l=!0,i.exports}return t.m=r,t.c=l,t.d=function(a,i,u){t.o(a,i)||Object.defineProperty(a,i,{enumerable:!0,get:u})},t.r=function(a){typeof Symbol<"u"&&Symbol.toStringTag&&Object.defineProperty(a,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(a,"__esModule",{value:!0})},t.t=function(a,i){if(i&1&&(a=t(a)),i&8||i&4&&typeof a=="object"&&a&&a.__esModule)return a;var u=Object.create(null);if(t.r(u),Object.defineProperty(u,"default",{enumerable:!0,value:a}),i&2&&typeof a!="string")for(var d in a)t.d(u,d,(function(f){return a[f]}).bind(null,d));return u},t.n=function(a){var i=a&&a.__esModule?function(){return a.default}:function(){return a};return t.d(i,"a",i),i},t.o=function(a,i){return Object.prototype.hasOwnProperty.call(a,i)},t.p="",t(t.s="fb15")}({"00ee":function(r,l,t){var a=t("b622"),i=a("toStringTag"),u={};u[i]="z",r.exports=String(u)==="[object z]"},"0366":function(r,l,t){var a=t("1c0b");r.exports=function(i,u,d){if(a(i),u===void 0)return i;switch(d){case 0:return function(){return i.call(u)};case 1:return function(f){return i.call(u,f)};case 2:return function(f,c){return i.call(u,f,c)};case 3:return function(f,c,v){return i.call(u,f,c,v)}}return function(){return i.apply(u,arguments)}}},"057f":function(r,l,t){var a=t("fc6a"),i=t("241c").f,u={}.toString,d=typeof window=="object"&&window&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[],f=function(c){try{return i(c)}catch{return d.slice()}};r.exports.f=function(v){return d&&u.call(v)=="[object Window]"?f(v):i(a(v))}},"06cf":function(r,l,t){var a=t("83ab"),i=t("d1e7"),u=t("5c6c"),d=t("fc6a"),f=t("c04e"),c=t("5135"),v=t("0cfb"),h=Object.getOwnPropertyDescriptor;l.f=a?h:function(g,b){if(g=d(g),b=f(b,!0),v)try{return h(g,b)}catch{}if(c(g,b))return u(!i.f.call(g,b),g[b])}},"0cfb":function(r,l,t){var a=t("83ab"),i=t("d039"),u=t("cc12");r.exports=!a&&!i(function(){return Object.defineProperty(u("div"),"a",{get:function(){return 7}}).a!=7})},"13d5":function(r,l,t){var a=t("23e7"),i=t("d58f").left,u=t("a640"),d=t("ae40"),f=u("reduce"),c=d("reduce",{1:0});a({target:"Array",proto:!0,forced:!f||!c},{reduce:function(h){return i(this,h,arguments.length,arguments.length>1?arguments[1]:void 0)}})},"14c3":function(r,l,t){var a=t("c6b6"),i=t("9263");r.exports=function(u,d){var f=u.exec;if(typeof f=="function"){var c=f.call(u,d);if(typeof c!="object")throw TypeError("RegExp exec method returned something other than an Object or null");return c}if(a(u)!=="RegExp")throw TypeError("RegExp#exec called on incompatible receiver");return i.call(u,d)}},"159b":function(r,l,t){var a=t("da84"),i=t("fdbc"),u=t("17c2"),d=t("9112");for(var f in i){var c=a[f],v=c&&c.prototype;if(v&&v.forEach!==u)try{d(v,"forEach",u)}catch{v.forEach=u}}},"17c2":function(r,l,t){var a=t("b727").forEach,i=t("a640"),u=t("ae40"),d=i("forEach"),f=u("forEach");r.exports=!d||!f?function(v){return a(this,v,arguments.length>1?arguments[1]:void 0)}:[].forEach},"1be4":function(r,l,t){var a=t("d066");r.exports=a("document","documentElement")},"1c0b":function(r,l){r.exports=function(t){if(typeof t!="function")throw TypeError(String(t)+" is not a function");return t}},"1c7e":function(r,l,t){var a=t("b622"),i=a("iterator"),u=!1;try{var d=0,f={next:function(){return{done:!!d++}},return:function(){u=!0}};f[i]=function(){return this},Array.from(f,function(){throw 2})}catch{}r.exports=function(c,v){if(!v&&!u)return!1;var h=!1;try{var p={};p[i]=function(){return{next:function(){return{done:h=!0}}}},c(p)}catch{}return h}},"1d80":function(r,l){r.exports=function(t){if(t==null)throw TypeError("Can't call method on "+t);return t}},"1dde":function(r,l,t){var a=t("d039"),i=t("b622"),u=t("2d00"),d=i("species");r.exports=function(f){return u>=51||!a(function(){var c=[],v=c.constructor={};return v[d]=function(){return{foo:1}},c[f](Boolean).foo!==1})}},"23cb":function(r,l,t){var a=t("a691"),i=Math.max,u=Math.min;r.exports=function(d,f){var c=a(d);return c<0?i(c+f,0):u(c,f)}},"23e7":function(r,l,t){var a=t("da84"),i=t("06cf").f,u=t("9112"),d=t("6eeb"),f=t("ce4e"),c=t("e893"),v=t("94ca");r.exports=function(h,p){var g=h.target,b=h.global,S=h.stat,T,x,P,O,j,$;if(b?x=a:S?x=a[g]||f(g,{}):x=(a[g]||{}).prototype,x)for(P in p){if(j=p[P],h.noTargetGet?($=i(x,P),O=$&&$.value):O=x[P],T=v(b?P:g+(S?".":"#")+P,h.forced),!T&&O!==void 0){if(typeof j==typeof O)continue;c(j,O)}(h.sham||O&&O.sham)&&u(j,"sham",!0),d(x,P,j,h)}}},"241c":function(r,l,t){var a=t("ca84"),i=t("7839"),u=i.concat("length","prototype");l.f=Object.getOwnPropertyNames||function(f){return a(f,u)}},"25f0":function(r,l,t){var a=t("6eeb"),i=t("825a"),u=t("d039"),d=t("ad6d"),f="toString",c=RegExp.prototype,v=c[f],h=u(function(){return v.call({source:"a",flags:"b"})!="/a/b"}),p=v.name!=f;(h||p)&&a(RegExp.prototype,f,function(){var b=i(this),S=String(b.source),T=b.flags,x=String(T===void 0&&b instanceof RegExp&&!("flags"in c)?d.call(b):T);return"/"+S+"/"+x},{unsafe:!0})},"2ca0":function(r,l,t){var a=t("23e7"),i=t("06cf").f,u=t("50c4"),d=t("5a34"),f=t("1d80"),c=t("ab13"),v=t("c430"),h="".startsWith,p=Math.min,g=c("startsWith"),b=!v&&!g&&!!function(){var S=i(String.prototype,"startsWith");return S&&!S.writable}();a({target:"String",proto:!0,forced:!b&&!g},{startsWith:function(T){var x=String(f(this));d(T);var P=u(p(arguments.length>1?arguments[1]:void 0,x.length)),O=String(T);return h?h.call(x,O,P):x.slice(P,P+O.length)===O}})},"2d00":function(r,l,t){var a=t("da84"),i=t("342f"),u=a.process,d=u&&u.versions,f=d&&d.v8,c,v;f?(c=f.split("."),v=c[0]+c[1]):i&&(c=i.match(/Edge\/(\d+)/),(!c||c[1]>=74)&&(c=i.match(/Chrome\/(\d+)/),c&&(v=c[1]))),r.exports=v&&+v},"342f":function(r,l,t){var a=t("d066");r.exports=a("navigator","userAgent")||""},"35a1":function(r,l,t){var a=t("f5df"),i=t("3f8c"),u=t("b622"),d=u("iterator");r.exports=function(f){if(f!=null)return f[d]||f["@@iterator"]||i[a(f)]}},"37e8":function(r,l,t){var a=t("83ab"),i=t("9bf2"),u=t("825a"),d=t("df75");r.exports=a?Object.defineProperties:function(c,v){u(c);for(var h=d(v),p=h.length,g=0,b;p>g;)i.f(c,b=h[g++],v[b]);return c}},"3bbe":function(r,l,t){var a=t("861d");r.exports=function(i){if(!a(i)&&i!==null)throw TypeError("Can't set "+String(i)+" as a prototype");return i}},"3ca3":function(r,l,t){var a=t("6547").charAt,i=t("69f3"),u=t("7dd0"),d="String Iterator",f=i.set,c=i.getterFor(d);u(String,"String",function(v){f(this,{type:d,string:String(v),index:0})},function(){var h=c(this),p=h.string,g=h.index,b;return g>=p.length?{value:void 0,done:!0}:(b=a(p,g),h.index+=b.length,{value:b,done:!1})})},"3f8c":function(r,l){r.exports={}},4160:function(r,l,t){var a=t("23e7"),i=t("17c2");a({target:"Array",proto:!0,forced:[].forEach!=i},{forEach:i})},"428f":function(r,l,t){var a=t("da84");r.exports=a},"44ad":function(r,l,t){var a=t("d039"),i=t("c6b6"),u="".split;r.exports=a(function(){return!Object("z").propertyIsEnumerable(0)})?function(d){return i(d)=="String"?u.call(d,""):Object(d)}:Object},"44d2":function(r,l,t){var a=t("b622"),i=t("7c73"),u=t("9bf2"),d=a("unscopables"),f=Array.prototype;f[d]==null&&u.f(f,d,{configurable:!0,value:i(null)}),r.exports=function(c){f[d][c]=!0}},"44e7":function(r,l,t){var a=t("861d"),i=t("c6b6"),u=t("b622"),d=u("match");r.exports=function(f){var c;return a(f)&&((c=f[d])!==void 0?!!c:i(f)=="RegExp")}},4930:function(r,l,t){var a=t("d039");r.exports=!!Object.getOwnPropertySymbols&&!a(function(){return!String(Symbol())})},"4d64":function(r,l,t){var a=t("fc6a"),i=t("50c4"),u=t("23cb"),d=function(f){return function(c,v,h){var p=a(c),g=i(p.length),b=u(h,g),S;if(f&&v!=v){for(;g>b;)if(S=p[b++],S!=S)return!0}else for(;g>b;b++)if((f||b in p)&&p[b]===v)return f||b||0;return!f&&-1}};r.exports={includes:d(!0),indexOf:d(!1)}},"4de4":function(r,l,t){var a=t("23e7"),i=t("b727").filter,u=t("1dde"),d=t("ae40"),f=u("filter"),c=d("filter");a({target:"Array",proto:!0,forced:!f||!c},{filter:function(h){return i(this,h,arguments.length>1?arguments[1]:void 0)}})},"4df4":function(r,l,t){var a=t("0366"),i=t("7b0b"),u=t("9bdd"),d=t("e95a"),f=t("50c4"),c=t("8418"),v=t("35a1");r.exports=function(p){var g=i(p),b=typeof this=="function"?this:Array,S=arguments.length,T=S>1?arguments[1]:void 0,x=T!==void 0,P=v(g),O=0,j,$,I,M,N,Y;if(x&&(T=a(T,S>2?arguments[2]:void 0,2)),P!=null&&!(b==Array&&d(P)))for(M=P.call(g),N=M.next,$=new b;!(I=N.call(M)).done;O++)Y=x?u(M,T,[I.value,O],!0):I.value,c($,O,Y);else for(j=f(g.length),$=new b(j);j>O;O++)Y=x?T(g[O],O):g[O],c($,O,Y);return $.length=O,$}},"4fad":function(r,l,t){var a=t("23e7"),i=t("6f53").entries;a({target:"Object",stat:!0},{entries:function(d){return i(d)}})},"50c4":function(r,l,t){var a=t("a691"),i=Math.min;r.exports=function(u){return u>0?i(a(u),9007199254740991):0}},5135:function(r,l){var t={}.hasOwnProperty;r.exports=function(a,i){return t.call(a,i)}},5319:function(r,l,t){var a=t("d784"),i=t("825a"),u=t("7b0b"),d=t("50c4"),f=t("a691"),c=t("1d80"),v=t("8aa5"),h=t("14c3"),p=Math.max,g=Math.min,b=Math.floor,S=/\$([$&'`]|\d\d?|<[^>]*>)/g,T=/\$([$&'`]|\d\d?)/g,x=function(P){return P===void 0?P:String(P)};a("replace",2,function(P,O,j,$){var I=$.REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE,M=$.REPLACE_KEEPS_$0,N=I?"$":"$0";return[function(R,X){var w=c(this),U=R==null?void 0:R[P];return U!==void 0?U.call(R,w,X):O.call(String(w),R,X)},function(C,R){if(!I&&M||typeof R=="string"&&R.indexOf(N)===-1){var X=j(O,C,this,R);if(X.done)return X.value}var w=i(C),U=String(this),tt=typeof R=="function";tt||(R=String(R));var ot=w.global;if(ot){var St=w.unicode;w.lastIndex=0}for(var ft=[];;){var dt=h(w,U);if(dt===null||(ft.push(dt),!ot))break;var yt=String(dt[0]);yt===""&&(w.lastIndex=v(U,d(w.lastIndex),St))}for(var bt="",gt=0,at=0;at=gt&&(bt+=U.slice(gt,Mt)+Et,gt=Mt+lt.length)}return bt+U.slice(gt)}];function Y(C,R,X,w,U,tt){var ot=X+C.length,St=w.length,ft=T;return U!==void 0&&(U=u(U),ft=S),O.call(tt,ft,function(dt,yt){var bt;switch(yt.charAt(0)){case"$":return"$";case"&":return C;case"`":return R.slice(0,X);case"'":return R.slice(ot);case"<":bt=U[yt.slice(1,-1)];break;default:var gt=+yt;if(gt===0)return dt;if(gt>St){var at=b(gt/10);return at===0?dt:at<=St?w[at-1]===void 0?yt.charAt(1):w[at-1]+yt.charAt(1):dt}bt=w[gt-1]}return bt===void 0?"":bt})}})},5692:function(r,l,t){var a=t("c430"),i=t("c6cd");(r.exports=function(u,d){return i[u]||(i[u]=d!==void 0?d:{})})("versions",[]).push({version:"3.6.5",mode:a?"pure":"global",copyright:"© 2020 Denis Pushkarev (zloirock.ru)"})},"56ef":function(r,l,t){var a=t("d066"),i=t("241c"),u=t("7418"),d=t("825a");r.exports=a("Reflect","ownKeys")||function(c){var v=i.f(d(c)),h=u.f;return h?v.concat(h(c)):v}},"5a34":function(r,l,t){var a=t("44e7");r.exports=function(i){if(a(i))throw TypeError("The method doesn't accept regular expressions");return i}},"5c6c":function(r,l){r.exports=function(t,a){return{enumerable:!(t&1),configurable:!(t&2),writable:!(t&4),value:a}}},"5db7":function(r,l,t){var a=t("23e7"),i=t("a2bf"),u=t("7b0b"),d=t("50c4"),f=t("1c0b"),c=t("65f0");a({target:"Array",proto:!0},{flatMap:function(h){var p=u(this),g=d(p.length),b;return f(h),b=c(p,0),b.length=i(b,p,p,g,0,1,h,arguments.length>1?arguments[1]:void 0),b}})},6547:function(r,l,t){var a=t("a691"),i=t("1d80"),u=function(d){return function(f,c){var v=String(i(f)),h=a(c),p=v.length,g,b;return h<0||h>=p?d?"":void 0:(g=v.charCodeAt(h),g<55296||g>56319||h+1===p||(b=v.charCodeAt(h+1))<56320||b>57343?d?v.charAt(h):g:d?v.slice(h,h+2):(g-55296<<10)+(b-56320)+65536)}};r.exports={codeAt:u(!1),charAt:u(!0)}},"65f0":function(r,l,t){var a=t("861d"),i=t("e8b5"),u=t("b622"),d=u("species");r.exports=function(f,c){var v;return i(f)&&(v=f.constructor,typeof v=="function"&&(v===Array||i(v.prototype))?v=void 0:a(v)&&(v=v[d],v===null&&(v=void 0))),new(v===void 0?Array:v)(c===0?0:c)}},"69f3":function(r,l,t){var a=t("7f9a"),i=t("da84"),u=t("861d"),d=t("9112"),f=t("5135"),c=t("f772"),v=t("d012"),h=i.WeakMap,p,g,b,S=function(I){return b(I)?g(I):p(I,{})},T=function(I){return function(M){var N;if(!u(M)||(N=g(M)).type!==I)throw TypeError("Incompatible receiver, "+I+" required");return N}};if(a){var x=new h,P=x.get,O=x.has,j=x.set;p=function(I,M){return j.call(x,I,M),M},g=function(I){return P.call(x,I)||{}},b=function(I){return O.call(x,I)}}else{var $=c("state");v[$]=!0,p=function(I,M){return d(I,$,M),M},g=function(I){return f(I,$)?I[$]:{}},b=function(I){return f(I,$)}}r.exports={set:p,get:g,has:b,enforce:S,getterFor:T}},"6eeb":function(r,l,t){var a=t("da84"),i=t("9112"),u=t("5135"),d=t("ce4e"),f=t("8925"),c=t("69f3"),v=c.get,h=c.enforce,p=String(String).split("String");(r.exports=function(g,b,S,T){var x=T?!!T.unsafe:!1,P=T?!!T.enumerable:!1,O=T?!!T.noTargetGet:!1;if(typeof S=="function"&&(typeof b=="string"&&!u(S,"name")&&i(S,"name",b),h(S).source=p.join(typeof b=="string"?b:"")),g===a){P?g[b]=S:d(b,S);return}else x?!O&&g[b]&&(P=!0):delete g[b];P?g[b]=S:i(g,b,S)})(Function.prototype,"toString",function(){return typeof this=="function"&&v(this).source||f(this)})},"6f53":function(r,l,t){var a=t("83ab"),i=t("df75"),u=t("fc6a"),d=t("d1e7").f,f=function(c){return function(v){for(var h=u(v),p=i(h),g=p.length,b=0,S=[],T;g>b;)T=p[b++],(!a||d.call(h,T))&&S.push(c?[T,h[T]]:h[T]);return S}};r.exports={entries:f(!0),values:f(!1)}},"73d9":function(r,l,t){var a=t("44d2");a("flatMap")},7418:function(r,l){l.f=Object.getOwnPropertySymbols},"746f":function(r,l,t){var a=t("428f"),i=t("5135"),u=t("e538"),d=t("9bf2").f;r.exports=function(f){var c=a.Symbol||(a.Symbol={});i(c,f)||d(c,f,{value:u.f(f)})}},7839:function(r,l){r.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},"7b0b":function(r,l,t){var a=t("1d80");r.exports=function(i){return Object(a(i))}},"7c73":function(r,l,t){var a=t("825a"),i=t("37e8"),u=t("7839"),d=t("d012"),f=t("1be4"),c=t("cc12"),v=t("f772"),h=">",p="<",g="prototype",b="script",S=v("IE_PROTO"),T=function(){},x=function(I){return p+b+h+I+p+"/"+b+h},P=function(I){I.write(x("")),I.close();var M=I.parentWindow.Object;return I=null,M},O=function(){var I=c("iframe"),M="java"+b+":",N;return I.style.display="none",f.appendChild(I),I.src=String(M),N=I.contentWindow.document,N.open(),N.write(x("document.F=Object")),N.close(),N.F},j,$=function(){try{j=document.domain&&new ActiveXObject("htmlfile")}catch{}$=j?P(j):O();for(var I=u.length;I--;)delete $[g][u[I]];return $()};d[S]=!0,r.exports=Object.create||function(M,N){var Y;return M!==null?(T[g]=a(M),Y=new T,T[g]=null,Y[S]=M):Y=$(),N===void 0?Y:i(Y,N)}},"7dd0":function(r,l,t){var a=t("23e7"),i=t("9ed3"),u=t("e163"),d=t("d2bb"),f=t("d44e"),c=t("9112"),v=t("6eeb"),h=t("b622"),p=t("c430"),g=t("3f8c"),b=t("ae93"),S=b.IteratorPrototype,T=b.BUGGY_SAFARI_ITERATORS,x=h("iterator"),P="keys",O="values",j="entries",$=function(){return this};r.exports=function(I,M,N,Y,C,R,X){i(N,M,Y);var w=function(at){if(at===C&&ft)return ft;if(!T&&at in ot)return ot[at];switch(at){case P:return function(){return new N(this,at)};case O:return function(){return new N(this,at)};case j:return function(){return new N(this,at)}}return function(){return new N(this)}},U=M+" Iterator",tt=!1,ot=I.prototype,St=ot[x]||ot["@@iterator"]||C&&ot[C],ft=!T&&St||w(C),dt=M=="Array"&&ot.entries||St,yt,bt,gt;if(dt&&(yt=u(dt.call(new I)),S!==Object.prototype&&yt.next&&(!p&&u(yt)!==S&&(d?d(yt,S):typeof yt[x]!="function"&&c(yt,x,$)),f(yt,U,!0,!0),p&&(g[U]=$))),C==O&&St&&St.name!==O&&(tt=!0,ft=function(){return St.call(this)}),(!p||X)&&ot[x]!==ft&&c(ot,x,ft),g[M]=ft,C)if(bt={values:w(O),keys:R?ft:w(P),entries:w(j)},X)for(gt in bt)(T||tt||!(gt in ot))&&v(ot,gt,bt[gt]);else a({target:M,proto:!0,forced:T||tt},bt);return bt}},"7f9a":function(r,l,t){var a=t("da84"),i=t("8925"),u=a.WeakMap;r.exports=typeof u=="function"&&/native code/.test(i(u))},"825a":function(r,l,t){var a=t("861d");r.exports=function(i){if(!a(i))throw TypeError(String(i)+" is not an object");return i}},"83ab":function(r,l,t){var a=t("d039");r.exports=!a(function(){return Object.defineProperty({},1,{get:function(){return 7}})[1]!=7})},8418:function(r,l,t){var a=t("c04e"),i=t("9bf2"),u=t("5c6c");r.exports=function(d,f,c){var v=a(f);v in d?i.f(d,v,u(0,c)):d[v]=c}},"861d":function(r,l){r.exports=function(t){return typeof t=="object"?t!==null:typeof t=="function"}},8875:function(r,l,t){var a,i,u;(function(d,f){i=[],a=f,u=typeof a=="function"?a.apply(l,i):a,u!==void 0&&(r.exports=u)})(typeof self<"u"?self:this,function(){function d(){var f=Object.getOwnPropertyDescriptor(document,"currentScript");if(!f&&"currentScript"in document&&document.currentScript||f&&f.get!==d&&document.currentScript)return document.currentScript;try{throw new Error}catch(j){var c=/.*at [^(]*\((.*):(.+):(.+)\)$/ig,v=/@([^@]*):(\d+):(\d+)\s*$/ig,h=c.exec(j.stack)||v.exec(j.stack),p=h&&h[1]||!1,g=h&&h[2]||!1,b=document.location.href.replace(document.location.hash,""),S,T,x,P=document.getElementsByTagName("script");p===b&&(S=document.documentElement.outerHTML,T=new RegExp("(?:[^\\n]+?\\n){0,"+(g-2)+"}[^<]* diff --git a/src/resources/assets/js/volumes/components/geotiffOverlayForm.vue b/src/resources/assets/js/volumes/components/geotiffOverlayForm.vue new file mode 100644 index 00000000..7be2e3fb --- /dev/null +++ b/src/resources/assets/js/volumes/components/geotiffOverlayForm.vue @@ -0,0 +1,84 @@ + + + diff --git a/src/resources/assets/js/volumes/components/overlayItem.vue b/src/resources/assets/js/volumes/components/overlayItem.vue new file mode 100644 index 00000000..d9395b2d --- /dev/null +++ b/src/resources/assets/js/volumes/components/overlayItem.vue @@ -0,0 +1,116 @@ + + + + diff --git a/src/resources/assets/js/volumes/components/overlayTable.vue b/src/resources/assets/js/volumes/components/overlayTable.vue new file mode 100644 index 00000000..830c12a9 --- /dev/null +++ b/src/resources/assets/js/volumes/components/overlayTable.vue @@ -0,0 +1,141 @@ + + + + + diff --git a/src/resources/assets/js/volumes/components/webmapOverlayForm.vue b/src/resources/assets/js/volumes/components/webmapOverlayForm.vue new file mode 100644 index 00000000..67fa113d --- /dev/null +++ b/src/resources/assets/js/volumes/components/webmapOverlayForm.vue @@ -0,0 +1,82 @@ + + + + + diff --git a/src/resources/assets/js/volumes/geoFilter.js b/src/resources/assets/js/volumes/geoFilter.js index 58093ad0..ffc50bae 100644 --- a/src/resources/assets/js/volumes/geoFilter.js +++ b/src/resources/assets/js/volumes/geoFilter.js @@ -1,5 +1,5 @@ -import {VolumeFilters} from './import.js'; -import {FilterList} from './import.js'; +import { VolumeFilters } from './import.js'; +import { FilterList } from './import.js'; import FilterSelect from '../volumes/components/filterByLocationComponent.vue'; /** @@ -24,7 +24,7 @@ if (Array.isArray(VolumeFilters)) { extends: FilterSelect, }, getSequence(volumeId, data) { - return Promise.resolve({data}); + return Promise.resolve({ data }); } }); } diff --git a/src/resources/assets/js/volumes/geoOverlayUpload.vue b/src/resources/assets/js/volumes/geoOverlayUpload.vue new file mode 100644 index 00000000..6b46826c --- /dev/null +++ b/src/resources/assets/js/volumes/geoOverlayUpload.vue @@ -0,0 +1,93 @@ + diff --git a/src/resources/assets/js/volumes/import.js b/src/resources/assets/js/volumes/import.js index 69df9f2e..c8895caf 100644 --- a/src/resources/assets/js/volumes/import.js +++ b/src/resources/assets/js/volumes/import.js @@ -1,5 +1,12 @@ +export let EditorMixin = biigle.$require('core.mixins.editor'); export let FilterList = biigle.$require('volumes.components.filterListComponent'); +export let handleErrorResponse = biigle.$require('messages').handleErrorResponse; +export let Messages = biigle.$require('messages'); export let LoaderMixin = biigle.$require('core.mixins.loader'); -export let Resource = biigle.$require('resource'); +export let Tab = biigle.$require('uiv.tab'); +export let Tabs = biigle.$require('uiv.tabs'); export let VolumeFilters = biigle.$require('volumes.stores.filters'); +export let Resource = biigle.$require('resource'); export let Modal = biigle.$require('uiv.modal'); +export let Echo = biigle.$require('echo'); +export let Events = biigle.$require('events'); diff --git a/src/resources/assets/js/volumes/mounts.js b/src/resources/assets/js/volumes/mounts.js new file mode 100644 index 00000000..feb37544 --- /dev/null +++ b/src/resources/assets/js/volumes/mounts.js @@ -0,0 +1,3 @@ +import GeoOverlayUpload from './geoOverlayUpload.vue'; + +biigle.$mount('volume-geo-overlay-upload', GeoOverlayUpload); diff --git a/src/resources/assets/js/volumes/main.js b/src/resources/assets/js/volumes/volumes.js similarity index 53% rename from src/resources/assets/js/volumes/main.js rename to src/resources/assets/js/volumes/volumes.js index 449fae97..9ea5e539 100644 --- a/src/resources/assets/js/volumes/main.js +++ b/src/resources/assets/js/volumes/volumes.js @@ -1 +1,2 @@ import './geoFilter.js'; +import './mounts.js'; diff --git a/src/resources/views/imagesIndex.blade.php b/src/resources/views/imagesIndex.blade.php index a099c2f3..6ebba09c 100644 --- a/src/resources/views/imagesIndex.blade.php +++ b/src/resources/views/imagesIndex.blade.php @@ -1,26 +1,27 @@ @if ($image->lng !== null && $image->lat !== null) -@push('scripts') -{{vite_hot(base_path('vendor/biigle/geo/hot'), ['src/resources/assets/js/geo/main.js'], 'vendor/geo')}} - -@endpush + @push('scripts') + {{vite_hot(base_path('vendor/biigle/geo/hot'), ['src/resources/assets/js/geo/main.js'], 'vendor/geo')}} + + @endpush -@push('styles') -{{vite_hot(base_path('vendor/biigle/geo/hot'), ['src/resources/assets/sass/main.scss'], 'vendor/geo')}} -@endpush + @push('styles') + {{vite_hot(base_path('vendor/biigle/geo/hot'), ['src/resources/assets/sass/main.scss'], 'vendor/geo')}} + @endpush -
-
-
- Location - - show all - +
+
+
+ Location + + show all + +
+
-
-
@endif diff --git a/src/resources/views/manual/tutorials/volume-edit-geo-overlay.blade.php b/src/resources/views/manual/tutorials/volume-edit-geo-overlay.blade.php new file mode 100644 index 00000000..a67c12e8 --- /dev/null +++ b/src/resources/views/manual/tutorials/volume-edit-geo-overlay.blade.php @@ -0,0 +1,71 @@ +@extends('manual.base') + +@section('manual-title') Geo Overlays @stop + +@section('manual-content') +
+

+ Geo Overlays are geo-referenced layers that can be used on maps to filter images. +

+

+ In the Geo Overlays panel, overlays can be created by uploading GeoTIFF files or linking web-map-services (WMS) + via URLs. + The panel is located in the Volume Edit View (click the button in the volume overview). It is displayed only if at least + one image in the volume contains geo information. + Show available upload options by using the button in the top-right corner of the Geo Overlays panel. +

+

GeoTIFF

+

+ The first upload option is to provide a GeoTIFF file (.tif or .tiff). The upload allows only GeoTIFFs that have + projected coordinate reference systems (CRS) and use the common EPSG Geodetic Parameter Dataset codes (e.g. EPSG:4326 for WGS84 CRS). It does not + support user-defined projected CRS.
+ After the upload, the GeoTIFF is tiled into lower-resolution JPG files for web-opimization. To ensure that the + uploaded GeoTIFF is displayed as expected, check the following two properties: +

+
    +
  1. + Make sure that the color-band of the GeoTIFF is normalized to the range of 0 to 255. +
  2. +
  3. + The NoData value should be smaller than the minimum value of all color bands (e.g. -9999). +
  4. +
+

Web Map Service (WMS)

+

+ The second option to embed an overlay is by providing the URL to a WMS source. If only the base URL of the WMS + is given, the first layer of the WMS is selected as the overlay. +

+

+ By providing an URL with query parameters, it is also possible to specify which layer of the WMS shall be used, + e.g., +

+
+ https://example.com/ows?service=WMS&version=1.3.0&request=GetCapabilities&layers=LAYER. +
+
+

+

Overlay Usage

+

+ In the Geo Overlay panel, each overlay is listed with its name and a button to show or hide it on the image volume map. + It can be removed by using the corresponding button. +

+
+
+

+ Overlapping overlays can be displayed in a custom order on the volume map. To sort overlays, drag the + them via the button to + the desired position (highest = top) in the Geo Overlays panel. +

+
+
+

+ Images can be filtered by using the Geo Filter + in the volume overview. +

+
+@endsection diff --git a/src/resources/views/manual/tutorials/volume-map.blade.php b/src/resources/views/manual/tutorials/volume-map.blade.php index 3bcb35cc..b84b7db5 100644 --- a/src/resources/views/manual/tutorials/volume-map.blade.php +++ b/src/resources/views/manual/tutorials/volume-map.blade.php @@ -3,36 +3,60 @@ @section('manual-title') Image volume map @stop @section('manual-content') -
-

- The image volume map shows the locations of images on a world map. -

-

- If images of a volume contain the geo location in their metadata, they can be disblayed on the volume map. For these volumes the button appears in the sidebar of the volume overview. Click this button to view the image volume map. The volume map is not available for video volumes. -

-

- -

-

- The locations of the images are displayed as dots on the map. Grab and move the map with the cursor to pan around or use the mouse wheel to zoom. Use the button to fit the view back to the viewport that shows the locations of all images. -

-

Annotation filter

-

- You can filter the displayed locations by annotations that the images contain. This allows you to explore the spatial occurrence of different species or objects that you annotated earlier. Open the label trees tab at the right with a click on the button. Now select a label from the label trees. The displayed locations will immediately update to show only images that contain annotations which have the selected label attached. You can also select multiple labels at the same time. The map will show the locations of images where any of the selected labels occur. -

-

- -

-

Geo filter

-

- The volume map allows you to filter the images displayed in the volume overview as well. To do this, activate the "geo selection" filter in the filter tab of the volume overview. Then select image locations on the volume map by drawing an encompassing rectangle. To do this, press and hold Ctrl as well as the left mouse button and move the cursor on the map. Release the mouse button to finish the rectangle. You can also select individual locations with a single click or add locations to an existing selection with Shift and a single click. -

-

- - -

-

- Once there are selected image locations on the volume map, the volume overview will be immediately updated. You can use the geo filter in a "link and brush" way if you display the volume map and the volume overview side by side in two separate browser windows. -

-
+
+

+ An image volume map shows the locations of images on a world map. +

+

+ If images of a volume contain the geo location in their metadata, they can be disblayed on + the volume map. For these volumes the button appears in the sidebar of the volume overview. Click this + button to view the image volume map. The volume map is not available for video volumes. +

+

+ +

+

+ The locations of the images are displayed as dots on the map. Grab and move the map with the cursor to pan + around or use the mouse wheel to zoom. Use the button to fit the view back to the + viewport that shows the locations of all images. +

+

Annotation filter

+

+ You can filter the displayed locations by annotations that the images contain. This allows you to explore the + spatial occurrence of different species or objects that you annotated earlier. Open the label trees tab at the + right with a click on the button. Now + select a label from the label trees. The displayed locations will immediately update to show only images that + contain annotations which have the selected label attached. You can also select multiple labels at the same + time. The map will show the locations of images where any of the selected labels occur. +

+

+ +

+

Geo filter

+

+ Besides volume images, the volume map can also show Geo Overlays, which represent + uploaded GeoTIFFs or Web Map Service resources. The map allows you to filter images displayed in the volume + overview. To start filtering images, use the "geo selection" filter in the filter tab of the volume overview. Then + select image locations on the volume map by drawing an encompassing rectangle. Draw by pressing and holding + Ctrl as well as the left mouse button. Release the mouse button to finish the rectangle. You can also + select individual locations with a single click or add locations to an existing selection with Shift + and a single click. +

+ + +

+

+ Once there are selected image locations on the volume map, the volume overview will be immediately updated. You + can use the geo filter in a "link and brush" way if you display the volume map and the volume overview side by + side in two separate browser windows. +

+
@endsection diff --git a/src/resources/views/manualVolumes.blade.php b/src/resources/views/manualVolumes.blade.php new file mode 100644 index 00000000..67be821e --- /dev/null +++ b/src/resources/views/manualVolumes.blade.php @@ -0,0 +1,15 @@ +

+ Geo Overlays +

+ +

+ Geo Overlays can be used to filter images on the image volume map. +

+ +

+ Image Volume Map +

+ +

+ An image volume map shows image locations on a world map. +

diff --git a/src/resources/views/projects/show.blade.php b/src/resources/views/projects/show.blade.php index 31fe2a44..bf452e7a 100644 --- a/src/resources/views/projects/show.blade.php +++ b/src/resources/views/projects/show.blade.php @@ -3,39 +3,36 @@ @section('title', $project->name) @push('styles') -{{vite_hot(base_path('vendor/biigle/geo/hot'), ['src/resources/assets/sass/main.scss'], 'vendor/geo')}} + {{vite_hot(base_path('vendor/biigle/geo/hot'), ['src/resources/assets/sass/main.scss'], 'vendor/geo')}} @endpush @push('scripts') -{{vite_hot(base_path('vendor/biigle/geo/hot'), ['src/resources/assets/js/geo/main.js'], 'vendor/geo')}} - + {{vite_hot(base_path('vendor/biigle/geo/hot'), ['src/resources/assets/js/geo/main.js'], 'vendor/geo')}} + @endpush @section('content') -
- - - - - - -
+
+ + + + + + +
@endsection @section('navbar') - + @endsection diff --git a/src/resources/views/projectsShowTabs.blade.php b/src/resources/views/projectsShowTabs.blade.php index 0a9c425c..ca0891c5 100644 --- a/src/resources/views/projectsShowTabs.blade.php +++ b/src/resources/views/projectsShowTabs.blade.php @@ -1,5 +1,6 @@ @if ($project->hasGeoInfo()) -
  • - Map -
  • +
  • + Map +
  • @endif diff --git a/src/resources/views/volumes/edit/geotiffOverlayForm.blade.php b/src/resources/views/volumes/edit/geotiffOverlayForm.blade.php new file mode 100644 index 00000000..733f4399 --- /dev/null +++ b/src/resources/views/volumes/edit/geotiffOverlayForm.blade.php @@ -0,0 +1,10 @@ +
    +

    Upload a geo overlay in geoTIFF (.tif) format

    +
    +
    + + +
    +
    +
    +
    diff --git a/src/resources/views/volumes/edit/webmapOverlayForm.blade.php b/src/resources/views/volumes/edit/webmapOverlayForm.blade.php new file mode 100644 index 00000000..fb1fe3b2 --- /dev/null +++ b/src/resources/views/volumes/edit/webmapOverlayForm.blade.php @@ -0,0 +1,23 @@ +
    +

    Embed a geo overlay by providing a web-map-service url.

    +
    +
    +
    +
    + + +
    +
    + +
    +
    +
    +
    diff --git a/src/resources/views/volumesEditRight.blade.php b/src/resources/views/volumesEditRight.blade.php new file mode 100644 index 00000000..1a793208 --- /dev/null +++ b/src/resources/views/volumesEditRight.blade.php @@ -0,0 +1,44 @@ +@push('scripts') + +@endpush + +@if ($volume->isImageVolume() && $volume->hasGeoInfo()) +
    +
    + Geo overlays + + + + +
    +
    + + + + @include('geo::volumes.edit.geotiffOverlayForm') + + + + + @include('geo::volumes.edit.webmapOverlayForm') + + + +
    +
    + +
    +
    +
      +
    • This volume has no geo overlays. Add some.
    • +
    +
    +
    +@endif diff --git a/src/resources/views/volumesEditScripts.blade.php b/src/resources/views/volumesEditScripts.blade.php new file mode 100644 index 00000000..eb9ac9c5 --- /dev/null +++ b/src/resources/views/volumesEditScripts.blade.php @@ -0,0 +1,8 @@ +@if ($volume->isImageVolume() && $volume->hasGeoInfo()) + @push('scripts') + {{vite_hot(base_path('vendor/biigle/geo/hot'), ['src/resources/assets/js/volumes/volumes.js'], 'vendor/geo')}} + + @endpush +@endif diff --git a/src/resources/views/volumesEditStyles.blade.php b/src/resources/views/volumesEditStyles.blade.php new file mode 100644 index 00000000..b009342b --- /dev/null +++ b/src/resources/views/volumesEditStyles.blade.php @@ -0,0 +1 @@ + diff --git a/src/resources/views/volumesScripts.blade.php b/src/resources/views/volumesScripts.blade.php index d2f154a8..885921ee 100644 --- a/src/resources/views/volumesScripts.blade.php +++ b/src/resources/views/volumesScripts.blade.php @@ -1,3 +1,3 @@ @if ($volume->isImageVolume() && $volume->hasGeoInfo()) -{{vite_hot(base_path('vendor/biigle/geo/hot'), ['src/resources/assets/js/volumes/main.js'], 'vendor/geo')}} + {{vite_hot(base_path('vendor/biigle/geo/hot'), ['src/resources/assets/js/volumes/volumes.js'], 'vendor/geo')}} @endif diff --git a/src/resources/views/volumesSidebar.blade.php b/src/resources/views/volumesSidebar.blade.php index 97074a5c..d1b1c98b 100644 --- a/src/resources/views/volumesSidebar.blade.php +++ b/src/resources/views/volumesSidebar.blade.php @@ -1,3 +1,4 @@ @if ($volume->isImageVolume() && $volume->hasGeoInfo()) - + @endif diff --git a/src/resources/views/volumesStyles.blade.php b/src/resources/views/volumesStyles.blade.php index b3b1f7fb..1f5a089e 100644 --- a/src/resources/views/volumesStyles.blade.php +++ b/src/resources/views/volumesStyles.blade.php @@ -1,3 +1,3 @@ @if ($volume->isImageVolume() && $volume->hasGeoInfo()) -{{vite_hot(base_path('vendor/biigle/geo/hot'), ['src/resources/assets/sass/main.scss'], 'vendor/geo')}} + {{vite_hot(base_path('vendor/biigle/geo/hot'), ['src/resources/assets/sass/main.scss'], 'vendor/geo')}} @endif diff --git a/src/routes.php b/src/routes.php index 78ce64ba..584d02a6 100644 --- a/src/routes.php +++ b/src/routes.php @@ -5,12 +5,12 @@ 'namespace' => 'Views', ], function ($router) { $router->get('volumes/{id}/geo', [ - 'as' => 'volume-geo', + 'as' => 'volume-geo', 'uses' => 'VolumeController@show', ]); $router->get('projects/{id}/geo', [ - 'as' => 'project-geo', + 'as' => 'project-geo', 'uses' => 'ProjectController@show', ]); }); @@ -23,7 +23,32 @@ $router->get('projects/{id}/images/filter/annotation-label/{id2}', [ 'uses' => 'ProjectImageAnnotationLabelController@index', ]); + $router->get('volumes/{id}/coordinates', [ 'uses' => 'FileCoordinatesController@index', ]); -}); \ No newline at end of file + + // GeoTIFF + $router->post('volumes/{id}/geo-overlays/geotiff', [ + 'uses' => 'GeoTiffOverlayController@storeGeoTiff', + ]); + + // WebMap + $router->post('volumes/{id}/geo-overlays/webmap', [ + 'uses' => 'WebMapOverlayController@store', + ]); + + // GeoOverlays + $router->get('volumes/{id}/geo-overlays', [ + 'uses' => 'GeoOverlayController@getOverlays', + ]); + + $router->resource('geo-overlays', 'GeoOverlayController', [ + 'only' => ['destroy'], + 'parameters' => ['geo-overlays' => 'id'], + ]); + + $router->put('volumes/{id}/geo-overlays', [ + 'uses' => 'GeoOverlayController@updateGeoOverlays', + ]); +}); diff --git a/tests/GeoOverlayTest.php b/tests/GeoOverlayTest.php new file mode 100644 index 00000000..a66bb738 --- /dev/null +++ b/tests/GeoOverlayTest.php @@ -0,0 +1,114 @@ +create(); + $this->assertNotNull($geotiff->name); + $this->assertTrue(is_float(floatval($geotiff->attrs['top_left_lng']))); + $this->assertTrue(is_float(floatval($geotiff->attrs['top_left_lat']))); + $this->assertTrue(is_float(floatval($geotiff->attrs['bottom_right_lng']))); + $this->assertTrue(is_float(floatval($geotiff->attrs['bottom_right_lat']))); + $this->assertNull($geotiff->created_at); + $this->assertNull($geotiff->updated_at); + $this->assertTrue(is_int($geotiff->attrs['width'])); + $this->assertTrue(is_int($geotiff->attrs['height'])); + $this->assertEquals($geotiff->type, 'geotiff'); + + $webmap = GeoOverlay::factory()->webMap()->create(); + $this->assertNotNull($webmap->name); + $this->assertTrue(is_string($webmap->attrs['layer'])); + $this->assertTrue(is_string($webmap->attrs['url'])); + $this->assertNull($webmap->created_at); + $this->assertNull($webmap->updated_at); + $this->assertEquals($webmap->type, 'webmap'); + } + + public function testBuildGeoTiff() + { + $volume = Volume::factory()->create(); + $overlay = GeoOverlay::build($volume->id, "test", "geotiff", 0, [ + [-2.9213164328107, 57.096651484989, -2.9185182540292, 57.097626526122], + [3, 2] + ]); + + $this->assertEquals($volume->id, $overlay->volume_id); + $this->assertEquals($overlay->type, 'geotiff'); + $this->assertEquals($overlay->name, 'test'); + $this->assertEquals($overlay->layer_index, 0); + $this->assertEquals(-2.9213164328107, $overlay->attrs['top_left_lng']); + $this->assertEquals(57.096651484989, $overlay->attrs['top_left_lat']); + $this->assertEquals(-2.9185182540292, $overlay->attrs['bottom_right_lng']); + $this->assertEquals(57.097626526122, $overlay->attrs['bottom_right_lat']); + $this->assertNull($overlay->created_at); + $this->assertNull($overlay->updated_at); + $this->assertEquals(3, $overlay->attrs['width']); + $this->assertEquals(2, $overlay->attrs['height']); + } + + public function testBuildWebMap() + { + $volume = Volume::factory()->create(); + $overlay = GeoOverlay::build($volume->id, "test", "webmap", 0, [ + [-2.9213164328107, 57.096651484989, -2.9185182540292, 57.097626526122], + 'https://example.com', + 'test' + ]); + + $this->assertEquals($volume->id, $overlay->volume_id); + $this->assertEquals($overlay->type, 'webmap'); + $this->assertEquals($overlay->name, 'test'); + $this->assertEquals($overlay->layer_index, 0); + $this->assertEquals(-2.9213164328107, $overlay->attrs['top_left_lng']); + $this->assertEquals(57.096651484989, $overlay->attrs['top_left_lat']); + $this->assertEquals(-2.9185182540292, $overlay->attrs['bottom_right_lng']); + $this->assertEquals(57.097626526122, $overlay->attrs['bottom_right_lat']); + $this->assertNull($overlay->created_at); + $this->assertNull($overlay->updated_at); + $this->assertEquals('https://example.com', $overlay->attrs['url']); + $this->assertEquals('test', $overlay->attrs['layer']); + } + + public function testBuildWebMapWithoutCoords() + { + $volume = Volume::factory()->create(); + $overlay = GeoOverlay::build($volume->id, "test", "webmap", 0, [ + [], + 'https://example.com', + 'test' + ]); + + $this->assertEquals($volume->id, $overlay->volume_id); + $this->assertEquals($overlay->type, 'webmap'); + $this->assertEquals($overlay->name, 'test'); + $this->assertEquals($overlay->layer_index, 0); + $this->assertArrayNotHasKey('top_left_lng', $overlay->attrs); + $this->assertArrayNotHasKey('top_left_lat', $overlay->attrs); + $this->assertArrayNotHasKey('bottom_right_lng', $overlay->attrs); + $this->assertArrayNotHasKey('bottom_right_lat', $overlay->attrs); + $this->assertNull($overlay->created_at); + $this->assertNull($overlay->updated_at); + $this->assertEquals('https://example.com', $overlay->attrs['url']); + $this->assertEquals('test', $overlay->attrs['layer']); + } + + public function testVolumeOnDeleteCascade() + { + $model = GeoOverlay::factory()->create(); + $model->volume->delete(); + $this->assertNull($model->fresh()); + } + + public function testPathAttribute() + { + $model = GeoOverlay::factory()->create(); + $this->assertEquals("{$model->id}/{$model->id}_original.tif", $model->getPathAttribute()); + } +} diff --git a/tests/Http/Controllers/Api/FileCoordinatesControllerTest.php b/tests/Http/Controllers/Api/FileCoordinatesControllerTest.php index 47ea44b4..54d2bd1d 100644 --- a/tests/Http/Controllers/Api/FileCoordinatesControllerTest.php +++ b/tests/Http/Controllers/Api/FileCoordinatesControllerTest.php @@ -38,7 +38,7 @@ public function testIndexImage() $this->get("/api/v1/volumes/{$id}/coordinates") ->assertExactJson([ [ - 'id' => 1, + 'id' => 1, 'lat' => -7.0772818384026, 'lng' => -88.464813199987 ] diff --git a/tests/Http/Controllers/Api/GeoOverlayControllerTest.php b/tests/Http/Controllers/Api/GeoOverlayControllerTest.php new file mode 100644 index 00000000..cedfa616 --- /dev/null +++ b/tests/Http/Controllers/Api/GeoOverlayControllerTest.php @@ -0,0 +1,228 @@ +volume()->id; + + // Create overlay-instance + $overlay = GeoOverlay::factory()->create(['volume_id' => $id]); + $updated_overlays = [ + [ + 'id' => $overlay->id, + 'volume_id' => $overlay->volume_id, + 'name' => $overlay->name, + 'browsing_layer' => false + ] + ]; + + $this->doTestApiRoute('PUT', "/api/v1/volumes/{$id}/geo-overlays"); + + $this->beEditor(); + // 403: The client does not have access rights to the content + $this->putJson("/api/v1/volumes/{$id}/geo-overlays", [ + 'updated_overlays' => $updated_overlays + ])->assertStatus(403); + + $this->beAdmin(); + // 422: The request was well-formed but was unable to be followed due to semantic errors. + // reason: no input data + $this->json('PUT', "/api/v1/volumes/{$id}/geo-overlays") + ->assertInvalid(['updated_overlays']); + + $this->putJson("/api/v1/volumes/{$id}/geo-overlays", [ + 'updated_overlays' => [] + ])->assertInvalid(['updated_overlays']); + + // invalid type + $updated_overlays[0]['browsing_layer'] = "test"; + $this->putJson("/api/v1/volumes/{$id}/geo-overlays", [ + 'updated_overlays' => $updated_overlays + ])->assertInvalid(['updated_overlays.0.browsing_layer']); + + // invalid id + $updated_overlays[0]['browsing_layer'] = true; + $updated_overlays[1] = $updated_overlays[0]; + $updated_overlays[0]['id'] = 99; + $this->putJson("/api/v1/volumes/{$id}/geo-overlays", [ + 'updated_overlays' => $updated_overlays + ])->assertJsonValidationErrors(['invalidIds' => 'GeoOverlay(s) with ids "99" do not exist.']); + + $updated_overlays[0]['id'] = $overlay->id; + unset($updated_overlays[1]); + // now test if updating with data will succeed with the correct values being returned + $this->putJson("/api/v1/volumes/{$id}/geo-overlays", [ + 'updated_overlays' => $updated_overlays + ])->assertStatus(200); + + $this->assertTrue($overlay->refresh()->browsing_layer); + } + + public function testUpdateGeoOverlayWrongOverlayIds() + { + $id = $this->volume()->id; + $vol = Volume::factory()->create(); + + // Overlay belongs to other volume + $overlay = GeoOverlay::factory()->create(['volume_id' => $vol->id]); + $updated_overlays = [ + [ + 'id' => $overlay->id, + 'volume_id' => $overlay->volume_id, + 'name' => $overlay->name, + 'layer_index' => 0 + ] + ]; + $this->beAdmin(); + + $this->putJson("/api/v1/volumes/{$id}/geo-overlays", [ + 'updated_overlays' => $updated_overlays + ])->assertInvalid(['invalidIds']); + + $overlay = GeoOverlay::factory()->create(['volume_id' => $id]); + $updated_overlays = [ + [ + 'id' => $overlay->id, + 'volume_id' => $overlay->volume_id, + 'name' => $overlay->name, + 'layer_index' => 0 + ] + ]; + + $this->putJson("/api/v1/volumes/{$vol->id}/geo-overlays", [ + 'updated_overlays' => $updated_overlays + ])->assertForbidden(); + } + + public function testUpdateGeoOverlayLayerIndex() + { + $id = $this->volume()->id; + $overlay = GeoOverlay::factory()->create(['volume_id' => $id]); + $updated_overlays = [ + [ + 'id' => $overlay->id, + 'volume_id' => $overlay->volume_id, + 'name' => $overlay->name, + 'layer_index' => 0 + ] + ]; + $this->beAdmin(); + + $updated_overlays[0]['layer_index'] = -1; + $this->putJson("/api/v1/volumes/{$id}/geo-overlays", [ + 'updated_overlays' => $updated_overlays + ])->assertInvalid(['updated_overlays.0.layer_index']); + + $updated_overlays[0]['layer_index'] = 0.1; + $this->putJson("/api/v1/volumes/{$id}/geo-overlays", [ + 'updated_overlays' => $updated_overlays + ])->assertInvalid(['updated_overlays.0.layer_index']); + + $updated_overlays[0]['layer_index'] = GeoOverlay::where('volume_id', $id)->count() + 1; + $this->putJson("/api/v1/volumes/{$id}/geo-overlays", [ + 'updated_overlays' => $updated_overlays + ])->assertInvalid(['updated_overlays.0.layer_index']); + + $updated_overlays[0]['layer_index'] = 0; + $this->putJson("/api/v1/volumes/{$id}/geo-overlays", [ + 'updated_overlays' => $updated_overlays + ])->assertStatus(200); + } + + public function testUpdateGeoOverlayInvalidRequest() + { + Storage::fake('geo-overlays'); + $id = $this->volume()->id; + $overlay = GeoOverlay::factory()->create(['volume_id' => $id]); + $updated_overlays = [ + [ + 'id' => $overlay->id, + 'volume_id' => $overlay->volume_id, + 'name' => $overlay->name + ] + ]; + $this->beAdmin(); + + $this->putJson("/api/v1/volumes/{$id}/geo-overlays", [ + 'updated_overlays' => $updated_overlays + ])->assertInvalid(['invalidUpdateKey']); + + $updated_overlays[0]['layer_index'] = 0; + $updated_overlays[0]['browsing_layer'] = true; + + $this->putJson("/api/v1/volumes/{$id}/geo-overlays", [ + 'updated_overlays' => $updated_overlays + ])->assertInvalid(['invalidUpdateKey']); + + $overlay2 = GeoOverlay::factory()->create(['volume_id' => $id]); + $updated_overlays = [ + [ + 'id' => $overlay->id, + 'volume_id' => $overlay->volume_id, + 'name' => $overlay->name, + 'browsing_layer' => true + ], + [ + 'id' => $overlay2->id, + 'volume_id' => $overlay2->volume_id, + 'name' => $overlay2->name, + 'layer_index' => 1 + ] + ]; + + $this->putJson("/api/v1/volumes/{$id}/geo-overlays", [ + 'updated_overlays' => $updated_overlays + ])->assertInvalid(['invalidRequest']); + } + + public function testGetOverlays() + { + $urlTemplate = "http://localhost:8000/storage/geo-overlays/:id/:id_tiles/{TileGroup}/{z}-{x}-{y}.png"; + // This overlay is still processing and should not be returned + GeoOverlay::factory()->create(['volume_id' => $this->volume()->id]); + // This overlay is already processed + $overlay = GeoOverlay::factory()->create([ + 'volume_id' => $this->volume()->id, + 'processed' => true + ]); + $overlayCount = GeoOverlay::where('volume_id', $this->volume()->id)->count(); + $id = $this->volume()->id; + + $this->beAdmin(); + $res = $this->getJson("/api/v1/volumes/{$id}/geo-overlays"); + $res->assertSuccessful(); + $overlay = json_decode($res->getContent(), true); + + $this->assertEquals(2, $overlayCount); + $this->assertCount(1, $overlay['geoOverlays']); + $this->assertEquals($urlTemplate, $overlay["urlTemplate"]); + } + + public function testDestroy() + { + Storage::fake('geo-overlays'); + $overlay = GeoOverlay::factory()->create(); + $overlay->volume_id = $this->volume()->id; + $overlay->save(); + $id = $overlay->id; + Storage::disk('geo-overlays')->put($overlay->path, 'content'); + + $this->doTestApiRoute('DELETE', "/api/v1/geo-overlays/{$id}"); + + $this->beEditor(); + $this->delete("/api/v1/geo-overlays/{$id}")->assertStatus(403); + + $this->beAdmin(); + $this->delete("/api/v1/geo-overlays/{$id}")->assertStatus(200); + $this->assertFalse(Storage::disk('geo-overlays')->exists($overlay->id)); + } +} diff --git a/tests/Http/Controllers/Api/GeoTiffOverlayControllerTest.php b/tests/Http/Controllers/Api/GeoTiffOverlayControllerTest.php new file mode 100644 index 00000000..5dce1f84 --- /dev/null +++ b/tests/Http/Controllers/Api/GeoTiffOverlayControllerTest.php @@ -0,0 +1,613 @@ +mock = Mockery::mock(GeoManager::class)->makePartial()->shouldAllowMockingProtectedMethods(); + $this->app->bind(GeoManager::class, fn() => $this->mock); + } + + public function testStoreGeotiff() + { + $id = $this->volume()->id; + $exif = [ + "System:FileName" => "geotiff_standardEPSG2013.tif", + "IFD0:ImageWidth" => 3, + "IFD0:ImageHeight" => 2, + "IFD0:PixelScale" => "57 53.125 0", + "IFD0:ModelTiePoint" => "0 0 0 344275.42 801113.187 0", + "GeoTiff:GTModelType" => 1, + "GeoTiff:ProjectedCSType" => 27700, + ]; + $file = UploadedFile::fake()->create('standardEPSG2013.tif', 1, 'image/tiff'); + + $this->doTestApiRoute('POST', "/api/v1/volumes/{$id}/geo-overlays/geotiff"); + + $this->beEditor(); + // 403: The client does not have access rights to the content + $this->postJson( + "/api/v1/volumes/{$id}/geo-overlays/geotiff", + [ + 'geotiff' => $file, + 'layer_index' => 0 + ] + )->assertStatus(403); + + $this->beAdmin(); + // 422: The request was well-formed but was unable to be followed due to semantic errors. + $this->postJson("/api/v1/volumes/{$id}/geo-overlays/geotiff") + ->assertInvalid(['geotiff', 'layer_index']); + + $emptyFile = UploadedFile::fake()->create('overlay.tif', 0, 'image/tiff'); + // check if "empty" geotiff fails properly + $this->postJson("/api/v1/volumes/{$id}/geo-overlays/geotiff", [ + 'geotiff' => $emptyFile, + 'layer_index' => 0 + ]) + ->assertInvalid('size'); + + $this->assertFalse(GeoOverlay::exists()); + + $this->mock->shouldReceive('getExifData')->once()->andReturn($exif); + + $response = $this->postJson( + "/api/v1/volumes/{$id}/geo-overlays/geotiff", + [ + 'geotiff' => $file, + 'layer_index' => 0 + ] + )->assertSuccessful(); + + Queue::assertPushed(TileSingleOverlay::class); + $overlay = json_decode($response->getContent(), true); + $this->assertNotNull($overlay); + $this->assertSame(57.0966514849888, $overlay['attrs']['top_left_lat']); + $this->assertSame(-2.9213164328107, $overlay['attrs']['top_left_lng']); + $this->assertSame(57.0976265261217, $overlay['attrs']['bottom_right_lat']); + $this->assertSame(-2.9185182540292, $overlay['attrs']['bottom_right_lng']); + $this->assertSame(3, $overlay['attrs']['width']); + $this->assertSame(2, $overlay['attrs']['height']); + $this->assertSame($overlay['type'], 'geotiff'); + $this->assertEquals(0, $overlay['layer_index']); + $this->assertSame($overlay['name'], 'standardEPSG2013.tif'); + $this->assertTrue($overlay['browsing_layer']); + $this->assertTrue(Storage::disk('geo-overlays')->exists($overlay['id'])); + } + + public function testStoreGeoTiffModelTransformTag() + { + $id = $this->volume()->id; + $this->beAdmin(); + $exif = [ + "System:FileName" => "geotiff_modelTransform.tiff", + "IFD0:ImageWidth" => 396, + "IFD0:ImageHeight" => 183, + "IFD0:ModelTransform" => "10 0 0 677920 0 10 0 5150930 0 0 0 0 0 0 0 1", + "GeoTiff:GTModelType" => 1, + "GeoTiff:GTRasterType" => 1, + "GeoTiff:ProjectedCSType" => 32632, + ]; + + $this->mock->shouldReceive('getExifData')->once()->andReturn($exif); + $file = UploadedFile::fake()->create('geotiff_modelTransform.tiff', 1, 'image/tiff'); + + $response = $this->postJson( + "/api/v1/volumes/{$id}/geo-overlays/geotiff", + [ + 'geotiff' => $file, + 'layer_index' => 0 + ] + )->assertSuccessful(); + + Queue::assertPushed(TileSingleOverlay::class); + $overlay2 = json_decode($response->getContent(), true); + $this->assertNotNull($overlay2); + $this->assertSame(46.4884400488204, $overlay2['attrs']['top_left_lat']); + $this->assertSame(11.3182638714155, $overlay2['attrs']['top_left_lng']); + $this->assertSame(46.503838038652, $overlay2['attrs']['bottom_right_lat']); + $this->assertSame(11.3705327969833, $overlay2['attrs']['bottom_right_lng']); + $this->assertSame(396, $overlay2['attrs']['width']); + $this->assertSame(183, $overlay2['attrs']['height']); + $this->assertSame('geotiff', $overlay2['type']); + $this->assertSame('geotiff_modelTransform.tiff', $overlay2['name']); + $this->assertTrue($overlay2['browsing_layer']); + $this->assertEquals(0, $overlay2['layer_index']); + $this->assertTrue(Storage::disk('geo-overlays')->exists($overlay2['id'])); + } + + public function testStoreGeotiffWrapPointCoords() + { + $id = $this->volume()->id; + $this->beAdmin(); + // _ + // Coordinates point to the map's wrapping point (case: LL = _| and UR = | ) + $exif = [ + 'IFD0:ImageWidth' => 5490, + 'IFD0:ImageHeight' => 5490, + 'IFD0:PixelScale' => '20 20 0', + 'IFD0:ModelTiePoint' => '0 0 0 300000 3100000 0', + 'IFD0:GDALNoData' => 0, + 'GeoTiff:GTModelType' => 1, + 'GeoTiff:GTRasterType' => 1, + 'GeoTiff:ProjectedCSType' => 32701, + ]; + + $this->mock->shouldReceive('getExifData')->once()->andReturn($exif); + $file = UploadedFile::fake()->create('geotiff_wrap_coords.tiff', 1, 'image/tiff'); + + $response = $this->postJson( + "/api/v1/volumes/{$id}/geo-overlays/geotiff", + [ + 'geotiff' => $file, + 'layer_index' => 0 + ] + )->assertSuccessful(); + + Queue::assertPushed(TileSingleOverlay::class); + $overlay2 = json_decode($response->getContent(), true); + $this->assertNotNull($overlay2); + $this->assertSame(-63.1617421941426, $overlay2['attrs']['top_left_lat']); + $this->assertSame(179.02766304111955, $overlay2['attrs']['top_left_lng']); + $this->assertSame(-62.2209238067761, $overlay2['attrs']['bottom_right_lat']); + $this->assertSame(181.2651555508601, $overlay2['attrs']['bottom_right_lng']); + $this->assertSame(5490, $overlay2['attrs']['width']); + $this->assertSame(5490, $overlay2['attrs']['height']); + $this->assertSame('geotiff', $overlay2['type']); + $this->assertSame('geotiff_wrap_coords.tiff', $overlay2['name']); + $this->assertTrue($overlay2['browsing_layer']); + $this->assertEquals(0, $overlay2['layer_index']); + $this->assertTrue(Storage::disk('geo-overlays')->exists($overlay2['id'])); + } + + public function testStoreGeotiffPixelScaleIllDefined() + { + $id = $this->volume()->id; + $this->beAdmin(); + + $exif = [ + 'IFD0:ImageWidth' => 5490, + 'IFD0:ImageHeight' => 5490, + 'IFD0:PixelScale' => '0 0 0', + 'IFD0:ModelTiePoint' => '0 0 0 300000 3100000 0', + 'IFD0:GDALNoData' => 0, + 'GeoTiff:GTModelType' => 1, + 'GeoTiff:GTRasterType' => 1, + 'GeoTiff:ProjectedCSType' => 32701, + ]; + + $this->mock->shouldReceive('getExifData')->once()->andReturn($exif); + $file = UploadedFile::fake()->create('geotiff_wrap_coords.tiff', 1, 'image/tiff'); + + $this->postJson( + "/api/v1/volumes/{$id}/geo-overlays/geotiff", + [ + 'geotiff' => $file, + 'layer_index' => 0 + ] + )->assertInvalid('affineTransformation'); + + Queue::assertNotPushed(TileSingleOverlay::class); + } + + public function testStoreGeotiffMissingData() + { + $id = $this->volume()->id; + $this->beAdmin(); + + // Missing PixelScale + $exif = [ + 'IFD0:ImageWidth' => 5490, + 'IFD0:ImageHeight' => 5490, + 'IFD0:ModelTiePoint' => '0 0 0 300000 3100000 0', + 'IFD0:GDALNoData' => 0, + 'GeoTiff:GTModelType' => 1, + 'GeoTiff:GTRasterType' => 1, + 'GeoTiff:ProjectedCSType' => 32701, + ]; + + $this->mock->shouldReceive('getExifData')->once()->andReturn($exif); + $file = UploadedFile::fake()->create('geotiff_wrap_coords.tiff', 1, 'image/tiff'); + + $this->postJson( + "/api/v1/volumes/{$id}/geo-overlays/geotiff", + [ + 'geotiff' => $file, + 'layer_index' => 0 + ] + )->assertInvalid('affineTransformation'); + + Queue::assertNotPushed(TileSingleOverlay::class); + + // Missing ModelTiePoint + $exif = [ + 'IFD0:ImageWidth' => 5490, + 'IFD0:ImageHeight' => 5490, + 'IFD0:PixelScale' => '0 0 0', + 'IFD0:GDALNoData' => 0, + 'GeoTiff:GTModelType' => 1, + 'GeoTiff:GTRasterType' => 1, + 'GeoTiff:ProjectedCSType' => 32701, + ]; + + $this->mock->shouldReceive('getExifData')->once()->andReturn($exif); + $file = UploadedFile::fake()->create('geotiff_wrap_coords.tiff', 1, 'image/tiff'); + + $this->postJson( + "/api/v1/volumes/{$id}/geo-overlays/geotiff", + [ + 'geotiff' => $file, + 'layer_index' => 0 + ] + )->assertInvalid('affineTransformation'); + + Queue::assertNotPushed(TileSingleOverlay::class); + + // No transform data given + $exif = [ + "IFD0:ImageWidth" => 396, + "IFD0:ImageHeight" => 183, + "GeoTiff:GTModelType" => 1, + "GeoTiff:ProjectedCSType" => 32632, + ]; + + $this->mock->shouldReceive('getExifData')->once()->andReturn($exif); + $file = UploadedFile::fake()->create('geotiff_modelTransform.tiff', 1, 'image/tiff'); + + $this->postJson( + "/api/v1/volumes/{$id}/geo-overlays/geotiff", + [ + 'geotiff' => $file, + 'layer_index' => 0 + ] + )->assertInvalid(['affineTransformation']); + Queue::assertNothingPushed(); + } + + public function testStoreGeotiffPrioritizeModelTransform() + { + $id = $this->volume()->id; + $this->beAdmin(); + + // Pixelscale is ill-defined, so use ModelTransform instead + $exif = [ + "System:FileName" => "geotiff_modelTransform.tiff", + "IFD0:ImageWidth" => 396, + "IFD0:ImageHeight" => 183, + 'IFD0:PixelScale' => '0 0 0', + 'IFD0:ModelTiePoint' => '0 0 0 300000 3100000 0', + "IFD0:ModelTransform" => "10 0 0 677920 0 10 0 5150930 0 0 0 0 0 0 0 1", + "GeoTiff:GTModelType" => 1, + "GeoTiff:GTRasterType" => 1, + "GeoTiff:ProjectedCSType" => 32632, + ]; + + $this->mock->shouldReceive('getExifData')->once()->andReturn($exif); + $file = UploadedFile::fake()->create('geotiff_modelTransform.tiff', 1, 'image/tiff'); + + $response = $this->postJson( + "/api/v1/volumes/{$id}/geo-overlays/geotiff", + [ + 'geotiff' => $file, + 'layer_index' => 0 + ] + )->assertSuccessful(); + + Queue::assertPushed(TileSingleOverlay::class); + $overlay2 = json_decode($response->getContent(), true); + $this->assertNotNull($overlay2); + $this->assertSame(46.4884400488204, $overlay2['attrs']['top_left_lat']); + $this->assertSame(11.3182638714155, $overlay2['attrs']['top_left_lng']); + $this->assertSame(46.503838038652, $overlay2['attrs']['bottom_right_lat']); + $this->assertSame(11.3705327969833, $overlay2['attrs']['bottom_right_lng']); + $this->assertSame(396, $overlay2['attrs']['width']); + $this->assertSame(183, $overlay2['attrs']['height']); + $this->assertSame('geotiff', $overlay2['type']); + $this->assertSame('geotiff_modelTransform.tiff', $overlay2['name']); + $this->assertTrue($overlay2['browsing_layer']); + $this->assertEquals(0, $overlay2['layer_index']); + $this->assertTrue(Storage::disk('geo-overlays')->exists($overlay2['id'])); + } + + + public function testStoreGeotiffWGS84() + { + $id = $this->volume()->id; + $this->beAdmin(); + // Allow geographic CRS if code EPSG 4326 is used + $exif = [ + 'IFD0:ImageWidth' => 768, + 'IFD0:ImageHeight' => 608, + 'IFD0:ModelTransform' => '0.0132309081041667 0 0 5.554322947 0 -0.0132389576726974 0 55.118670158 0 0 0 0 0 0 0 1', + 'IFD0:GDALNoData' => 0.0, + 'GeoTiff:GTModelType' => 2, + 'GeoTiff:GTRasterType' => 1, + 'GeoTiff:GeographicType' => 4326, + ]; + + $this->mock->shouldReceive('getExifData')->once()->andReturn($exif); + $file = UploadedFile::fake()->create('geotiff_wgs84.tiff', 1, 'image/tiff'); + + $response = $this->postJson( + "/api/v1/volumes/{$id}/geo-overlays/geotiff", + [ + 'geotiff' => $file, + 'layer_index' => 0 + ] + ); + $response->assertSuccessful(); + + Queue::assertPushed(TileSingleOverlay::class); + $overlay2 = json_decode($response->getContent(), true); + $this->assertNotNull($overlay2); + $this->assertSame(47.069383893, $overlay2['attrs']['top_left_lat']); + $this->assertSame(5.554322947, $overlay2['attrs']['top_left_lng']); + $this->assertSame(55.118670158, actual: $overlay2['attrs']['bottom_right_lat']); + $this->assertSame(15.715660371, $overlay2['attrs']['bottom_right_lng']); + $this->assertSame(768, $overlay2['attrs']['width']); + $this->assertSame(608, $overlay2['attrs']['height']); + $this->assertSame('geotiff', $overlay2['type']); + $this->assertSame('geotiff_wgs84.tiff', $overlay2['name']); + $this->assertTrue($overlay2['browsing_layer']); + $this->assertEquals(0, $overlay2['layer_index']); + $this->assertTrue(Storage::disk('geo-overlays')->exists($overlay2['id'])); + } + + public function testStoreGeotiffTransformErr() + { + $id = $this->volume()->id; + $this->beAdmin(); + $exif = [ + 'IFD0:ImageWidth' => 768, + 'IFD0:ImageHeight' => 608, + 'IFD0:ModelTransform' => '0.0132309081041667 0 0 5.554322947 0 -0.0132389576726974 0 55.118670158 0 0 0 0 0 0 0 1', + 'IFD0:GDALNoData' => 0.0, + 'GeoTiff:GTModelType' => 1, + 'GeoTiff:GTRasterType' => 1, + 'GeoTiff:ProjectedCSType' => 32701, + ]; + + $this->mock->shouldReceive('getExifData')->once()->andReturn($exif); + $this->mock->shouldReceive('transformToEPSG4326')->andThrow(new TransformCoordsException()); + $file = UploadedFile::fake()->create('geotiff_modelTransform.tiff', 1, 'image/tiff'); + + $this->postJson( + "/api/v1/volumes/{$id}/geo-overlays/geotiff", + [ + 'geotiff' => $file, + 'layer_index' => 0 + ] + )->assertInvalid(['failedTransformation']); + Queue::assertNothingPushed(); + } + + public function testStoreGeotiffAnyException() + { + $id = $this->volume()->id; + $this->beAdmin(); + $exif = [ + 'IFD0:ImageWidth' => 768, + 'IFD0:ImageHeight' => 608, + 'IFD0:ModelTransform' => '0.0132309081041667 0 0 5.554322947 0 -0.0132389576726974 0 55.118670158 0 0 0 0 0 0 0 1', + 'IFD0:GDALNoData' => 0.0, + 'GeoTiff:GTModelType' => 1, + 'GeoTiff:GTRasterType' => 1, + 'GeoTiff:ProjectedCSType' => 32701, + ]; + + $this->mock->shouldReceive('getExifData')->once()->andReturn($exif); + $this->mock->shouldReceive('convertToModelSpace')->andThrow(new Exception()); + $file = UploadedFile::fake()->create('geotiff_modelTransform.tiff', 1, 'image/tiff'); + + $this->postJson( + "/api/v1/volumes/{$id}/geo-overlays/geotiff", + [ + 'geotiff' => $file, + 'layer_index' => 0 + ] + )->assertInvalid(['failedUpload']); + Queue::assertNothingPushed(); + } + + public function testStoreInvalidLayerIndex() + { + $id = $this->volume()->id; + $this->beAdmin(); + + $this->mock->shouldReceive('getExifData')->never(); + $file = UploadedFile::fake()->create('geotiff_modelTransform.tiff', 1, 'image/tiff'); + + $this->postJson( + "/api/v1/volumes/{$id}/geo-overlays/geotiff", + [ + 'geotiff' => $file, + 'layer_index' => 99 + ] + )->assertInvalid(['layer_index']); + Queue::assertNothingPushed(); + } + + public function testStoreGeotiffMissingModelType() + { + $id = $this->volume()->id; + $this->beAdmin(); + $exif = [ + 'IFD0:ImageWidth' => 768, + 'IFD0:ImageHeight' => 608, + 'IFD0:GDALNoData' => 0.0, + 'GeoTiff:GTRasterType' => 1, + 'GeoTiff:ProjectedCSType' => 32701, + ]; + + $this->mock->shouldReceive('getExifData')->once()->andReturn($exif); + $file = UploadedFile::fake()->create('geotiff_color.tiff', 1, 'image/tiff'); + + $this->postJson( + "/api/v1/volumes/{$id}/geo-overlays/geotiff", + [ + 'geotiff' => $file, + 'layer_index' => 0 + ] + )->assertInvalid(['MissingModelType']); + Queue::assertNothingPushed(); + } + + public function testStoreGeotiffWrongModelType() + { + $id = $this->volume()->id; + $this->beAdmin(); + $exif = [ + 'IFD0:ImageWidth' => 768, + 'IFD0:ImageHeight' => 608, + 'GeoTiff:GTModelType' => 3, + 'GeoTiff:GTRasterType' => 1, + 'GeoTiff:GeocentricType' => 32701, + ]; + + $this->mock->shouldReceive('getExifData')->once()->andReturn($exif); + $file = UploadedFile::fake()->create('geotiff_modelTransform.tiff', 1, 'image/tiff'); + + $this->postJson( + "/api/v1/volumes/{$id}/geo-overlays/geotiff", + [ + 'geotiff' => $file, + 'layer_index' => 0 + ] + )->assertInvalid(['wrongModelType', 'noPCSKEY']); + Queue::assertNothingPushed(); + } + + public function testStoreGeotiffUndefinedCRS() + { + $id = $this->volume()->id; + $this->beAdmin(); + $exif = [ + 'IFD0:ImageWidth' => 768, + 'IFD0:ImageHeight' => 608, + 'IFD0:ModelTransform' => '0.0132309081041667 0 0 5.554322947 0 -0.0132389576726974 0 55.118670158 0 0 0 0 0 0 0 1', + 'IFD0:GDALNoData' => 0.0, + 'GeoTiff:GTModelType' => 1, + 'GeoTiff:GTRasterType' => 1, + 'GeoTiff:ProjectedCSType' => 0, + ]; + + $this->mock->shouldReceive('getExifData')->once()->andReturn($exif); + $file = UploadedFile::fake()->create('geotiff_modelTransform.tiff', 1, 'image/tiff'); + + $this->postJson( + "/api/v1/volumes/{$id}/geo-overlays/geotiff", + [ + 'geotiff' => $file, + 'layer_index' => 0 + ] + )->assertInvalid(['unDefined']); + Queue::assertNothingPushed(); + } + + public function testStoreGeotiffInvalidColorSpace() + { + $id = $this->volume()->id; + $this->beAdmin(); + $exif = [ + 'IFD0:ImageWidth' => 768, + 'IFD0:ImageHeight' => 608, + 'IFD0:ModelTransform' => '0.0132309081041667 0 0 5.554322947 0 -0.0132389576726974 0 55.118670158 0 0 0 0 0 0 0 1', + 'IFD0:GDALNoData' => 0.0, + 'GeoTiff:GTModelType' => 1, + 'GeoTiff:GTRasterType' => 1, + 'GeoTiff:ProjectedCSType' => 32701, + 'IFD0:SamplesPerPixel' => 5 + ]; + + $this->mock->shouldReceive('getExifData')->once()->andReturn($exif); + $this->mock->shouldReceive('convertToModelSpace')->andThrow(new Exception()); + $file = UploadedFile::fake()->create('geotiff_modelTransform.tiff', 1, 'image/tiff'); + + $this->postJson( + "/api/v1/volumes/{$id}/geo-overlays/geotiff", + [ + 'geotiff' => $file, + 'layer_index' => 0 + ] + )->assertInvalid(['invalidColorSpace']); + Queue::assertNothingPushed(); + } + + public function testStoreGeotiffCustomCode() + { + $id = $this->volume()->id; + $this->beAdmin(); + $exif = [ + "GeoTiff:GTModelType" => 1, + "GeoTiff:ProjectedCSType" => 32767, + ]; + + $this->mock->shouldReceive('getExifData')->once()->andReturn($exif); + $file = UploadedFile::fake()->create('geotiff_modelTransform.tiff', 1, 'image/tiff'); + + + $this->postJson( + "/api/v1/volumes/{$id}/geo-overlays/geotiff", + [ + 'geotiff' => $file, + 'layer_index' => 0 + ] + )->assertInvalid(['userDefined']); + Queue::assertNothingPushed(); + } + + public function testStoreDupliate() + { + $id = $this->volume()->id; + $this->beAdmin(); + + GeoOverlay::factory()->create([ + 'volume_id' => $id, + 'name' => 'test123.tiff' + ]); + + $file = UploadedFile::fake()->create('test123.tiff', 1, 'image/tiff'); + $this->postJson( + "/api/v1/volumes/{$id}/geo-overlays/geotiff", + [ + 'geotiff' => $file, + 'layer_index' => 0 + ] + )->assertInvalid(['fileExists']); + Queue::assertNothingPushed(); + } + + public function testStoreVideoVolume() + { + $id = $this->volume(['media_type_id' => MediaType::videoId()])->id; + $file = UploadedFile::fake()->create('overlay.tif'); + $this->beAdmin(); + $this->postJson( + "/api/v1/volumes/{$id}/geo-overlays/geotiff", + [ + 'geotiff' => $file, + 'layer_index' => 0 + ] + )->assertInvalid('id'); + Queue::assertNothingPushed(); + } +} diff --git a/tests/Http/Controllers/Api/WebMapOverlayControllerTest.php b/tests/Http/Controllers/Api/WebMapOverlayControllerTest.php new file mode 100644 index 00000000..2e01a013 --- /dev/null +++ b/tests/Http/Controllers/Api/WebMapOverlayControllerTest.php @@ -0,0 +1,388 @@ +mock = Mockery::mock(WebMapSource::class)->makePartial()->shouldAllowMockingProtectedMethods(); + $this->app->bind(WebMapSource::class, fn() => $this->mock); + } + public function testStoreWebMap() + { + $id = $this->volume()->id; + + $this->doTestApiRoute('POST', "/api/v1/volumes/{$id}/geo-overlays/webmap"); + + $this->beEditor(); + // 403: The client does not have access rights to the content + $this->postJson( + "/api/v1/volumes/{$id}/geo-overlays/webmap", + [ + 'url' => 'https://maps.geomar.de/geoserver/GEOMAR-Bathymetry/wms', + 'layer_index' => 0 + ] + )->assertStatus(403); + + $this->beAdmin(); + // 422: The request was well-formed but was unable to be followed due to semantic errors (no input) + $this->json('POST', "/api/v1/volumes/{$id}/geo-overlays/webmap") + ->assertStatus(422); + + $xml = 'test 123'; + $this->mock->shouldReceive('request')->once()->andReturn($xml); + + // test upload of invalid WMS-URL (should cause invalidWMS error) + $response = $this->postJson("/api/v1/volumes/{$id}/geo-overlays/webmap", [ + 'url' => 'https://google.com', + 'layer_index' => 0 + ])->assertStatus(422); + + $xml = $this->getXMLResponse(1); + $xml_array = $this->XmlToJson($xml); + + $this->mock->shouldReceive('request')->once()->andReturn($xml); + + // test upload of valid WMS-URL (with query-parameters, but NO LAYERS declared) + // should enter fallback method and return first valid layer anyways + $url = 'https://maps.geomar.de/geoserver/GEOMAR-Bathymetry/wms?service=WMS&version=1.1.0&request=GetMap&layers='; + $response = $this->postJson("/api/v1/volumes/{$id}/geo-overlays/webmap", [ + 'url' => $url, + 'layer_index' => 0 + ])->assertSuccessful(); + + $overlay = json_decode($response->getContent(), true); + $this->assertNotNull($overlay); + $this->assertTrue($overlay['browsing_layer']); + $this->assertEquals(0, $overlay['layer_index']); + $this->assertEquals(Str::before($url, '?'), $overlay['attrs']['url']); + $this->assertEquals($xml_array['Layer']['Layer']['Name'], $overlay['name']); + $this->assertEquals($xml_array['Layer']['Layer']['Title'], $overlay['attrs']['layer']); + } + + public function testStoreWebMapLayer() + { + $id = $this->volume()->id; + $this->beAdmin(); + + $xml = $this->getXMLResponse(3); + $xml_array = $this->XmlToJson($xml); + $xml_names = array_map(fn($l) => $l['Name'], $xml_array['Layer']['Layer']); + $this->mock->shouldReceive('request')->once()->andReturn($xml); + + // test upload of valid WMS-URL (with query-parameters and SEVERAL LAYERS declared) + $url = 'https://maps.geomar.de/geoserver/CONMAR/wms?service=WMS&version=1.1.0&request=GetMap&layers=Name_0'; + $response = $this->postJson("/api/v1/volumes/{$id}/geo-overlays/webmap", [ + 'url' => $url, + 'layer_index' => 0 + ])->assertSuccessful(); + + $overlay = json_decode($response->getContent(), true); + $this->assertNotNull($overlay); + $this->assertTrue($overlay['browsing_layer']); + $this->assertEquals(0, $overlay['layer_index']); + $this->assertEquals(Str::before($url, '?'), $overlay['attrs']['url']); + $this->assertEquals($xml_names[0], $overlay['name']); + $this->assertEquals($xml_array['Layer']['Layer'][0]['Title'], $overlay['attrs']['layer']); + } + + public function testStoreWebMapOverlayMaliciousXML() + { + $id = $this->volume()->id; + $this->beAdmin(); + + $xml = ' + + + + + + + + + + ]> + &lol9;'; + $this->mock->shouldReceive('request')->once()->andReturn($xml); + + // test billion laugh attack + $url = 'https://maps.geomar.de/geoserver/CONMAR/wms?service=WMS&version=1.1.0&request=GetMap&layers=Name_0'; + $response = $this->postJson("/api/v1/volumes/{$id}/geo-overlays/webmap", [ + 'url' => $url, + 'layer_index' => 0 + ])->assertInvalid('invalidWMS'); + + $xml = ' + ]> + + &harmless;&harmless; + '; + $this->mock->shouldReceive('request')->once()->andReturn($xml); + + // test XEE + $url = 'https://maps.geomar.de/geoserver/CONMAR/wms?service=WMS&version=1.1.0&request=GetMap'; + $response = $this->postJson("/api/v1/volumes/{$id}/geo-overlays/webmap", [ + 'url' => $url, + 'layer_index' => 0 + ])->assertInvalid('noValidLayer'); + + $xml = ' + + ]> + + &harmless;&harmless; + '; + + $this->mock->shouldReceive('request')->once()->andReturn($xml); + + // test XEE with network access attempt + $url = 'https://maps.geomar.de/geoserver/CONMAR/wms?service=WMS&version=1.1.0&request=GetMap'; + $response = $this->postJson("/api/v1/volumes/{$id}/geo-overlays/webmap", [ + 'url' => $url, + 'layer_index' => 0 + ])->assertInvalid('noValidLayer'); + } + + public function testStoreMultipleLayers() + { + $id = $this->volume()->id; + $this->beAdmin(); + + $url = 'https://maps.geomar.de/geoserver/CONMAR/wms?service=WMS&version=1.1.0&request=GetMap&layers=Name_0,Name_1'; + $this->postJson("/api/v1/volumes/{$id}/geo-overlays/webmap", [ + 'url' => $url, + 'layer_index' => 0 + ])->assertInvalid(['noValidLayer']); + + $url = 'https://maps.geomar.de/geoserver/CONMAR/wms?service=WMS&version=1.1.0&request=GetMap&layers=Name_0 Name_1'; + $this->postJson("/api/v1/volumes/{$id}/geo-overlays/webmap", [ + 'url' => $url, + 'layer_index' => 0 + ])->assertInvalid(['url']); + } + + public function testStoreWebMapBaseURL() + { + $id = $this->volume()->id; + $this->beAdmin(); + + $xml = $this->getXMLResponse(3, true); + $xml_array = $this->XmlToJson($xml)['Layer']['Layer']; + $this->mock->shouldReceive('request')->once()->andReturn($xml); + + // test upload of valid WMS-URL (baseUrl without query-parameters) + $url = 'https://maps.geomar.de/geoserver/MSM96/wms'; + $response = $this->postJson("/api/v1/volumes/{$id}/geo-overlays/webmap", [ + 'url' => $url, + 'layer_index' => 0 + ])->assertSuccessful(); + + $overlay = json_decode($response->getContent(), true); + $this->assertNotNull($overlay); + $this->assertTrue($overlay['browsing_layer']); + $this->assertEquals(0, $overlay['layer_index']); + $this->assertEquals($url, $overlay['attrs']['url']); + $this->assertEquals($xml_array[1]['Name'], $overlay['name']); + $this->assertEquals($xml_array[1]['Title'], $overlay['attrs']['layer']); + } + + public function testStoreNoValidLayer() + { + $id = $this->volume()->id; + $xml = $this->getXMLResponse(1, true); + $this->beAdmin(); + + $this->mock->shouldReceive('request')->once()->andReturn($xml); + + $url = 'https://maps.geomar.de/geoserver/GEOMAR-Bathymetry/wms?service=WMS&version=1.1.0&request=GetMap&layers='; + $this->postJson("/api/v1/volumes/{$id}/geo-overlays/webmap", [ + 'url' => $url, + 'layer_index' => 0 + ])->assertInvalid(['noValidLayer']); + } + + public function testStoreInvalidUrl() + { + $id = $this->volume()->id; + $this->beAdmin(); + + $this->mock->shouldReceive('request')->never(); + + $url = 'https://localhost:8000/wms?service=WMS&version=1.1.0&request=GetMap&layers='; + $this->postJson("/api/v1/volumes/{$id}/geo-overlays/webmap", [ + 'url' => $url, + 'layer_index' => 0 + ])->assertInvalid(['url']); + + $url = 'https://127.0.0.1:8000/wms?service=WMS&version=1.1.0&request=GetMap&layers='; + $this->postJson("/api/v1/volumes/{$id}/geo-overlays/webmap", [ + 'url' => $url, + 'layer_index' => 0 + ])->assertInvalid(['url']); + + $url = 'https://[0:0:0:0:0:0:0:1]:8000/wms?service=WMS&version=1.1.0&request=GetMap&layers='; + $this->postJson("/api/v1/volumes/{$id}/geo-overlays/webmap", [ + 'url' => $url, + 'layer_index' => 0 + ])->assertInvalid(['url']); + + $url = 'https://[::1]:8000/wms?service=WMS&version=1.1.0&request=GetMap&layers='; + $this->postJson("/api/v1/volumes/{$id}/geo-overlays/webmap", [ + 'url' => $url, + 'layer_index' => 0 + ])->assertInvalid(['url']); + } + + public function testStoreWebMapServiceWithCoordsEPSG4326() + { + + $this->beAdmin(); + $id = $this->volume()->id; + // CRS with EPSG:4326 does not need transformation + $xml = '' . + 'Name_0Title_0' . + ' + ' . + ''; + + $xml_array = $this->XmlToJson($xml)['Layer']['Layer']; + $this->mock->shouldReceive('request')->once()->andReturn($xml); + + $url = 'https://maps.geomar.de/geoserver/MSM96/wms'; + $response = $this->postJson("/api/v1/volumes/{$id}/geo-overlays/webmap", [ + 'url' => $url, + 'layer_index' => 0 + ])->assertSuccessful(); + + $round = fn($c) => round($c, 13); + $coords = $xml_array['BoundingBox'][1]['@attributes']; + $overlay = json_decode($response->getContent(), true); + $this->assertNotNull($overlay); + $this->assertTrue($overlay['browsing_layer']); + $this->assertEquals(0, $overlay['layer_index']); + $this->assertEquals($url, $overlay['attrs']['url']); + $this->assertEquals($xml_array['Name'], $overlay['name']); + $this->assertEquals($xml_array['Title'], $overlay['attrs']['layer']); + $this->assertEquals('EPSG:4326', $coords['SRS']); + $this->assertEquals($round($coords['minx']), $overlay['attrs']['top_left_lng']); + $this->assertEquals($round($coords['miny']), $overlay['attrs']['top_left_lat']); + $this->assertEquals($round($coords['maxx']), $overlay['attrs']['bottom_right_lng']); + $this->assertEquals($round($coords['maxy']), $overlay['attrs']['bottom_right_lat']); + } + + public function testStoreWebMapServiceWithCoordsEPSG32647() + { + + $this->beAdmin(); + $id = $this->volume()->id; + // CRS with EPSG:32647 needs transformation + $xml = '' . + 'Name_0Title_0' . + '' . + ''; + + $xml_array = $this->XmlToJson($xml)['Layer']['Layer']; + $this->mock->shouldReceive('request')->once()->andReturn($xml); + + $url = 'https://maps.geomar.de/geoserver/MSM96/wms'; + $response = $this->postJson("/api/v1/volumes/{$id}/geo-overlays/webmap", [ + 'url' => $url, + 'layer_index' => 0 + ])->assertSuccessful(); + + $overlay = json_decode($response->getContent(), true); + $this->assertNotNull($overlay); + $this->assertTrue($overlay['browsing_layer']); + $this->assertEquals(0, $overlay['layer_index']); + $this->assertEquals($url, $overlay['attrs']['url']); + $this->assertEquals($xml_array['Name'], $overlay['name']); + $this->assertEquals($xml_array['Title'], $overlay['attrs']['layer']); + $this->assertEquals(95.9531411952078, $overlay['attrs']['top_left_lng']); + $this->assertEquals(10.0899544815049, $overlay['attrs']['top_left_lat']); + $this->assertEquals(99, $overlay['attrs']['bottom_right_lng']); + $this->assertEquals(50.3023009095724, $overlay['attrs']['bottom_right_lat']); + } + + public function testStoreNotExistingLayer() + { + $id = $this->volume()->id; + $xml = $this->getXMLResponse(1); + $this->beAdmin(); + + $this->mock->shouldReceive('request')->once()->andReturn($xml); + + $url = 'https://maps.geomar.de/geoserver/GEOMAR-Bathymetry/wms?service=WMS&version=1.1.0&request=GetMap&layers=test123'; + $this->postJson("/api/v1/volumes/{$id}/geo-overlays/webmap", [ + 'url' => $url, + 'layer_index' => 0 + ])->assertInvalid(['noValidLayer']); + } + + public function testStoreInvalidLayerIndex() + { + $id = $this->volume()->id; + $this->beAdmin(); + + $this->mock->shouldReceive('request')->never(); + + $url = 'https://maps.geomar.de/geoserver/GEOMAR-Bathymetry/wms?service=WMS&version=1.1.0&request=GetMap'; + $this->postJson("/api/v1/volumes/{$id}/geo-overlays/webmap", [ + 'url' => $url, + 'layer_index' => 99 + ])->assertInvalid(['layer_index']); + } + + public function testStoreDuplicate() + { + $id = $this->volume()->id; + $url = 'https://maps.geomar.de/geoserver/MSM96/wms'; + GeoOverlay::factory()->webMap()->create([ + 'volume_id' => $id, + 'name' => 'Name_1', + ]); + + $this->beAdmin(); + + $xml = $this->getXMLResponse(3, true); + $this->mock->shouldReceive('request')->once()->andReturn($xml); + + // test upload of valid WMS-URL (baseUrl without query-parameters) + $this->postJson("/api/v1/volumes/{$id}/geo-overlays/webmap", [ + 'url' => $url, + 'layer_index' => 0 + ])->assertInvalid('duplicate'); + } + + public function getXMLResponse($layers, $hasInvalidLayer = false) + { + $content = ''; + for ($i = 0; $i < $layers; $i++) { + if ($hasInvalidLayer) { + // First layer is invalid due to a missing name tag + $content .= "Title_$i"; + $hasInvalidLayer = false; + } else { + $content .= "Name_$iTitle_$i"; + } + } + $content .= ""; + return $content; + } + + public function XmlToJson($xml) + { + return json_decode(json_encode(simplexml_load_string($xml)), true); + } +} diff --git a/tests/Jobs/TileSingleOverlayTest.php b/tests/Jobs/TileSingleOverlayTest.php new file mode 100644 index 00000000..eb03292a --- /dev/null +++ b/tests/Jobs/TileSingleOverlayTest.php @@ -0,0 +1,239 @@ +user = User::factory()->create(); + + } + + public function testGenerateOverlayTiles() + { + $overlay = GeoOverlay::newFactory()->create(); + $file = new GenericFile("test"); + + $job = new TileSingleOverlayStub($overlay, $this->user, []); + $job->generateTiles($file, "test"); + + $files = [ + $job->tempPath . "/ImageProperties.xml", + $job->tempPath . "/TileGroup0/0-0-0.png", + $job->tempPath . '/vips-properties.xml' + ]; + + $this->assertCount(3, File::allFiles($job->tempPath)); + $this->assertSame($files, array_map(fn($f) => $f->getPathname(), File::allFiles($job->tempPath))); + } + + public function testGenerateOverlayTilesInvalidColorspace() + { + $overlay = GeoOverlay::newFactory()->create(); + $file = new GenericFile("test"); + + Event::fake(); + $job = new TileSingleOverlayStub($overlay, $this->user, []); + $job->invalidColorspace = true; + $job->withFakeQueueInteractions(); + $job->generateTiles($file, "test"); + + $job->assertFailed(); + Event::assertDispatched(GeoTiffUploadFailed::class); + $this->assertFalse(GeoOverlay::where('id', $overlay->id)->exists()); + } + + public function testGenerateOverlayTilesThrowException() + { + $overlay = GeoOverlay::newFactory()->create(); + + Event::fake(); + $job = new TileSingleOverlayStub($overlay, $this->user, []); + $job->failed(new Exception()); + + Event::assertDispatched(GeoTiffUploadFailed::class); + $this->assertFalse(GeoOverlay::where('id', $overlay->id)->exists()); + } + + public function testGenerateOverlayTilesWithNormalization() + { + $file = new GenericFile("test"); + $overlay = GeoOverlay::newFactory()->create(); + $job = new TileSingleOverlayStub($overlay, $this->user, []); + $job->useGrayImage = true; + $job->generateTiles($file, "test"); + $getPixel = fn($img) => $img->getpoint(2, 3)[0]; + $normImg = $job->outputImg; + + $files = [ + $job->tempPath . "/ImageProperties.xml", + $job->tempPath . "/TileGroup0/0-0-0.png", + $job->tempPath . '/vips-properties.xml' + ]; + + $this->assertEquals(0, $normImg->min()); + $this->assertEquals(255, $normImg->max()); + $this->assertEquals(54, $getPixel($normImg)); + $this->assertCount(3, File::allFiles($job->tempPath)); + $this->assertSame($files, array_map(fn($f) => $f->getPathname(), File::allFiles($job->tempPath))); + } + + public function testGenerateOverlayTilesWithNormalizationEdgeCase() + { + $file = new GenericFile("test"); + $getPixel = fn($img) => $img->getpoint(2, 3)[0]; + $overlay = GeoOverlay::newFactory()->create(); + $job = new TileSingleOverlayStub($overlay, $this->user, []); + $job->useGrayImage = true; + $job->edgeCase = 90; + $job->generateTiles($file, "test"); + $normImg = $job->outputImg; + + $files = [ + $job->tempPath . "/ImageProperties.xml", + $job->tempPath . "/TileGroup0/0-0-0.png", + $job->tempPath . '/vips-properties.xml' + ]; + + $this->assertEquals(0, $normImg->min()); + $this->assertEquals(255, $normImg->max()); + $this->assertEquals(60, $getPixel($normImg)); + $this->assertCount(3, File::allFiles($job->tempPath)); + $this->assertSame($files, array_map(fn($f) => $f->getPathname(), File::allFiles($job->tempPath))); + } + + public function testUploadOverlayToStorage() + { + config(['geo.tiles.overlay_storage_disk' => 'geo-overlays']); + $overlay = GeoOverlay::newFactory()->create(); + + $targetPath = "{$overlay->id}/{$overlay->id}_tiles"; + $job = new TileSingleOverlayStub($overlay, $this->user, []); + File::makeDirectory($job->tempPath); + File::put("{$job->tempPath}/test.txt", 'test'); + + try { + Storage::fake('geo-overlays'); + $job->uploadToStorage(); + Storage::disk('geo-overlays')->assertExists($targetPath); + Storage::disk('geo-overlays')->assertExists("{$targetPath}/test.txt"); + } finally { + File::deleteDirectory($job->tempPath); + } + } + + public function testGenerateOverlayTilesWithNormalizationWithNoDataValue() + { + $file = new GenericFile("test"); + + $overlay = GeoOverlay::newFactory()->create(); + $job = new TileSingleOverlayStub($overlay, $this->user, ['IFD0:GDALNoData' => 0]); + $job->useGrayImage = true; + $job->generateTiles($file, "test"); + $getPixel = fn($img) => $img->getpoint(2, 3)[0]; + $normImg = $job->outputImg; + + $files = [ + $job->tempPath . "/ImageProperties.xml", + $job->tempPath . "/TileGroup0/0-0-0.png", + $job->tempPath . '/vips-properties.xml' + ]; + + $this->assertEquals(0, $normImg->min()); + $this->assertEquals(255, $normImg->max()); + $this->assertEquals(49, $getPixel($normImg)); + $this->assertCount(3, File::allFiles($job->tempPath)); + $this->assertSame($files, array_map(fn($f) => $f->getPathname(), File::allFiles($job->tempPath))); + } + + public function testGenerateOverlayTilesCreateAlphaMask() + { + $file = new GenericFile("test"); + + $overlay = GeoOverlay::newFactory()->create(); + $job = new TileSingleOverlayStub($overlay, $this->user, ['IFD0:GDALNoData' => -9999]); + $job->useGrayImage = true; + $job->edgeCase = -9999; + $job->generateTiles($file, "test"); + $getPixel = fn($img) => $img->getpoint(2, 3)[0]; + $normImg = $job->outputImg; + $mask = $normImg->extract_band(1); + $mask_hist = $mask->hist_find()->writeToArray(); + + $files = [ + $job->tempPath . "/ImageProperties.xml", + $job->tempPath . "/TileGroup0/0-0-0.png", + $job->tempPath . '/vips-properties.xml' + ]; + + $this->assertTrue($normImg->hasAlpha()); + $this->assertEquals(0, $normImg->getpoint(1, 0)[1]); + $this->assertEquals(1, $mask_hist[0]); + $this->assertEquals(0, $normImg->min()); + $this->assertEquals(255, $normImg->max()); + $this->assertEquals(60, $getPixel($normImg)); + $this->assertCount(3, File::allFiles($job->tempPath)); + $this->assertSame($files, array_map(fn($f) => $f->getPathname(), File::allFiles($job->tempPath))); + } + +} + +class TileSingleOverlayStub extends TileSingleOverlay +{ + + public $useGrayImage = false; + + public $edgeCase = 0; + + public $outputImg; + + public $invalidColorspace = false; + + public function generateTiles($file, $path) + { + parent::generateTiles($file, $path); + $this->outputImg = $this->vipsImage; + } + + protected function getVipsImage($path) + { + if ($this->useGrayImage) { + $pixels = [ + [0, 100, 36, 29, 13], + [46, 50, 2, 71, 5], + [68, 59, 85, 86, 66], + [52, 89, 21, 68, 71], + ]; + + if ($this->edgeCase != 0) { + $pixels[0][1] = $this->edgeCase; + } + + return VipsImage::newFromArray($pixels); + } + + if ($this->invalidColorspace) { + return VipsImage::black(5, 5, ['bands' => 5]); + } + + return VipsImage::black(5, 5); + } +} diff --git a/tests/files/geotiff_missing_ModelTiePoint_and_ModelTransform.tiff b/tests/files/geotiff_missing_ModelTiePoint_and_ModelTransform.tiff new file mode 100644 index 00000000..b0a780fc Binary files /dev/null and b/tests/files/geotiff_missing_ModelTiePoint_and_ModelTransform.tiff differ diff --git a/tests/files/geotiff_modelTransform.tiff b/tests/files/geotiff_modelTransform.tiff new file mode 100644 index 00000000..889fbd02 Binary files /dev/null and b/tests/files/geotiff_modelTransform.tiff differ diff --git a/tests/files/geotiff_standardEPSG2013.tif b/tests/files/geotiff_standardEPSG2013.tif new file mode 100644 index 00000000..0d7f1ed0 Binary files /dev/null and b/tests/files/geotiff_standardEPSG2013.tif differ diff --git a/tests/files/geotiff_user_defined2011.tif b/tests/files/geotiff_user_defined2011.tif new file mode 100644 index 00000000..0cb3b7dd Binary files /dev/null and b/tests/files/geotiff_user_defined2011.tif differ diff --git a/vite.config.js b/vite.config.js index 7d45154e..512c3352 100644 --- a/vite.config.js +++ b/vite.config.js @@ -22,7 +22,7 @@ export default defineConfig({ input: [ 'src/resources/assets/sass/main.scss', 'src/resources/assets/js/geo/main.js', - 'src/resources/assets/js/volumes/main.js', + 'src/resources/assets/js/volumes/volumes.js', ], hotFile: 'hot', }),