a
    1$ec                     @   s   d Z ddlZddlZddlZddlZddlmZmZmZm	Z	 ddl
mZmZmZmZmZmZmZmZmZmZmZmZ ddlmZmZmZmZmZmZ ddlmZ ddl m!Z!m"Z"m#Z# ddl$m%Z%m&Z& dd	l'm(Z( dd
l)m*Z* e+dej,Z-G dd dej.Z/d2e0e1e2dddZ3e2e2dddZ4e2e2dddZ5e2e	e2e6f dddZ7e	e2e6f dddZ8ee1dddZ9G d d! d!Z:G d"d# d#e:Z;G d$d% d%e;Z<G d&d' d'e;Z=G d(d) d)e;Z>G d*d+ d+e;Z?G d,d- d-e;Z@G d.d/ d/e;ZAG d0d1 d1e;ZBdS )3zx
This module interfaces with PROJ to produce a pythonic interface
to the coordinate reference system (CRS) information.
    N)AnyCallableOptionalUnion)_CRS	AreaOfUseAuthorityMatchInfoAxisCoordinateOperationCoordinateSystemDatum	EllipsoidPrimeMeridian_load_proj_jsonis_projis_wkt)!_GEOGRAPHIC_GRID_MAPPING_NAME_MAP_GRID_MAPPING_NAME_MAP)_INVERSE_GEOGRAPHIC_GRID_MAPPING_NAME_MAP_INVERSE_GRID_MAPPING_NAME_MAP_horizontal_datum_from_params_try_list_if_string)ToWGS84Transformation)Cartesian2DCSEllipsoidal2DCS
VerticalCS)ProjVersion
WktVersion)CRSError)Geoda9  
    \+              # parameter starts with '+' character
    (?P<param>\w+)    # capture parameter name
    \=?             # match both key only and key-value parameters
    (?P<value>\S+)? # capture all characters up to next space (None if no value)
    \s*?            # consume remaining whitespace, if any
c                       s    e Zd ZdZ fddZ  ZS )CRSLocalz
    Threading local instance for cython CRS class.

    For more details, see:
    https://github.com/pyproj4/pyproj/issues/782
    c                    s   d | _ t   d S N)crssuper__init__self	__class__ J/var/www/html/django/DPS/env/lib/python3.9/site-packages/pyproj/crs/crs.pyr$   <   s    zCRSLocal.__init__)__name__
__module____qualname____doc__r$   __classcell__r)   r)   r'   r*   r    4   s   r    T)
projparams
allow_jsonreturnc                 C   s   t | tstdd| vr0d| vr0|r0t| S g }|  D ]t\}}t |ttfrfddd |D }|d u szt	|dkr|
d|  q<t	|d	krq<|
d| d
|  q<td|S )NzCRS input is not a dictprojinit,c                 S   s   g | ]}t |qS r)   )str).0valr)   r)   r*   
<listcomp>L       z&_prepare_from_dict.<locals>.<listcomp>True+False= )
isinstancedictr   jsondumpsitemslisttuplejoinr6   append_prepare_from_string)r0   r1   Zpjargskeyvaluer)   r)   r*   _prepare_from_dictA   s    

rL   in_crs_stringr2   c                 C   s   t dd|  } d}| |sjg }d}|  D ].}|sT||rT|d| d}q0|| q0d|} d| vrd	| v r| d
7 } n| d7 } | dd	 } | drt
jdtdd | S )Nz[\s+]?=[\s+]?r>   )+initz+projr4   r3   Fr   Tr?   ztype=crsr<   z
 +type=crsz	 type=crsz
+init=EPSGz
+init=epsg)rO   r4   z'+init=<authority>:<code>' syntax is deprecated. '<authority>:<code>' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6   )
stacklevel)resublstrip
startswithsplitinsertrH   rG   replacestripwarningswarnFutureWarning)rN   Zstarting_paramsZkvpairsZfirst_item_insertedZkvpairr)   r)   r*   _prepare_from_proj_stringW   s.    



	r]   c              
   C   s   t | tstd| s$td| d| v rztj| dd}W n. tyl } ztd|W Y d }~n
d }~0 0 |sztdt|} nt| rt| } | S )NzCRS input is not a stringz CRS string is empty or invalid: {F)strictz'CRS appears to be JSON but is not validzCRS is empty JSON)	r@   r6   r   rB   loads
ValueErrorrL   r   r]   )rN   crs_dicterrr)   r)   r*   rI   }   s    
 
rI   	auth_name	auth_codec                 C   s   |  d| S )N:r)   rd   r)   r)   r*   _prepare_from_authority   s    rh   rf   c                 C   s
   t d| S )NZEPSG)rh   ri   r)   r)   r*   _prepare_from_epsg   s    rj   )rf   r2   c                 C   s@   t | trdS t | tr$|  r$dS t| dr<| jdkr<dS dS )NTshaper)   F)r@   intr6   	isnumerichasattrrk   ri   r)   r)   r*   _is_epsg_code   s    
ro   c                   @   s  e Zd ZdZdee ddddZedd Ze	e
ee
ef d dd	d
Ze	ee
ef d dddZe	e
d dddZe	e
d dddZe	e
d dddZe
dddZe	ed dddZee dddZe	ed dd d!Ze	e
d d"d#d$Ze	ed d%d&d'Zedd(d)Zejd*feee
f eed+d,d-Zedeee ee ee d d.d/d0Z e!e dd1d2Z"eed3d4d5Z#deeed6d7d8Z$eed  dd9d:Z%eed  dd;d<Z&eed  dd=d>Z'ee!d  dd?d@Z(eee
 ddAdBZ)ee
ddCdDZ*ee
ddEdFZ+ee!e, ddGdHZ-eee. ddIdJZ/eee0 ddKdLZ1eee2 ddMdNZ3eee4 ddOdPZ5eee6 ddQdRZ7eee8 ddSdTZ9ee
ddUdVZ:ee
ddWdXZ;ejd*dfeee
f eee e
dYdZd[Z<deee
d]d^d_Z=edd`daZ>e?j@fee?ef e
dbdcddZAdeee dfdgdhZBdee
 edidjdkZCdee
 ee!eD dldmdnZEdee
 d dodpdqZFdee
 d dodrdsZGeeddtduZHeeddvdwZIeeddxdyZJeeddzd{ZKeedd|d}ZLeedd~dZMeedddZNedd ZOeed3ddZPee
e
f dddZQee
ef dddZRedddZSe
dddZTe
dddZUdS )CRSaK  
    A pythonic Coordinate Reference System manager.

    .. versionadded:: 2.0.0

    See: :c:func:`proj_create`

    The functionality is based on other fantastic projects:

    * `rasterio <https://github.com/mapbox/rasterio/blob/c13f0943b95c0eaa36ff3f620bd91107aa67b381/rasterio/_crs.pyx>`_  # noqa: E501
    * `opendatacube <https://github.com/opendatacube/datacube-core/blob/83bae20d2a2469a6417097168fd4ede37fd2abe5/datacube/utils/geometry/_base.py>`_  # noqa: E501

    Attributes
    ----------
    srs: str
        The string form of the user input used to create the CRS.

    N)r0   r2   c                 K   s   d}|rt |tr|j}nt|r,t|}nnt |tr@t|}nZt |trTt|}nFt |t	t
frxt|dkrxt| }n"t|dr| }ntd||rt|dd}td||f}|| _t | _t |tr|| j_nt| j| j_dS )	u  
        Initialize a CRS class instance with:
          - PROJ string
          - Dictionary of PROJ parameters
          - PROJ keyword arguments for parameters
          - JSON string with PROJ parameters
          - CRS WKT string
          - An authority string [i.e. 'epsg:4326']
          - An EPSG integer code [i.e. 4326]
          - A tuple of ("auth_name": "auth_code") [i.e ('epsg', '4326')]
          - An object with a `to_wkt` method.
          - A :class:`pyproj.crs.CRS` class

        Example usage:

        >>> from pyproj import CRS
        >>> crs_utm = CRS.from_user_input(26915)
        >>> crs_utm
        <Projected CRS: EPSG:26915>
        Name: NAD83 / UTM zone 15N
        Axis Info [cartesian]:
        - E[east]: Easting (metre)
        - N[north]: Northing (metre)
        Area of Use:
        - name: North America - 96°W to 90°W and NAD83 by country
        - bounds: (-96.0, 25.61, -90.0, 84.0)
        Coordinate Operation:
        - name: UTM zone 15N
        - method: Transverse Mercator
        Datum: North American Datum 1983
        - Ellipsoid: GRS 1980
        - Prime Meridian: Greenwich
        <BLANKLINE>
        >>> crs_utm.area_of_use.bounds
        (-96.0, 25.61, -90.0, 84.0)
        >>> crs_utm.ellipsoid
        ELLIPSOID["GRS 1980",6378137,298.257222101,
            LENGTHUNIT["metre",1],
            ID["EPSG",7019]]
        >>> crs_utm.ellipsoid.inverse_flattening
        298.257222101
        >>> crs_utm.ellipsoid.semi_major_metre
        6378137.0
        >>> crs_utm.ellipsoid.semi_minor_metre
        6356752.314140356
        >>> crs_utm.prime_meridian
        PRIMEM["Greenwich",0,
            ANGLEUNIT["degree",0.0174532925199433],
            ID["EPSG",8901]]
        >>> crs_utm.prime_meridian.unit_name
        'degree'
        >>> crs_utm.prime_meridian.unit_conversion_factor
        0.017453292519943295
        >>> crs_utm.prime_meridian.longitude
        0.0
        >>> crs_utm.datum
        DATUM["North American Datum 1983",
            ELLIPSOID["GRS 1980",6378137,298.257222101,
                LENGTHUNIT["metre",1]],
            ID["EPSG",6269]]
        >>> crs_utm.coordinate_system
        CS[Cartesian,2],
            AXIS["(E)",east,
                ORDER[1],
                LENGTHUNIT["metre",1,
                    ID["EPSG",9001]]],
            AXIS["(N)",north,
                ORDER[2],
                LENGTHUNIT["metre",1,
                    ID["EPSG",9001]]]
        >>> print(crs_utm.coordinate_operation.to_wkt(pretty=True))
        CONVERSION["UTM zone 15N",
            METHOD["Transverse Mercator",
                ID["EPSG",9807]],
            PARAMETER["Latitude of natural origin",0,
                ANGLEUNIT["degree",0.0174532925199433],
                ID["EPSG",8801]],
            PARAMETER["Longitude of natural origin",-93,
                ANGLEUNIT["degree",0.0174532925199433],
                ID["EPSG",8802]],
            PARAMETER["Scale factor at natural origin",0.9996,
                SCALEUNIT["unity",1],
                ID["EPSG",8805]],
            PARAMETER["False easting",500000,
                LENGTHUNIT["metre",1],
                ID["EPSG",8806]],
            PARAMETER["False northing",0,
                LENGTHUNIT["metre",1],
                ID["EPSG",8807]],
            ID["EPSG",16015]]
        >>> crs = CRS(proj='utm', zone=10, ellps='WGS84')
        >>> print(crs.to_wkt(pretty=True))
        PROJCRS["unknown",
            BASEGEOGCRS["unknown",
                DATUM["Unknown based on WGS84 ellipsoid",
                    ELLIPSOID["WGS 84",6378137,298.257223563,
                        LENGTHUNIT["metre",1],
                        ID["EPSG",7030]]],
                PRIMEM["Greenwich",0,
                    ANGLEUNIT["degree",0.0174532925199433],
                    ID["EPSG",8901]]],
            CONVERSION["UTM zone 10N",
                METHOD["Transverse Mercator",
                    ID["EPSG",9807]],
                PARAMETER["Latitude of natural origin",0,
                    ANGLEUNIT["degree",0.0174532925199433],
                    ID["EPSG",8801]],
                PARAMETER["Longitude of natural origin",-123,
                    ANGLEUNIT["degree",0.0174532925199433],
                    ID["EPSG",8802]],
                PARAMETER["Scale factor at natural origin",0.9996,
                    SCALEUNIT["unity",1],
                    ID["EPSG",8805]],
                PARAMETER["False easting",500000,
                    LENGTHUNIT["metre",1],
                    ID["EPSG",8806]],
                PARAMETER["False northing",0,
                    LENGTHUNIT["metre",1],
                    ID["EPSG",8807]],
                ID["EPSG",16010]],
            CS[Cartesian,2],
                AXIS["(E)",east,
                    ORDER[1],
                    LENGTHUNIT["metre",1,
                        ID["EPSG",9001]]],
                AXIS["(N)",north,
                    ORDER[2],
                    LENGTHUNIT["metre",1,
                        ID["EPSG",9001]]]]
        >>> geod = crs.get_geod()
        >>> f"+a={geod.a:.0f} +f={geod.f:.8f}"
        '+a=6378137 +f=0.00335281'
        >>> crs.is_projected
        True
        >>> crs.is_geographic
        False
         rP   to_wktzInvalid CRS input: F)r1   r?   N)r@   r   srsro   rj   r6   rI   rA   rL   rE   rF   lenrh   rn   rr   r   rG   r    _localr"   )r&   r0   kwargsZ
projstringZ
projkwargsr)   r)   r*   r$      s0     










zCRS.__init__c                 C   s"   | j jdu rt| j| j _| j jS )zH
        Retrieve the Cython based _CRS object for this thread.
        N)ru   r"   r   rs   r%   r)   r)   r*   _crs^  s    zCRS._crs)re   coder2   c                 C   s   |  t||S )a?  
        .. versionadded:: 2.2.0

        Make a CRS from an authority name and authority code

        Parameters
        ----------
        auth_name: str
            The name of the authority.
        code : int or str
            The code used by the authority.

        Returns
        -------
        CRS
        )from_user_inputrh   )clsre   rx   r)   r)   r*   from_authorityg  s    zCRS.from_authority)rx   r2   c                 C   s   |  t|S )zMake a CRS from an EPSG code

        Parameters
        ----------
        code : int or str
            An EPSG code.

        Returns
        -------
        CRS
        )ry   rj   )rz   rx   r)   r)   r*   	from_epsg{  s    zCRS.from_epsg)in_proj_stringr2   c                 C   s$   t |std| | t|S )z
        .. versionadded:: 2.2.0

        Make a CRS from a PROJ string

        Parameters
        ----------
        in_proj_string : str
            A PROJ string.

        Returns
        -------
        CRS
        zInvalid PROJ string: )r   r   ry   r]   )rz   r}   r)   r)   r*   
from_proj4  s    zCRS.from_proj4)in_wkt_stringr2   c                 C   s$   t |std| | t|S )z
        .. versionadded:: 2.2.0

        Make a CRS from a WKT string

        Parameters
        ----------
        in_wkt_string : str
            A WKT string.

        Returns
        -------
        CRS
        zInvalid WKT string: )r   r   ry   rI   )rz   r   r)   r)   r*   from_wkt  s    zCRS.from_wktrM   c                 C   s   |  t|S )az  
        Make a CRS from:

        Initialize a CRS class instance with:
         - PROJ string
         - JSON string with PROJ parameters
         - CRS WKT string
         - An authority string [i.e. 'epsg:4326']

        Parameters
        ----------
        in_crs_string : str
            An EPSG, PROJ, or WKT string.

        Returns
        -------
        CRS
        )ry   rI   )rz   rN   r)   r)   r*   from_string  s    zCRS.from_stringr2   c                 C   s    | j dd}|rd|S | jS )a  
        .. versionadded:: 2.2.0

        Convert the CRS to a string.

        It attempts to convert it to the authority string.
        Otherwise, it uses the string format of the user
        input to create the CRS.

        Returns
        -------
        str
        d   min_confidencerg   )to_authorityrG   rs   )r&   Z	auth_infor)   r)   r*   	to_string  s    
zCRS.to_stringrK   r2   c                 K   s   t || r|S | |fi |S a  
        Initialize a CRS class instance with:
          - PROJ string
          - Dictionary of PROJ parameters
          - PROJ keyword arguments for parameters
          - JSON string with PROJ parameters
          - CRS WKT string
          - An authority string [i.e. 'epsg:4326']
          - An EPSG integer code [i.e. 4326]
          - A tuple of ("auth_name": "auth_code") [i.e ('epsg', '4326')]
          - An object with a `to_wkt` method.
          - A :class:`pyproj.crs.CRS` class

        Parameters
        ----------
        value : obj
            A Python int, dict, or str.

        Returns
        -------
        CRS
        )r@   )rz   rK   rv   r)   r)   r*   ry     s    
zCRS.from_user_inputc                 C   s(   | j du rdS t| j j| j j| j jdS )zs
        Returns
        -------
        pyproj.geod.Geod:
            Geod object based on the ellipsoid.
        N)arfb)	ellipsoidr   semi_major_metreinverse_flatteningsemi_minor_metrer%   r)   r)   r*   get_geod  s    
zCRS.get_geod)	proj_dictr2   c                 C   s   |  t|S )z
        .. versionadded:: 2.2.0

        Make a CRS from a dictionary of PROJ parameters.

        Parameters
        ----------
        proj_dict : str
            PROJ params in dict format.

        Returns
        -------
        CRS
        )ry   rL   )rz   r   r)   r)   r*   	from_dict  s    zCRS.from_dict)crs_jsonr2   c                 C   s   |  t|S )z
        .. versionadded:: 2.4.0

        Create CRS from a CRS JSON string.

        Parameters
        ----------
        crs_json: str
            CRS JSON string.

        Returns
        -------
        CRS
        )ry   r   )rz   r   r)   r)   r*   	from_json  s    zCRS.from_json)rb   r2   c                 C   s   |  t|S )z
        .. versionadded:: 2.4.0

        Create CRS from a JSON dictionary.

        Parameters
        ----------
        crs_dict: dict
            CRS dictionary.

        Returns
        -------
        CRS
        )ry   rB   rC   )rz   rb   r)   r)   r*   from_json_dict*  s    zCRS.from_json_dictc                 C   s`   |   }|du ri S dd }i }t|D ]0}| \}}|durJ||}|dur*|||< q*|S )a  
        .. versionadded:: 2.2.0

        Converts the CRS to dictionary of PROJ parameters.

        .. warning:: You will likely lose important projection
          information when converting to a PROJ string from
          another format. See: https://proj.org/faq.html#what-is-the-best-format-for-describing-coordinate-reference-systems  # noqa: E501

        Returns
        -------
        dict:
            PROJ params in dict format.

        Nc                 S   sd   |   dkrdS |   dkr dS z
t| W S  ty<   Y n0 z
t| W S  tyZ   Y n0 t| S )NtrueTfalseF)lowerrl   ra   floatr   )r8   r)   r)   r*   _parseQ  s    

zCRS.to_dict.<locals>._parseF)to_proj4_RE_PROJ_PARAMfinditergroups)r&   Zproj_stringr   r   paramrJ   rK   r)   r)   r*   to_dict<  s    
zCRS.to_dictF)wkt_versionerrcheckr2   c           	      C   sR  d|  |i}| jr\| jr\| jjr\| jr\| jj||d}|d || | jj|d< |S | jr| j	D ]&}|j||d}|d || qh|S | j
r|  }d|v r|d d |d< | jr| jj|d< |S | jr|j| jj| jj| jjd | jj|d	< | jr| jj|d
< | jj|d< | jrJ| jj|d< | jjrJ| jjj|d< | jr| jr| jj tvr|rtd| jj  d|d iS |t| jj  | j nd|d< |S d}| js| jr| j}| j|d< |sdn|j dd}|tvr<|r0|r&td|j  n
td d|d iS |t| | |S )aS  
        .. versionadded:: 2.2.0

        This converts a :obj:`pyproj.crs.CRS` object
        to a Climate and Forecast (CF) Grid Mapping Version 1.8 dict.

        :ref:`build_crs_cf`

        Parameters
        ----------
        wkt_version: str or pyproj.enums.WktVersion
            Version of WKT supported by CRS.to_wkt.
            Default is :attr:`pyproj.enums.WktVersion.WKT2_2019`.
        errcheck: bool, default=False
            If True, will warn when parameters are ignored.

        Returns
        -------
        dict:
            CF-1.8 version of the projection.

        crs_wkt)r   r   towgs84geoid_modelname
geoid_namegeopotential_datum_name)Zsemi_major_axisZsemi_minor_axisr   Zreference_ellipsoid_nameZlongitude_of_prime_meridianZprime_meridian_namegeographic_crs_nameZhorizontal_datum_namez"Unsupported coordinate operation: latitude_longitudegrid_mapping_nameNprojected_crs_namer?   _zCoordinate operation not found.)rr   is_boundcoordinate_operationr   
source_crsto_cfpopupdateis_compoundsub_crs_listis_verticalto_json_dictdatumr   r   r   r   r   prime_meridianZ	longitudegeodetic_crsis_geographicmethod_namer   r   rZ   r[   is_projectedrX   r   )	r&   r   r   Zcf_dictZsub_cfsub_crsZ	vert_jsonr   Zcoordinate_operation_namer)   r)   r*   r   j  s    









z	CRS.to_cf)in_cfellipsoidal_cscartesian_csvertical_csr2   c                 C   s  d}d| v rt | d S d| v r,t | d S | d}|du rFtdt| }zt| }W n typ   d}Y n0 | d}|rt|pd||d	}	nJ|r||vrt |}	|dur|	 }
t	| |
d
< t |
}	n
t|d}	|dkr|	S |durt
|	|| |dS zt| }W n$ ty6   td| dY n0 t| dd|| |	|d}d}d| v rt|dt|jgt| d R  d}d| vr|p|S td| d | d|d}td|p||gdS )a  
        .. versionadded:: 2.2.0

        .. versionadded:: 3.0.0 ellipsoidal_cs, cartesian_cs, vertical_cs

        This converts a Climate and Forecast (CF) Grid Mapping Version 1.8
        dict to a :obj:`pyproj.crs.CRS` object.

        :ref:`build_crs_cf`

        Parameters
        ----------
        in_cf: dict
            CF version of the projection.
        ellipsoidal_cs: Any, optional
            Input to create an Ellipsoidal Coordinate System.
            Anything accepted by :meth:`pyproj.crs.CoordinateSystem.from_user_input`
            or an Ellipsoidal Coordinate System created from :ref:`coordinate_system`.
        cartesian_cs: Any, optional
            Input to create a Cartesian Coordinate System.
            Anything accepted by :meth:`pyproj.crs.CoordinateSystem.from_user_input`
            or :class:`pyproj.crs.coordinate_system.Cartesian2DCS`.
        vertical_cs: Any, optional
            Input to create a Vertical Coordinate System accepted by
            :meth:`pyproj.crs.CoordinateSystem.from_user_input`
            or :class:`pyproj.crs.coordinate_system.VerticalCS`

        Returns
        -------
        CRS
        )unknown	undefinedr   Zspatial_refr   Nz4CF projection parameters missing 'grid_mapping_name'r   r   )r   r   r   coordinate_system)r   r   )base_crs
conversionr   zUnsupported grid mapping name: r   )r   r   r   r   r   zWGS 84)r   
target_crstransformationr   r   )r   r   r   r   )r   
components)rp   getr   r   r   KeyErrorGeographicCRSr   r   ry   DerivedGeographicCRSr   ProjectedCRSBoundCRSr   r   r   VerticalCRSCompoundCRS)r   r   r   r   Zunknown_namesr   r   Zgeographic_conversion_methodr   Zgeographic_crsgeographic_crs_jsonZconversion_methodZprojected_crsZ	bound_crsZvertical_crsr)   r)   r*   from_cf  s    (










zCRS.from_cfc           	      C   s,  g }dd }| j dkr| jr| j }|dd d}t|dkrR| d}| jd	 }d
d
|dd 	dddd}|j
 	dd }|r| d| |d< || | jr|| jj|| d nT| jr| jr| jjr|| jjj|| jd n| jD ]}||  q|S )a1  
        .. versionadded:: 3.0.0

        This converts all coordinate systems (cs) in the CRS
        to a list of Climate and Forecast (CF) Version 1.8 dicts.

        :ref:`build_crs_cf`

        Returns
        -------
        list[dict]:
            CF-1.8 version of the coordinate systems.
        c                 S   s2   z| j o| j j tv W S  ty,   Y dS 0 d S )NF)r   r   r   r   r   )r"   r)   r)   r*   rotated_pole|  s    
z"CRS.cs_to_cf.<locals>.rotated_polezTemporal CRSZtime_originz
1875-05-20ZzZ   z-01-01r   timecalendarZproleptic_gregorianr?   r   T)Zstandard_nameZ	long_namer   axisrq   z since Zunits)r   )	type_namer   r   r   rY   rstriprt   	axis_infor   rX   	unit_namerH   r   extendr   r   r   r   cs_to_cf)	r&   Zcf_axis_listr   Z
datum_jsonoriginr   Zcf_temporal_axisr   r   r)   r)   r*   r   l  s@    






zCRS.cs_to_cf)otherr2   c                 C   s2   zt |}W n ty"   Y dS 0 | j|jS )ab  
        Check if the CRS objects are the exact same.

        Parameters
        ----------
        other: Any
            Check if the other CRS is the exact same to this object.
            If the other object is not a CRS, it will try to create one.
            On Failure, it will return False.

        Returns
        -------
        bool
        F)rp   ry   r   rw   is_exact_samer&   r   r)   r)   r*   r     s
    zCRS.is_exact_same)r   ignore_axis_orderr2   c                 C   s6   zt |}W n ty"   Y dS 0 | jj|j|dS )a  

        .. versionadded:: 2.5.0

        Check if the CRS objects are equivalent.

        Parameters
        ----------
        other: Any
            Check if the other object is equivalent to this object.
            If the other object is not a CRS, it will try to create one.
            On Failure, it will return False.
        ignore_axis_order: bool, default=False
            If True, it will compare the CRS class and ignore the axis order.

        Returns
        -------
        bool
        F)r   )rp   ry   r   rw   equals)r&   r   r   r)   r)   r*   r     s
    z
CRS.equalsc                 C   s   | j jdu rdS | | j jS z
        .. versionadded:: 2.2.0

        Returns
        -------
        CRS:
            The geodeticCRS / geographicCRS from the CRS.

        N)rw   r   r(   r%   r)   r)   r*   r     s    
zCRS.geodetic_crsc                 C   s   | j jdu rdS | | j jS z
        The base CRS of a BoundCRS or a DerivedCRS/ProjectedCRS,
        or the source CRS of a CoordinateOperation.

        Returns
        -------
        CRS
        N)rw   r   r(   r%   r)   r)   r*   r     s    
zCRS.source_crsc                 C   s   | j jdu rdS | | j jS z
        .. versionadded:: 2.2.0

        Returns
        -------
        CRS:
            The hub CRS of a BoundCRS or the target CRS of a CoordinateOperation.

        N)rw   r   r(   r%   r)   r)   r*   r     s    
zCRS.target_crsc                    s    fdd j jD S )
        If the CRS is a compound CRS, it will return a list of sub CRS objects.

        Returns
        -------
        list[CRS]
        c                    s   g | ]}  |qS r)   r'   r7   r   r%   r)   r*   r9     r:   z$CRS.sub_crs_list.<locals>.<listcomp>rw   r   r%   r)   r%   r*   r     s    	zCRS.sub_crs_listc                 C   sh   | j r| jr| jjS | jr8| jD ]}|jr |j  S q n,| jrdd| jj v rd| jj dd S dS )z
        .. versionadded:: 2.6.0

        Finds the UTM zone in a Projected CRS, Bound CRS, or Compound CRS

        Returns
        -------
        Optional[str]:
            The UTM zone number and letter if applicable.
        zUTM ZONEz	UTM ZONE N)r   r   utm_zoner   r   r   upperrV   )r&   r   r)   r)   r*   r     s    
zCRS.utm_zonec                 C   s   | j jS )zx
        Returns
        -------
        str:
            The name of the CRS (from :cpp:func:`proj_get_name`).
        )rw   r   r%   r)   r)   r*   r   /  s    zCRS.namec                 C   s   | j jS )zj
        Returns
        -------
        str:
            The name of the type of the CRS object.
        )rw   r   r%   r)   r)   r*   r   9  s    zCRS.type_namec                 C   s   | j jS )a;  
        Retrieves all relevant axis information in the CRS.
        If it is a Bound CRS, it gets the axis list from the Source CRS.
        If it is a Compound CRS, it gets the axis list from the Sub CRS list.

        Returns
        -------
        list[Axis]:
            The list of axis information.
        )rw   r   r%   r)   r)   r*   r   C  s    zCRS.axis_infoc                 C   s   | j jS )z{
        Returns
        -------
        AreaOfUse:
            The area of use object with associated attributes.
        )rw   area_of_user%   r)   r)   r*   r   Q  s    zCRS.area_of_usec                 C   s   | j jS )z
        .. versionadded:: 2.2.0

        Returns
        -------
        Ellipsoid:
            The ellipsoid object with associated attributes.
        )rw   r   r%   r)   r)   r*   r   [  s    
zCRS.ellipsoidc                 C   s   | j jS )z
        .. versionadded:: 2.2.0

        Returns
        -------
        PrimeMeridian:
            The prime meridian object with associated attributes.
        )rw   r   r%   r)   r)   r*   r   g  s    
zCRS.prime_meridianc                 C   s   | j jS )zX
        .. versionadded:: 2.2.0

        Returns
        -------
        Datum
        )rw   r   r%   r)   r)   r*   r   s  s    	z	CRS.datumc                 C   s   | j jS )zc
        .. versionadded:: 2.2.0

        Returns
        -------
        CoordinateSystem
        )rw   r   r%   r)   r)   r*   r   ~  s    	zCRS.coordinate_systemc                 C   s   | j jS )zf
        .. versionadded:: 2.2.0

        Returns
        -------
        CoordinateOperation
        )rw   r   r%   r)   r)   r*   r     s    	zCRS.coordinate_operationc                 C   s   | j jS )zy
        .. versionadded:: 2.4.0

        Returns
        -------
        str:
            Remarks about object.
        )rw   remarksr%   r)   r)   r*   r     s    
zCRS.remarksc                 C   s   | j jS )zt
        .. versionadded:: 2.4.0

        Returns
        -------
        str:
            Scope of object.
        )rw   scoper%   r)   r)   r*   r     s    
z	CRS.scope)versionprettyoutput_axis_ruler2   c                 C   s.   | j j|||d}|du r*td| d|S )aA  
        Convert the projection to a WKT string.

        Version options:
          - WKT2_2015
          - WKT2_2015_SIMPLIFIED
          - WKT2_2019
          - WKT2_2019_SIMPLIFIED
          - WKT1_GDAL
          - WKT1_ESRI

        .. versionadded:: 3.6.0 output_axis_rule

        Parameters
        ----------
        version: pyproj.enums.WktVersion, optional
            The version of the WKT output.
            Default is :attr:`pyproj.enums.WktVersion.WKT2_2019`.
        pretty: bool, default=False
            If True, it will set the output to be a multiline string.
        output_axis_rule: bool, optional, default=None
            If True, it will set the axis rule on any case. If false, never.
            None for AUTO, that depends on the CRS and version.

        Returns
        -------
        str
        )r   r   r   Nz.CRS cannot be converted to a WKT string of a 'zG' version. Select a different version of a WKT string or edit your CRS.)rw   rr   r   )r&   r   r   r   Zwktr)   r)   r*   rr     s    "
z
CRS.to_wktrP   )r   indentationr2   c                 C   s$   | j j||d}|du r td|S )a  
        .. versionadded:: 2.4.0

        Convert the object to a JSON string.

        Parameters
        ----------
        pretty: bool, default=False
            If True, it will set the output to be a multiline string.
        indentation: int, default=2
            If pretty is True, it will set the width of the indentation.

        Returns
        -------
        str
        )r   r   Nz.CRS cannot be converted to a PROJ JSON string.)rw   to_jsonr   )r&   r   r   Z	proj_jsonr)   r)   r*   r     s    zCRS.to_jsonc                 C   s
   | j  S )z
        .. versionadded:: 2.4.0

        Convert the object to a JSON dictionary.

        Returns
        -------
        dict
        )rw   r   r%   r)   r)   r*   r     s    
zCRS.to_json_dict)r   r2   c                 C   s"   | j j|d}|du rtd|S )a<  
        Convert the projection to a PROJ string.

        .. warning:: You will likely lose important projection
          information when converting to a PROJ string from
          another format. See:
          https://proj.org/faq.html#what-is-the-best-format-for-describing-coordinate-reference-systems  # noqa: E501

        Parameters
        ----------
        version: pyproj.enums.ProjVersion
            The version of the PROJ string output.
            Default is :attr:`pyproj.enums.ProjVersion.PROJ_4`.

        Returns
        -------
        str
        )r   Nz)CRS cannot be converted to a PROJ string.)rw   r   r   )r&   r   r3   r)   r)   r*   r     s    zCRS.to_proj4F   )r   r2   c                 C   s   | j j|dS )ac  
        Return the EPSG code best matching the CRS
        or None if it a match is not found.

        Example:

        >>> from pyproj import CRS
        >>> ccs = CRS("EPSG:4328")
        >>> ccs.to_epsg()
        4328

        If the CRS is bound, you can attempt to get an epsg code from
        the source CRS:

        >>> from pyproj import CRS
        >>> ccs = CRS("+proj=geocent +datum=WGS84 +towgs84=0,0,0")
        >>> ccs.to_epsg()
        >>> ccs.source_crs.to_epsg()
        4978
        >>> ccs == CRS.from_epsg(4978)
        False

        Parameters
        ----------
        min_confidence: int, default=70
            A value between 0-100 where 100 is the most confident.
            :ref:`min_confidence`


        Returns
        -------
        Optional[int]:
            The best matching EPSG code matching the confidence level.
        r   )rw   to_epsg)r&   r   r)   r)   r*   r     s    #zCRS.to_epsgre   r   c                 C   s   | j j||dS )a!  
        .. versionadded:: 2.2.0

        Return the authority name and code best matching the CRS
        or None if it a match is not found.

        Example:

        >>> from pyproj import CRS
        >>> ccs = CRS("EPSG:4328")
        >>> ccs.to_authority()
        ('EPSG', '4328')

        If the CRS is bound, you can get an authority from
        the source CRS:

        >>> from pyproj import CRS
        >>> ccs = CRS("+proj=geocent +datum=WGS84 +towgs84=0,0,0")
        >>> ccs.to_authority()
        >>> ccs.source_crs.to_authority()
        ('EPSG', '4978')
        >>> ccs == CRS.from_authorty('EPSG', '4978')
        False

        Parameters
        ----------
        auth_name: str, optional
            The name of the authority to filter by.
        min_confidence: int, default=70
            A value between 0-100 where 100 is the most confident.
            :ref:`min_confidence`

        Returns
        -------
        tuple(str, str) or None:
            The best matching (<auth_name>, <code>) for the confidence level.
        r   )rw   r   r&   re   r   r)   r)   r*   r   7  s    &zCRS.to_authority)re   r   r2   c                 C   s   | j j||dS )aT  
        .. versionadded:: 3.2.0

        Return the authority names and codes best matching the CRS.

        Example:

        >>> from pyproj import CRS
        >>> ccs = CRS("EPSG:4328")
        >>> ccs.list_authority()
        [AuthorityMatchInfo(auth_name='EPSG', code='4326', confidence=100)]

        If the CRS is bound, you can get an authority from
        the source CRS:

        >>> from pyproj import CRS
        >>> ccs = CRS("+proj=geocent +datum=WGS84 +towgs84=0,0,0")
        >>> ccs.list_authority()
        []
        >>> ccs.source_crs.list_authority()
        [AuthorityMatchInfo(auth_name='EPSG', code='4978', confidence=70)]
        >>> ccs == CRS.from_authorty('EPSG', '4978')
        False

        Parameters
        ----------
        auth_name: str, optional
            The name of the authority to filter by.
        min_confidence: int, default=70
            A value between 0-100 where 100 is the most confident.
            :ref:`min_confidence`

        Returns
        -------
        list[AuthorityMatchInfo]:
            List of authority matches for the CRS.
        r   )rw   list_authorityr   r)   r)   r*   r   a  s    (zCRS.list_authorityr   r2   c                 C   s   |  | jj|dS a  
        .. versionadded:: 3.1.0

        Convert the current CRS to the 3D version if it makes sense.

        New vertical axis attributes:
          - ellipsoidal height
          - oriented upwards
          - metre units

        Parameters
        ----------
        name: str, optional
            CRS name. Defaults to use the name of the original CRS.

        Returns
        -------
        CRS
        r   )r(   rw   to_3dr&   r   r)   r)   r*   r    s    z	CRS.to_3dc                 C   s   |  | jj|dS )a#  
        .. versionadded:: 3.6.0

        Convert the current CRS to the 2D version if it makes sense.

        Parameters
        ----------
        name: str, optional
            CRS name. Defaults to use the name of the original CRS.

        Returns
        -------
        CRS
        r   )r(   rw   to_2dr  r)   r)   r*   r    s    z	CRS.to_2dc                 C   s   | j jS )aW  
        This checks if the CRS is geographic.
        It will check if it has a geographic CRS
        in the sub CRS if it is a compound CRS and will check if
        the source CRS is geographic if it is a bound CRS.

        Returns
        -------
        bool:
            True if the CRS is in geographic (lon/lat) coordinates.
        )rw   r   r%   r)   r)   r*   r     s    zCRS.is_geographicc                 C   s   | j jS )a6  
        This checks if the CRS is projected.
        It will check if it has a projected CRS
        in the sub CRS if it is a compound CRS and will check if
        the source CRS is projected if it is a bound CRS.

        Returns
        -------
        bool:
            True if CRS is projected.
        )rw   r   r%   r)   r)   r*   r     s    zCRS.is_projectedc                 C   s   | j jS )aS  
        .. versionadded:: 2.2.0

        This checks if the CRS is vertical.
        It will check if it has a vertical CRS
        in the sub CRS if it is a compound CRS and will check if
        the source CRS is vertical if it is a bound CRS.

        Returns
        -------
        bool:
            True if CRS is vertical.
        )rw   r   r%   r)   r)   r*   r     s    zCRS.is_verticalc                 C   s   | j jS )zY
        Returns
        -------
        bool:
            True if CRS is bound.
        )rw   r   r%   r)   r)   r*   r     s    zCRS.is_boundc                 C   s   | j jS )z}
        .. versionadded:: 3.1.0

        Returns
        -------
        bool:
            True if CRS is compound.
        )rw   r   r%   r)   r)   r*   r     s    
zCRS.is_compoundc                 C   s   | j jS )z
        .. versionadded:: 2.2.0

        Returns
        -------
        bool:
            True if CRS is local/engineering.
        )rw   is_engineeringr%   r)   r)   r*   r    s    
zCRS.is_engineeringc                 C   s   | j jS )z
        This checks if the CRS is geocentric and
        takes into account if the CRS is bound.

        Returns
        -------
        bool:
            True if CRS is in geocentric (x/y) coordinates.
        )rw   is_geocentricr%   r)   r)   r*   r    s    zCRS.is_geocentricc                 C   s   | j jS )z
        .. versionadded:: 3.2.0

        Returns
        -------
        bool:
            True if CRS is a Derived CRS.
        )rw   
is_derivedr%   r)   r)   r*   r    s    
zCRS.is_derivedc                 C   s
   |  |S r!   )r   r   r)   r)   r*   __eq__  s    z
CRS.__eq__c                 C   s
   d| j iS )Nrs   rs   r%   r)   r)   r*   __getstate__!  s    zCRS.__getstate__)statec                 C   s   | j | t | _d S r!   )__dict__r   r    ru   )r&   r
  r)   r)   r*   __setstate__$  s    zCRS.__setstate__c                 C   s   t |  S r!   )hashrr   r%   r)   r)   r*   __hash__(  s    zCRS.__hash__c                 C   s   | j S r!   r  r%   r)   r)   r*   __str__+  s    zCRS.__str__c                 C   s  g }| j D ]}|dt|dg q
d|}d}d}| jrP| jjrPt| j}nv| jrz| jrzt| jj}d| jj d}nLg }dg}| j	D ]&}	|
t|	j |d|	jdg qd|}d|}d}
| jrdddt| jd	| jjdg}
|  }t|d
kr
|nd|d d
 dg}|p(d}d| j d| d| j d|pJd d| d| jp^d d|
 d| j d| jpzd d| jpd d| | S )Nz- 
rq   zSource CRS: z	Sub CRS:
|zCoordinate Operation:
z- name: z
- method: 2   r?   z...z- undefined
<z: z>
Name: z
Axis Info [r   z]:
zArea of Use:
z- undefinedzDatum: z
- Ellipsoid: z
- Prime Meridian: )r   r   r6   rG   r   Z	axis_listr   r   r   r   rH   r   r   r   rt   r   r   r   r   r   )r&   Zaxis_info_listr   Zaxis_info_strZsource_crs_reprZsub_crs_reprZcoordinate_system_nameZcoordinate_system_namesZsub_crs_repr_listr   r   Zsrs_reprr)   r)   r*   __repr__.  sl    




(


	

zCRS.__repr__)N)NNN)F)FrP   )r   )Nr   )Nr   )N)N)Vr+   r,   r-   r.   r   r   r$   propertyrw   classmethodr6   r   rl   r{   r|   r~   r   r   r   ry   r   r   rA   r   r   r   r   r   Z	WKT2_2019boolr   staticmethodr   rE   r   r   r   r   r   r   r   r   r   r   r	   r   r   r   r   r   r   r   r   r   r   r   r
   r   r   r   rr   r   r   r   ZPROJ_5r   r   r   r   r   r  r  r   r   r   r   r   r  r  r  r  r	  r  r  r  r  r)   r)   r)   r*   rp      s    (
0
    ~>
			



,%+ ,	
rp   c                       s   e Zd ZdZeeedf dddZdd Ze	e
dd	 fd
dZeed dddZeed dddZeed dddZeed dddZdee ddddZ  ZS )CustomConstructorCRSz
    This class is a base class for CRS classes
    that use a different constructor than the main CRS class.

    .. versionadded:: 3.2.0

    See: https://github.com/pyproj4/pyproj/issues/847
    .r   c                 C   s   t dS )zt
        These are the type names of the CRS class
        that are expected when using the from_* methods.
        N)NotImplementedErrorr%   r)   r)   r*   _expected_typesr  s    z$CustomConstructorCRS._expected_typesc                 C   s*   | j | jvr&td| j  d| j ddS )zl
        This validates that the type of the CRS is expected
        when using the from_* methods.
        zInvalid type z. Expected .N)r   r  r   r%   r)   r)   r*   _check_typez  s    z CustomConstructorCRS._check_typerp   r   c                    s<   t || r|S | | }tt|j|fi | |  |S r   )r@   __new__r#   r  r$   r  )rz   rK   rv   r"   r'   r)   r*   ry     s    

z$CustomConstructorCRS.from_user_inputc                 C   s   | j jdu rdS t| j jS r   )rw   r   rp   r%   r)   r)   r*   r     s    z!CustomConstructorCRS.geodetic_crsc                 C   s   | j jdu rdS t| j jS r   )rw   r   rp   r%   r)   r)   r*   r     s    
zCustomConstructorCRS.source_crsc                 C   s   | j jdu rdS t| j jS r   )rw   r   rp   r%   r)   r)   r*   r     s    zCustomConstructorCRS.target_crsc                 C   s   dd | j jD S )r   c                 S   s   g | ]}t |qS r)   )rp   r   r)   r)   r*   r9     r:   z5CustomConstructorCRS.sub_crs_list.<locals>.<listcomp>r   r%   r)   r)   r*   r     s    	z!CustomConstructorCRS.sub_crs_listNr   c                 C   s   t | jj|dS r   )rp   rw   r  r  r)   r)   r*   r    s    zCustomConstructorCRS.to_3d)N)r+   r,   r-   r.   r  rF   r6   r  r  r  r   ry   r   r   r   r   rE   r   r  r/   r)   r)   r'   r*   r  h  s   	

r  c                       s6   e Zd ZdZdZd	eeee dd fddZ  Z	S )
r   zR
    .. versionadded:: 2.5.0

    This class is for building a Geographic CRS
    )zGeographic CRSzGeographic 2D CRSzGeographic 3D CRSr   urn:ogc:def:ensemble:EPSG::6326N)r   r   r   r2   c                    sZ   t | }dd|t|p t  d}|d dkrB||d< n||d< t | dS )	aC  
        Parameters
        ----------
        name: str, default="undefined"
            Name of the CRS.
        datum: Any, default="urn:ogc:def:ensemble:EPSG::6326"
            Anything accepted by :meth:`pyproj.crs.Datum.from_user_input` or
            a :class:`pyproj.crs.datum.CustomDatum`.
        ellipsoidal_cs: Any, optional
            Input to create an Ellipsoidal Coordinate System.
            Anything accepted by :meth:`pyproj.crs.CoordinateSystem.from_user_input`
            or an Ellipsoidal Coordinate System created from :ref:`coordinate_system`.
        2https://proj.org/schemas/v0.2/projjson.schema.jsonr   )$schematyper   r   r"  ZDatumEnsembleZdatum_ensembler   N)r   ry   r   r   r   r#   r$   )r&   r   r   r   r   r'   r)   r*   r$     s    
zGeographicCRS.__init__)r   r  N
r+   r,   r-   r.   r  r6   r   r   r$   r/   r)   r)   r'   r*   r     s      r   c                       s8   e Zd ZdZdZdeeee edd fddZ  Z	S )	r   zZ
    .. versionadded:: 2.5.0

    This class is for building a Derived Geographic CRS
    )zDerived Geographic CRSzDerived Geographic 2D CRSzDerived Geographic 3D CRSNr   )r   r   r   r   r2   c                    sF   dd|t | t| t|p*t  d}t | dS )a  
        Parameters
        ----------
        base_crs: Any
            Input to create the Geodetic CRS, a :class:`GeographicCRS` or
            anything accepted by :meth:`pyproj.crs.CRS.from_user_input`.
        conversion: Any
            Anything accepted by :meth:`pyproj.crs.CoordinateSystem.from_user_input`
            or a conversion from :ref:`coordinate_operation`.
        ellipsoidal_cs: Any, optional
            Input to create an Ellipsoidal Coordinate System.
            Anything accepted by :meth:`pyproj.crs.CoordinateSystem.from_user_input`
            or an Ellipsoidal Coordinate System created from :ref:`coordinate_system`.
        name: str, default="undefined"
            Name of the CRS.
        r   r   r!  r"  r   r   r   r   N)rp   ry   r   r
   r   r   r#   r$   )r&   r   r   r   r   Zderived_geographic_crs_jsonr'   r)   r*   r$   $  s    zDerivedGeographicCRS.__init__)Nr   )
r+   r,   r-   r.   r  r   r   r6   r$   r/   r)   r)   r'   r*   r     s   
  r   c                       s0   e Zd ZdZdZd	eedd fddZ  ZS )
GeocentricCRSzR
    .. versionadded:: 3.2.0

    This class is for building a Geocentric CRS
    )zGeocentric CRSr   urn:ogc:def:datum:EPSG::6326N)r   r   r2   c                    sT   dd|t | ddddddd	d
ddddddddgdd}t | dS )a0  
        Parameters
        ----------
        name: str, default="undefined"
            Name of the CRS.
        datum: Any, default="urn:ogc:def:datum:EPSG::6326"
            Anything accepted by :meth:`pyproj.crs.Datum.from_user_input` or
            a :class:`pyproj.crs.datum.CustomDatum`.
        r   ZGeodeticCRSZ	CartesianzGeocentric XXZgeocentricXZmetre)r   Zabbreviation	directionunitzGeocentric YYZgeocentricYzGeocentric ZZZgeocentricZ)subtyper   r!  r"  r   r   r   N)r   ry   r   r#   r$   )r&   r   r   Zgeocentric_crs_jsonr'   r)   r*   r$   S  s0    zGeocentricCRS.__init__)r   r&  )	r+   r,   r-   r.   r  r6   r   r$   r/   r)   r)   r'   r*   r%  J  s     r%  c                       s<   e Zd ZdZdZdeeee ee dd fddZ  Z	S )	r   zR
    .. versionadded:: 2.5.0

    This class is for building a Projected CRS.
    )zProjected CRSzDerived Projected CRSr   N)r   r   r   r   r2   c                    sL   dd|t |pt  t| t|p0t  d}t | dS )a  
        Parameters
        ----------
        conversion: Any
            Anything accepted by :meth:`pyproj.crs.CoordinateSystem.from_user_input`
            or a conversion from :ref:`coordinate_operation`.
        name: str, optional
            The name of the Projected CRS. Default is undefined.
        cartesian_cs: Any, optional
            Input to create a Cartesian Coordinate System.
            Anything accepted by :meth:`pyproj.crs.CoordinateSystem.from_user_input`
            or :class:`pyproj.crs.coordinate_system.Cartesian2DCS`.
        geodetic_crs: Any, optional
            Input to create the Geodetic CRS, a :class:`GeographicCRS` or
            anything accepted by :meth:`pyproj.crs.CRS.from_user_input`.
        r   r   r$  N)	rp   ry   r   r   r
   r   r   r#   r$   )r&   r   r   r   r   Zproj_crs_jsonr'   r)   r*   r$     s    zProjectedCRS.__init__)r   NN)
r+   r,   r-   r.   r  r   r6   r   r$   r/   r)   r)   r'   r*   r     s      r   c                       s<   e Zd ZdZdZdeeee ee dd fddZ  Z	S )r   z
    .. versionadded:: 2.5.0

    This class is for building a Vetical CRS.

    .. warning:: geoid_model support only exists in PROJ >= 6.3.0

    )zVertical CRSN)r   r   r   r   r2   c                    sN   dd|t | t|pt  d}|dur>d|i|d< t | dS )a!  
        Parameters
        ----------
        name: str
            The name of the Vertical CRS (e.g. NAVD88 height).
        datum: Any
            Anything accepted by :meth:`pyproj.crs.Datum.from_user_input`
        vertical_cs: Any, optional
            Input to create a Vertical Coordinate System accepted by
            :meth:`pyproj.crs.CoordinateSystem.from_user_input`
            or :class:`pyproj.crs.coordinate_system.VerticalCS`
        geoid_model: str, optional
            The name of the GEOID Model (e.g. GEOID12B).
        r   r   r-  Nr   r   )r   ry   r   r   r   r#   r$   )r&   r   r   r   r   Zvert_crs_jsonr'   r)   r*   r$     s    	zVerticalCRS.__init__)NNr#  r)   r)   r'   r*   r     s   	  r   c                       s2   e Zd ZdZdZeee dd fddZ  Z	S )r   zQ
    .. versionadded:: 2.5.0

    This class is for building a Compound CRS.
    )zCompound CRSN)r   r   r2   c                    s(   dd|dd |D d}t  | dS )a#  
        Parameters
        ----------
        name: str
            The name of the Compound CRS.
        components: list[Any], optional
            List of CRS to create a Compound Coordinate System.
            List of anything accepted by :meth:`pyproj.crs.CRS.from_user_input`
        r   r   c                 S   s   g | ]}t | qS r)   )rp   ry   r   )r7   	componentr)   r)   r*   r9     s   z(CompoundCRS.__init__.<locals>.<listcomp>)r!  r"  r   r   N)r#   r$   )r&   r   r   Zcompound_crs_jsonr'   r)   r*   r$     s    
zCompoundCRS.__init__)
r+   r,   r-   r.   r  r6   rE   r   r$   r/   r)   r)   r'   r*   r     s   r   c                       s0   e Zd ZdZdZeeedd fddZ  ZS )r   zN
    .. versionadded:: 2.5.0

    This class is for building a Bound CRS.
    )z	Bound CRSN)r   r   r   r2   c                    s>   ddt | t | t| d}t | dS )a  
        Parameters
        ----------
        source_crs: Any
            Input to create a source CRS.
        target_crs: Any
            Input to create the target CRS.
        transformation: Any
            Input to create the transformation.
        r   r   )r!  r"  r   r   r   N)rp   ry   r   r
   r#   r$   )r&   r   r   r   Zbound_crs_jsonr'   r)   r*   r$     s    
zBoundCRS.__init__)r+   r,   r-   r.   r  r   r$   r/   r)   r)   r'   r*   r     s   r   )T)Cr.   rB   rR   	threadingrZ   typingr   r   r   r   Zpyproj._crsr   r   r   r	   r
   r   r   r   r   r   r   r   Zpyproj.crs._cf1x8r   r   r   r   r   r   Zpyproj.crs.coordinate_operationr   Zpyproj.crs.coordinate_systemr   r   r   Zpyproj.enumsr   r   Zpyproj.exceptionsr   Zpyproj.geodr   compiler'  r   localr    rA   r  r6   rL   r]   rI   rl   rh   rj   ro   rp   r  r   r   r%  r   r   r   r   r)   r)   r)   r*   <module>   sX   8 &
           P ,3710 