3
(h~                 @   s   d dl Z d dlmZmZmZmZ d dlmZ d dlm	Z	m
Z
mZmZ d dlmZ d dlmZm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 dlmZ d dlmZ G dd deZ dS )    N)GeometryFieldLineStringField
PointFieldget_srid_info)	GISLookup)	AreaFieldDistanceField	GeomFieldGMLField)Geometry)AreaDistance)connections)
LOOKUP_SEP)RawSQL)Field)QuerySet)six)RemovedInDjango20Warningc               @   s6  e Zd ZdZdLddZdd Zdd Zd	d
 Zdd Zdd Z	dMddZ
dNddZdOddZdd Zdd Zdd Zdd  Zd!d" Zd#d$ Zd%d& Zd'd( Zd)d* ZdPd,d-Zd.d/ ZdQd0d1Zd2d3 ZdRd4d5ZdSd7d8Zd9d: ZdTd<d=ZdUd>d?ZdVd@dAZdWdBdCZ dXdDdEZ!dFdG Z"dYdHdIZ#dZdJdKZ$d;S )[GeoQuerySetzThe Geographic QuerySet.皙?c             K   s   | j d|jdd\}}||dd}t| j }|j}|jr\d|d< ||d d	< td
|d< nL|jsh|jr|j	r|td
|d< n,|j
|sttj|j||d< ntd| jd|f|S )z~
        Returns the area of the geographic field in an `area` attribute on
        each element of this GeoQuerySet.
        area
field_name)r   F)procedure_args	geo_fieldsetupz%(geo_col)s,%(tolerance)sprocedure_fmtr   	toleranceZsq_mselect_fieldz2Area on geodetic coordinate systems not supported.)_spatial_setupgetr   dbopsoracler   postgis
spatialite	geographygeodeticr   unit_attname
units_name	Exception_spatial_attribute)selfr   kwargsr   r   s
connectionbackend r1   F/tmp/pip-install-q3hcpn_q/Django/django/contrib/gis/db/models/query.pyr      s$    

zGeoQuerySet.areac             K   s   | j d|S )z
        Returns the centroid of the geographic field in a `centroid`
        attribute on each element of this GeoQuerySet.
        centroid)r3   )_geom_attribute)r,   r-   r1   r1   r2   r3   8   s    zGeoQuerySet.centroidc             K   s   | j d|f|S )z
        Returns the spatial difference of the geographic field in a `difference`
        attribute on each element of this GeoQuerySet.
        
difference)_geomset_attribute)r,   geomr-   r1   r1   r2   r5   ?   s    zGeoQuerySet.differencec             K   s   | j d|f|S )a~  
        Returns the distance from the given geographic field name to the
        given geometry in a `distance` attribute on each element of the
        GeoQuerySet.

        Keyword Arguments:
         `spheroid`  => If the geometry field is geodetic and PostGIS is
                        the spatial database, then the more accurate
                        spheroid calculation will be used instead of the
                        quicker sphere calculation.

         `tolerance` => Used only for Oracle. The tolerance is
                        in meters -- a default of 5 centimeters (0.05)
                        is used.
        distance)_distance_attribute)r,   r7   r-   r1   r1   r2   r8   F   s    zGeoQuerySet.distancec             K   s   | j d|S )z
        Returns a Geometry representing the bounding box of the
        Geometry field in an `envelope` attribute on each element of
        the GeoQuerySet.
        envelope)r:   )r4   )r,   r-   r1   r1   r2   r:   X   s    zGeoQuerySet.envelopec             K   s   | j d|S )z
        Returns a modified version of the Polygon/MultiPolygon in which
        all of the vertices follow the Right-Hand-Rule.  By default,
        this is attached as the `force_rhr` attribute on each element
        of the GeoQuerySet.
        	force_rhr)r;   )r4   )r,   r-   r1   r1   r2   r;   `   s    zGeoQuerySet.force_rhr   Fc             K   st   t | j j}|jstdt|tjs.tdd}|r@|r@d}n|rJd}n|rRd}d||dd	d
}| j	d|f|S )a\  
        Returns a GeoJSON representation of the geometry field in a `geojson`
        attribute on each element of the GeoQuerySet.

        The `crs` and `bbox` keywords may be set to True if the user wants
        the coordinate reference system and the bounding box to be included
        in the GeoJSON representation of the geometry.
        z:Only PostGIS and SpatiaLite support GeoJSON serialization.z.Precision keyword must be set with an integer.r            ZGeoJSON)	precisionoptionsz%%(geo_col)s,%(precision)s,%(options)s)descr   r   geojson)
r   r!   r"   rC   NotImplementedError
isinstancer   integer_types	TypeErrorr+   )r,   r@   ZcrsZbboxr-   r0   rA   r.   r1   r1   r2   rC   i   s     	zGeoQuerySet.geojson   c             K   s    dd|idd}| j d|f|S )a  
        Returns a GeoHash representation of the given field in a `geohash`
        attribute on each element of the GeoQuerySet.

        The `precision` keyword may be used to custom the number of
        _characters_ used in the output GeoHash, the default is 20.
        ZGeoHashr@   z%(geo_col)s,%(precision)s)rB   r   r   geohash)r+   )r,   r@   r-   r.   r1   r1   r2   rI      s    zGeoQuerySet.geohashr?   c             K   sV   t | j j}dd|id}|jr6d|d< ||d|d< |jrFt |d< | jd	|f|S )
z
        Returns GML representation of the given field in a `gml` attribute
        on each element of the GeoQuerySet.
        ZGMLr@   )rB   r   z%%(version)s,%(geo_col)s,%(precision)sr   )r@   versionr   r   gml)r   r!   r"   r$   r#   r
   r+   )r,   r@   rJ   r-   r0   r.   r1   r1   r2   rK      s    
zGeoQuerySet.gmlc             K   s   | j d|f|S )z
        Returns the spatial intersection of the Geometry field in
        an `intersection` attribute on each element of this
        GeoQuerySet.
        intersection)r6   )r,   r7   r-   r1   r1   r2   rL      s    zGeoQuerySet.intersectionc             K   s(   ddd|j ddid}| jd|f|S )z
        Returns KML representation of the geometry field in a `kml`
        attribute on each element of this GeoQuerySet.
        ZKMLz%(geo_col)s,%(precision)sr@   r<   )rB   r   r   kml)popr+   )r,   r-   r.   r1   r1   r2   rM      s    zGeoQuerySet.kmlc             K   s   | j d|S )z
        Returns the length of the geometry field as a `Distance` object
        stored in a `length` attribute on each element of this GeoQuerySet.
        lengthN)rO   N)r9   )r,   r-   r1   r1   r2   rO      s    zGeoQuerySet.lengthc             K   s   | j di f|S )z
        Returns the memory size (number of bytes) that the geometry field takes
        in a `mem_size` attribute  on each element of this GeoQuerySet.
        mem_size)r+   )r,   r-   r1   r1   r2   rP      s    zGeoQuerySet.mem_sizec             K   s   | j di f|S )z
        Returns the number of geometries if the field is a
        GeometryCollection or Multi* Field in a `num_geom`
        attribute on each element of this GeoQuerySet; otherwise
        the sets with None.
        num_geom)r+   )r,   r-   r1   r1   r2   rQ      s    zGeoQuerySet.num_geomc             K   s   | j di f|S )z
        Returns the number of points in the first linestring in the
        Geometry field in a `num_points` attribute on each element of
        this GeoQuerySet; otherwise sets with None.
        
num_points)r+   )r,   r-   r1   r1   r2   rR      s    zGeoQuerySet.num_pointsc             K   s   | j d|S )z
        Returns the perimeter of the geometry field as a `Distance` object
        stored in a `perimeter` attribute on each element of this GeoQuerySet.
        	perimeterN)rS   N)r9   )r,   r-   r1   r1   r2   rS      s    zGeoQuerySet.perimeterc             K   s   | j d|S )z
        Returns a Point geometry guaranteed to lie on the surface of the
        Geometry field in a `point_on_surface` attribute on each element
        of this GeoQuerySet; otherwise sets with None.
        point_on_surface)rT   )r4   )r,   r-   r1   r1   r2   rT      s    zGeoQuerySet.point_on_surfacec             K   s<   dt  i}|jdd t| j jjr,t|d< | jd|f|S )z
        Reverses the coordinate order of the geometry, and attaches as a
        `reverse` attribute on each element of this GeoQuerySet.
        r   	model_attreverse_geomgeo_field_typereverse)r	   
setdefaultr   r!   r"   r#   r   r+   )r,   r-   r.   r1   r1   r2   rV      s
    
zGeoQuerySet.reverse_geom        c             K   sZ   t | j jjr4|dkrtdd||dt d}nd|||dt d}| jd|f|S )	z|
        Scales the geometry to a new size by multiplying the ordinates
        with the given x,y,z scale factors.
        g        z'SpatiaLite does not support 3D scaling.z%(geo_col)s,%(x)s,%(y)s)xy)r   r   r   z%(geo_col)s,%(x)s,%(y)s,%(z)s)r[   r\   zscale)r   r!   r"   r%   rD   r	   r+   )r,   r[   r\   r]   r-   r.   r1   r1   r2   r^      s    

zGeoQuerySet.scalec             O   s   ddd |D krt dt|}|dkr@|d }d}d|i}nP|d	kr`|\}}d
}||d}n0|dkr|\}}}	}
d}|||	|
d}ntd||t d}| jd|f|S )ag  
        Snap all points of the input geometry to the grid.  How the
        geometry is snapped to the grid depends on how many arguments
        were given:
          - 1 argument : A single size to snap both the X and Y grids to.
          - 2 arguments: X and Y sizes to snap the grid to.
          - 4 arguments: X, Y sizes and the X, Y origins.
        Fc             S   s   g | ]}t |tftj qS r1   )rE   floatr   rF   ).0argr1   r1   r2   
<listcomp>  s    z,GeoQuerySet.snap_to_grid.<locals>.<listcomp>z@Size argument(s) for the grid must be a float or integer values.r>   r   z%(geo_col)s,%(size)ssizer?   z%(geo_col)s,%(xsize)s,%(ysize)s)xsizeysize   z7%(geo_col)s,%(xorigin)s,%(yorigin)s,%(xsize)s,%(ysize)s)rd   re   xoriginyoriginz4Must provide 1, 2, or 4 arguments to `snap_to_grid`.)r   r   r   snap_to_grid)rG   len
ValueErrorr	   r+   )r,   argsr-   nargsrc   r   r   rd   re   rg   rh   r.   r1   r1   r2   ri     s*    	

zGeoQuerySet.snap_to_gridc             K   sB   t t|}t|tjs tddd||dd}| jd|f|S )a  
        Returns SVG representation of the geographic field in a `svg`
        attribute on each element of this GeoQuerySet.

        Keyword Arguments:
         `relative`  => If set to True, this will evaluate the path in
                        terms of relative moves (rather than absolute).

         `precision` => May be used to set the maximum number of decimal
                        digits used in output (defaults to 8).
        z2SVG precision keyword argument must be an integer.ZSVGz!%(geo_col)s,%(rel)s,%(precision)s)relr@   )rB   r   r   svg)intboolrE   r   rF   rG   r+   )r,   Zrelativer@   r-   r.   r1   r1   r2   ro   &  s    zGeoQuerySet.svgc             K   s   | j d|f|S )z
        Returns the symmetric difference of the geographic field in a
        `sym_difference` attribute on each element of this GeoQuerySet.
        sym_difference)r6   )r,   r7   r-   r1   r1   r2   rr   ?  s    zGeoQuerySet.sym_differencec             K   sZ   t | j jjr4|dkrtdd||dt d}nd|||dt d}| jd|f|S )	zr
        Translates the geometry to a new location using the given numeric
        parameters as offsets.
        g        z+SpatiaLite does not support 3D translation.z%(geo_col)s,%(x)s,%(y)s)r[   r\   )r   r   r   z%(geo_col)s,%(x)s,%(y)s,%(z)s)r[   r\   r]   	translate)r   r!   r"   r%   rD   r	   r+   )r,   r[   r\   r]   r-   r.   r1   r1   r2   rs   F  s    

zGeoQuerySet.translate  c             K   sB   t |tjstd|jd}| jd|d | jjd| | j S )z
        Transforms the given geometry field to the given SRID.  If no SRID is
        provided, the transformation will default to using 4326 (WGS84).
        z!An integer SRID must be provided.r   	transform)r   transformed_srid)	rE   r   rF   rG   r    r   queryZadd_contextZ_clone)r,   sridr-   r   r1   r1   r2   ru   Y  s    
zGeoQuerySet.transformc             K   s   | j d|f|S )z
        Returns the union of the geographic field with the given
        Geometry in a `union` attribute on each element of this GeoQuerySet.
        union)r6   )r,   r7   r-   r1   r1   r2   ry   e  s    zGeoQuerySet.unionNc       	      C   s   t | j }t|j|d}|dkr$|}|s<td||jjf d|i}| j|}|s^td| |dk	rt|| rtd||j	f | j
|||d< ||fS )zE
        Performs set up for executing the spatial function.
        FNz4%s stored procedure not available on the %s backend.functionz+%s output only available on GeometryFields.z1"%s" stored procedures may only be called on %ss.Zgeo_col)r   r!   getattrr"   rD   name
_geo_fieldrG   rE   __name___geocol_select)	r,   attrB   r   rW   r/   funcr   r   r1   r1   r2   r   m  s    

zGeoQuerySet._spatial_setupc             C   s  t jd| tdd |jdd |jdf  |jdd |jdi  |jd	d
 |jdg  t| j }|jddr| j||d ||jdd\}}x0tj	|D ]\}}	|d j||	 qW n|d }t
|tjs|}xr|d D ]f}
|j|d |
 }|jd||d}|j|d|}d|
 }|d }|d	 j|||d	< |d j| qW d|d	  }|jdrz|d }|jjrd|_nt }| jjt||d  |d || | S )a  
        DRY routine for calling a spatial stored procedure on a geometry column
        and attaching its output as an attribute of the model.

        Arguments:
         att:
          The name of the spatial attribute that holds the spatial
          SQL function to call.

         settings:
          Dictionary of internal settings to customize for the spatial procedure.

        Public Keyword Arguments:

         field_name:
          The name of the geographic field to call the spatial
          function on.  May also be a lookup to a geometry field
          as part of a foreign key relation.

         model_att:
          The name of the model attribute to attach the output of
          the spatial function to.
        zxThe %s GeoQuerySet method is deprecated. See GeoDjango Functions documentation to find the expression-based replacement.r?   )
stacklevelrB   N	geom_argsZ
geom_fieldr   r   z%(geo_col)sselect_paramsr   TrW   )rB   r   rW   r   contains)r/   z%%(%s)sz%%sz%%(function)s(%s)r   F)warningswarnr   rY   r   r!   r    r   r   	iteritemsrE   string_typesget_prep_value_get_db_prep_lookupZget_placeholderreplaceextendr"   r#   Zempty_strings_allowedr   rw   Zadd_annotationr   )r,   r   settingsr   rU   r/   Zdefault_argsr   kvr|   r7   paramsZgeom_placeholderZold_fmtZnew_fmtfmtr   r1   r1   r2   r+     sL    



zGeoQuerySet._spatial_attributec             K   sJ  | j ||jdd\}}t| j }|j|}	|j}
|	r<d}ntj|j|}|dk}|dk}|dk}|pn|pn|s|t	d| |j
dk}|pd	d
g}|j}|s|jr|	r|
 r|r|jd |j|}|jd||d}t|}|jr|rd}n|s|rd}||d< n| jjd}|r6t||\}}}|j |jk}	|	rP|jj rPt	d|rr|rd}d|j|f }|jdks|j|kr|jr|d|j|f 7 }n|d7 }n6|jr|d|j|j|j|f 7 }n|d|j|f 7 }nd}|
 r|	r|js:t|tst	dtt t!j"|d
 j#j$dks:t	d|r`|d7 }|j%|j&|d d n|j%d |j'i n|s~|rd!}|
 r|	r|r|d7 }|j%|j(|d d n>|r|jj)r|r|j%d |j*i n|r|j%d |j+i t,|d|||d"}|r$d'|d$< ||d% d#< n|r:|j-|g|d&< | j.||f|S )(zJ
        DRY routine for GeoQuerySet distance attribute routines.
        r   )r   mr8   rO   rS   zUnknown distance function: %sr=   zPOINT (0 0)r   spheroidZdistance_lte)r/   z"%(geo_col)s,%(geom)s,%(tolerance)sz%(geo_col)s,%(tolerance)sr   rv   z[This database does not support linear distance calculations on geodetic coordinate systems.Fz%s(%%(geo_col)s, %s)Nz, %s(%%%%s, %s)z, %%sz, %s(%s(%%%%s, %s), %s)z%(geo_col)s,%(geom)sz=Spherical distance calculation only supported on PointFields.ZPointzLSpherical distance calculation only supported with Point Geometry parametersz,'%(spheroid)s'r>   )rz   r   rz   z%(geo_col)s)r   r   r   r   r   r7   r   r   r   )r7   )/r   r    r   r!   r'   r&   r   r(   r)   rk   Zdimr"   r$   appendr   r   rq   r#   rw   Zget_contextr   lowerZgeodetic_unitsfeaturesZsupports_distance_geodeticru   rx   r%   Z	from_textrE   r   strr   r   
memoryviewZewkbZ	geom_typeupdateZdistance_spheroidZdistance_sphereZlength_spheroidZsupports_3d_functionsZperimeter3dZlength3dr   ZAdapterr+   )r,   r   r7   r   r   r-   r   r   r/   r'   r&   Zdist_attr8   rO   rS   Zgeom_3dZlookup_paramsr0   r   r   r   rx   uZ	unit_namer.   r1   r1   r2   r9     s    






 zGeoQuerySet._distance_attributec             K   s<   dt  i}t| j jjr,d|d< d|i|d< | j||f|S )z
        DRY routine for setting up a GeoQuerySet method that attaches a
        Geometry attribute (e.g., `centroid`, `point_on_surface`).
        r   z%(geo_col)s,%(tolerance)sr   r   r   )r	   r   r!   r"   r#   r+   )r,   r   r   r-   r.   r1   r1   r2   r4   ~  s
    
zGeoQuerySet._geom_attributec             K   sN   dt  dd|id}t| j jjr>|d  d7  < ||d d< | j||f|S )	a  
        DRY routine for setting up a GeoQuerySet method that attaches a
        Geometry attribute and takes a Geoemtry parameter.  This is used
        for geometry set-like operations (e.g., intersection, difference,
        union, sym_difference).
        r7   z%(geo_col)s,%(geom)s)r   r   r   r   r   z,%(tolerance)sr   r   )r7   )r	   r   r!   r"   r#   r+   )r,   r   r7   r   r-   r.   r1   r1   r2   r6     s    zGeoQuerySet._geomset_attributec             C   s   | j j| j}| jj}||jkr| j j|jtdd g |j	  x0|j
D ]&\}}}|j|krJ|j||jd S qJW td| n2||jkr|jjj}| j|||jjS | j||S dS )z
        Helper routine for constructing the SQL to select the geographic
        column.  Takes into account if the geographic field is in a
        ForeignKey relation to the current model.
        r>   r   z(%r not in compiler's related_select_colsN)rw   Zget_compilerr!   model_metafieldsZadd_select_relatedrsplitr   Zpre_sql_setupselectZoutput_fieldZas_sqlr/   rk   Zlocal_fieldsZconcrete_model_field_columndb_table)r,   r   r   compileroptscol_Zparent_modelr1   r1   r2   r     s    



zGeoQuerySet._geocol_selectc             C   sB   |dkr.x | j jjD ]}t|tr|S qW dS tj| j j|S dS )a'  
        Returns the first Geometry field encountered or the one specified via
        the `field_name` keyword. The `field_name` may be a string specifying
        the geometry field on this GeoQuerySet's model, or a lookup string
        to a geometry field via a ForeignKey relation.
        NF)r   r   r   rE   r   r   Z_check_geo_field)r,   r   fieldr1   r1   r2   r}     s    
zGeoQuerySet._geo_fieldc             C   s6   |dkr|j j j}d|j||jjj|p.|jf S )a  
        Helper function that returns the database column for the given field.
        The table and column are returned (quoted) in the proper format, e.g.,
        `"geoapp_city"."point"`.  If `table_alias` is not specified, the
        database table associated with the model of this `GeoQuerySet` will be
        used.  If `column` is specified, it will be used instead of the value
        in `field.column`.
        Nz%s.%s)rw   Zget_metar   Zquote_name_unless_aliasr/   r"   Z
quote_namecolumn)r,   r   r   Ztable_aliasr   r1   r1   r2   r     s    	
zGeoQuerySet._field_column)r   )r<   FF)rH   )r<   r?   )rZ   )Fr<   )rZ   )rt   )NNN)NN)Nr   F)r   )r   )N)NN)%r~   
__module____qualname____doc__r   r3   r5   r8   r:   r;   rC   rI   rK   rL   rM   rO   rP   rQ   rR   rS   rT   rV   r^   ri   ro   rr   rs   ru   ry   r   r+   r9   r4   r6   r   r}   r   r1   r1   r1   r2   r      sF   
	


	
$



!
W
 


r   )!r   Z#django.contrib.gis.db.models.fieldsr   r   r   r   Z$django.contrib.gis.db.models.lookupsr   Z django.contrib.gis.db.models.sqlr   r   r	   r
   Z#django.contrib.gis.geometry.backendr   Zdjango.contrib.gis.measurer   r   Z	django.dbr   Zdjango.db.models.constantsr   Zdjango.db.models.expressionsr   Zdjango.db.models.fieldsr   Zdjango.db.models.queryr   Zdjango.utilsr   Zdjango.utils.deprecationr   r   r1   r1   r1   r2   <module>   s   