====================== GeoDjango Database API ====================== .. currentmodule:: django.contrib.gis.db.models GeoDjango's lookup types may be used with any manager method like ``filter()``, ``exclude()``, etc. However, the lookup types unique to GeoDjango are only available with geographic fields. Filters on 'normal' fields (e.g. ``CharField``) may be chained with those on geographic fields. Thus, geographic queries take the following form (assuming the ``Zipcode`` model used in the `GeoDjango Model API`_):: >>> qs = Zipcode.objects.filter(__=) >>> qs = Zipcode.objects.exclude(...) For example:: >>> qs = Zipcode.objects.filter(poly__contains=pnt) In this case, ``poly`` is the geographic field, ``contains`` is the lookup type, and ``pnt`` is the parameter (which may be a ``GEOSGeometry`` object or a string of GeoJSON , WKT, or HEXEWKB). .. note:: GeoDjango constructs spatial SQL with the ``GeoQuerySet``, a subclass of Django's ``QuerySet``. The ``GeoManager`` instance attached to your model allows it to use ``GeoQuerySet``. .. _GeoDjango Model API: model-api.html Creating and Saving Geographic Models ===================================== Here is an example of how to create a geometry object (assuming the ``Zipcode`` model):: >>> from zipcode.models import Zipcode >>> z = Zipcode(code=77096, poly='POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))') >>> z.save() `GEOS geometry objects`_ may also be used to save geometric models:: >>> from django.contrib.gis.geos import GEOSGeometry >>> z = Zipcode(code=77096, poly=GEOSGeometry('POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))')) >>> z.save() Moreover, if the ``GEOSGeometry`` is in a different coordinate system (has a different SRID value) than that of the field, then it will be implicitly transformed into the SRID of the model's field, using the spatial database's transform procedure:: >>> poly_3084 = GEOSGeometry('POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))', srid=3084) # SRID 3084 is 'NAD83(HARN) / Texas Centric Lambert Conformal' >>> z = Zipcode(code=78212, poly=poly_3084) >>> z.save() >>> from django.db import connection >>> print connection.queries[-1]['sql'] # printing the last SQL statement executed (requires DEBUG=True) INSERT INTO "geoapp_zipcode" ("code", "poly") VALUES (78212, ST_Transform(ST_GeomFromWKB('\\001 ... ', 3084), 4326)) Thus, geometry parameters may be passed in using the ``GEOSGeometry`` object, WKT (Well Known Text [#]_), HEXEWKB (PostGIS specific -- a WKB geometry in hexadecimal [#]_), and GeoJSON [#]_ (requires GDAL). Essentially, if the input is not a ``GEOSGeometry`` object, the geometry field will attempt to create a ``GEOSGeometry`` instance from the input. Below are some examples of GEOS Geometry objects, WKT, and HEXEWKB, and GeoJSON: * GEOS Geometry:: >>> from django.contrib.gis.geos import * >>> pnt = Point(5, 23) >>> ls = LineString((0, 0), (5, 23)) >>> poly = GEOSGeometry('POLYGON (( 10 10, 10 20, 20 20, 20 15, 10 10))') * WKT Polygon: ``'POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))'`` * HEXEWKB Polygon : ``'0103000000010000000 ... 00000000000002440'`` * GeoJSON Point: ``{ "type": "Point", "coordinates": [100.0, 0.0] }`` .. _GEOS geometry objects: geos.html Spatial Lookup Types ==================== PostGIS ------- Spatial Operators ^^^^^^^^^^^^^^^^^ The following lookup types correspond to PostGIS spatial operators. [#]_ :lookup:`bbcontains` Tests if the geometry field's bounding box completely contains the lookup geometry's bounding box. Example:: Zipcode.objects.filter(poly__bbcontains=geom) PostGIS equivalent:: SELECT ... WHERE poly ~ geom :lookup:`bboverlaps` Tests if the geometry field's bounding box overlaps the lookup geometry's bounding box. Example:: Zipcode.objects.filter(poly__bboverlaps=geom) PostGIS equivalent:: SELECT ... WHERE poly && geom :lookup:`contained` Tests if the geometry field's bounding box is completely contained by the lookup geometry's bounding box. Example:: Zipcode.objects.filter(poly__contained=geom) PostGIS equivalent:: SELECT ... WHERE poly @ geom :lookup:`exact` or :lookup:`same_as` Tests actual geometric equality of the geometry field against the the given lookup geometry, vertex-by-vertex. The following examples are equivalent:: Zipcode.objects.filter(poly__exact=geom) Zipcode.objects.filter(poly=geom) Zipcode.objects.filter(poly__same_as=geom) PostGIS equivalent:: SELECT ... WHERE poly ~= geom :lookup:`left` Tests if the geometry field's bounding box is strictly to the left of the lookup geometry's bounding box. Example:: Zipcode.objects.filter(poly__left=geom) PostGIS equivalent:: SELECT ... WHERE poly << geom :lookup:`right` Tests if the geometry field's bounding box is strictly to the right of the lookup geometry's bounding box. Example:: Zipcode.objects.filter(poly__right=geom) PostGIS equivalent:: SELECT ... WHERE poly >> geom lookup:`overlaps_left` Tests if the geometry field's bounding box overlaps or is to the left of the lookup geometry's bounding box. Example:: Zipcode.objects.filter(poly__overlaps_left=geom) PostGIS equivalent:: SELECT ... WHERE poly &< geom :lookup:`overlaps_right` Tests if the geometry field's bounding box overlaps or is to the right of the lookup geometry's bounding box. Example:: Zipcode.objects.filter(poly__overlaps_right=geom) PostGIS equivalent:: SELECT ... WHERE poly &> geom :lookup:`overlaps_above` Tests if the geometry field's bounding box overlaps or is above the lookup geometry's bounding box. Example:: Zipcode.objects.filter(poly__overlaps_above=geom) PostGIS equivalent:: SELECT ... WHERE poly |&> geom :lookup:`overlaps_below` Tests if the geometry field's bounding box overlaps or is below the lookup geometry's bounding box. Example:: Zipcode.objects.filter(poly__overlaps_below=geom) PostGIS equivalent:: SELECT ... WHERE poly &<| geom :lookup:`strictly_above` Tests if the geometry field's bounding box is strictly above the lookup geometry's bounding box. Example:: Zipcode.objects.filter(poly__strictly_above=geom) PostGIS equivalent:: SELECT ... WHERE poly |>> geom :lookup:`strictly_below` Tests if the geometry field's bounding box is strictly below the lookup geometry's bounding box. Example:: Zipcode.objects.filter(poly__strictly_below=geom) PostGIS equivalent:: SELECT ... WHERE poly <<| geom Geometry Relationship Functions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The following lookup types correspond to PostGIS geometry relationship functions. [#]_ Please note that when using PostGIS 1.3.1 and above, index support is automatically "inlined" -- in other words, the bounding box equivalent is automatically evaluated prior to calling these, more computationally expensive, functions. :lookup:`contains` Tests if the geometry field spatially contains the lookup geometry. Example:: Zipcode.objects.filter(poly__contains=geom) PostGIS equivalent:: SELECT ... WHERE ST_Contains(poly, geom) :lookup:`coveredby` Tests if no point in the geometry field is outside the lookup geometry. [#]_ Only available in PostGIS 1.3.1 and above. Example:: Zipcode.objects.filter(poly__coveredby=geom) PostGIS equivalent:: SELECT ... WHERE ST_CoveredBy(poly, geom) :lookup:`covers` Tests if no point in the lookup geometry is outside the geometry field. [#]_ Only available in PostGIS 1.3.1 and above. Example:: Zipcode.objects.filter(poly__covers=geom) PostGIS equivalent:: SELECT ... WHERE ST_Covers(poly, geom) :lookup:`crosses` Tests if the geometry field spatially crosses the lookup geometry. Example:: Zipcode.objects.filter(poly__crosses=geom) PostGIS equivalent:: SELECT ... WHERE ST_Crosses(poly, geom) :lookup:`disjoint` Tests if the geometry field is spatially disjoint from the lookup geometry. Example:: Zipcode.objects.filter(poly__disjoint=geom) PostGIS equivalent:: SELECT ... WHERE ST_Disjoint(poly, geom) .. _dwithin_postgis: :lookup:`dwithin` Tests if the geometry field is within the specified distance of the lookup geometry; uses indexes if available. The lookup parameter is a two-element tuple: ``(geom, distance)``, where ``distance`` is a ``Distance`` object or a numeric value in units. Only available in PostGIS versions 1.3.1 and above. .. admonition:: Distance Parameters and Geographic Coordinate Systems The ``dwithin`` lookup is meant for projected coordinate systems because PostGIS uses ``ST_Distance``, which calculates the Cartesian distance between geometries. In other words, this will not return accurate results for geographic coordinate systems such as WGS84. Thus, an exception will be raised if a ``Distance`` object is used on a geometry field in a geographic coordinate system. However, a numeric value is allowed for geometry fields in geographic coordinate systems. This advanced usage allows users to limit querysets by distance more efficiently using units of degrees. Example:: # If Zipcode uses a projected coordinate system, this is allowed. Zipcode.objects.filter(poly__dwithin=(geom, D(mi=5))) # If Zipcode uses a geographic coordinate system, then the # distance unit must be a numeric value in units of degrees. Zipcode.objects.filter(poly__dwithin=(geom, 0.5)) PostGIS equivalent:: SELECT ... WHERE ST_DWithin(poly, geom, ) :lookup:`equals` Tests if the geometry field is spatially equal to the lookup geometry. Example:: Zipcode.objects.filter(poly__equals=geom) PostGIS equivalent:: SELECT ... WHERE ST_Equals(poly, geom) :lookup:`intersects` Tests if the geometry field spatially intersects the lookup geometry. Example:: Zipcode.objects.filter(poly__intersects=geom) PostGIS equivalent:: SELECT ... WHERE ST_Intersects(poly, geom) :lookup:`overlaps` Tests if the geometry field spatially overlaps the lookup geometry. Example:: Zipcode.objects.filter(poly__overlaps=geom) PostGIS equivalent:: SELECT ... WHERE ST_Overlaps(poly, geom) :lookup:`relate` Tests if the geometry field is spatially related to the the lookup geometry by the values given in the intersection pattern matrix. The intersection pattern matrix is a string comprising nine characters, which define intersections between the interior, boundary, and exterior of the geometry field and the lookup geometry. The intersection pattern matrix may only use the following characters: ``1``, ``2``, ``T``, ``F``, or ``*``. This lookup type allows users to "fine tune" a specific geometric relationship consistent with the DE-9IM model. [#]_ Example:: # A tuple lookup parameter is used to specify the geometry and # the intersection pattern (the pattern here is for 'contains'). Zipcode.objects.filter(poly__relate(geom, 'T*T***FF*')) PostGIS equivalent:: SELECT ... WHERE ST_Relate(poly, geom, 'T*T***FF*') :lookup:`touches` Tests if the geometry field spatially touches the lookup geometry. Example:: Zipcode.objects.filter(poly__touches=geom) PostGIS equivalent:: SELECT ... WHERE ST_Touches(poly, geom) :lookup:`within` Tests if the geometry field is spatially within the lookup geometry. Example:: Zipcode.objects.filter(poly__within=geom) PostGIS equivalent:: SELECT ... WHERE ST_Within(poly, geom) Oracle ------ For more information, see Oracle's `Spatial Operators`__ documentation. [#]_ __ http://download.oracle.com/docs/html/B14255_01/sdo_operat.htm :lookup:`contains` Tests if the geometry field spatially contains the lookup geometry. Example:: Zipcode.objects.filter(poly__contains=geom) Oracle equivalent:: SELECT ... WHERE SDO_CONTAINS(poly, geom) :lookup:`covers` Tests if no point in the lookup geometry is outside the geometry field. Oracle equivalent:: SELECT ... WHERE SDO_COVERS(poly, geom) :lookup:`coveredby` Tests if no point in the geometry field is outside the lookup geometry. Oracle equivalent:: SELECT ... WHERE SDO_COVEREDBY(poly, geom) :lookup:`disjoint` Tests if the geometry field is spatially disjoint from the lookup geometry. Oracle equivalent:: SELECT ... WHERE SDO_GEOM.RELATE(poly, 'DISJOINT', geom, 0.05) :lookup:`dwithin` Tests if the geometry field is within the specified distance of the lookup geometry; uses indexes if available. The lookup parameter is a two-element tuple: ``(geom, distance)``, where ``distance`` is a ``Distance`` object or a numeric value in units. Oracle equivalent:: SELECT ... WHERE SDO_WITHIN_DISTANCE(poly, geom, 'distance=distance') :lookup:`equals`, :lookup:`exact`, :lookup:`same_as` Tests if the geometry field is spatially equal to the lookup geometry. The following examples are equivalent on Oracle:: Zipcode.objects.filter(poly=geom) Zipcode.objects.filter(poly__exact=geom) Zipcode.objects.filter(poly__equals=geom) Zipcode.objects.filter(poly__same_as=geom) Oracle equivalent:: SELECT ... WHERE SDO_EQUALS(poly, geom) :lookup:`intersects` Tests if the geometry field spatially intersects the lookup geometry. Oracle equivalent:: SELECT ... WHERE SDO_OVERLAPBDYINTERSECT(poly, geom) :lookup:`overlaps` Tests if the geometry field spatially overlaps the lookup geometry. Oracle equivalent:: SELECT ... WHERE SDO_OVERLAPS(poly, geom) :lookup:`relate` Tests if the geometry field is spatially related to the the lookup geometry by the given mask component. This lookup requires a tuple parameter, ``(geom, mask)``, where ``mask`` is at least one of the nine-intersection patterns: ``TOUCH``, ``OVERLAPBDYDISJOINT``, ``OVERLAPBDYINTERSECT``, ``EQUAL``, ``INSIDE``, ``COVEREDBY``, ``CONTAINS``, ``COVERS``, ``ANYINTERACT``, and ``ON``. Multiple masks may be combined with the logical Boolean operator OR, for example, ``'inside+touch'``. [#]_ The mask relation strings are case-insensitive. Example:: # A tuple lookup parameter is used to specify the geometry and # the mask component. Zipcode.objects.filter(poly__relate(geom, 'anyinteract')) Oracle equivalent:: SELECT ... WHERE SDO_RELATE(poly, geom, 'anyinteract') :lookup:`touches` Tests if the geometry field spatially touches the lookup geometry. Oracle equivalent:: SELECT ... WHERE SDO_TOUCH(poly, geom) :lookup:`within` Tests if the geometry field is spatially within (inside) the lookup geometry. Oracle equivalent:: SELECT ... WHERE SDO_INSIDE(poly, geom) MySQL ----- For more information, see `Relations on Geometry Minimal Bounding Rectangles (MBRs)`__. [#]_ __ http://dev.mysql.com/doc/refman/5.0/en/relations-on-geometry-mbr.html :lookup:`bbcontains`, :lookup:`contains` * MySQL equivalent ``MBRContains(g1, g2)`` :lookup:`contained`, :lookup:`within` * MySQL equivalent ``MBRWithin(g1, g2)`` :lookup:`disjoint` * MySQL equivalent ``MBRDisjoint(g1, g2)`` :lookup:`equals`, :lookup:`exact`, :lookup:`same_as` * MySQL equivalent ``MBREqual(g1, g2)`` :lookup:`intersects` * MySQL equivalent ``MBRIntersects(g1, g2)`` :lookup:`overlaps` * MySQL equivalent ``MBROverlaps(g1, g2)`` :lookup:`touches` * MySQL equivalent ``MBRTouches(g1, g2)`` SpatiaLite ---------- For more information consult the `SpatiaLite SQL functions reference list`__. __ http://www.gaia-gis.it/spatialite/spatialite-sql-2.3.1.html :lookup:`bbcontains` * SpatiaLite equivalient ``MbrContains(g1, g2)`` :lookup:`bboverlaps` * SpatiaLite equivalent ``MbrOverlaps(g1, g2)`` :lookup:`contained` * SpatiaLite equivalent ``MbrWithin(g1, g2)`` :lookup:`contains` * SpatiaLite equivalent ``Contains(g1, g2)`` :lookup:`crosses` * SpatiaLite equivalent ``Crosses(g1, g2)`` :lookup:`disjoint` * SpatiaLite equivalent ``Disjoint(g1, g2)`` :lookup:`equals`, :lookup:`exact`, :lookup:`same_as` * SpatiaLite equivalent ``Equals(g1, g2)`` :lookup:`intersects` * SpatiaLite equivalent ``Intersects(g1, g2)`` :lookup:`overlaps` * SpatiaLite equivalent ``Overlaps(g1, g2)`` :lookup:`relate` * SpatiaLite equivalent ``Relate(geom, pattern)`` :lookup:`touches` * SpatiaLite equivalent ``Touches(g1, g2)`` :lookup:`within` * SpatiaLite equivalent ``Within(g1, g2)`` Distance Queries ================ Introduction ------------ Distance calculations with spatial data is tricky because, unfortunately, the Earth is not flat. Some distance queries with fields in a geographic coordinate system may have to be expressed differently because of limitations in PostGIS. Please see the `Selecting an SRID`_ section in the model API documentation for more details. .. _Selecting an SRID: model-api.html#selecting-an-srid Distance Lookups ---------------- *Availability*: PostGIS, Oracle, SpatiaLite Distance lookups take a tuple parameter comprising: #. A geometry to base calculations from; and #. A number or ``Distance`` object containing the distance. If a ``Distance`` [#]_ object is used, it may be expressed in any units (the SQL generated will use units converted to those of the field); otherwise, numeric parameters will be assumed to be in the units of the field. .. note:: For PostGIS users, the routine ``ST_distance_sphere`` is used by default for calculating distances on geographic coordinate systems -- which may only be called with point geometries [#]_. Thus, geographic distance lookups on PostGIS are only allowed on ``PointField`` model fields using points for the geographic parameter. The following distance lookups are available: * :lookup:`distance_lt` * :lookup:`distance_lte` * :lookup:`distance_gt` * :lookup:`distance_gte` * :lookup:`dwithin` In addition, there's the :ref:`distance` ``GeoQuerySet`` method. For example, let's say we have a ``SouthTexasCity`` model (from the `GeoDjango distance tests`__ ) on a *projected* coordinate system valid for cities in southern Texas:: from django.contrib.gis.db import models class SouthTexasCity(models.Model): name = models.CharField(max_length=30) # A projected coordinate system (only valid for South Texas!) # is used, units are in meters. point = models.PointField(srid=32140) objects = models.GeoManager() Then distance queries may be performed as follows:: >>> from django.contrib.gis.geos import * >>> from django.contrib.gis.measure import D # ``D`` is a shortcut for ``Distance`` >>> from geoapp import SouthTexasCity # Distances will be calculated from this point, which does not have to be projected. >>> pnt = fromstr('POINT(-96.876369 29.905320)', srid=4326) # If numeric parameter, units of field (meters in this case) are assumed. >>> qs = SouthTexasCity.objects.filter(point__distance_lte=(pnt, 7000)) # Find all Cities within 7 km, > 20 miles away, and > 100 chains away (an obscure unit) >>> qs = SouthTexasCity.objects.filter(point__distance_lte=(pnt, D(km=7))) >>> qs = SouthTexasCity.objects.filter(point__distance_gte=(pnt, D(mi=20))) >>> qs = SouthTexasCity.objects.filter(point__distance_gte=(pnt, D(chain=100))) __ http://code.djangoproject.com/browser/django/trunk/django/contrib/gis/tests/distapp/models.py .. _geoqs_methods: ``GeoQuerySet`` Methods ======================= ``GeoQuerySet`` methods perform a spatial operation on each geographic field in the queryset and store its output in a new attribute on the model (which is generally the name of the ``GeoQuerySet`` method). There are also aggregate ``GeoQuerySet`` methods which return a single value instead of a queryset. This section will describe the API and availability of every ``GeoQuerySet`` method available in GeoDjango. With a few exceptions, the following keyword arguments may be used with all ``GeoQuerySet`` methods: ===================== ===================================================== Keyword Argument Description ===================== ===================================================== ``field_name`` By default, ``GeoQuerySet`` methods use the first geographic field encountered in the model. This keyword should be used to specify another geographic field (e.g., ``field_name='point2'``) when there are multiple geographic fields in a model. On PostGIS, the ``field_name`` keyword may also be used on geometry fields in models that are related via a ``ForeignKey`` relation (e.g., ``field_name='related__point'``). ``model_att`` By default, ``GeoQuerySet`` methods typically attach their output in an attribute with the same name as the ``GeoQuerySet`` method. Setting this keyword with the desired attribute name will override this default behavior. For example, ``qs = Zipcode.objects.centroid(model_att='c')`` will attach the centroid of the ``Zipcode`` geometry field in a ``c`` attribute on every model rather than in a ``centroid`` attribute. This keyword is required if a method name clashes with an existing ``GeoQuerySet`` method -- if you wanted to use the ``area()`` method on model with a ``PolygonField`` named ``area``, for example. ===================== ===================================================== Aggregate Objects ----------------- .. versionadded:: 1.1 Example:: >>> from django.contrib.gis.db.models import Extent, Union >>> WorldBorders.objects.aggregate(Extent('mpoly'), Union('mpoly')) .. method:: Collect Returns the same as the :ref:`collect` aggregate method. .. method:: Extent Returns the same as the :ref:`extent` aggregate method. .. method:: Extent3D .. versionadded:: 1.2 Returns the same as the :ref:`extent3d` aggregate method. .. method:: MakeLine Returns the same as the :ref:`makeline` aggregate method. .. method:: Union Returns the same as the :ref:`unionagg` aggregate method. Aggregate Methods ----------------- .. _collect: .. method:: collect() .. versionadded:: 1.1 *Availability*: PostGIS Returns a ``GEOMETRYCOLLECTION`` or a ``MULTI`` geometry object from the geometry column. This is analagous to a simplified version of the :ref:`unionagg` routine, except it can be several orders of magnitude faster than peforming a union because it simply rolls up geometries into a collection or multi object, not caring about dissolving boundaries. .. _extent: .. method:: extent() *Availability*: PostGIS, Oracle Returns the extent of the ``GeoQuerySet`` as a four-tuple, comprising the lower left coordinate and the upper right coordinate. Example:: >>> qs = City.objects.filter(name__in=('Houston', 'Dallas')) >>> print qs.extent() (-96.8016128540039, 29.7633724212646, -95.3631439208984, 32.782058715820) .. _extent3d: .. method:: extent3d() .. versionadded:: 1.2 *Availability*: PostGIS Returns the 3D extent of the ``GeoQuerySet`` as a six-tuple, comprising the lower left coordinate and upper right coordinate. Example:: >>> qs = City.objects.filter(name__in=('Houston', 'Dallas')) >>> print qs.extent3d() (-96.8016128540039, 29.7633724212646, 0, -95.3631439208984, 32.782058715820, 0) .. _makeline: .. method:: make_line() *Availability*: PostGIS Returns a ``LineString`` constructed from the point field geometries in the ``GeoQuerySet``. Currently, ordering the queryset has no effect. Example:: >>> print City.objects.filter(name__in=('Houston', 'Dallas')).make_line() LINESTRING (-95.3631510000000020 29.7633739999999989, -96.8016109999999941 32.7820570000000018) .. _unionagg: .. function:: unionagg() *Availability*: PostGIS, Oracle, SpatiaLite This method returns a ``GEOSGeometry`` object comprising the union of every geometry in the queryset. Please note that use of `unionagg` is processor intensive and may take a significant amount of time on large querysets. Example:: >>> u = Zipcode.objects.unionagg() # This may take a long time. >>> u = Zipcode.objects.filter(poly__within=bbox).unionagg() # A more sensible approach. ===================== ===================================================== Keyword Argument Description ===================== ===================================================== ``tolerance`` This keyword is for Oracle only. It is for the tolerance value used by the ``SDOAGGRTYPE`` procedure; the `Oracle documentation`__ has more details. ===================== ===================================================== __ http://download.oracle.com/docs/html/B14255_01/sdo_intro.htm#sthref150 Measurement ----------- *Availability*: PostGIS, Oracle, SpatiaLite .. _area: .. function:: area() Returns the area of the geographic field in an ``area`` attribute on each element of this GeoQuerySet. .. _distance: .. function:: distance(geom) This method takes a geometry as a parameter, and attaches a ``distance`` attribute to every model in the returned queryset that contains the distance (as a ``Distance`` object) to the given geometry. In the following example (taken from the `GeoDjango distance tests`__), the distance from the `Tasmanian`__ city of Hobart to every other ``PointField`` in the ``AustraliaCity`` queryset is calculated:: >>> pnt = AustraliaCity.objects.get(name='Hobart').point >>> for city in AustraliaCity.objects.distance(pnt): print city.name, city.distance Wollongong 990071.220408 m Shellharbour 972804.613941 m Thirroul 1002334.36351 m Mittagong 975691.632637 m Batemans Bay 834342.185561 m Canberra 598140.268959 m Melbourne 575337.765042 m Sydney 1056978.87363 m Hobart 0.0 m Adelaide 1162031.83522 m Hillsdale 1049200.46122 m .. note:: Because the ``distance`` attribute is a ``Distance`` object, you can easily express the value in the units of your choice. For example, ``city.distance.mi`` is the distance value in miles and ``city.distance.km`` is the distance value in kilometers. See the `distance documentation`_ for usage details and the list of `supported units`_. .. _distance documentation: measure.html#the-distance-and-area-objects .. _supported units: measure.html#supported-units __ http://en.wikipedia.org/wiki/Tasmania __ http://code.djangoproject.com/browser/django/trunk/django/contrib/gis/tests/distapp/models.py .. function:: length() Returns the length of the geometry field in a ``length`` attribute (a ``Distance`` object) on each model in the queryset. .. function:: perimiter() Returns the perimeter of the geometry field in a ``perimeter`` attribute (a ``Distance`` object) on each model in the queryset. Geometry Methods ---------------- With the exception of ``transform``, all of the following attach geometry objects to each element of the ``GeoQuerySet`` that is the result of the method. .. function:: centroid() *Availability*: PostGIS, Oracle, SpatiaLite Returns the ``centroid`` value for the geographic field in a ``centroid`` attribute on each element of the ``GeoQuerySet``. .. function:: envelope() *Availability*: PostGIS, SpatiaLite Returns a geometry representing the bounding box of the geometry field in an ``envelope`` attribute on each element of the ``GeoQuerySet``. .. function: point_on_surface() *Availability*: PostGIS, Oracle, SpatiaLite 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. .. function:: scale(x, y, z=0.0) *Availability*: PostGIS, SpatiaLite .. function:: snap_to_grid(*args) .. versionadded:: 1.1 Snap all points of the input geometry to the grid. How the geometry is snapped to the grid depends on how many numeric (either float, integer, or long) arguments are given. =================== ===================================================== Number of Arguments Description =================== ===================================================== 1 A single size to snap bot the X and Y grids to. 2 X and Y sizes to snap the grid to. 4 X, Y sizes and the corresponding X, Y origins. =================== ===================================================== .. function:: translate(x, y, z=0.0) *Availability*: PostGIS, SpatiaLite Translates the geometry to a new location using the given numeric parameters as offsets. .. function:: transform(srid) *Availability*: PostGIS, Oracle The ``transform`` method transforms the geometries in a model to the spatial reference system specified by the ``srid`` parameter. If no ``srid`` is given, then 4326 (WGS84) is used by default. .. note :: What spatial reference system an integer SRID corresponds to may depend on the spatial database used. In other words, the SRID numbers used for Oracle are not necessarily the same as those used by PostGIS. Example:: >>> qs = Zipcode.objects.all().transform() # Transforms to WGS84 >>> qs = Zipcode.objects.all().transform(32140) # Transforming to "NAD83 / Texas South Central" >>> print qs[0].poly.srid 32140 >>> print qs[0].poly POLYGON ((234055.1698884720099159 4937796.9232223574072123 ... Geometry Operations ------------------- *Availability*: PostGIS, Oracle, SpatiaLite The following methods all take a geometry as a parameter and attach a geometry to each element of the ``GeoQuerySet`` that is the result of the operation. .. function:: difference(geom) Returns the spatial difference of the geographic field with the given geometry in a ``difference`` attribute on each element of the ``GeoQuerySet``. .. function:: intersection(geom) Returns the spatial intersection of the geographic field with the given geometry in an ``intersection`` attribute on each element of the ``GeoQuerySet``. .. function:: sym_difference(geom) Returns the symmetric difference of the geographic field with the given geometry in a ``sym_difference`` attribute on each element of the ``GeoQuerySet``. .. function:: union(geom) Returns the union of the geographic field with the given geometry in an ``union`` attribute on each element of the ``GeoQuerySet``. Output ------ The following ``GeoQuerySet`` methods will return an attribute that has the value of the geometry field in each model converted to the requested output format. .. function:: geojson() .. versionadded:: 1.1 *Availability*: PostGIS Attaches a ``geojson`` attribute to every model in the queryset that contains the `GeoJSON`__ representation of the geometry. ===================== ===================================================== Keyword Argument Description ===================== ===================================================== ``precision`` It may be used to specify the number of significant digits for the coordinates in the GeoJSON representation -- the default value is 8. ``crs`` Set this to ``True`` if you want the coordinate reference system to be included in the returned GeoJSON. ``bbox`` Set this to ``True`` if you want the bounding box to be included in the returned GeoJSON. ===================== ===================================================== __ http://geojson.org/ .. function:: gml() *Availability*: PostGIS, Oracle Attaches a ``gml`` attribute to every model in the queryset that contains the `Geographic Markup Language (GML)`__ representation of the geometry. Example:: >>> qs = Zipcode.objects.all().gml() >>> print qs[0].gml -147.78711,70.245363 ... -147.78711,70.245363 ===================== ===================================================== Keyword Argument Description ===================== ===================================================== ``precision`` This keyword is for PostGIS only. It may be used to specify the number of significant digits for the coordinates in the GML representation -- the default value is 8. ``version`` This keyword is for PostGIS only. It may be used to specify the GML version used, and may only be values of 2 or 3. The default value is 2. ===================== ===================================================== __ http://en.wikipedia.org/wiki/Geography_Markup_Language .. function:: kml() *Availability*: PostGIS Attaches a ``kml`` attribute to every model in the queryset that contains the `Keyhole Markup Language (KML)`__ representation of the geometry fields. It should be noted that the contents of the KML are transformed to WGS84 if necessary. Example:: >>> qs = Zipcode.objects.all().kml() >>> print qs[0].kml -103.04135,36.217596,0 ... -103.04135,36.217596,0 ===================== ===================================================== Keyword Argument Description ===================== ===================================================== ``precision`` This keyword may be used to specify the number of significant digits for the coordinates in the KML representation -- the default value is 8. ===================== ===================================================== __ http://code.google.com/apis/kml/documentation/ .. function:: svg() *Availability*: PostGIS, SpatiaLite Attaches a ``svg`` attribute to every model in the queryset that contains the `Scalable Vector Graphics (SVG)`__ path data of the geometry fields. ===================== ===================================================== Keyword Argument Description ===================== ===================================================== ``relative`` If set to ``True``, the path data will be implemented in terms of relative moves. Defaults to ``False``, meaning that absolute moves are used instead. ``precision`` This keyword may be used to specify the number of significant digits for the coordinates in the SVG representation -- the default value is 8. ===================== ===================================================== __ http://www.w3.org/Graphics/SVG/ Miscellaneous ------------- .. function:: mem_size() *Availability*: PostGIS Returns the memory size (number of bytes) that the geometry field takes in a ``mem_size`` attribute on each element of the ``GeoQuerySet``. .. function:: num_geom() *Availability*: PostGIS, Oracle, SpatiaLite Returns the number of geometries in a ``num_geom`` attribute on each element of the ``GeoQuerySet`` if the geometry field is a collection (e.g., a ``GEOMETRYCOLLECTION`` or ``MULTI*`` field); otherwise sets with ``None``. .. function:: num_points() *Availability*: PostGIS, Oracle, SpatiaLite Returns the number of points in the first linestring in the geometry field in a ``num_points`` attribute on each element of the ``GeoQuerySet``; otherwise sets with ``None``. Compatibility Table =================== Spatial Lookup Types -------------------- The following table provides a summary of what lookup types are available on each spatial backend. =========================== ========= ======== ============ ========== Lookup Type PostGIS Oracle MySQL [#]_ SpatiaLite =========================== ========= ======== ============ ========== ``bbcontains`` X X X ``bboverlaps`` X X X ``contained`` X X X ``contains`` X X X X ``coveredby`` X X ``covers`` X X ``crosses`` X X ``disjoint`` X X X X ``distance_gt`` X X X ``distance_gte`` X X X ``distance_lt`` X X X ``distance_lte`` X X X ``dwithin`` X X ``equals`` X X X X ``exact`` X X X X ``intersects`` X X X X ``overlaps`` X X X X ``relate`` X X X ``same_as`` X X X X ``touches`` X X X X ``within`` X X X X ``left`` X ``right`` X ``overlaps_left`` X ``overlaps_right`` X ``overlaps_above`` X ``overlaps_below`` X ``strictly_above`` X ``strictly_below`` X =========================== ========= ======== ============ ========== ``GeoQuerySet`` Methods ----------------------- The following table provides a summary of what ``GeoQuerySet`` methods are available on each spatial backend. Please note that MySQL does not support any of these methods, and is thus excluded from the table. =========================== ========= ======== ========== Method PostGIS Oracle SpatiaLite =========================== ========= ======== ========== ``area`` X X X ``centroid`` X X X ``collect`` X ``difference`` X X X ``distance`` X X X ``envelope`` X X ``extent`` X X ``extent3d`` X ``geojson`` X ``gml`` X X ``intersection`` X X X ``kml`` X ``length`` X X X ``make_line`` X ``mem_size`` X ``num_geom`` X X X ``num_points`` X X X ``perimeter`` X X ``point_on_surface`` X X X ``scale`` X X ``snap_to_grid`` X ``svg`` X X ``sym_difference`` X X X ``transform`` X X X ``translate`` X X ``union`` X X X ``unionagg`` X X X =========================== ========= ======== ========== .. rubric:: Footnotes .. [#] *See* Open Geospatial Consortium, Inc., `OpenGIS Simple Feature Specification For SQL `_, Document 99-049 (May 5, 1999), at Ch. 3.2.5, p. 3-11 (SQL Textual Representation of Geometry). .. [#] *See* `PostGIS EWKB, EWKT and Canonical Forms `_, PostGIS documentation at Ch. 4.1.2. .. [#] *See* Howard Butler, Martin Daly, Allan Doyle, Tim Schaub, & Christopher Schmidt, `The GeoJSON Format Specification `_, Revision 1.0 (June 16, 2008). .. [#] *See generally*, `Operators `_, PostGIS Documentation at Ch. 6.2.2. .. [#] *See generally*, `Geometry Relationship Functions `_ PostGIS Documentation at Ch. 6.1.2. .. [#] For an explanation of this routine, see `this entry `_ at the blog of Martin Davis (a PostGIS developer). .. [#] *See id.* .. [#] *See* `OpenGIS Simple Feature Specification For SQL `_, at Ch. 2.1.13.2, p. 2-13 (The Dimensionally Extended Nine-Intersection Model). .. [#] Oracle Spatial User's Guide and Manual, at Ch. 11. .. [#] *See id.* at `SDO_RELATE documentation `_. .. [#] MySQL 5.0 Reference Manual, at Ch. 17.5.5. .. [#] *See* the `distance documentation`_ for more information on the ``Distance`` object. .. [#] *See* ``ST_distance_sphere`` in `Measurement Functions `_, PostGIS documentation at Ch. 6.2.3. .. [#] MySQL only supports bounding box operations (known as minimum bounding rectangles, or MBR, in MySQL). Thus, spatial lookups such as ``contains`` are really equivalent to ``bbcontains``.