Skip to content

Commit eba1736

Browse files
authored
ENH: Added pyproj.database.query_utm_crs_info (#712)
1 parent 69dc136 commit eba1736

File tree

5 files changed

+115
-0
lines changed

5 files changed

+115
-0
lines changed

docs/api/database.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
.. _database:
2+
13
Database
24
=========
35

@@ -36,3 +38,8 @@ pyproj.database.query_crs_info
3638
.. autofunction:: pyproj.database.query_crs_info
3739

3840
.. autoclass:: pyproj.database.CRSInfo
41+
42+
pyproj.database.query_utm_crs_info
43+
-----------------------------------
44+
45+
.. autofunction:: pyproj.database.query_utm_crs_info

docs/examples.rst

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,29 @@ This is just a small subset of what is available.
204204
Param(name=False northing, auth_name=EPSG, code=8807, value=0.0, unit_name=metre, unit_auth_name=, unit_code=, unit_category=linear)]
205205
206206
207+
Find UTM CRS by Latitude and Longitude
208+
---------------------------------------
209+
210+
.. note:: For more database methods see: :ref:`database`.
211+
212+
.. code-block:: python
213+
214+
from pyproj import CRS
215+
from pyproj.aoi import AreaOfInterest
216+
from pyproj.database import query_utm_crs_info
217+
218+
utm_crs_list = query_utm_crs_info(
219+
datum_name="WGS 84",
220+
area_of_interest=AreaOfInterest(
221+
west_lon_degree=-93.581543,
222+
south_lat_degree=42.032974,
223+
east_lon_degree=-93.581543,
224+
north_lat_degree=42.032974,
225+
),
226+
)
227+
utm_crs = CRS.from_epsg(utm_crs_list[0].code)
228+
229+
207230
Transformations from CRS to CRS
208231
-------------------------------
209232

docs/history.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Change Log
2424
* ENH: Added support for debugging internal PROJ (pull #696)
2525
* ENH: Added pathlib support for data directory methods (pull #702)
2626
* ENH: Added :func:`pyproj.database.query_crs_info` (pull #703)
27+
* ENH: Added :func:`pyproj.database.query_utm_crs_info` (pull #712)
2728
* REF: Refactor Proj to inherit from Transformer (issue #624)
2829
* REF: Added `pyproj.database`, `pyproj.aoi`, and `pyproj.list` modules (pull #703)
2930
* BUG: Fix handling of polygon holes when calculating area in Geod (pull #686)

pyproj/database.pyx

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,46 @@ def query_crs_info(
261261
return code_list
262262

263263

264+
def query_utm_crs_info(
265+
datum_name=None,
266+
area_of_interest=None,
267+
contains=False,
268+
):
269+
"""
270+
.. versionadded:: 3.0
271+
272+
Query for EPSG UTM CRS information from the PROJ database.
273+
274+
Parameters
275+
----------
276+
datum_name: Optional[str]
277+
The name of the datum in the CRS name ('NAD27', 'NAD83', 'WGS 84', ...).
278+
area_of_interest: Optional[AreaOfInterest]
279+
Filter returned CRS by the area of interest. Default method is intersection.
280+
contains: Optional[bool]
281+
Only works if the area of interest is passed in.
282+
If True, then only CRS whose area of use entirely contains the specified
283+
bounding box will be returned. If False, then only CRS whose area of use
284+
intersects the specified bounding box will be returned.
285+
286+
Returns
287+
-------
288+
List[CRSInfo]:
289+
UTM CRS information from the PROJ database.
290+
"""
291+
projected_crs = query_crs_info(
292+
auth_name="EPSG",
293+
pj_types=PJType.PROJECTED_CRS,
294+
area_of_interest=area_of_interest,
295+
contains=contains,
296+
)
297+
utm_crs = [crs for crs in projected_crs if "UTM zone" in crs.name]
298+
if datum_name is None:
299+
return utm_crs
300+
datum_name = datum_name.replace(" ", "")
301+
return [crs for crs in utm_crs if datum_name in crs.name.replace(" ", "")]
302+
303+
264304
Unit = namedtuple(
265305
"Unit",
266306
[

test/test_database.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
get_codes,
88
get_units_map,
99
query_crs_info,
10+
query_utm_crs_info,
1011
)
1112
from pyproj.enums import PJType
1213

@@ -201,3 +202,46 @@ def test_query_crs_info__aoi_contains():
201202
assert crs_info.auth_name == "IGNF"
202203
assert crs_info.type == PJType.PROJECTED_CRS
203204
assert not crs_info.deprecated
205+
206+
207+
@pytest.mark.parametrize("datum_name", ["WGS 84", "WGS84", "NAD27"])
208+
def test_query_utm_crs_info__aoi_datum_name(datum_name):
209+
aoi = BBox(west=-93.581543, south=42.032974, east=-93.581543, north=42.032974)
210+
crs_info_list = query_utm_crs_info(
211+
datum_name=datum_name,
212+
area_of_interest=AreaOfInterest(
213+
west_lon_degree=aoi.west,
214+
south_lat_degree=aoi.south,
215+
east_lon_degree=aoi.east,
216+
north_lat_degree=aoi.north,
217+
),
218+
)
219+
assert len(crs_info_list) == 1
220+
crs_info = crs_info_list[0]
221+
bbox = BBox(*crs_info.area_of_use.bounds)
222+
assert bbox.intersects(aoi)
223+
assert "UTM zone" in crs_info.name
224+
assert datum_name.replace(" ", "") in crs_info.name.replace(" ", "")
225+
assert crs_info.auth_name == "EPSG"
226+
assert crs_info.type == PJType.PROJECTED_CRS
227+
assert not crs_info.deprecated
228+
229+
230+
def test_query_utm_crs_info__aoi_contains():
231+
aoi = BBox(west=41, south=50, east=42, north=51)
232+
crs_info_list = query_utm_crs_info(
233+
area_of_interest=AreaOfInterest(
234+
west_lon_degree=aoi.west,
235+
south_lat_degree=aoi.south,
236+
east_lon_degree=aoi.east,
237+
north_lat_degree=aoi.north,
238+
),
239+
contains=True,
240+
)
241+
assert crs_info_list
242+
for crs_info in crs_info_list:
243+
assert BBox(*crs_info.area_of_use.bounds).contains(aoi)
244+
assert "UTM zone" in crs_info.name
245+
assert crs_info.auth_name == "EPSG"
246+
assert crs_info.type == PJType.PROJECTED_CRS
247+
assert not crs_info.deprecated

0 commit comments

Comments
 (0)