@@ -6,9 +6,10 @@ from collections import namedtuple
66from libc.stdlib cimport free, malloc
77
88from pyproj._compat cimport cstrdecode, cstrencode
9- from pyproj._context cimport pyproj_context_create
9+ from pyproj._context cimport _clear_proj_error, pyproj_context_create
1010
1111from pyproj.aoi import AreaOfUse
12+ from pyproj.crs import CRS
1213from pyproj.enums import PJType
1314
1415
@@ -465,3 +466,98 @@ def get_database_metadata(str key not None):
465466 if metadata == NULL :
466467 return None
467468 return metadata
469+
470+
471+ def query_geodetic_crs_from_datum (
472+ str crs_auth_name ,
473+ str datum_auth_name not None ,
474+ str datum_code not None ,
475+ pj_type = None
476+ ):
477+ """
478+ .. versionadded:: 3.8.0
479+
480+ Return GeodeticCRS that use the specified datum
481+
482+ See: :c:func:`proj_query_geodetic_crs_from_datum`
483+
484+ Parameters
485+ ----------
486+ crs_auth_name: str | None
487+ The authority name to filter by (e.g. EPSG, ESRI). None is all.
488+ datum_auth_name: str
489+ The authority of the datum
490+ datum_code: str
491+ Datum code
492+ pj_type: pyproj.enums.PJType | None, optional
493+ The type of object to get the CRSs. Can be PJType.GEOCENTRIC_CRS,
494+ PJType.GEOGRAPHIC_3D_CRS, PJType.GEOGRAPHIC_2D_CRS or None for all.
495+
496+ Returns
497+ -------
498+ list[CRS]
499+ """
500+
501+ cdef const char * c_crs_type = NULL
502+ if pj_type is None :
503+ pass
504+ elif pj_type is PJType.GEOCENTRIC_CRS:
505+ c_crs_type = b" geocentric"
506+ elif pj_type is PJType.GEOGRAPHIC_2D_CRS:
507+ c_crs_type = b" geographic 2D"
508+ elif pj_type is PJType.GEOGRAPHIC_3D_CRS:
509+ c_crs_type = b" geographic 3D"
510+ else :
511+ raise ValueError (" type must be GEOCENTRIC_CRS, GEOGRAPHIC_2D_CRS, GEOGRAPHIC_3D_CRS or None" )
512+
513+ cdef const char * c_crs_auth_name = NULL
514+ cdef const char * c_datum_auth_name = NULL
515+ cdef const char * c_datum_code = NULL
516+ cdef bytes b_crs_auth_name
517+ cdef bytes b_datum_auth_name
518+ cdef bytes b_datum_code
519+
520+ if crs_auth_name is not None :
521+ b_crs_auth_name = cstrencode(crs_auth_name)
522+ c_crs_auth_name = b_crs_auth_name
523+
524+ if datum_auth_name is not None :
525+ b_datum_auth_name = cstrencode(datum_auth_name)
526+ c_datum_auth_name = b_datum_auth_name
527+
528+ if datum_code is not None :
529+ b_datum_code = cstrencode(datum_code)
530+ c_datum_code = b_datum_code
531+
532+ ret_list = []
533+
534+ cdef PJ_OBJ_LIST * proj_list = NULL
535+ cdef int num_proj_objects = 0
536+
537+ cdef PJ_CONTEXT* context = pyproj_context_create()
538+ proj_list = proj_query_geodetic_crs_from_datum(
539+ context,
540+ c_crs_auth_name,
541+ c_datum_auth_name,
542+ c_datum_code,
543+ c_crs_type
544+ )
545+
546+ if proj_list != NULL :
547+ num_proj_objects = proj_list_get_count(proj_list)
548+
549+ cdef PJ* proj = NULL
550+ try :
551+ for iii in range (num_proj_objects):
552+ proj = proj_list_get(context, proj_list, iii)
553+ ret_list.append(CRS(proj_as_wkt(context, proj, PJ_WKT2_2019, NULL )))
554+ proj_destroy(proj)
555+ proj = NULL
556+ finally :
557+ # If there was an error we have to call proj_destroy
558+ # If there was none, calling it on NULL does nothing
559+ proj_destroy(proj)
560+ proj_list_destroy(proj_list)
561+ _clear_proj_error()
562+
563+ return ret_list
0 commit comments