o
    EDiXx                     @   s  d dl Z d dlZd dlZd dlmZ d dlmZ d dlmZ d dlmZ d dlm	Z	 dZ
dZd	Zd
dddddddZddddddddZddddddddZd d!d"d#d$d%d&dZeeeed'Zee	d(d) e D  Zd*d+d,d-Zd.d/ Zd0d1 Zd2d3 Zd[d5d6Zd7d8 Zd9d: Zd\d;d<Zd=d> Zd?d@ ZdAdB ZdCdD Z dEdF Z!dGdH Z"dIdJ Z#dKdL Z$dMdN Z%dOdP Z&dQdR Z'dSdT Z(dUdV Z)dWdX Z*dYdZ Z+eeee e!e"e#dZ,e$e%e&e'e(e)e+dZ-dS )]    N)block_splitter)take)
as_bin_str)flatten_multi_dim)chain           s      s      s      s      s      s      s      )Point
LineStringPolygon
MultiPointMultiLineStringMultiPolygonGeometryCollections     s     s     s     s     s     s     s     s     s     s     s     s     s     s     s     s     s     s     s     s     )2DZMZMc                 c   s"    | ]}d d |  D V  qdS )c                 s   s    | ]}t |V  qd S N)reversed.0x r   C/var/www/Datamplify/venv/lib/python3.10/site-packages/geomet/wkb.py	<genexpr>g   s    z<genexpr>.<genexpr>N)items)r   wkb_mapr   r   r   r   g   s    r   r   r   r   )         c                 C   sV   | d }t jrt|g}|dk}|rtd| dd  } nt| } t| }|| |fS )a  Get the GeoJSON geometry type label from a WKB type byte string.

    :param type_bytes:
        4 byte string in big endian byte order containing a WKB type number.
        It may also contain a "has SRID" flag in the high byte (the first type,
        since this is big endian byte order), indicated as 0x20. If the SRID
        flag is not set, the high byte will always be null (0x00).
    :returns:
        3-tuple ofGeoJSON geometry type label, the bytes resprenting the
        geometry type, and a separate "has SRID" flag. If the input
        `type_bytes` contains an SRID flag, it will be removed.

        >>> # Z Point, with SRID flag
        >>> _get_geom_type(b'\x20\x00\x03\xe9') == (
        ... 'Point', b'\x00\x00\x03\xe9', True)
        True

        >>> # 2D MultiLineString, without SRID flag
        >>> _get_geom_type(b'\x00\x00\x00\x05') == (
        ... 'MultiLineString', b'\x00\x00\x00\x05', False)
        True

    r   r	   r      N)sixPY3bytesr   _BINARY_TO_GEOM_TYPEget)
type_bytes	high_bytehas_srid	geom_typer   r   r   _get_geom_typen   s   


r,   c                 C   s   | t|  dS )a  
    Dump GeoJSON-like `dict` to WKB and write it to the `dest_file`.

    :param dict obj:
        A GeoJSON-like dictionary. It must at least the keys 'type' and
        'coordinates'.
    :param dest_file:
        Open and writable file-like object.
    N)writedumps)obj	dest_filer   r   r   dump   s   
r1   c                 C   s   t |  S )z
    Load a GeoJSON `dict` object from a ``source_file`` containing WKB (as a
    byte string).

    :param source_file:
        Open and readable file-like object.

    :returns:
        A GeoJSON `dict` representing the geometry read from the file.
    )loadsread)source_filer   r   r   load   s   r5   Tc                 C   sh   | d }|  di }t |}|du rt| |  d|  d}ttt|dkr.td|| ||S )a  
    Dump a GeoJSON-like `dict` to a WKB string.

    .. note::
        The dimensions of the generated WKB will be inferred from the first
        vertex in the GeoJSON `coordinates`. It will be assumed that all
        vertices are uniform. There are 4 types:

        - 2D (X, Y): 2-dimensional geometry
        - Z (X, Y, Z): 3-dimensional geometry
        - M (X, Y, M): 2-dimensional geometry with a "Measure"
        - ZM (X, Y, Z, M): 3-dimensional geometry with a "Measure"

        If the first vertex contains 2 values, we assume a 2D geometry.
        If the first vertex contains 3 values, this is slightly ambiguous and
        so the most common case is chosen: Z.
        If the first vertex contains 4 values, we assume a ZM geometry.

        The WKT/WKB standards provide a way of differentiating normal (2D), Z,
        M, and ZM geometries (http://en.wikipedia.org/wiki/Well-known_text),
        but the GeoJSON spec does not. Therefore, for the sake of interface
        simplicity, we assume that geometry that looks 3D contains XYZ
        components, instead of XYM.

        If the coordinates list has no coordinate values (this includes nested
        lists, for example, `[[[[],[]], []]]`, the geometry is considered to be
        empty. Geometries, with the exception of points, have a reasonable
        "empty" representation in WKB; however, without knowing the number of
        coordinate values per vertex, the type is ambigious, and thus we don't
        know if the geometry type is 2D, Z, M, or ZM. Therefore in this case
        we expect a `ValueError` to be raised.

    :param dict obj:
        GeoJson-like `dict` object.
    :param bool big_endian:
        Defaults to `True`. If `True`, data values in the generated WKB will
        be represented using big endian byte order. Else, little endian.

    TODO: remove this

    :param str dims:
        Indicates to WKB representation desired from converting the given
        GeoJSON `dict` ``obj``. The accepted values are:

        * '2D': 2-dimensional geometry (X, Y)
        * 'Z': 3-dimensional geometry (X, Y, Z)
        * 'M': 3-dimensional geometry (X, Y, M)
        * 'ZM': 4-dimensional geometry (X, Y, Z, M)

    :returns:
        A WKB binary string representing of the ``obj``.
    typemetaNcoordinates
geometriesr   zhEmpty geometries cannot be represented in WKB. Reason: The dimensionality of the WKB would be ambiguous.)r'   _dumps_registry_unsupported_geom_typelenlistr   
ValueError)r/   
big_endianr+   r7   exportercoords_or_geomsr   r   r   r.      s   5
r.   c                 C   s  t | } ttd| }|tkrd}n|tkrd}ntdt| 	  |r*dnd}ttd| }|s<|ddd	 }t
|\}}}d}|rWttd| }td
| |\}| }	t|}
|
du rft| t |	}	|
|||	}|rdt|i|d< ddd| id|d< |S )aF  
    Construct a GeoJSON `dict` from WKB (`string`).

    The resulting GeoJSON `dict` will include the SRID as an integer in the
    `meta` object. This was an arbitrary decision made by `geomet, the
    discussion of which took place here:
    https://github.com/geomet/geomet/issues/28.

    In order to be consistent with other libraries [1] and (deprecated)
    specifications [2], also include the same information in a `crs`
    object. This isn't ideal, but the `crs` member is no longer part of
    the GeoJSON standard, according to RFC7946 [3]. However, it's still
    useful to include this information in GeoJSON payloads because it
    supports conversion to EWKT/EWKB (which are canonical formats used by
    PostGIS and the like).

    Example:

        {'type': 'Point',
         'coordinates': [0.0, 1.0],
         'meta': {'srid': 4326},
         'crs': {'type': 'name', 'properties': {'name': 'EPSG4326'}}}

    NOTE(larsbutler): I'm not sure if it's valid to just prefix EPSG
    (European Petroluem Survey Group) to an SRID like this, but we'll
    stick with it for now until it becomes a problem.

    NOTE(larsbutler): Ideally, we should use URNs instead of this
    notation, according to the new GeoJSON spec [4]. However, in
    order to be consistent with [1], we'll stick with this approach
    for now.

    References:

    [1] - https://github.com/bryanjos/geo/issues/76
    [2] - http://geojson.org/geojson-spec.html#coordinate-reference-system-objects
    [3] - https://tools.ietf.org/html/rfc7946#appendix-B.1
    [4] - https://tools.ietf.org/html/rfc7946#section-4
    r"   TFz2Invalid endian byte: '0x%s'. Expected 0x00 or 0x01><r!   Nz%sisridr7   namezEPSG%s)r6   
propertiescrs)iterr   r   
BIG_ENDIANLITTLE_ENDIANr>   binasciihexlifyencodedecoder,   structunpack_loads_registryr'   r;   int)string
endiannessr?   endian_tokenr(   r+   r*   rE   
srid_field
data_bytesimporterresultr   r   r   r2      s<   (


r2   c                 C   s   t d|  )NzUnsupported geometry type '%s')r>   )r+   r   r   r   r;   N  s   r;   c                 C   s   t |}|du r
	 t| |  }|d}|dur!t|dd  }|r*t}d}d}	nt}d}d}	|ddd }||7 }|durVt|}|rLtd	|}
ntd
|}
||
7 }|d| 7 }|||	fS )z|
    Utility function to get the WKB header (endian byte + type header), byte
    format string, and byte order string.
    NrE   r"      >rB      <rC   rD   z>iz<i   d)	_INT_TO_DIM_LABELr'   _WKB	SRID_FLAGrJ   rK   rS   rP   pack)r+   num_dimsr?   r7   dimtype_byte_strrE   headerbyte_fmt
byte_ordersrid_headerr   r   r   _header_bytefmt_byteorderS  s0   


ri   c                 C   s>   | d }t |}td|||\}}}|tj|g|R  7 }|S )aZ  
    Dump a GeoJSON-like `dict` to a point WKB string.

    :param dict obj:
        GeoJson-like `dict` object.
    :param bool big_endian:
        If `True`, data values in the generated WKB will be represented using
        big endian byte order. Else, little endian.
    :param dict meta:
        Metadata associated with the GeoJSON object. Currently supported
        metadata:

        - srid: Used to support EWKT/EWKB. For example, ``meta`` equal to
          ``{'srid': '4326'}`` indicates that the geometry is defined using
          Extended WKT/WKB and that it bears a Spatial Reference System
          Identifier of 4326. This ID will be encoded into the resulting
          binary.

        Any other meta data objects will simply be ignored by this function.

    :returns:
        A WKB binary string representing of the Point ``obj``.
    r8   r
   r<   ri   rP   ra   )r/   r?   r7   coordsrb   
wkb_stringrf   _r   r   r   _dump_point{  s   
rn   c           	      C   sh   | d }|d }t |}td|||\}}}|td| t |7 }|D ]}|tj|g|R  7 }q$|S )z
    Dump a GeoJSON-like `dict` to a linestring WKB string.

    Input parameters and output are similar to :func:`_dump_point`.
    r8   r   r   %slrj   )	r/   r?   r7   rk   vertexrb   rl   rf   rg   r   r   r   _dump_linestring  s   
rq   c           
      C   s   | d }|d d }t |}td|||\}}}|td| t |7 }|D ]}	|td| t |	7 }|	D ]}|tj|g|R  7 }q6q&|S )z
    Dump a GeoJSON-like `dict` to a polygon WKB string.

    Input parameters and output are similar to :funct:`_dump_point`.
    r8   r   r   ro   rj   )
r/   r?   r7   rk   rp   rb   rl   rf   rg   ringr   r   r   _dump_polygon  s   
rs   c           
      C   s   | d }|d }t |}td|||\}}}tt| d }	|r&t|	 }	n	t|	ddd  }	|td| t |7 }|D ]}||	7 }|tj|g|R  7 }q=|S )z
    Dump a GeoJSON-like `dict` to a multipoint WKB string.

    Input parameters and output are similar to :funct:`_dump_point`.
    r8   r   r   r
   NrD   ro   	r<   ri   r_   r^   r'   rJ   rK   rP   ra   )
r/   r?   r7   rk   rp   rb   rl   rf   rg   
point_typer   r   r   _dump_multipoint  s   

rv   c                 C   s   | d }|d d }t |}td|||\}}}tt| d }	|r(t|	 }	n	t|	ddd  }	|td| t |7 }|D ]"}
||	7 }|td| t |
7 }|
D ]}|tj|g|R  7 }qSq?|S )z
    Dump a GeoJSON-like `dict` to a multilinestring WKB string.

    Input parameters and output are similar to :funct:`_dump_point`.
    r8   r   r   r   NrD   ro   rt   )r/   r?   r7   rk   rp   rb   rl   rf   rg   ls_type
linestringr   r   r   _dump_multilinestring  s$   

ry   c                 C   s   | d }|d d d }t |}td|||\}}}tt| d }	|r*t|	 }	n	t|	ddd  }	|td| t |7 }|D ]3}
||	7 }|td| t |
7 }|
D ]}|td| t |7 }|D ]}|tj|g|R  7 }qeqUqA|S )z
    Dump a GeoJSON-like `dict` to a multipolygon WKB string.

    Input parameters and output are similar to :funct:`_dump_point`.
    r8   r   r   r   NrD   ro   rt   )r/   r?   r7   rk   rp   rb   rl   rf   rg   	poly_typepolygonrr   r   r   r   _dump_multipolygon  s*   

r|   c                 C   s   | d }|d }|dd  }t ||d}|dd }|s#|d d d }|t v r,d}n|t v r5d}n|t v r=d	}td
|||\}	}
}|	td| t|7 }	|	|7 }	|D ]
}|	t ||d7 }	qY|	S )Nr9   r   r"   )r?      rD   r   r    r!   r   ro   )	r.   WKB_2DvaluesWKB_ZWKB_ZMri   rP   ra   r<   )r/   r?   r7   geoms
first_geomrest	first_wkb
first_typerb   rl   rf   rg   geomr   r   r   _dump_geometrycollection2  s*   
r   c                 C   s   | rdnd}|t d krtd| ttd|}nC|td kr.td| ttd|}n/|td krJttd| ttd|}|dd	 n|t	d kr]td
| ttd|}t
dt|dS )ah  
    Convert byte data for a Point to a GeoJSON `dict`.

    :param bool big_endian:
        If `True`, interpret the ``data_bytes`` in big endian order, else
        little endian.
    :param str type_bytes:
        4-byte integer (as a binary string) indicating the geometry type
        (Point) and the dimensions (2D, Z, M or ZM). For consistency, these
        bytes are expected to always be in big endian order, regardless of the
        value of ``big_endian``.
    :param str data_bytes:
        Coordinate data in a binary string.

    :returns:
        GeoJSON `dict` representing the Point geometry.
    rB   rC   r
   z%sdd   z%sddd   r           z%sdddd    r6   r8   )r~   rP   rQ   r   r   r   WKB_Mr=   insertr   dict)r?   r(   rX   rV   rk   r   r   r   _load_pointS  s&   


r   c                 C   s   | rdnd}d}|t  v rd}n|t v rd}n|t v r%d}d}n|t v r-d}g }td| ttd|\}	 ttd	| |}d
d|  }	t	t|	| |}
|r_|

dd ||
 t||krknq>tdt	|dS )NrB   rC   Fr   r    Tr!   ro      %sdr   r   r   )r~   r   r   r   r   rP   rQ   r   r   r=   r   appendr<   r   )r?   r(   rX   rV   is_mrb   rk   	num_vertsvert_wkbfmtvertr   r   r   _load_linestring|  s4   

r   c                    sP  | rdnd t |}d}|t v rd}n|t v rd}n|t v r)d}d}n|t v r1d}g }td  tt	d|\}	 g }td  tt	d|\}tt	d	| | |}	t
|	d	}
tjrmd
d |
D }
n
tjrwdd |
D }
t
|
|D ]} fdd|D }|r|dd || q||| t||krnqBtd|dS )NrB   rC   Fr   r    Tr!   ro   r   c                 s   s    | ]}d  |V  qdS )    Njoinr   r   r   r   r         z _load_polygon.<locals>.<genexpr>c                 s   s$    | ]}d  dd |D V  qdS )r   c                 s   s    | ]}t |gV  qd S r   )r%   )r   yr   r   r   r     r   z*_load_polygon.<locals>.<genexpr>.<genexpr>Nr   r   r   r   r   r     s   " c                    s    g | ]}t d   |d qS )z%sdr   )rP   rQ   r   rV   r   r   
<listcomp>  s    z!_load_polygon.<locals>.<listcomp>r   r   r   )rI   r~   r   r   r   r   rP   rQ   r   r   r   r#   PY2r$   r   r   r<   r   )r?   r(   rX   r   rb   rk   	num_ringsrr   r   	verts_wkbvertsr   r   r   r   r   _load_polygon  sN   




r   c                 C   sj  | rdnd}t |}d}|t v rd}n|t v rd}n|t v r)d}d}n|t v r1d}|r6d}nt| }g }td	| t	t
d|\}	 t	t
d
|}	t	t
d|}
td|d| f t	t
d| |}t|}|rx|dd | r|	tksJ |
t| d ksJ n|	tksJ |
d d d t| d ksJ |t| t||krnqKtd|dS )NrB   rC   Fr   r    Tr!   r   ro   r"   z%s%sr   r   r   r
   rD   r   r   )rI   r~   r   r   r   r   r^   rP   rQ   r   r   r=   r   rJ   r_   rK   r   r<   r   )r?   r(   rX   rV   r   rb   rc   rk   
num_pointspoint_endianru   r   r   r   r   _load_multipoint  sL   
r   c                 C   s  | rdnd}t |}d}|t v rd}n|t v rd}n|t v r)d}d}n|t v r1d}|r6d}nt| }td	| t	t
d|\}g }	 t	t
d
|}	t	t
d|}
| rl|	tksaJ |
t| d kskJ n|	tksrJ |
d d d t| d ksJ td	| t	t
d|\}|| }t|d|  t	t
d| |}tt||}|r|D ]}|dd q|| t||krnqKtd|dS )NrB   rC   Fr   r    Tr!   r   ro   r"   r   rD   r   r   r   r   r   )rI   r~   r   r   r   r   r^   rP   rQ   r   r   rJ   r_   rK   r=   r   r   r   r<   r   )r?   r(   rX   rV   r   rb   rc   num_lsrk   	ls_endianrw   r   
num_valuesr   vr   r   r   _load_multilinestring  sV   


r   c                 C   s  | rdnd}d}|t  v rd}n|t v rd}n|t v r%d}d}n|t v r-d}|r2d}nt| }td	| tt	d|\}g }	 g }	tt	d
|}
tt	d|}| rj|
t
ks_J |t| d ksiJ n|
tkspJ |d d d t| d ksJ td	| tt	d|\}t|D ]D}g }td	| tt	d|\}t|D ](}tt	d| |}dd|  }tt|| |}|r|dd || q|	| q||	 t||krnqGtd|dS )NrB   rC   Fr   r    Tr!   r   ro   r"   r   rD   r   r   r   r   r   r   )r~   r   r   r   r   r^   rP   rQ   r   r   rJ   r_   rK   ranger=   r   r   r<   r   )r?   r(   rX   rV   r   rb   rc   	num_polysrk   r{   poly_endianrz   r   rm   rr   r   r   r   r   r   r   r   _load_multipolygon.  s`   



 r   c                 C   sV   dd }dd dd dd dd dd |d	}t || d
  | |ks)d}t|d S )Nc                 S   s&   | d D ]}|d dks|  S qd S )Nr9   r6   r   r   )gcgr   r   r   r   i  s
   z)_check_dimensionality.<locals>.first_geomc                 S   s   | d S )Nr8   r   r   r   r   r   <lambda>o  s    z'_check_dimensionality.<locals>.<lambda>c                 S   s   | d d S Nr8   r   r   r   r   r   r   r   p  s    c                 S      | d d d S r   r   r   r   r   r   r   q      c                 S   r   r   r   r   r   r   r   r   r  r   c                 S   s   | d d d d S r   r   r   r   r   r   r   s  s    )r
   r   r   r   r   r   r6   z'Cannot mix dimensionality in a geometry)r<   	Exception)r   rb   r   
first_verterrorr   r   r   _check_dimensionalityh  s   r   c           	      C   s   | rdnd}d}|t  v rd}n|t v rd}n|t v r%d}d}n|t v r-d}g }td| ttd|\}	 t	|}|rJt
|d nt
|| || t||kr[nq>td	|d
S )NrB   rC   Fr   r    Tr!   ro   r   )r6   r9   )r~   r   r   r   r   rP   rQ   r   r   r2   r   r   r<   r   )	r?   r(   rX   rV   r   rb   r9   	num_geomsgeometryr   r   r   _load_geometrycollection{  s2   


r   )Tr   ).rL   r#   rP   geomet.utilr   r   r   r   	itertoolsr   rJ   rK   r`   r~   r   r   r   r_   r   r   r&   r^   r,   r1   r5   r.   r2   r;   ri   rn   rq   rs   rv   ry   r|   r   r   r   r   r   r   r   r   r   r:   rR   r   r   r   r   <module>   s   
(
HU
(#!%!)",04:"
