morecantile 6.0.0__tar.gz → 6.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {morecantile-6.0.0 → morecantile-6.2.0}/.pre-commit-config.yaml +5 -10
- {morecantile-6.0.0 → morecantile-6.2.0}/PKG-INFO +7 -3
- morecantile-6.2.0/benchmarks/README.md +63 -0
- morecantile-6.2.0/benchmarks/benchmarks.py +96 -0
- morecantile-6.2.0/benchmarks/requirements.txt +6 -0
- {morecantile-6.0.0 → morecantile-6.2.0}/morecantile/__init__.py +1 -1
- {morecantile-6.0.0 → morecantile-6.2.0}/morecantile/defaults.py +1 -1
- {morecantile-6.0.0 → morecantile-6.2.0}/morecantile/models.py +35 -12
- {morecantile-6.0.0 → morecantile-6.2.0}/morecantile/utils.py +4 -6
- {morecantile-6.0.0 → morecantile-6.2.0}/pyproject.toml +9 -4
- {morecantile-6.0.0 → morecantile-6.2.0}/.gitignore +0 -0
- {morecantile-6.0.0 → morecantile-6.2.0}/LICENSE +0 -0
- {morecantile-6.0.0 → morecantile-6.2.0}/README.md +0 -0
- {morecantile-6.0.0 → morecantile-6.2.0}/morecantile/commons.py +0 -0
- {morecantile-6.0.0 → morecantile-6.2.0}/morecantile/data/CDB1GlobalGrid.json +0 -0
- {morecantile-6.0.0 → morecantile-6.2.0}/morecantile/data/CanadianNAD83_LCC.json +0 -0
- {morecantile-6.0.0 → morecantile-6.2.0}/morecantile/data/EuropeanETRS89_LAEAQuad.json +0 -0
- {morecantile-6.0.0 → morecantile-6.2.0}/morecantile/data/GNOSISGlobalGrid.json +0 -0
- {morecantile-6.0.0 → morecantile-6.2.0}/morecantile/data/LINZAntarticaMapTilegrid.json +0 -0
- {morecantile-6.0.0 → morecantile-6.2.0}/morecantile/data/NZTM2000Quad.json +0 -0
- {morecantile-6.0.0 → morecantile-6.2.0}/morecantile/data/README.md +0 -0
- {morecantile-6.0.0 → morecantile-6.2.0}/morecantile/data/UPSAntarcticWGS84Quad.json +0 -0
- {morecantile-6.0.0 → morecantile-6.2.0}/morecantile/data/UPSArcticWGS84Quad.json +0 -0
- {morecantile-6.0.0 → morecantile-6.2.0}/morecantile/data/UTM31WGS84Quad.json +0 -0
- {morecantile-6.0.0 → morecantile-6.2.0}/morecantile/data/WGS1984Quad.json +0 -0
- {morecantile-6.0.0 → morecantile-6.2.0}/morecantile/data/WebMercatorQuad.json +0 -0
- {morecantile-6.0.0 → morecantile-6.2.0}/morecantile/data/WorldCRS84Quad.json +0 -0
- {morecantile-6.0.0 → morecantile-6.2.0}/morecantile/data/WorldMercatorWGS84Quad.json +0 -0
- {morecantile-6.0.0 → morecantile-6.2.0}/morecantile/errors.py +0 -0
- {morecantile-6.0.0 → morecantile-6.2.0}/morecantile/py.typed +0 -0
- {morecantile-6.0.0 → morecantile-6.2.0}/morecantile/scripts/__init__.py +0 -0
- {morecantile-6.0.0 → morecantile-6.2.0}/morecantile/scripts/cli.py +0 -0
|
@@ -4,26 +4,21 @@ repos:
|
|
|
4
4
|
hooks:
|
|
5
5
|
- id: validate-pyproject
|
|
6
6
|
|
|
7
|
-
- repo: https://github.com/psf/black
|
|
8
|
-
rev: 22.12.0
|
|
9
|
-
hooks:
|
|
10
|
-
- id: black
|
|
11
|
-
language_version: python
|
|
12
|
-
|
|
13
7
|
- repo: https://github.com/PyCQA/isort
|
|
14
|
-
rev: 5.
|
|
8
|
+
rev: 5.13.2
|
|
15
9
|
hooks:
|
|
16
10
|
- id: isort
|
|
17
11
|
language_version: python
|
|
18
12
|
|
|
19
|
-
- repo: https://github.com/
|
|
20
|
-
rev: v0.
|
|
13
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
14
|
+
rev: v0.3.5
|
|
21
15
|
hooks:
|
|
22
16
|
- id: ruff
|
|
23
17
|
args: ["--fix"]
|
|
18
|
+
- id: ruff-format
|
|
24
19
|
|
|
25
20
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
26
|
-
rev: v1.
|
|
21
|
+
rev: v1.11.2
|
|
27
22
|
hooks:
|
|
28
23
|
- id: mypy
|
|
29
24
|
language_version: python
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
2
|
Name: morecantile
|
|
3
|
-
Version: 6.
|
|
3
|
+
Version: 6.2.0
|
|
4
4
|
Summary: Construct and use map tile grids (a.k.a TileMatrixSet / TMS).
|
|
5
5
|
Keywords: GIS,TMS,TileMatrixSet,Map Tile
|
|
6
6
|
Author-email: Vincent Sarago <vincent@developmentseed.com>
|
|
@@ -14,10 +14,13 @@ Classifier: Programming Language :: Python :: 3.9
|
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.10
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.11
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
18
|
Classifier: Topic :: Scientific/Engineering :: GIS
|
|
18
19
|
Requires-Dist: attrs
|
|
19
|
-
Requires-Dist: pyproj
|
|
20
|
+
Requires-Dist: pyproj>=3.1,<4.0
|
|
20
21
|
Requires-Dist: pydantic~=2.0
|
|
22
|
+
Requires-Dist: pytest ; extra == "benchmark"
|
|
23
|
+
Requires-Dist: pytest-benchmark ; extra == "benchmark"
|
|
21
24
|
Requires-Dist: pre-commit ; extra == "dev"
|
|
22
25
|
Requires-Dist: bump-my-version ; extra == "dev"
|
|
23
26
|
Requires-Dist: mkdocs>=1.4.3 ; extra == "docs"
|
|
@@ -32,6 +35,7 @@ Requires-Dist: pytest-cov ; extra == "test"
|
|
|
32
35
|
Requires-Dist: rasterio>=1.2.1 ; extra == "test"
|
|
33
36
|
Project-URL: Documentation, https://developmentseed.org/morecantile/
|
|
34
37
|
Project-URL: Source, https://github.com/developmentseed/morecantile
|
|
38
|
+
Provides-Extra: benchmark
|
|
35
39
|
Provides-Extra: dev
|
|
36
40
|
Provides-Extra: docs
|
|
37
41
|
Provides-Extra: rasterio
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
|
|
2
|
+
## Benchmark
|
|
3
|
+
|
|
4
|
+
Compare `mercantile`, `utiles` and `morecantile`
|
|
5
|
+
|
|
6
|
+
```sh
|
|
7
|
+
python -m pip install -r requirements.txt
|
|
8
|
+
python -m pytest benchmarks.py --benchmark-only --benchmark-columns 'min, max, mean, median' --benchmark-sort 'min'
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
----------------------------------------------------- benchmark 'bounds': 21 tests ----------------------------------------------------
|
|
13
|
+
Name (time in ns) Min Max Mean Median
|
|
14
|
+
---------------------------------------------------------------------------------------------------------------------------------------
|
|
15
|
+
test_bounds[utiles-(486, 332, 30)] 83.0000 (1.0) 52,000.0000 (52.97) 195.3371 (1.48) 208.0000 (1.60)
|
|
16
|
+
test_bounds[utiles-(0, 0, 0)] 83.0000 (1.00) 31,167.0000 (31.75) 193.5957 (1.47) 208.0000 (1.60)
|
|
17
|
+
test_bounds[utiles-(1, 0, 1)] 125.0000 (1.51) 981.6700 (1.0) 132.0177 (1.0) 130.8300 (1.01)
|
|
18
|
+
test_bounds[utiles-(1, 40, 7)] 125.0000 (1.51) 8,606.2500 (8.77) 132.5298 (1.00) 130.0000 (1.0)
|
|
19
|
+
test_bounds[utiles-(486, 332, 10)] 128.3300 (1.55) 1,600.8300 (1.63) 133.4046 (1.01) 131.6700 (1.01)
|
|
20
|
+
test_bounds[utiles-(1, 1, 1)] 129.5900 (1.56) 16,846.2500 (17.16) 141.9846 (1.08) 134.1700 (1.03)
|
|
21
|
+
test_bounds[utiles-(486, 332, 20)] 138.3300 (1.67) 1,123.3300 (1.14) 142.5420 (1.08) 141.2500 (1.09)
|
|
22
|
+
test_bounds[mercantile-(1, 40, 7)] 1,000.0000 (12.05) 92,416.0000 (94.14) 1,193.0112 (9.04) 1,167.0000 (8.98)
|
|
23
|
+
test_bounds[mercantile-(1, 1, 1)] 1,075.0000 (12.95) 48,066.8000 (48.96) 1,154.8100 (8.75) 1,141.6000 (8.78)
|
|
24
|
+
test_bounds[mercantile-(0, 0, 0)] 1,083.0000 (13.05) 21,041.0000 (21.43) 1,214.6049 (9.20) 1,208.0000 (9.29)
|
|
25
|
+
test_bounds[mercantile-(1, 0, 1)] 1,083.0000 (13.05) 75,291.0000 (76.70) 1,213.7837 (9.19) 1,208.0000 (9.29)
|
|
26
|
+
test_bounds[mercantile-(486, 332, 10)] 1,083.0000 (13.05) 55,750.0000 (56.79) 1,223.7598 (9.27) 1,208.0000 (9.29)
|
|
27
|
+
test_bounds[mercantile-(486, 332, 20)] 1,083.0000 (13.05) 89,041.0000 (90.70) 1,248.4256 (9.46) 1,209.0000 (9.30)
|
|
28
|
+
test_bounds[mercantile-(486, 332, 30)] 1,083.0000 (13.05) 194,958.0000 (198.60) 1,239.4339 (9.39) 1,209.0000 (9.30)
|
|
29
|
+
test_bounds[morecantile-(1, 0, 1)] 20,083.0000 (241.96) 132,625.0000 (135.10) 20,893.1235 (158.26) 20,667.0000 (158.98)
|
|
30
|
+
test_bounds[morecantile-(0, 0, 0)] 20,166.0000 (242.96) 120,333.0000 (122.58) 20,974.1961 (158.87) 20,708.0000 (159.29)
|
|
31
|
+
test_bounds[morecantile-(1, 1, 1)] 20,334.0000 (244.99) 60,958.0000 (62.10) 21,236.2953 (160.86) 20,750.0000 (159.62)
|
|
32
|
+
test_bounds[morecantile-(1, 40, 7)] 21,667.0000 (261.05) 173,458.0000 (176.70) 22,622.6537 (171.36) 22,333.0000 (171.79)
|
|
33
|
+
test_bounds[morecantile-(486, 332, 10)] 22,166.0000 (267.06) 205,125.0000 (208.96) 23,512.1607 (178.10) 22,875.0000 (175.96)
|
|
34
|
+
test_bounds[morecantile-(486, 332, 20)] 24,708.0000 (297.69) 129,250.0000 (131.66) 25,775.0796 (195.24) 25,375.0000 (195.19)
|
|
35
|
+
test_bounds[morecantile-(486, 332, 30)] 71,292.0000 (858.94) 205,625.0000 (209.46) 73,569.4565 (557.27) 72,667.0000 (558.98)
|
|
36
|
+
---------------------------------------------------------------------------------------------------------------------------------------
|
|
37
|
+
|
|
38
|
+
---------------------------------------------------- benchmark 'xy_bounds': 21 tests -----------------------------------------------------
|
|
39
|
+
Name (time in ns) Min Max Mean Median
|
|
40
|
+
------------------------------------------------------------------------------------------------------------------------------------------
|
|
41
|
+
test_xy_bounds[utiles-(0, 0, 0)] 83.0000 (1.0) 57,375.0000 (112.55) 145.9127 (1.57) 125.0000 (1.36)
|
|
42
|
+
test_xy_bounds[utiles-(1, 1, 1)] 88.3400 (1.06) 1,335.4200 (2.62) 93.1478 (1.00) 92.5000 (1.00)
|
|
43
|
+
test_xy_bounds[utiles-(1, 40, 7)] 88.7500 (1.07) 1,451.2500 (2.85) 93.1258 (1.0) 92.0900 (1.0)
|
|
44
|
+
test_xy_bounds[utiles-(1, 0, 1)] 89.5900 (1.08) 861.6600 (1.69) 93.6428 (1.01) 93.3300 (1.01)
|
|
45
|
+
test_xy_bounds[utiles-(486, 332, 10)] 90.0000 (1.08) 509.7950 (1.0) 93.2818 (1.00) 92.9150 (1.01)
|
|
46
|
+
test_xy_bounds[utiles-(486, 332, 20)] 90.4100 (1.09) 864.1700 (1.70) 94.2974 (1.01) 94.1600 (1.02)
|
|
47
|
+
test_xy_bounds[utiles-(486, 332, 30)] 90.4100 (1.09) 1,377.5000 (2.70) 94.7366 (1.02) 94.1600 (1.02)
|
|
48
|
+
test_xy_bounds[mercantile-(0, 0, 0)] 708.0000 (8.53) 42,250.0000 (82.88) 843.2292 (9.05) 833.0000 (9.05)
|
|
49
|
+
test_xy_bounds[mercantile-(486, 332, 10)] 731.2500 (8.81) 5,393.7500 (10.58) 770.8331 (8.28) 764.6000 (8.30)
|
|
50
|
+
test_xy_bounds[mercantile-(486, 332, 30)] 731.2500 (8.81) 7,316.6500 (14.35) 770.2423 (8.27) 764.6000 (8.30)
|
|
51
|
+
test_xy_bounds[mercantile-(1, 0, 1)] 732.1429 (8.82) 9,404.8571 (18.45) 791.7721 (8.50) 785.7143 (8.53)
|
|
52
|
+
test_xy_bounds[mercantile-(1, 40, 7)] 733.3000 (8.83) 5,950.0000 (11.67) 772.3273 (8.29) 766.7000 (8.33)
|
|
53
|
+
test_xy_bounds[mercantile-(486, 332, 20)] 733.3500 (8.84) 7,408.3000 (14.53) 773.4718 (8.31) 768.7500 (8.35)
|
|
54
|
+
test_xy_bounds[mercantile-(1, 1, 1)] 735.4000 (8.86) 4,762.5000 (9.34) 783.2100 (8.41) 777.1000 (8.44)
|
|
55
|
+
test_xy_bounds[morecantile-(0, 0, 0)] 3,042.0000 (36.65) 108,208.0000 (212.26) 3,287.1089 (35.30) 3,250.0000 (35.29)
|
|
56
|
+
test_xy_bounds[morecantile-(1, 0, 1)] 3,291.0000 (39.65) 68,166.0000 (133.71) 3,503.4695 (37.62) 3,459.0000 (37.56)
|
|
57
|
+
test_xy_bounds[morecantile-(1, 1, 1)] 3,291.0000 (39.65) 72,875.0000 (142.95) 3,506.8544 (37.66) 3,500.0000 (38.01)
|
|
58
|
+
test_xy_bounds[morecantile-(1, 40, 7)] 4,375.0000 (52.71) 76,375.0000 (149.82) 4,630.2893 (49.72) 4,584.0000 (49.78)
|
|
59
|
+
test_xy_bounds[morecantile-(486, 332, 10)] 4,875.0000 (58.73) 85,208.0000 (167.14) 5,197.3581 (55.81) 5,125.0000 (55.65)
|
|
60
|
+
test_xy_bounds[morecantile-(486, 332, 20)] 6,916.0000 (83.33) 78,458.0000 (153.90) 7,221.0669 (77.54) 7,166.0000 (77.82)
|
|
61
|
+
test_xy_bounds[morecantile-(486, 332, 30)] 52,667.0000 (634.54) 404,208.0000 (792.88) 54,749.1232 (587.90) 54,333.0000 (590.00)
|
|
62
|
+
------------------------------------------------------------------------------------------------------------------------------------------
|
|
63
|
+
```
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"""Morecantile/Mercantile/Utiles comparison benchmark
|
|
2
|
+
|
|
3
|
+
The benchmark suite is adapted from jessekrubin/utiles
|
|
4
|
+
https://github.com/jessekrubin/utiles/blob/ea58b9a017a2e3528f03cc20f16ef531737b863f/utiles-pyo3/bench/test_bench.py#L17-L25
|
|
5
|
+
"""
|
|
6
|
+
# This file is a modified version of https://github.com/jessekrubin/utiles/blob/ea58b9a017a2e3528f03cc20f16ef531737b863f/utiles-pyo3/bench/test_bench.py.
|
|
7
|
+
#
|
|
8
|
+
# The original license follows.
|
|
9
|
+
#
|
|
10
|
+
# MIT License
|
|
11
|
+
#
|
|
12
|
+
# Copyright (c) 2023 jessekrubin
|
|
13
|
+
#
|
|
14
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
15
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
16
|
+
# in the Software without restriction, including without limitation the rights
|
|
17
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
18
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
19
|
+
# furnished to do so, subject to the following conditions:
|
|
20
|
+
#
|
|
21
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
22
|
+
# copies or substantial portions of the Software.
|
|
23
|
+
#
|
|
24
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
25
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
26
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
27
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
28
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
29
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
30
|
+
# SOFTWARE.
|
|
31
|
+
|
|
32
|
+
from typing import Callable, Tuple
|
|
33
|
+
|
|
34
|
+
import mercantile
|
|
35
|
+
import pytest
|
|
36
|
+
import utiles
|
|
37
|
+
|
|
38
|
+
import morecantile
|
|
39
|
+
|
|
40
|
+
tms = morecantile.tms.get("WebMercatorQuad")
|
|
41
|
+
|
|
42
|
+
TEST_TILES = (
|
|
43
|
+
(0, 0, 0),
|
|
44
|
+
(1, 0, 1),
|
|
45
|
+
(1, 1, 1),
|
|
46
|
+
(1, 40, 7),
|
|
47
|
+
(486, 332, 10),
|
|
48
|
+
# HIGH ZOOM
|
|
49
|
+
(486, 332, 20),
|
|
50
|
+
# OUTSIDE TMS Range
|
|
51
|
+
(486, 332, 30),
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@pytest.mark.parametrize(
|
|
56
|
+
"tile",
|
|
57
|
+
[pytest.param(t, id=str(t)) for t in TEST_TILES],
|
|
58
|
+
)
|
|
59
|
+
@pytest.mark.parametrize(
|
|
60
|
+
"func",
|
|
61
|
+
[
|
|
62
|
+
pytest.param(mercantile.bounds, id="mercantile"),
|
|
63
|
+
pytest.param(tms.bounds, id="morecantile"),
|
|
64
|
+
pytest.param(utiles.bounds, id="utiles"),
|
|
65
|
+
],
|
|
66
|
+
)
|
|
67
|
+
@pytest.mark.benchmark(group="bounds")
|
|
68
|
+
def test_bounds(
|
|
69
|
+
tile: Tuple[int, int, int],
|
|
70
|
+
func: Callable[[Tuple[int, int, int]], Tuple[float, float]],
|
|
71
|
+
benchmark,
|
|
72
|
+
) -> None:
|
|
73
|
+
"""Benchmark bounds() method."""
|
|
74
|
+
_ = benchmark(func, *tile)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@pytest.mark.parametrize(
|
|
78
|
+
"tile",
|
|
79
|
+
[pytest.param(t, id=str(t)) for t in TEST_TILES],
|
|
80
|
+
)
|
|
81
|
+
@pytest.mark.parametrize(
|
|
82
|
+
"func",
|
|
83
|
+
[
|
|
84
|
+
pytest.param(mercantile.xy_bounds, id="mercantile"),
|
|
85
|
+
pytest.param(tms.xy_bounds, id="morecantile"),
|
|
86
|
+
pytest.param(utiles.xy_bounds, id="utiles"),
|
|
87
|
+
],
|
|
88
|
+
)
|
|
89
|
+
@pytest.mark.benchmark(group="xy_bounds")
|
|
90
|
+
def test_xy_bounds(
|
|
91
|
+
tile: Tuple[int, int, int],
|
|
92
|
+
func: Callable[[Tuple[int, int, int]], Tuple[float, float]],
|
|
93
|
+
benchmark,
|
|
94
|
+
) -> None:
|
|
95
|
+
"""Benchmark xy_bounds() method."""
|
|
96
|
+
_ = benchmark(func, *tile)
|
|
@@ -55,7 +55,7 @@ class TileMatrixSets:
|
|
|
55
55
|
"""Register TileMatrixSet(s)."""
|
|
56
56
|
for identifier in custom_tms.keys():
|
|
57
57
|
if identifier in self.tms and not overwrite:
|
|
58
|
-
raise
|
|
58
|
+
raise InvalidIdentifier(f"{identifier} is already a registered TMS.")
|
|
59
59
|
|
|
60
60
|
return TileMatrixSets({**self.tms, **custom_tms})
|
|
61
61
|
|
|
@@ -488,10 +488,16 @@ class TileMatrixSet(BaseModel, arbitrary_types_allowed=True):
|
|
|
488
488
|
_to_geographic: pyproj.Transformer = PrivateAttr()
|
|
489
489
|
_from_geographic: pyproj.Transformer = PrivateAttr()
|
|
490
490
|
|
|
491
|
+
_tile_matrices_idx: Dict[int, int] = PrivateAttr()
|
|
492
|
+
|
|
491
493
|
def __init__(self, **data):
|
|
492
494
|
"""Set private attributes."""
|
|
493
495
|
super().__init__(**data)
|
|
494
496
|
|
|
497
|
+
self._tile_matrices_idx = {
|
|
498
|
+
int(mat.id): idx for idx, mat in enumerate(self.tileMatrices)
|
|
499
|
+
}
|
|
500
|
+
|
|
495
501
|
try:
|
|
496
502
|
self._to_geographic = pyproj.Transformer.from_crs(
|
|
497
503
|
self.crs._pyproj_crs, self.crs._pyproj_crs.geodetic_crs, always_xy=True
|
|
@@ -504,6 +510,7 @@ class TileMatrixSet(BaseModel, arbitrary_types_allowed=True):
|
|
|
504
510
|
"Could not create coordinate Transformer from input CRS to the given geographic CRS"
|
|
505
511
|
"some methods might not be available.",
|
|
506
512
|
UserWarning,
|
|
513
|
+
stacklevel=1,
|
|
507
514
|
)
|
|
508
515
|
self._to_geographic = None
|
|
509
516
|
self._from_geographic = None
|
|
@@ -531,10 +538,8 @@ class TileMatrixSet(BaseModel, arbitrary_types_allowed=True):
|
|
|
531
538
|
def is_variable(self) -> bool:
|
|
532
539
|
"""Check if TMS has variable width matrix."""
|
|
533
540
|
return any(
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
for matrix in self.tileMatrices
|
|
537
|
-
]
|
|
541
|
+
True if matrix.variableMatrixWidths is not None else False
|
|
542
|
+
for matrix in self.tileMatrices
|
|
538
543
|
)
|
|
539
544
|
|
|
540
545
|
def __iter__(self):
|
|
@@ -765,9 +770,8 @@ class TileMatrixSet(BaseModel, arbitrary_types_allowed=True):
|
|
|
765
770
|
|
|
766
771
|
def matrix(self, zoom: int) -> TileMatrix:
|
|
767
772
|
"""Return the TileMatrix for a specific zoom."""
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
return m
|
|
773
|
+
if (idx := self._tile_matrices_idx.get(zoom, None)) is not None:
|
|
774
|
+
return self.tileMatrices[idx]
|
|
771
775
|
|
|
772
776
|
#######################################################################
|
|
773
777
|
# If user wants a deeper matrix we calculate it
|
|
@@ -795,6 +799,7 @@ class TileMatrixSet(BaseModel, arbitrary_types_allowed=True):
|
|
|
795
799
|
warnings.warn(
|
|
796
800
|
f"TileMatrix not found for level: {zoom} - Creating values from TMS Scale.",
|
|
797
801
|
UserWarning,
|
|
802
|
+
stacklevel=1,
|
|
798
803
|
)
|
|
799
804
|
|
|
800
805
|
# TODO: what if we want to construct a matrix for a level up ?
|
|
@@ -889,6 +894,7 @@ class TileMatrixSet(BaseModel, arbitrary_types_allowed=True):
|
|
|
889
894
|
warnings.warn(
|
|
890
895
|
f"Point ({x}, {y}) is outside TMS bounds {list(self.xy_bbox)}.",
|
|
891
896
|
PointOutsideTMSBounds,
|
|
897
|
+
stacklevel=1,
|
|
892
898
|
)
|
|
893
899
|
|
|
894
900
|
lng, lat = self._to_geographic.transform(x, y)
|
|
@@ -908,6 +914,7 @@ class TileMatrixSet(BaseModel, arbitrary_types_allowed=True):
|
|
|
908
914
|
warnings.warn(
|
|
909
915
|
f"Point ({lng}, {lat}) is outside TMS bounds {list(self.bbox)}.",
|
|
910
916
|
PointOutsideTMSBounds,
|
|
917
|
+
stacklevel=1,
|
|
911
918
|
)
|
|
912
919
|
|
|
913
920
|
x, y = self._from_geographic.transform(lng, lat)
|
|
@@ -1093,8 +1100,23 @@ class TileMatrixSet(BaseModel, arbitrary_types_allowed=True):
|
|
|
1093
1100
|
"""
|
|
1094
1101
|
t = _parse_tile_arg(*tile)
|
|
1095
1102
|
|
|
1096
|
-
|
|
1097
|
-
|
|
1103
|
+
matrix = self.matrix(t.z)
|
|
1104
|
+
origin_x, origin_y = self._matrix_origin(matrix)
|
|
1105
|
+
|
|
1106
|
+
cf = (
|
|
1107
|
+
matrix.get_coalesce_factor(t.y)
|
|
1108
|
+
if matrix.variableMatrixWidths is not None
|
|
1109
|
+
else 1
|
|
1110
|
+
)
|
|
1111
|
+
|
|
1112
|
+
left = origin_x + math.floor(t.x / cf) * matrix.cellSize * cf * matrix.tileWidth
|
|
1113
|
+
top = origin_y - t.y * matrix.cellSize * matrix.tileHeight
|
|
1114
|
+
right = (
|
|
1115
|
+
origin_x
|
|
1116
|
+
+ (math.floor(t.x / cf) + 1) * matrix.cellSize * cf * matrix.tileWidth
|
|
1117
|
+
)
|
|
1118
|
+
bottom = origin_y - (t.y + 1) * matrix.cellSize * matrix.tileHeight
|
|
1119
|
+
|
|
1098
1120
|
return BoundingBox(left, bottom, right, top)
|
|
1099
1121
|
|
|
1100
1122
|
def ul(self, *tile: Tile) -> Coords:
|
|
@@ -1146,10 +1168,10 @@ class TileMatrixSet(BaseModel, arbitrary_types_allowed=True):
|
|
|
1146
1168
|
BoundingBox: The bounding box of the input tile.
|
|
1147
1169
|
|
|
1148
1170
|
"""
|
|
1149
|
-
|
|
1171
|
+
_left, _bottom, _right, _top = self.xy_bounds(*tile)
|
|
1172
|
+
left, top = self.lnglat(_left, _top)
|
|
1173
|
+
right, bottom = self.lnglat(_right, _bottom)
|
|
1150
1174
|
|
|
1151
|
-
left, top = self.ul(t)
|
|
1152
|
-
right, bottom = self.lr(t)
|
|
1153
1175
|
return BoundingBox(left, bottom, right, top)
|
|
1154
1176
|
|
|
1155
1177
|
@property
|
|
@@ -1352,6 +1374,7 @@ class TileMatrixSet(BaseModel, arbitrary_types_allowed=True):
|
|
|
1352
1374
|
"CRS is no longer part of the GeoJSON specification."
|
|
1353
1375
|
"Other projection than EPSG:4326 might not be supported.",
|
|
1354
1376
|
UserWarning,
|
|
1377
|
+
stacklevel=1,
|
|
1355
1378
|
)
|
|
1356
1379
|
feat.update(
|
|
1357
1380
|
{
|
|
@@ -118,12 +118,10 @@ def is_power_of_two(number: int) -> bool:
|
|
|
118
118
|
def check_quadkey_support(tms: List) -> bool:
|
|
119
119
|
"""Check if a Tile Matrix Set supports quadkeys"""
|
|
120
120
|
return all(
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
for i, t in enumerate(tms[:-1])
|
|
126
|
-
]
|
|
121
|
+
(t.matrixWidth == t.matrixHeight)
|
|
122
|
+
and is_power_of_two(t.matrixWidth)
|
|
123
|
+
and ((t.matrixWidth * 2) == tms[i + 1].matrixWidth)
|
|
124
|
+
for i, t in enumerate(tms[:-1])
|
|
127
125
|
)
|
|
128
126
|
|
|
129
127
|
|
|
@@ -17,12 +17,13 @@ classifiers = [
|
|
|
17
17
|
"Programming Language :: Python :: 3.10",
|
|
18
18
|
"Programming Language :: Python :: 3.11",
|
|
19
19
|
"Programming Language :: Python :: 3.12",
|
|
20
|
+
"Programming Language :: Python :: 3.13",
|
|
20
21
|
"Topic :: Scientific/Engineering :: GIS",
|
|
21
22
|
]
|
|
22
23
|
dynamic = ["version"]
|
|
23
24
|
dependencies = [
|
|
24
25
|
"attrs",
|
|
25
|
-
"pyproj
|
|
26
|
+
"pyproj>=3.1,<4.0",
|
|
26
27
|
"pydantic~=2.0",
|
|
27
28
|
]
|
|
28
29
|
|
|
@@ -36,6 +37,10 @@ test = [
|
|
|
36
37
|
"pytest-cov",
|
|
37
38
|
"rasterio>=1.2.1",
|
|
38
39
|
]
|
|
40
|
+
benchmark = [
|
|
41
|
+
"pytest",
|
|
42
|
+
"pytest-benchmark",
|
|
43
|
+
]
|
|
39
44
|
dev = [
|
|
40
45
|
"pre-commit",
|
|
41
46
|
"bump-my-version",
|
|
@@ -91,7 +96,7 @@ default_section = "THIRDPARTY"
|
|
|
91
96
|
[tool.mypy]
|
|
92
97
|
no_strict_optional = true
|
|
93
98
|
|
|
94
|
-
[tool.ruff]
|
|
99
|
+
[tool.ruff.lint]
|
|
95
100
|
select = [
|
|
96
101
|
"D1", # pydocstyle errors
|
|
97
102
|
"E", # pycodestyle errors
|
|
@@ -106,7 +111,7 @@ ignore = [
|
|
|
106
111
|
"B905", # ignore zip() without an explicit strict= parameter, only support with python >3.10
|
|
107
112
|
]
|
|
108
113
|
|
|
109
|
-
[tool.ruff.per-file-ignores]
|
|
114
|
+
[tool.ruff.lint.per-file-ignores]
|
|
110
115
|
"tests/*.py" = ["D1"]
|
|
111
116
|
|
|
112
117
|
|
|
@@ -116,7 +121,7 @@ filterwarnings = [
|
|
|
116
121
|
]
|
|
117
122
|
|
|
118
123
|
[tool.bumpversion]
|
|
119
|
-
current_version = "6.
|
|
124
|
+
current_version = "6.2.0"
|
|
120
125
|
|
|
121
126
|
search = "{current_version}"
|
|
122
127
|
replace = "{new_version}"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|