morecantile 5.1.0__tar.gz → 5.2.1__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-5.1.0 → morecantile-5.2.1}/.bumpversion.cfg +1 -1
- {morecantile-5.1.0 → morecantile-5.2.1}/PKG-INFO +1 -1
- {morecantile-5.1.0 → morecantile-5.2.1}/morecantile/__init__.py +1 -1
- {morecantile-5.1.0 → morecantile-5.2.1}/morecantile/models.py +61 -47
- {morecantile-5.1.0 → morecantile-5.2.1}/.gitignore +0 -0
- {morecantile-5.1.0 → morecantile-5.2.1}/.pre-commit-config.yaml +0 -0
- {morecantile-5.1.0 → morecantile-5.2.1}/LICENSE +0 -0
- {morecantile-5.1.0 → morecantile-5.2.1}/README.md +0 -0
- {morecantile-5.1.0 → morecantile-5.2.1}/morecantile/commons.py +0 -0
- {morecantile-5.1.0 → morecantile-5.2.1}/morecantile/data/CDB1GlobalGrid.json +0 -0
- {morecantile-5.1.0 → morecantile-5.2.1}/morecantile/data/CanadianNAD83_LCC.json +0 -0
- {morecantile-5.1.0 → morecantile-5.2.1}/morecantile/data/EuropeanETRS89_LAEAQuad.json +0 -0
- {morecantile-5.1.0 → morecantile-5.2.1}/morecantile/data/GNOSISGlobalGrid.json +0 -0
- {morecantile-5.1.0 → morecantile-5.2.1}/morecantile/data/LINZAntarticaMapTilegrid.json +0 -0
- {morecantile-5.1.0 → morecantile-5.2.1}/morecantile/data/NZTM2000Quad.json +0 -0
- {morecantile-5.1.0 → morecantile-5.2.1}/morecantile/data/README.md +0 -0
- {morecantile-5.1.0 → morecantile-5.2.1}/morecantile/data/UPSAntarcticWGS84Quad.json +0 -0
- {morecantile-5.1.0 → morecantile-5.2.1}/morecantile/data/UPSArcticWGS84Quad.json +0 -0
- {morecantile-5.1.0 → morecantile-5.2.1}/morecantile/data/UTM31WGS84Quad.json +0 -0
- {morecantile-5.1.0 → morecantile-5.2.1}/morecantile/data/WGS1984Quad.json +0 -0
- {morecantile-5.1.0 → morecantile-5.2.1}/morecantile/data/WebMercatorQuad.json +0 -0
- {morecantile-5.1.0 → morecantile-5.2.1}/morecantile/data/WorldCRS84Quad.json +0 -0
- {morecantile-5.1.0 → morecantile-5.2.1}/morecantile/data/WorldMercatorWGS84Quad.json +0 -0
- {morecantile-5.1.0 → morecantile-5.2.1}/morecantile/defaults.py +0 -0
- {morecantile-5.1.0 → morecantile-5.2.1}/morecantile/errors.py +0 -0
- {morecantile-5.1.0 → morecantile-5.2.1}/morecantile/py.typed +0 -0
- {morecantile-5.1.0 → morecantile-5.2.1}/morecantile/scripts/__init__.py +0 -0
- {morecantile-5.1.0 → morecantile-5.2.1}/morecantile/scripts/cli.py +0 -0
- {morecantile-5.1.0 → morecantile-5.2.1}/morecantile/utils.py +0 -0
- {morecantile-5.1.0 → morecantile-5.2.1}/pyproject.toml +0 -0
|
@@ -6,6 +6,7 @@ import warnings
|
|
|
6
6
|
from functools import cached_property
|
|
7
7
|
from typing import Any, Dict, Iterator, List, Literal, Optional, Sequence, Tuple, Union
|
|
8
8
|
|
|
9
|
+
import pyproj
|
|
9
10
|
from pydantic import (
|
|
10
11
|
AnyHttpUrl,
|
|
11
12
|
AnyUrl,
|
|
@@ -16,7 +17,6 @@ from pydantic import (
|
|
|
16
17
|
field_validator,
|
|
17
18
|
model_validator,
|
|
18
19
|
)
|
|
19
|
-
from pyproj import CRS, Transformer
|
|
20
20
|
from pyproj.exceptions import CRSError, ProjError
|
|
21
21
|
|
|
22
22
|
from morecantile.commons import BoundingBox, Coords, Tile
|
|
@@ -44,7 +44,7 @@ else:
|
|
|
44
44
|
NumType = Union[float, int]
|
|
45
45
|
BoundsType = Tuple[NumType, NumType]
|
|
46
46
|
LL_EPSILON = 1e-11
|
|
47
|
-
WGS84_CRS = CRS.from_epsg(4326)
|
|
47
|
+
WGS84_CRS = pyproj.CRS.from_epsg(4326)
|
|
48
48
|
axesInfo = Annotated[List[str], Field(min_length=2, max_length=2)]
|
|
49
49
|
|
|
50
50
|
|
|
@@ -64,30 +64,28 @@ class CRSUri(BaseModel):
|
|
|
64
64
|
|
|
65
65
|
|
|
66
66
|
class CRSWKT(BaseModel):
|
|
67
|
-
"""Coordinate Reference System (CRS) from WKT."""
|
|
67
|
+
"""Coordinate Reference System (CRS) from WKT encoded as PROJJSON Object."""
|
|
68
68
|
|
|
69
69
|
wkt: Annotated[
|
|
70
|
-
|
|
70
|
+
Dict,
|
|
71
71
|
Field(
|
|
72
|
-
description="
|
|
73
|
-
examples=[
|
|
74
|
-
'GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]',
|
|
75
|
-
],
|
|
72
|
+
description="An object defining the CRS using the JSON encoding for Well-known text representation of coordinate reference systems 2.0",
|
|
76
73
|
),
|
|
77
74
|
]
|
|
78
75
|
|
|
79
76
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
77
|
+
class CRSRef(BaseModel):
|
|
78
|
+
"""CRS from referenceSystem."""
|
|
79
|
+
|
|
80
|
+
referenceSystem: Annotated[
|
|
81
|
+
Dict[str, Any],
|
|
82
|
+
Field(
|
|
83
|
+
description="A reference system data structure as defined in the MD_ReferenceSystem of the ISO 19115",
|
|
84
|
+
),
|
|
85
|
+
]
|
|
88
86
|
|
|
89
87
|
|
|
90
|
-
class
|
|
88
|
+
class CRS(RootModel[Union[str, Union[CRSUri, CRSWKT, CRSRef]]]):
|
|
91
89
|
"""CRS model.
|
|
92
90
|
|
|
93
91
|
Ref: https://github.com/opengeospatial/ogcapi-tiles/blob/master/openapi/schemas/common-geodata/crs.yaml
|
|
@@ -95,12 +93,25 @@ class CRSType(RootModel[Union[str, Union[CRSUri, CRSWKT]]]):
|
|
|
95
93
|
Code generated using https://github.com/koxudaxi/datamodel-code-generator/
|
|
96
94
|
"""
|
|
97
95
|
|
|
98
|
-
_pyproj_crs: CRS = PrivateAttr()
|
|
96
|
+
_pyproj_crs: pyproj.CRS = PrivateAttr()
|
|
99
97
|
|
|
100
98
|
def model_post_init(self, __context: Any) -> None:
|
|
101
99
|
"""Post Init: Set private attr."""
|
|
102
100
|
super().model_post_init(__context)
|
|
103
|
-
|
|
101
|
+
|
|
102
|
+
if isinstance(self.root, str):
|
|
103
|
+
self._pyproj_crs = pyproj.CRS.from_user_input(self.root)
|
|
104
|
+
|
|
105
|
+
elif isinstance(self.root, CRSUri):
|
|
106
|
+
self._pyproj_crs = pyproj.CRS.from_user_input(str(self.root.uri))
|
|
107
|
+
|
|
108
|
+
elif isinstance(self.root, CRSWKT):
|
|
109
|
+
self._pyproj_crs = pyproj.CRS.from_json_dict(self.root.wkt)
|
|
110
|
+
|
|
111
|
+
elif isinstance(self.root, CRSRef):
|
|
112
|
+
raise NotImplementedError(
|
|
113
|
+
"Morecantile does not support `MD_ReferenceSystem` defined CRS"
|
|
114
|
+
)
|
|
104
115
|
|
|
105
116
|
@property
|
|
106
117
|
def srs(self) -> str:
|
|
@@ -128,7 +139,11 @@ class CRSType(RootModel[Union[str, Union[CRSUri, CRSWKT]]]):
|
|
|
128
139
|
return self._pyproj_crs.to_json(*args, **kwargs)
|
|
129
140
|
|
|
130
141
|
|
|
131
|
-
|
|
142
|
+
# For compatibility
|
|
143
|
+
CRSType = CRS
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def CRS_to_uri(crs: pyproj.CRS) -> str:
|
|
132
147
|
"""Convert CRS to URI."""
|
|
133
148
|
authority = "EPSG"
|
|
134
149
|
code = None
|
|
@@ -140,10 +155,11 @@ def CRS_to_uri(crs: CRS) -> str:
|
|
|
140
155
|
# if we have a version number in the authority, split it out
|
|
141
156
|
if "_" in authority:
|
|
142
157
|
authority, version = authority.split("_")
|
|
158
|
+
|
|
143
159
|
return f"http://www.opengis.net/def/crs/{authority}/{version}/{code}"
|
|
144
160
|
|
|
145
161
|
|
|
146
|
-
def crs_axis_inverted(crs: CRS) -> bool:
|
|
162
|
+
def crs_axis_inverted(crs: pyproj.CRS) -> bool:
|
|
147
163
|
"""Check if CRS has inverted AXIS (lat,lon) instead of (lon,lat)."""
|
|
148
164
|
return crs.axis_info[0].abbrev.upper() in ["Y", "LAT", "N"]
|
|
149
165
|
|
|
@@ -169,7 +185,7 @@ class TMSBoundingBox(BaseModel, arbitrary_types_allowed=True):
|
|
|
169
185
|
Field(description="A 2D Point in the CRS indicated elsewhere"),
|
|
170
186
|
]
|
|
171
187
|
crs: Annotated[
|
|
172
|
-
Optional[
|
|
188
|
+
Optional[CRS],
|
|
173
189
|
Field(description="Coordinate Reference System (CRS)"),
|
|
174
190
|
] = None
|
|
175
191
|
orderedAxes: Annotated[
|
|
@@ -252,17 +268,17 @@ class TileMatrix(BaseModel, extra="forbid"):
|
|
|
252
268
|
Field(description="Cell size of this tile matrix"),
|
|
253
269
|
]
|
|
254
270
|
cornerOfOrigin: Annotated[
|
|
255
|
-
|
|
271
|
+
Literal["topLeft", "bottomLeft"],
|
|
256
272
|
Field(
|
|
257
273
|
description="The corner of the tile matrix (_topLeft_ or _bottomLeft_) used as the origin for numbering tile rows and columns. This corner is also a corner of the (0, 0) tile.",
|
|
258
274
|
),
|
|
259
|
-
] =
|
|
275
|
+
] = "topLeft"
|
|
260
276
|
pointOfOrigin: Annotated[
|
|
261
277
|
BoundsType,
|
|
262
278
|
Field(
|
|
263
279
|
description="Precise position in CRS coordinates of the corner of origin (e.g. the top-left corner) for this tile matrix. This position is also a corner of the (0, 0) tile. In previous version, this was 'topLeftCorner' and 'cornerOfOrigin' did not exist.",
|
|
264
280
|
),
|
|
265
|
-
]
|
|
281
|
+
]
|
|
266
282
|
tileWidth: Annotated[
|
|
267
283
|
int,
|
|
268
284
|
Field(
|
|
@@ -363,7 +379,7 @@ class TileMatrixSet(BaseModel, arbitrary_types_allowed=True):
|
|
|
363
379
|
Field(description="Ordered list of names of the dimensions defined in the CRS"),
|
|
364
380
|
] = None
|
|
365
381
|
crs: Annotated[
|
|
366
|
-
|
|
382
|
+
CRS,
|
|
367
383
|
Field(description="Coordinate Reference System (CRS)"),
|
|
368
384
|
]
|
|
369
385
|
wellKnownScaleSet: Annotated[
|
|
@@ -382,9 +398,9 @@ class TileMatrixSet(BaseModel, arbitrary_types_allowed=True):
|
|
|
382
398
|
]
|
|
383
399
|
|
|
384
400
|
# Private attributes
|
|
385
|
-
_geographic_crs: CRS = PrivateAttr(default=WGS84_CRS)
|
|
386
|
-
_to_geographic: Transformer = PrivateAttr()
|
|
387
|
-
_from_geographic: Transformer = PrivateAttr()
|
|
401
|
+
_geographic_crs: pyproj.CRS = PrivateAttr(default=WGS84_CRS)
|
|
402
|
+
_to_geographic: pyproj.Transformer = PrivateAttr()
|
|
403
|
+
_from_geographic: pyproj.Transformer = PrivateAttr()
|
|
388
404
|
|
|
389
405
|
def __init__(self, **data):
|
|
390
406
|
"""Set private attributes."""
|
|
@@ -393,10 +409,10 @@ class TileMatrixSet(BaseModel, arbitrary_types_allowed=True):
|
|
|
393
409
|
self._geographic_crs = data.get("_geographic_crs", WGS84_CRS)
|
|
394
410
|
|
|
395
411
|
try:
|
|
396
|
-
self._to_geographic = Transformer.from_crs(
|
|
412
|
+
self._to_geographic = pyproj.Transformer.from_crs(
|
|
397
413
|
self.crs._pyproj_crs, self._geographic_crs, always_xy=True
|
|
398
414
|
)
|
|
399
|
-
self._from_geographic = Transformer.from_crs(
|
|
415
|
+
self._from_geographic = pyproj.Transformer.from_crs(
|
|
400
416
|
self._geographic_crs, self.crs._pyproj_crs, always_xy=True
|
|
401
417
|
)
|
|
402
418
|
except ProjError:
|
|
@@ -444,12 +460,10 @@ class TileMatrixSet(BaseModel, arbitrary_types_allowed=True):
|
|
|
444
460
|
|
|
445
461
|
def __repr__(self):
|
|
446
462
|
"""Simplify default pydantic model repr."""
|
|
447
|
-
return (
|
|
448
|
-
f"<TileMatrixSet title='{self.title}' id='{self.id}' crs='{self.crs.root}>"
|
|
449
|
-
)
|
|
463
|
+
return f"<TileMatrixSet title='{self.title}' id='{self.id}' crs='{CRS_to_uri(self.crs._pyproj_crs)}>"
|
|
450
464
|
|
|
451
465
|
@cached_property
|
|
452
|
-
def geographic_crs(self) -> CRS:
|
|
466
|
+
def geographic_crs(self) -> pyproj.CRS:
|
|
453
467
|
"""Return the TMS's geographic CRS."""
|
|
454
468
|
return self._geographic_crs
|
|
455
469
|
|
|
@@ -489,7 +503,7 @@ class TileMatrixSet(BaseModel, arbitrary_types_allowed=True):
|
|
|
489
503
|
|
|
490
504
|
Attributes
|
|
491
505
|
----------
|
|
492
|
-
supportedCRS:
|
|
506
|
+
supportedCRS: CRS
|
|
493
507
|
Tile Matrix Set coordinate reference system
|
|
494
508
|
title: str
|
|
495
509
|
Title of TMS
|
|
@@ -523,7 +537,7 @@ class TileMatrixSet(BaseModel, arbitrary_types_allowed=True):
|
|
|
523
537
|
v2_tms["crs"] = v2_tms.pop("supportedCRS")
|
|
524
538
|
v2_tms["tileMatrices"] = v2_tms.pop("tileMatrix")
|
|
525
539
|
v2_tms["id"] = v2_tms.pop("identifier")
|
|
526
|
-
mpu = meters_per_unit(CRS.from_user_input(v2_tms["crs"]))
|
|
540
|
+
mpu = meters_per_unit(pyproj.CRS.from_user_input(v2_tms["crs"]))
|
|
527
541
|
for i in range(len(v2_tms["tileMatrices"])):
|
|
528
542
|
v2_tms["tileMatrices"][i]["cellSize"] = (
|
|
529
543
|
v2_tms["tileMatrices"][i]["scaleDenominator"] * 0.28e-3 / mpu
|
|
@@ -542,17 +556,17 @@ class TileMatrixSet(BaseModel, arbitrary_types_allowed=True):
|
|
|
542
556
|
def custom(
|
|
543
557
|
cls,
|
|
544
558
|
extent: List[float],
|
|
545
|
-
crs: CRS,
|
|
559
|
+
crs: pyproj.CRS,
|
|
546
560
|
tile_width: int = 256,
|
|
547
561
|
tile_height: int = 256,
|
|
548
562
|
matrix_scale: Optional[List] = None,
|
|
549
|
-
extent_crs: Optional[CRS] = None,
|
|
563
|
+
extent_crs: Optional[pyproj.CRS] = None,
|
|
550
564
|
minzoom: int = 0,
|
|
551
565
|
maxzoom: int = 24,
|
|
552
566
|
title: Optional[str] = None,
|
|
553
567
|
id: Optional[str] = None,
|
|
554
568
|
ordered_axes: Optional[List[str]] = None,
|
|
555
|
-
geographic_crs: CRS = WGS84_CRS,
|
|
569
|
+
geographic_crs: pyproj.CRS = WGS84_CRS,
|
|
556
570
|
screen_pixel_size: float = 0.28e-3,
|
|
557
571
|
**kwargs: Any,
|
|
558
572
|
):
|
|
@@ -604,7 +618,7 @@ class TileMatrixSet(BaseModel, arbitrary_types_allowed=True):
|
|
|
604
618
|
is_inverted = crs_axis_inverted(crs)
|
|
605
619
|
|
|
606
620
|
if extent_crs:
|
|
607
|
-
transform = Transformer.from_crs(extent_crs, crs, always_xy=True)
|
|
621
|
+
transform = pyproj.Transformer.from_crs(extent_crs, crs, always_xy=True)
|
|
608
622
|
extent = transform.transform_bounds(*extent, densify_pts=21)
|
|
609
623
|
|
|
610
624
|
bbox = BoundingBox(*extent)
|
|
@@ -636,20 +650,20 @@ class TileMatrixSet(BaseModel, arbitrary_types_allowed=True):
|
|
|
636
650
|
)
|
|
637
651
|
|
|
638
652
|
if crs.to_authority(min_confidence=20):
|
|
639
|
-
|
|
653
|
+
crs_data: Any = CRS_to_uri(crs)
|
|
640
654
|
|
|
641
655
|
# Some old Proj version might not support URI
|
|
642
656
|
# so we fall back to wkt
|
|
643
657
|
try:
|
|
644
|
-
CRS.from_user_input(
|
|
658
|
+
pyproj.CRS.from_user_input(crs_data)
|
|
645
659
|
except CRSError:
|
|
646
|
-
|
|
660
|
+
crs_data = {"wkt": crs.to_json_dict()}
|
|
647
661
|
|
|
648
662
|
else:
|
|
649
|
-
|
|
663
|
+
crs_data = {"wkt": crs.to_json_dict()}
|
|
650
664
|
|
|
651
665
|
return cls(
|
|
652
|
-
crs=
|
|
666
|
+
crs=crs_data,
|
|
653
667
|
tileMatrices=tile_matrices,
|
|
654
668
|
id=id,
|
|
655
669
|
title=title,
|
|
@@ -1236,7 +1250,7 @@ class TileMatrixSet(BaseModel, arbitrary_types_allowed=True):
|
|
|
1236
1250
|
"properties": {
|
|
1237
1251
|
"title": f"XYZ tile {xyz}",
|
|
1238
1252
|
"grid_name": self.id,
|
|
1239
|
-
"grid_crs": self.crs.
|
|
1253
|
+
"grid_crs": CRS_to_uri(self.crs._pyproj_crs),
|
|
1240
1254
|
},
|
|
1241
1255
|
}
|
|
1242
1256
|
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|