diff --git a/docs/ref/contrib/gis/admin.txt b/docs/ref/contrib/gis/admin.txt new file mode 100644 index 0000000000..dc2336d9da --- /dev/null +++ b/docs/ref/contrib/gis/admin.txt @@ -0,0 +1,57 @@ +.. _ref-gis-admin: + +====================== +GeoDjango's admin site +====================== + +.. module:: django.contrib.gis.admin + :synopsis: GeoDjango's extensions to the admin site. + + +``GeoModelAdmin`` +================= + +.. class:: GeoModelAdmin + + .. attribute:: default_lon + + The default center longitude. + + .. attribute:: default_lat + + The default center latitude. + + .. attribute:: default_zoom + + The default zoom level to use. Defaults to 18. + + .. attribute:: extra_js + + Sequence of URLs to any extra JavaScript to include. + + .. attribute:: map_template + + Override the template used to generate the JavaScript slippy map. + Default is ``'gis/admin/openlayers.html'``. + + .. attribute:: map_width + + Width of the map, in pixels. Defaults to 600. + + .. attribute:: map_height + + Height of the map, in pixels. Defaults to 400. + + .. attribute:: openlayers_url + + Link to the URL of the OpenLayers JavaScript. Defaults to + ``'http://openlayers.org/api/2.8/OpenLayers.js'``. + +``OSMGeoAdmin`` +=============== + +.. class:: OSMGeoAdmin + + A subclass of :class:`GeoModelAdmin` that uses a spherical mercator projection + with OpenStreetMap street data tiles. See the :ref:`OSMGeoAdmin introduction ` + in the tutorial for a usage example. diff --git a/docs/ref/contrib/gis/commands.txt b/docs/ref/contrib/gis/commands.txt new file mode 100644 index 0000000000..2cb7f69887 --- /dev/null +++ b/docs/ref/contrib/gis/commands.txt @@ -0,0 +1,83 @@ +.. ref-geodjango-admin: + +============================= +GeoDjango Management Commands +============================= + +inspectdb +========= + +.. describe:: django-admin.py inspectdb + +When :mod:`django.contrib.gis` is in your :setting:`INSTALLED_APPS`, the +:djadmin:`inspectdb` management command is overridden with one from GeoDjango. +The overridden command is spatially-aware, and places geometry fields in the +auto-generated model definition, where appropriate. + +ogrinspect +===================================== + +.. django-admin:: ogrinspect + +The ``ogrinpsect`` management command will inspect the given OGR-compatible +:class:`~django.contrib.gis.gdal.DataSource` (e.g., a shapefile) and will +output a GeoDjango model with the given model name. There's a detailed example +of using ``ogrinspect`` :ref:`in the tutorial `. + +.. django-admin-option:: --blank + + Use a comma separated list of OGR field names to add the ``blank=True`` + keyword option to the field definition. Set with ``true`` to apply + to all applicable fields. + +.. django-admin-option:: --decimal + + Use a comma separated list of OGR float fields to generate + :class:`~django.db.models.DecimalField` instead of the default + :class:`~django.db.models.FloatField`. Set to ``true`` to apply to all + OGR float fields. + +.. django-admin-option:: --geom-name + + Specifies the model attribute name to use for the geometry field. + Defaults to ``'geom'``. + +.. django-admin-option:: --layer + + The key for specifying which layer in the OGR + :class:`~django.contrib.gis.gdal.DataSource` source to use. + Defaults to 0 (the first layer). May be an integer or a string identifier + for the :class:`~django.contrib.gis.gdal.Layer`. + +.. django-admin-option:: --mapping + + Automatically generate a mapping dictionary for use with + :class:`~django.contrib.gis.utils.LayerMapping`. + +.. django-admin-option:: --multi-geom + + When generating the geometry field, treat it as a geometry collection. + For example, if this setting is enabled then a + :class:`~django.contrib.gis.db.models.MultiPolygonField` will be placed + in the generated model rather than + :class:`~django.contrib.gis.db.models.PolygonField`. + +.. django-admin-option:: --name-field + + Generates a ``__unicode__`` routine on the model that will return the + the given field name. + +.. django-admin-option:: --no-imports + + Suppresses the ``from django.contrib.gis.db import models`` import statement. + +.. django-admin-option:: --null + + Use a comma separated list of OGR field names to add the ``null=True`` + keyword option to the field definition. Set with ``true`` to apply to + all applicable fields. + +.. django-admin-option:: --srid + + The SRID to use for the geometry field. If not set, ``ogrinspect`` attempts + to automatically determine of the SRID of the data source. diff --git a/docs/ref/contrib/gis/create_template_postgis-1.3.sh b/docs/ref/contrib/gis/create_template_postgis-1.3.sh new file mode 100755 index 0000000000..c9ab4fcebf --- /dev/null +++ b/docs/ref/contrib/gis/create_template_postgis-1.3.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +POSTGIS_SQL_PATH=`pg_config --sharedir` +createdb -E UTF8 template_postgis # Create the template spatial database. +createlang -d template_postgis plpgsql # Adding PLPGSQL language support. +psql -d postgres -c "UPDATE pg_database SET datistemplate='true' WHERE datname='template_postgis';" +psql -d template_postgis -f $POSTGIS_SQL_PATH/lwpostgis.sql # Loading the PostGIS SQL routines +psql -d template_postgis -f $POSTGIS_SQL_PATH/spatial_ref_sys.sql +psql -d template_postgis -c "GRANT ALL ON geometry_columns TO PUBLIC;" # Enabling users to alter spatial tables. +psql -d template_postgis -c "GRANT ALL ON spatial_ref_sys TO PUBLIC;" diff --git a/docs/ref/contrib/gis/create_template_postgis-1.4.sh b/docs/ref/contrib/gis/create_template_postgis-1.4.sh new file mode 100755 index 0000000000..74a6ef98d2 --- /dev/null +++ b/docs/ref/contrib/gis/create_template_postgis-1.4.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +POSTGIS_SQL_PATH=`pg_config --sharedir`/contrib/postgis-1.4 +createdb -E UTF8 template_postgis # Create the template spatial database. +createlang -d template_postgis plpgsql # Adding PLPGSQL language support. +psql -d postgres -c "UPDATE pg_database SET datistemplate='true' WHERE datname='template_postgis';" +psql -d template_postgis -f $POSTGIS_SQL_PATH/postgis.sql # Loading the PostGIS SQL routines +psql -d template_postgis -f $POSTGIS_SQL_PATH/spatial_ref_sys.sql +psql -d template_postgis -c "GRANT ALL ON geometry_columns TO PUBLIC;" # Enabling users to alter spatial tables. +psql -d template_postgis -c "GRANT ALL ON spatial_ref_sys TO PUBLIC;" diff --git a/docs/ref/contrib/gis/create_template_postgis-1.5.sh b/docs/ref/contrib/gis/create_template_postgis-1.5.sh new file mode 100755 index 0000000000..88c1e84aaf --- /dev/null +++ b/docs/ref/contrib/gis/create_template_postgis-1.5.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +POSTGIS_SQL_PATH=`pg_config --sharedir`/contrib/postgis-1.5 +createdb -E UTF8 template_postgis # Create the template spatial database. +createlang -d template_postgis plpgsql # Adding PLPGSQL language support. +psql -d postgres -c "UPDATE pg_database SET datistemplate='true' WHERE datname='template_postgis';" +psql -d template_postgis -f $POSTGIS_SQL_PATH/postgis.sql # Loading the PostGIS SQL routines +psql -d template_postgis -f $POSTGIS_SQL_PATH/spatial_ref_sys.sql +psql -d template_postgis -c "GRANT ALL ON geometry_columns TO PUBLIC;" # Enabling users to alter spatial tables. +psql -d template_postgis -c "GRANT ALL ON spatial_ref_sys TO PUBLIC;" diff --git a/docs/ref/contrib/gis/create_template_postgis-debian.sh b/docs/ref/contrib/gis/create_template_postgis-debian.sh new file mode 100755 index 0000000000..46bd074ff6 --- /dev/null +++ b/docs/ref/contrib/gis/create_template_postgis-debian.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +POSTGIS_SQL_PATH=/usr/share/postgresql-8.3-postgis +createdb -E UTF8 template_postgis # Create the template spatial database. +createlang -d template_postgis plpgsql # Adding PLPGSQL language support. +psql -d postgres -c "UPDATE pg_database SET datistemplate='true' WHERE datname='template_postgis';" +psql -d template_postgis -f $POSTGIS_SQL_PATH/lwpostgis.sql # Loading the PostGIS SQL routines +psql -d template_postgis -f $POSTGIS_SQL_PATH/spatial_ref_sys.sql +psql -d template_postgis -c "GRANT ALL ON geometry_columns TO PUBLIC;" # Enabling users to alter spatial tables. +psql -d template_postgis -c "GRANT ALL ON spatial_ref_sys TO PUBLIC;" diff --git a/docs/ref/contrib/gis/db-api.txt b/docs/ref/contrib/gis/db-api.txt new file mode 100644 index 0000000000..017c9ec142 --- /dev/null +++ b/docs/ref/contrib/gis/db-api.txt @@ -0,0 +1,304 @@ +.. _ref-gis-db-api: + +====================== +GeoDjango Database API +====================== + +.. module:: django.contrib.gis.db.models + :synopsis: GeoDjango's database API. + +.. _spatial-backends: + +Spatial Backends +================ + +.. versionadded:: 1.2 + +In Django 1.2, support for :ref:`multiple databases ` was +introduced. In order to support multiple databases, GeoDjango has segregated +its functionality into full-fledged spatial database backends: + +* :mod:`django.contrib.gis.db.backends.postgis` +* :mod:`django.contrib.gis.db.backends.mysql` +* :mod:`django.contrib.gis.db.backends.oracle` +* :mod:`django.contrib.gis.db.backends.spatialite` + +Backwards-Compatibility +----------------------- + +For those using the old database settings (e.g., the ``DATABASE_*`` settings) +Django 1.2 will automatically use the appropriate spatial backend as long +as :mod:`django.contrib.gis` is in your :setting:`INSTALLED_APPS`. For +example, if you have the following in your settings:: + + DATABASE_ENGINE='postgresql_psycopg2' + + ... + + INSTALLED_APPS = ( + ... + 'django.contrib.gis', + ... + ) + +Then, :mod:`django.contrib.gis.db.backends.postgis` will automatically be used as your +spatial backend. + +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() + +:class:`~django.contrib.gis.geos.GEOSGeometry` objects may also be used to save geometric models:: + + >>> from django.contrib.gis.geos import GEOSGeometry + >>> poly = GEOSGeometry('POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))') + >>> z = Zipcode(code=77096, poly=poly) + >>> 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 [#fnwkt]_), HEXEWKB (PostGIS specific -- a WKB geometry in +hexadecimal [#fnewkb]_), and GeoJSON [#fngeojson]_ (requires GDAL). Essentially, +if the input is not a ``GEOSGeometry`` object, the geometry field will attempt to +create a ``GEOSGeometry`` instance from the input. + +For more information creating :class:`~django.contrib.gis.geos.GEOSGeometry` +objects, refer to the :ref:`GEOS tutorial `. + +.. _spatial-lookups-intro: + +Spatial Lookups +=============== + +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 on geometry fields. +Filters on 'normal' fields (e.g. :class:`~django.db.models.CharField`) +may be chained with those on geographic fields. Thus, geographic queries +take the following general form (assuming the ``Zipcode`` model used in the +:ref:`ref-gis-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, :lookup:`contains ` +is the spatial lookup type, and ``pnt`` is the parameter (which may be a +:class:`~django.contrib.gis.geos.GEOSGeometry` object or a string of +GeoJSON , WKT, or HEXEWKB). + +A complete reference can be found in the :ref:`spatial lookup reference +`. + +.. note:: + + GeoDjango constructs spatial SQL with the :class:`GeoQuerySet`, a + subclass of :class:`~django.db.models.QuerySet`. The + :class:`GeoManager` instance attached to your model is what + enables use of :class:`GeoQuerySet`. + +.. _distance-queries: + +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 :ref:`selecting-an-srid` section +in the :ref:`ref-gis-model-api` documentation for more details. + +.. _distance-lookups-intro: + +Distance Lookups +---------------- +*Availability*: PostGIS, Oracle, SpatiaLite + +The following distance lookups are available: + +* :lookup:`distance_lt` +* :lookup:`distance_lte` +* :lookup:`distance_gt` +* :lookup:`distance_gte` +* :lookup:`dwithin` + +.. note:: + + For *measuring*, rather than querying on distances, use the + :meth:`GeoQuerySet.distance` method. + +Distance lookups take a tuple parameter comprising: + +#. A geometry to base calculations from; and +#. A number or :class:`~django.contrib.gis.measure.Distance` object containing the distance. + +If a :class:`~django.contrib.gis.measure.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 are 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 [#fndistsphere]_. Thus, + geographic distance lookups on traditional PostGIS geometry columns are + only allowed on :class:`PointField` model fields using a point for the + geometry parameter. + +.. note:: + + PostGIS 1.5 introduced :ref:`geography columns `, which + is limited on what geometry types distance queries are performed with. In + other words, if you have ``geography=True`` in your geometry field + definition you'll be allowed to peform arbitrary distance queries with your + data in geodetic units of WGS84. + + +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 + +.. _compatibility-table: + +Compatibility Tables +==================== + +.. _spatial-lookup-compatibility: + +Spatial Lookups +--------------- + +The following table provides a summary of what spatial lookups are available +for each spatial database backend. + +================================= ========= ======== ============ ========== +Lookup Type PostGIS Oracle MySQL [#]_ SpatiaLite +================================= ========= ======== ============ ========== +:lookup:`bbcontains` X X X +:lookup:`bboverlaps` X X X +:lookup:`contained` X X X +:lookup:`contains ` X X X X +:lookup:`contains_properly` X +:lookup:`coveredby` X X +:lookup:`covers` X X +:lookup:`crosses` X X +:lookup:`disjoint` X X X X +:lookup:`distance_gt` X X X +:lookup:`distance_gte` X X X +:lookup:`distance_lt` X X X +:lookup:`distance_lte` X X X +:lookup:`dwithin` X X +:lookup:`equals` X X X X +:lookup:`exact` X X X X +:lookup:`intersects` X X X X +:lookup:`overlaps` X X X X +:lookup:`relate` X X X +:lookup:`same_as` X X X X +:lookup:`touches` X X X X +:lookup:`within` X X X X +:lookup:`left` X +:lookup:`right` X +:lookup:`overlaps_left` X +:lookup:`overlaps_right` X +:lookup:`overlaps_above` X +:lookup:`overlaps_below` X +:lookup:`strictly_above` X +:lookup:`strictly_below` X +================================= ========= ======== ============ ========== + +.. _geoqueryset-method-compatibility: + +``GeoQuerySet`` Methods +----------------------- +The following table provides a summary of what :class:`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 +==================================== ======= ====== ========== +:meth:`GeoQuerySet.area` X X X +:meth:`GeoQuerySet.centroid` X X X +:meth:`GeoQuerySet.collect` X +:meth:`GeoQuerySet.difference` X X X +:meth:`GeoQuerySet.distance` X X X +:meth:`GeoQuerySet.envelope` X X +:meth:`GeoQuerySet.extent` X X +:meth:`GeoQuerySet.extent3d` X +:meth:`GeoQuerySet.force_rhr` X +:meth:`GeoQuerySet.geohash` X +:meth:`GeoQuerySet.geojson` X +:meth:`GeoQuerySet.gml` X X +:meth:`GeoQuerySet.intersection` X X X +:meth:`GeoQuerySet.kml` X +:meth:`GeoQuerySet.length` X X X +:meth:`GeoQuerySet.make_line` X +:meth:`GeoQuerySet.mem_size` X +:meth:`GeoQuerySet.num_geom` X X X +:meth:`GeoQuerySet.num_points` X X X +:meth:`GeoQuerySet.perimeter` X X +:meth:`GeoQuerySet.point_on_surface` X X X +:meth:`GeoQuerySet.reverse_geom` X X +:meth:`GeoQuerySet.scale` X X +:meth:`GeoQuerySet.snap_to_grid` X +:meth:`GeoQuerySet.svg` X X +:meth:`GeoQuerySet.sym_difference` X X X +:meth:`GeoQuerySet.transform` X X X +:meth:`GeoQuerySet.translate` X X +:meth:`GeoQuerySet.union` X X X +:meth:`GeoQuerySet.unionagg` X X X +==================================== ======= ====== ========== + +.. rubric:: Footnotes +.. [#fnwkt] *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). +.. [#fnewkb] *See* `PostGIS EWKB, EWKT and Canonical Forms `_, PostGIS documentation at Ch. 4.1.2. +.. [#fngeojson] *See* Howard Butler, Martin Daly, Allan Doyle, Tim Schaub, & Christopher Schmidt, `The GeoJSON Format Specification `_, Revision 1.0 (June 16, 2008). +.. [#fndistsphere] *See* PostGIS 1.5 ``ST_distance_sphere`` `documentation `_. +.. [#] MySQL only supports bounding box operations (known as minimum bounding rectangles, or MBR, in MySQL). Thus, spatial lookups such as :lookup:`contains ` are really equivalent to :lookup:`bbcontains`. diff --git a/docs/ref/contrib/gis/deployment.txt b/docs/ref/contrib/gis/deployment.txt new file mode 100644 index 0000000000..2cfd367fac --- /dev/null +++ b/docs/ref/contrib/gis/deployment.txt @@ -0,0 +1,99 @@ +=================== +Deploying GeoDjango +=================== + +.. warning:: + + GeoDjango uses the GDAL geospatial library which is + not thread safe at this time. Thus, it is *highly* recommended + to not use threading when deploying -- in other words, use a + an appropriate configuration of Apache or the prefork method + when using FastCGI through another web server. + +Apache +====== +In this section there are some example ``VirtualHost`` directives for +when deploying using either ``mod_python`` or ``mod_wsgi``. At this +time, we recommend ``mod_wsgi``, as it is now officially recommended +way to deploy Django applications with Apache. Moreover, if +``mod_python`` is used, then a prefork version of Apache must also be +used. As long as ``mod_wsgi`` is configured correctly, it does not +matter whether the version of Apache is prefork or worker. + +.. note:: + + The ``Alias`` and ``Directory`` configurations in the the examples + below use an example path to a system-wide installation folder of Django. + Substitute in an appropriate location, if necessary, as it may be + different than the path on your system. + +``mod_wsgi`` +------------ + +Example:: + + + WSGIDaemonProcess geodjango user=geo group=geo processes=5 threads=1 + WSGIProcessGroup geodjango + WSGIScriptAlias / /home/geo/geodjango/world.wsgi + + Alias /media/ "/usr/lib/python2.5/site-packages/django/contrib/admin/media/" + + Order allow,deny + Options Indexes + Allow from all + IndexOptions FancyIndexing + + + + +.. warning:: + + If the ``WSGIDaemonProcess`` attribute ``threads`` is not set to ``1``, then + Apache may crash when running your GeoDjango application. Increase the + number of ``processes`` instead. + +For more information, please consult Django's +:ref:`mod_wsgi documentation `. + +``mod_python`` +-------------- + +Example:: + + + + + SetHandler mod_python + PythonHandler django.core.handlers.modpython + SetEnv DJANGO_SETTINGS_MODULE world.settings + PythonDebug On + PythonPath "['/var/www/apps'] + sys.path" + + + Alias /media/ "/usr/lib/python2.5/site-packages/django/contrib/admin/media/" + + SetHandler None + + + + +.. warning:: + + When using ``mod_python`` you *must* be using a prefork version of Apache, or + else your GeoDjango application may crash Apache. + +For more information, please consult Django's +:ref:`mod_python documentation `. + +Lighttpd +======== + +FastCGI +------- + +Nginx +===== + +FastCGI +------- diff --git a/docs/ref/contrib/gis/feeds.txt b/docs/ref/contrib/gis/feeds.txt new file mode 100644 index 0000000000..bb9c12ae5d --- /dev/null +++ b/docs/ref/contrib/gis/feeds.txt @@ -0,0 +1,97 @@ +.. _ref-gis-feeds: + +================ +Geographic Feeds +================ + +.. module:: django.contrib.gis.feeds + :synopsis: GeoDjango's framework for generating spatial feeds. + +GeoDjango has its own :class:`Feed` subclass that may embed location information +in RSS/Atom feeds formatted according to either the `Simple GeoRSS`__ or +`W3C Geo`_ standards. Because GeoDjango's syndication API is a superset of +Django's, please consult `Django's syndication documentation ` +for details on general usage. + +.. _W3C Geo: http://www.w3.org/2003/01/geo/ + +__ http://georss.org/1.0#simple + +Example +======= + +API Reference +============= + +``Feed`` Subclass +----------------- + +.. class:: Feed + + In addition to methods provided by + the :class:`django.contrib.syndication.feeds.Feed` + base class, GeoDjango's ``Feed`` class provides + the following overrides. Note that these overrides may be done in multiple ways:: + + from django.contrib.gis.feeds import Feed + + class MyFeed(Feed): + + # First, as a class attribute. + geometry = ... + item_geometry = ... + + # Also a function with no arguments + def geometry(self): + ... + + def item_geometry(self): + ... + + # And as a function with a single argument + def geometry(self, obj): + ... + + def item_geometry(self, item): + ... + + .. method:: geometry(obj) + + Takes the object returned by ``get_object()`` and returns the *feed's* + geometry. Typically this is a ``GEOSGeometry`` instance, or can be a + tuple to represent a point or a box. For example:: + + class ZipcodeFeed(Feed): + + def geometry(self, obj): + # Can also return: `obj.poly`, and `obj.poly.centroid`. + return obj.poly.extent # tuple like: (X0, Y0, X1, Y1). + + .. method:: item_geometry(item) + + Set this to return the geometry for each *item* in the feed. This + can be a ``GEOSGeometry`` instance, or a tuple that represents a + point coordinate or bounding box. For example:: + + class ZipcodeFeed(Feed): + + def item_geometry(self, obj): + # Returns the polygon. + return obj.poly + +``SyndicationFeed`` Subclasses +------------------------------ + +The following :class:`django.utils.feedgenerator.SyndicationFeed` subclasses +are available: + +.. class:: GeoRSSFeed + +.. class:: GeoAtom1Feed + +.. class:: W3CGeoFeed + +.. note:: + + `W3C Geo`_ formatted feeds only support + :class:`~django.contrib.gis.db.models.PointField` geometries. diff --git a/docs/ref/contrib/gis/gdal.txt b/docs/ref/contrib/gis/gdal.txt new file mode 100644 index 0000000000..1ce21d9dd5 --- /dev/null +++ b/docs/ref/contrib/gis/gdal.txt @@ -0,0 +1,1114 @@ +.. _ref-gdal: + +======== +GDAL API +======== + +.. module:: django.contrib.gis.gdal + :synopsis: GeoDjango's high-level interface to the GDAL library. + +`GDAL`__ stands for **G**\ eospatial **D**\ ata **A**\ bstraction **L**\ ibrary, +and is a veritable "swiss army knife" of GIS data functionality. A subset +of GDAL is the `OGR`__ Simple Features Library, which specializes +in reading and writing vector geographic data in a variety of standard +formats. + +GeoDjango provides a high-level Python interface for some of the +capabilities of OGR, including the reading and coordinate transformation +of vector spatial data. + +.. note:: + + Although the module is named ``gdal``, GeoDjango only supports + some of the capabilities of OGR. Thus, none of GDAL's features + with respect to raster (image) data are supported at this time. + +__ http://www.gdal.org/ +__ http://www.gdal.org/ogr/ + +Overview +======== + +Sample Data +----------- + +The GDAL/OGR tools described here are designed to help you read in +your geospatial data, in order for most of them to be useful you have +to have some data to work with. If you're starting out and don't yet +have any data of your own to use, GeoDjango comes with a number of +simple data sets that you can use for testing. This snippet will +determine where these sample files are installed on your computer:: + + >>> import os + >>> import django.contrib.gis + >>> GIS_PATH = os.path.dirname(django.contrib.gis.__file__) + >>> CITIES_PATH = os.path.join(GIS_PATH, 'tests/data/cities/cities.shp') + +Vector Data Source Objects +========================== + +``DataSource`` +-------------- + +:class:`DataSource` is a wrapper for the OGR data source object that +supports reading data from a variety of OGR-supported geospatial file +formats and data sources using a simple, consistent interface. Each +data source is represented by a :class:`DataSource` object which contains +one or more layers of data. Each layer, represented by a :class:`Layer` +object, contains some number of geographic features (:class:`Feature`), +information about the type of features contained in that layer (e.g. +points, polygons, etc.), as well as the names and types of any +additional fields (:class:`Field`) of data that may be associated with +each feature in that layer. + +.. class:: DataSource(ds_input) + + The constructor for ``DataSource`` just a single parameter: the path of + the file you want to read. However, OGR + also supports a variety of more complex data sources, including + databases, that may be accessed by passing a special name string instead + of a path. For more information, see the `OGR Vector Formats`__ + documentation. The :attr:`name` property of a ``DataSource`` + instance gives the OGR name of the underlying data source that it is + using. + + Once you've created your ``DataSource``, you can find out how many + layers of data it contains by accessing the :attr:`layer_count` property, + or (equivalently) by using the ``len()`` function. For information on + accessing the layers of data themselves, see the next section:: + + >>> from django.contrib.gis.gdal import DataSource + >>> ds = DataSource(CITIES_PATH) + >>> ds.name # The exact filename may be different on your computer + '/usr/local/lib/python2.6/site-packages/django/contrib/gis/tests/data/cities/cities.shp' + >>> ds.layer_count # This file only contains one layer + 1 + + .. attribute:: layer_count + + Returns the number of layers in the data source. + + .. attribute:: name + + Returns the name of the data source. + +__ http://www.gdal.org/ogr/ogr_formats.html + +``Layer`` +--------- + +.. class:: Layer + + ``Layer`` is a wrapper for a layer of data in a ``DataSource`` object. + You never create a ``Layer`` object directly. Instead, you retrieve + them from a :class:`DataSource` object, which is essentially a standard + Python container of ``Layer`` objects. For example, you can access a + specific layer by its index (e.g. ``ds[0]`` to access the first + layer), or you can iterate over all the layers in the container in a + ``for`` loop. The ``Layer`` itself acts as a container for geometric + features. + + Typically, all the features in a given layer have the same geometry type. + The :attr:`geom_type` property of a layer is an :class:`OGRGeomType` + that identifies the feature type. We can use it to print out some basic + information about each layer in a :class:`DataSource`:: + + >>> for layer in ds: + ... print 'Layer "%s": %i %ss' % (layer.name, len(layer), layer.geom_type.name) + ... + Layer "cities": 3 Points + + The example output is from the cities data source, loaded above, which + evidently contains one layer, called ``"cities"``, which contains three + point features. For simplicity, the examples below assume that you've + stored that layer in the variable ``layer``:: + + >>> layer = ds[0] + + .. attribute:: name + + Returns the name of this layer in the data source. + + >>> layer.name + 'cities' + + .. attribute:: num_feat + + Returns the number of features in the layer. Same as ``len(layer)``:: + + >>> layer.num_feat + 3 + + .. attribute:: geom_type + + Returns the geometry type of the layer, as an :class:`OGRGeomType` + object:: + + >>> layer.geom_type.name + 'Point' + + .. attribute:: num_fields + + Returns the number of fields in the layer, i.e the number of fields of + data associated with each feature in the layer:: + + >>> layer.num_fields + 4 + + .. attribute:: fields + + Returns a list of the names of each of the fields in this layer:: + + >>> layer.fields + ['Name', 'Population', 'Density', 'Created'] + + .. attribute field_types + + Returns a list of the data types of each of the fields in this layer. + These are subclasses of ``Field``, discussed below:: + + >>> [ft.__name__ for ft in layer.field_types] + ['OFTString', 'OFTReal', 'OFTReal', 'OFTDate'] + + .. attribute:: field_widths + + Returns a list of the maximum field widths for each of the fields in + this layer:: + + >>> layer.field_widths + [80, 11, 24, 10] + + .. attribute:: field_precisions + + Returns a list of the numeric precisions for each of the fields in + this layer. This is meaningless (and set to zero) for non-numeric + fields:: + + >>> layer.field_precisions + [0, 0, 15, 0] + + .. attribute:: extent + + Returns the spatial extent of this layer, as an :class:`Envelope` + object:: + + >>> layer.extent.tuple + (-104.609252, 29.763374, -95.23506, 38.971823) + + .. attribute:: srs + + Property that returns the :class:`SpatialReference` associated + with this layer:: + + >>> print layer.srs + GEOGCS["GCS_WGS_1984", + DATUM["WGS_1984", + SPHEROID["WGS_1984",6378137,298.257223563]], + PRIMEM["Greenwich",0], + UNIT["Degree",0.017453292519943295]] + + If the :class:`Layer` has no spatial reference information associated + with it, ``None`` is returned. + + .. attribute:: spatial_filter + + .. versionadded:: 1.2 + + Property that may be used to retrieve or set a spatial filter for this + layer. A spatial filter can only be set with an :class:`OGRGeometry` + instance, a 4-tuple extent, or ``None``. When set with something + other than ``None``, only features that intersect the filter will be + returned when iterating over the layer:: + + >>> print layer.spatial_filter + None + >>> print len(layer) + 3 + >>> [feat.get('Name') for feat in layer] + ['Pueblo', 'Lawrence', 'Houston'] + >>> ks_extent = (-102.051, 36.99, -94.59, 40.00) # Extent for state of Kansas + >>> layer.spatial_filter = ks_extent + >>> len(layer) + 1 + >>> [feat.get('Name') for feat in layer] + ['Lawrence'] + >>> layer.spatial_filter = None + >>> len(layer) + 3 + + .. method:: get_fields() + + A method that returns a list of the values of a given field for each + feature in the layer:: + + >>> layer.get_fields('Name') + ['Pueblo', 'Lawrence', 'Houston'] + + .. method:: get_geoms([geos=False]) + + A method that returns a list containing the geometry of each feature + in the layer. If the optional argument ``geos`` is set to ``True`` + then the geometries are converted to :class:`~django.contrib.gis.geos.GEOSGeometry` + objects. Otherwise, they are returned as :class:`OGRGeometry` objects:: + + >>> [pt.tuple for pt in layer.get_geoms()] + [(-104.609252, 38.255001), (-95.23506, 38.971823), (-95.363151, 29.763374)] + + .. method:: test_capability(capability) + + Returns a boolean indicating whether this layer supports the + given capability (a string). Examples of valid capability strings + include: ``'RandomRead'``, ``'SequentialWrite'``, ``'RandomWrite'``, + ``'FastSpatialFilter'``, ``'FastFeatureCount'``, ``'FastGetExtent'``, + ``'CreateField'``, ``'Transactions'``, ``'DeleteFeature'``, and + ``'FastSetNextByIndex'``. + +``Feature`` +----------- + +.. class:: Feature + + + ``Feature`` wraps an OGR feature. You never create a ``Feature`` + object directly. Instead, you retrieve them from a :class:`Layer` object. + Each feature consists of a geometry and a set of fields containing + additional properties. The geometry of a field is accessible via its + ``geom`` property, which returns an :class:`OGRGeometry` object. A ``Feature`` + behaves like a standard Python container for its fields, which it returns as + :class:`Field` objects: you can access a field directly by its index or name, + or you can iterate over a feature's fields, e.g. in a ``for`` loop. + + .. attribute:: geom + + Returns the geometry for this feature, as an ``OGRGeometry`` object:: + + >>> city.geom.tuple + (-104.609252, 38.255001) + + .. attribute:: get + + A method that returns the value of the given field (specified by name) + for this feature, **not** a ``Field`` wrapper object:: + + >>> city.get('Population') + 102121 + + .. attribute:: geom_type + + Returns the type of geometry for this feature, as an :class:`OGRGeomType` + object. This will be the same for all features in a given layer, and + is equivalent to the :attr:`Layer.geom_type` property of the + :class:`Layer`` object the feature came from. + + .. attribute:: num_fields + + Returns the number of fields of data associated with the feature. + This will be the same for all features in a given layer, and is + equivalent to the :attr:`Layer.num_fields` property of the + :class:`Layer` object the feature came from. + + .. attribute:: fields + + Returns a list of the names of the fields of data associated with the + feature. This will be the same for all features in a given layer, and + is equivalent to the :attr:`Layer.fields` property of the :class:`Layer` + object the feature came from. + + .. attribute:: fid + + Returns the feature identifier within the layer:: + + >>> city.fid + 0 + + .. attribute:: layer_name + + Returns the name of the :class:`Layer` that the feature came from. + This will be the same for all features in a given layer:: + + >>> city.layer_name + 'cities' + + .. attribute:: index + + A method that returns the index of the given field name. This will be + the same for all features in a given layer:: + + >>> city.index('Population') + 1 + +``Field`` +--------- + +.. class:: Field + + .. attribute:: name + + Returns the name of this field:: + + >>> city['Name'].name + 'Name' + + .. attribute:: type + + Returns the OGR type of this field, as an integer. The + ``FIELD_CLASSES`` dictionary maps these values onto + subclasses of ``Field``:: + + >>> city['Density'].type + 2 + + .. attribute:: type_name + + Returns a string with the name of the data type of this field:: + + >>> city['Name'].type_name + 'String' + + .. attribute:: value + + Returns the value of this field. The ``Field`` class itself + returns the value as a string, but each subclass returns the + value in the most appropriate form:: + + >>> city['Population'].value + 102121 + + .. attribute:: width + + Returns the width of this field:: + + >>> city['Name'].width + 80 + + .. attribute:: precision + + Returns the numeric precision of this field. This is meaningless (and + set to zero) for non-numeric fields:: + + >>> city['Density'].precision + 15 + + .. method:: as_double() + + Returns the value of the field as a double (float):: + + >>> city['Density'].as_double() + 874.7 + + .. method:: as_int() + + Returns the value of the field as an integer:: + + >>> city['Population'].as_int() + 102121 + + .. method:: as_string() + + Returns the value of the field as a string:: + + >>> city['Name'].as_string() + 'Pueblo' + + .. method:: as_datetime() + + Returns the value of the field as a tuple of date and time components:: + + >>> city['Created'].as_datetime() + (c_long(1999), c_long(5), c_long(23), c_long(0), c_long(0), c_long(0), c_long(0)) + +``Driver`` +---------- + +.. class:: Driver(dr_input) + + The ``Driver`` class is used internally to wrap an OGR :class:`DataSource` driver. + + .. attribute:: driver_count + + Returns the number of OGR vector drivers currently registered. + + +OGR Geometries +============== + +``OGRGeometry`` +--------------- + +:class:`OGRGeometry` objects share similar functionality with +:class:`~django.contrib.gis.geos.GEOSGeometry` objects, and are thin +wrappers around OGR's internal geometry representation. Thus, +they allow for more efficient access to data when using :class:`DataSource`. +Unlike its GEOS counterpart, :class:`OGRGeometry` supports spatial reference +systems and coordinate transformation:: + + >>> from django.contrib.gis.gdal import OGRGeometry + >>> polygon = OGRGeometry('POLYGON((0 0, 5 0, 5 5, 0 5))') + +.. class:: OGRGeometry(geom_input[, srs=None]) + + This object is a wrapper for the `OGR Geometry`__ class. + These objects are instantiated directly from the given ``geom_input`` + parameter, which may be a string containing WKT or HEX, a ``buffer`` + containing WKB data, or an :class:`OGRGeomType` object. These objects + are also returned from the :class:`Feature.geom` attribute, when + reading vector data from :class:`Layer` (which is in turn a part of + a :class:`DataSource`). + + __ http://www.gdal.org/ogr/classOGRGeometry.html + + .. classmethod:: from_bbox(bbox) + + .. versionadded:: 1.1 + + Constructs a :class:`Polygon` from the given bounding-box (a 4-tuple). + + .. method:: __len__ + + Returns the number of points in a :class:`LineString`, the + number of rings in a :class:`Polygon`, or the number of geometries in a + :class:`GeometryCollection`. Not applicable to other geometry types. + + .. method:: __iter__ + + Iterates over the points in a :class:`LineString`, the rings in a + :class:`Polygon`, or the geometries in a :class:`GeometryCollection`. + Not applicable to other geometry types. + + .. method:: __getitem__ + + Returns the point at the specified index for a :class:`LineString`, the + interior ring at the specified index for a :class:`Polygon`, or the geometry + at the specified index in a :class:`GeometryCollection`. Not applicable to + other geometry types. + + .. attribute:: dimension + + Returns the number of coordinated dimensions of the geometry, i.e. 0 + for points, 1 for lines, and so forth:: + + >> polygon.dimension + 2 + + .. attribute:: coord_dim + + .. versionchanged:: 1.2 + + Returns or sets the coordinate dimension of this geometry. For + example, the value would be 2 for two-dimensional geometries. + + .. note:: + + Setting this property is only available in versions 1.2 and above. + + .. attribute:: geom_count + + Returns the number of elements in this geometry:: + + >>> polygon.geom_count + 1 + + .. attribute:: point_count + + Returns the number of points used to describe this geometry:: + + >>> polygon.point_count + 4 + + .. attribute:: num_points + + Alias for :attr:`point_count`. + + .. attribute:: num_coords + + Alias for :attr:`point_count`. + + .. attribute:: geom_type + + Returns the type of this geometry, as an :class:`OGRGeomType` object. + + .. attribute:: geom_name + + Returns the name of the type of this geometry:: + + >>> polygon.geom_name + 'POLYGON' + + .. attribute:: area + + Returns the area of this geometry, or 0 for geometries that do not + contain an area:: + + >>> polygon.area + 25.0 + + .. attribute:: envelope + + Returns the envelope of this geometry, as an :class:`Envelope` object. + + .. attribute:: extent + + Returns the envelope of this geometry as a 4-tuple, instead of as an + :class:`Envelope` object:: + + >>> point.extent + (0.0, 0.0, 5.0, 5.0) + + .. attribute:: srs + + This property controls the spatial reference for this geometry, or + ``None`` if no spatial reference system has been assigned to it. + If assigned, accessing this property returns a :class:`SpatialReference` + object. It may be set with another :class:`SpatialReference` object, + or any input that :class:`SpatialReference` accepts. Example:: + + >>> city.geom.srs.name + 'GCS_WGS_1984' + + .. attribute:: srid + + Returns or sets the spatial reference identifier corresponding to + :class:`SpatialReference` of this geometry. Returns ``None`` if + there is no spatial reference information associated with this + geometry, or if an SRID cannot be determined. + + .. attribute:: geos + + Returns a :class:`~django.contrib.gis.geos.GEOSGeometry` object + corresponding to this geometry. + + .. attribute:: gml + + Returns a string representation of this geometry in GML format:: + + >>> OGRGeometry('POINT(1 2)').gml + '1,2' + + .. attribute:: hex + + Returns a string representation of this geometry in HEX WKB format:: + + >>> OGRGeometry('POINT(1 2)').hex + '0101000000000000000000F03F0000000000000040' + + .. attribute:: json + + Returns a string representation of this geometry in JSON format:: + + >>> OGRGeometry('POINT(1 2)').json + '{ "type": "Point", "coordinates": [ 1.000000, 2.000000 ] }' + + + .. attribute:: kml + + .. versionadded:: 1.1 + + Returns a string representation of this geometry in KML format. + + .. attribute:: wkb_size + + Returns the size of the WKB buffer needed to hold a WKB representation + of this geometry:: + + >>> OGRGeometry('POINT(1 2)').wkb_size + 21 + + .. attribute:: wkb + + Returns a ``buffer`` containing a WKB representation of this geometry. + + .. attribute:: wkt + + Returns a string representation of this geometry in WKT format. + + .. attribute:: ewkt + + .. versionadded:: 1.2 + + Returns the EWKT representation of this geometry. + + .. method:: clone() + + Returns a new :class:`OGRGeometry` clone of this geometry object. + + .. method:: close_rings() + + If there are any rings within this geometry that have not been closed, + this routine will do so by adding the starting point to the end:: + + >>> triangle = OGRGeometry('LINEARRING (0 0,0 1,1 0)') + >>> triangle.close_rings() + >>> triangle.wkt + 'LINEARRING (0 0,0 1,1 0,0 0)' + + .. method:: transform(coord_trans, clone=False) + + Transforms this geometry to a different spatial reference system. May + take a :class:`CoordTransform` object, a :class:`SpatialReference` object, + or any other input accepted by :class:`SpatialReference` (including + spatial reference WKT and PROJ.4 strings, or an integer SRID). + By default nothing is returned and the geometry is transformed in-place. + However, if the `clone` keyword is set to ``True`` then a transformed clone + of this geometry is returned instead. + + .. method:: intersects(other) + + Returns ``True`` if this geometry intersects the other, otherwise returns + ``False``. + + .. method:: equals(other) + + Returns ``True`` if this geometry is equivalent to the other, otherwise returns + ``False``. + + .. method:: disjoint(other) + + Returns ``True`` if this geometry is spatially disjoint to (i.e. does + not intersect) the other, otherwise returns ``False``. + + .. method:: touches(other) + + Returns ``True`` if this geometry touches the other, otherwise returns + ``False``. + + .. method:: crosses(other) + + Returns ``True`` if this geometry crosses the other, otherwise returns + ``False``. + + .. method:: within(other) + + Returns ``True`` if this geometry is contained within the other, otherwise returns + ``False``. + + .. method:: contains(other) + + Returns ``True`` if this geometry contains the other, otherwise returns + ``False``. + + .. method:: overlaps(other) + + Returns ``True`` if this geometry overlaps the other, otherwise returns + ``False``. + + .. method:: boundary + + The boundary of this geometry, as a new :class:`OGRGeometry` object. + + .. attribute:: convex_hull + + The smallest convex polygon that contains this geometry, as a new + :class:`OGRGeometry` object. + + .. method:: difference + + Returns the region consisting of the difference of this geometry and + the other, as a new :class:`OGRGeometry` object. + + .. method:: intersection + + Returns the region consisting of the intersection of this geometry and + the other, as a new :class:`OGRGeometry` object. + + .. method:: sym_difference + + Returns the region consisting of the symmetric difference of this + geometry and the other, as a new :class:`OGRGeometry` object. + + .. method:: union + + Returns the region consisting of the union of this geometry and + the other, as a new :class:`OGRGeometry` object. + + .. attribute:: tuple + + Returns the coordinates of a point geometry as a tuple, the + coordinates of a line geometry as a tuple of tuples, and so forth:: + + >>> OGRGeometry('POINT (1 2)').tuple + (1.0, 2.0) + >>> OGRGeometry('LINESTRING (1 2,3 4)').tuple + ((1.0, 2.0), (3.0, 4.0)) + + .. attribute:: coords + + An alias for :attr:`tuple`. + +.. class:: Point + + .. attribute:: x + + Returns the X coordinate of this point:: + + >>> OGRGeometry('POINT (1 2)').x + 1.0 + + .. attribute:: y + + Returns the Y coordinate of this point:: + + >>> OGRGeometry('POINT (1 2)').y + 2.0 + + .. attribute:: z + + Returns the Z coordinate of this point, or ``None`` if the + the point does not have a Z coordinate:: + + >>> OGRGeometry('POINT (1 2 3)').z + 3.0 + +.. class:: LineString + + .. attribute:: x + + Returns a list of X coordinates in this line:: + + >>> OGRGeometry('LINESTRING (1 2,3 4)').x + [1.0, 3.0] + + .. attribute:: y + + Returns a list of Y coordinates in this line:: + + >>> OGRGeometry('LINESTRING (1 2,3 4)').y + [2.0, 4.0] + + .. attribute:: z + + Returns a list of Z coordinates in this line, or ``None`` if the + line does not have Z coordinates:: + + >>> OGRGeometry('LINESTRING (1 2 3,4 5 6)').z + [3.0, 6.0] + + +.. class:: Polygon + + .. attribute:: shell + + Returns the shell or exterior ring of this polygon, as a ``LinearRing`` + geometry. + + .. attribute:: exterior_ring + + An alias for :attr:`shell`. + + .. attribute:: centroid + + Returns a :class:`Point` representing the centroid of this polygon. + +.. class:: GeometryCollection + + .. method:: add(geom) + + Adds a geometry to this geometry collection. Not applicable to other + geometry types. + + +``OGRGeomType`` +--------------- + +.. class:: OGRGeomType(type_input) + + This class allows for the representation of an OGR geometry type + in any of several ways:: + + >>> from django.contrib.gis.gdal import OGRGeomType + >>> gt1 = OGRGeomType(3) # Using an integer for the type + >>> gt2 = OGRGeomType('Polygon') # Using a string + >>> gt3 = OGRGeomType('POLYGON') # It's case-insensitive + >>> print gt1 == 3, gt1 == 'Polygon' # Equivalence works w/non-OGRGeomType objects + True True + + .. attribute:: name + + Returns a short-hand string form of the OGR Geometry type:: + + >>> gt1.name + 'Polygon' + + .. attribute:: num + + Returns the number corresponding to the OGR geometry type:: + + >>> gt1.num + 3 + + .. attribute:: django + + Returns the Django field type (a subclass of GeometryField) to use for + storing this OGR type, or ``None`` if there is no appropriate Django + type:: + + >>> gt1.django + 'PolygonField' + +``Envelope`` +------------ + +.. class:: Envelope(*args) + + Represents an OGR Envelope structure that contains the + minimum and maximum X, Y coordinates for a rectangle bounding box. + The naming of the variables is compatible with the OGR Envelope + C structure. + + .. attribute:: min_x + + The value of the minimum X coordinate. + + .. attribute:: min_y + + The value of the maximum X coordinate. + + .. attribute:: max_x + + The value of the minimum Y coordinate. + + .. attribute:: max_y + + The value of the maximum Y coordinate. + + .. attribute:: ur + + The upper-right coordinate, as a tuple. + + .. attribute:: ll + + The lower-left coordinate, as a tuple. + + .. attribute:: tuple + + A tuple representing the envelope. + + .. attribute:: wkt + + A string representing this envelope as a polygon in WKT format. + + + .. method:: expand_to_include(self, *args) + + .. versionadded:: 1.1 + +Coordinate System Objects +========================= + +``SpatialReference`` +-------------------- + +.. class:: SpatialReference(srs_input) + + Spatial reference objects are initialized on the given ``srs_input``, + which may be one of the following: + + * OGC Well Known Text (WKT) (a string) + * EPSG code (integer or string) + * PROJ.4 string + * A shorthand string for well-known standards (``'WGS84'``, ``'WGS72'``, ``'NAD27'``, ``'NAD83'``) + + Example:: + + >>> wgs84 = SpatialReference('WGS84') # shorthand string + >>> wgs84 = SpatialReference(4326) # EPSG code + >>> wgs84 = SpatialReference('EPSG:4326') # EPSG string + >>> proj4 = '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs ' + >>> wgs84 = SpatialReference(proj4) # PROJ.4 string + >>> wgs84 = SpatialReference("""GEOGCS["WGS 84", + DATUM["WGS_1984", + SPHEROID["WGS 84",6378137,298.257223563, + AUTHORITY["EPSG","7030"]], + AUTHORITY["EPSG","6326"]], + PRIMEM["Greenwich",0, + AUTHORITY["EPSG","8901"]], + UNIT["degree",0.01745329251994328, + AUTHORITY["EPSG","9122"]], + AUTHORITY["EPSG","4326"]]""") # OGC WKT + + .. method:: __getitem__(target) + + Returns the value of the given string attribute node, ``None`` if the node + doesn't exist. Can also take a tuple as a parameter, (target, child), + where child is the index of the attribute in the WKT. For example:: + + >>> wkt = 'GEOGCS["WGS 84", DATUM["WGS_1984, ... AUTHORITY["EPSG","4326"]]') + >>> srs = SpatialReference(wkt) # could also use 'WGS84', or 4326 + >>> print srs['GEOGCS'] + WGS 84 + >>> print srs['DATUM'] + WGS_1984 + >>> print srs['AUTHORITY'] + EPSG + >>> print srs['AUTHORITY', 1] # The authority value + 4326 + >>> print srs['TOWGS84', 4] # the fourth value in this wkt + 0 + >>> print srs['UNIT|AUTHORITY'] # For the units authority, have to use the pipe symbole. + EPSG + >>> print srs['UNIT|AUTHORITY', 1] # The authority value for the untis + 9122 + + .. method:: attr_value(target, index=0) + + The attribute value for the given target node (e.g. ``'PROJCS'``). + The index keyword specifies an index of the child node to return. + + .. method:: auth_name(target) + + Returns the authority name for the given string target node. + + .. method:: auth_code(target) + + Returns the authority code for the given string target node. + + .. method:: clone() + + Returns a clone of this spatial reference object. + + .. method:: identify_epsg() + + This method inspects the WKT of this SpatialReference, and will + add EPSG authority nodes where an EPSG identifier is applicable. + + .. method:: from_esri() + + Morphs this SpatialReference from ESRI's format to EPSG + + .. method:: to_esri() + + Morphs this SpatialReference to ESRI's format. + + .. method:: validate() + + Checks to see if the given spatial reference is valid, if not + an exception will be raised. + + .. method:: import_epsg(epsg) + + Import spatial reference from EPSG code. + + .. method:: import_proj(proj) + + Import spatial reference from PROJ.4 string. + + .. method:: import_user_input(user_input) + + .. versionadded:: 1.1 + + .. method:: import_wkt(wkt) + + Import spatial reference from WKT. + + .. method:: import_xml(xml) + + Import spatial reference from XML. + + .. attribute:: name + + Returns the name of this Spatial Reference. + + .. attribute:: srid + + Returns the SRID of top-level authority, or ``None`` if undefined. + + .. attribute:: linear_name + + Returns the name of the linear units. + + .. attribute:: linear_units + + Returns the value of the linear units. + + .. attribute:: angular_name + + Returns the name of the angular units." + + .. attribute:: angular_units + + Returns the value of the angular units. + + .. attribute:: units + + Returns a 2-tuple of the units value and the units name, + and will automatically determines whether to return the linear + or angular units. + + .. attribute:: ellisoid + + Returns a tuple of the ellipsoid parameters for this spatial + reference: (semimajor axis, semiminor axis, and inverse flattening) + + .. attribute:: semi_major + + Returns the semi major axis of the ellipsoid for this spatial reference. + + .. attribute:: semi_minor + + Returns the semi minor axis of the ellipsoid for this spatial reference. + + .. attribute:: inverse_flattening + + Returns the inverse flattening of the ellipsoid for this spatial reference. + + .. attribute:: geographic + + Returns ``True`` if this spatial reference is geographic + (root node is ``GEOGCS``). + + .. attribute:: local + + Returns ``True`` if this spatial reference is local + (root node is ``LOCAL_CS``). + + .. attribute:: projected + + Returns ``True`` if this spatial reference is a projected coordinate + system (root node is ``PROJCS``). + + .. attribute:: wkt + + Returns the WKT representation of this spatial reference. + + .. attribute:: pretty_wkt + + Returns the 'pretty' representation of the WKT. + + .. attribute:: proj + + Returns the PROJ.4 representation for this spatial reference. + + .. attribute:: proj4 + + Alias for :attr:`SpatialReference.proj`. + + .. attribute:: xml + + Returns the XML representation of this spatial reference. + + +``CoordTransform`` +------------------ + +.. class:: CoordTransform(source, target) + +Represents a coordinate system transform. It is initialized with two +:class:`SpatialReference`, representing the source and target coordinate +systems, respectively. These objects should be used when performing +the same coordinate transformation repeatedly on different geometries:: + + >>> ct = CoordTransform(SpatialReference('WGS84'), SpatialReference('NAD83')) + >>> for feat in layer: + ... geom = feat.geom # getting clone of feature geometry + ... geom.transform(ct) # transforming + +Settings +======== + +.. setting:: GDAL_LIBRARY_PATH + +GDAL_LIBRARY_PATH +----------------- + +A string specifying the location of the GDAL library. Typically, +this setting is only used if the GDAL library is in a non-standard +location (e.g., ``/home/john/lib/libgdal.so``). diff --git a/docs/ref/contrib/gis/geoip.txt b/docs/ref/contrib/gis/geoip.txt new file mode 100644 index 0000000000..dedc36162d --- /dev/null +++ b/docs/ref/contrib/gis/geoip.txt @@ -0,0 +1,223 @@ +.. _ref-geoip: + +====================== +Geolocation with GeoIP +====================== + +.. module:: django.contrib.gis.utils.geoip + :synopsis: High-level Python interface for MaxMind's GeoIP C library. + +.. currentmodule:: django.contrib.gis.utils + +The :class:`GeoIP` object is a ctypes wrapper for the +`MaxMind GeoIP C API`__. [#]_ This interface is a BSD-licensed alternative +to the GPL-licensed `Python GeoIP`__ interface provided by MaxMind. + +In order to perform IP-based geolocation, the :class:`GeoIP` object requires +the GeoIP C libary and either the GeoIP `Country`__ or `City`__ +datasets in binary format (the CSV files will not work!). These datasets may be +`downloaded from MaxMind`__. Grab the ``GeoIP.dat.gz`` and ``GeoLiteCity.dat.gz`` +and unzip them in a directory corresponding to what you set +``GEOIP_PATH`` with in your settings. See the example and reference below +for more details. + +__ http://www.maxmind.com/app/c +__ http://www.maxmind.com/app/python +__ http://www.maxmind.com/app/country +__ http://www.maxmind.com/app/city +__ http://www.maxmind.com/download/geoip/database/ + +Example +======= + +Assuming you have the GeoIP C library installed, here is an example of its +usage:: + + >>> from django.contrib.gis.utils import GeoIP + >>> g = GeoIP() + >>> g.country('google.com') + {'country_code': 'US', 'country_name': 'United States'} + >>> g.city('72.14.207.99') + {'area_code': 650, + 'city': 'Mountain View', + 'country_code': 'US', + 'country_code3': 'USA', + 'country_name': 'United States', + 'dma_code': 807, + 'latitude': 37.419200897216797, + 'longitude': -122.05740356445312, + 'postal_code': '94043', + 'region': 'CA'} + >>> g.lat_lon('salon.com') + (37.789798736572266, -122.39420318603516) + >>> g.lon_lat('uh.edu') + (-95.415199279785156, 29.77549934387207) + >>> g.geos('24.124.1.80').wkt + 'POINT (-95.2087020874023438 39.0392990112304688)' + +``GeoIP`` Settings +================== + +.. setting:: GEOIP_PATH + +GEOIP_PATH +---------- + +A string specifying the directory where the GeoIP data files are +located. This setting is *required* unless manually specified +with ``path`` keyword when initializing the :class:`GeoIP` object. + +.. setting:: GEOIP_LIBRARY_PATH + +GEOIP_LIBRARY_PATH +------------------ + +A string specifying the location of the GeoIP C library. Typically, +this setting is only used if the GeoIP C library is in a non-standard +location (e.g., ``/home/sue/lib/libGeoIP.so``). + +.. setting:: GEOIP_COUNTRY + +GEOIP_COUNTRY +------------- + +The basename to use for the GeoIP country data file. +Defaults to ``'GeoIP.dat'``. + +.. setting:: GEOIP_CITY + +GEOIP_CITY +---------- + +The basename to use for the GeoIP city data file. +Defaults to ``'GeoLiteCity.dat'``. + +``GeoIP`` API +============= + +.. class:: GeoIP([path=None, cache=0, country=None, city=None]) + +The ``GeoIP`` object does not require any parameters to use the default +settings. However, at the very least the :setting:`GEOIP_PATH` setting +should be set with the path of the location of your GeoIP data sets. The +following intialization keywords may be used to customize any of the +defaults. + +=================== ======================================================= +Keyword Arguments Description +=================== ======================================================= +``path`` Base directory to where GeoIP data is located or the + full path to where the city or country data files + (.dat) are located. Assumes that both the city and + country data sets are located in this directory; + overrides the :setting:`GEOIP_PATH` settings attribute. + +``cache`` The cache settings when opening up the GeoIP datasets, + and may be an integer in (0, 1, 2, 4) corresponding to + the ``GEOIP_STANDARD``, ``GEOIP_MEMORY_CACHE``, + ``GEOIP_CHECK_CACHE``, and ``GEOIP_INDEX_CACHE`` + ``GeoIPOptions`` C API settings, respectively. + Defaults to 0 (``GEOIP_STANDARD``). + +``country`` The name of the GeoIP country data file. Defaults + to ``GeoIP.dat``. Setting this keyword overrides the + :setting:`GEOIP_COUNTRY` settings attribute. + +``city`` The name of the GeoIP city data file. Defaults to + ``GeoLiteCity.dat``. Setting this keyword overrides + the :setting:`GEOIP_CITY` settings attribute. +=================== ======================================================= + +``GeoIP`` Methods +================= + +Querying +-------- + +All the following querying routines may take either a string IP address +or a fully qualified domain name (FQDN). For example, both +``'24.124.1.80'`` and ``'djangoproject.com'`` would be valid query +parameters. + +.. method:: GeoIP.city(query) + +Returns a dictionary of city information for the given query. Some +of the values in the dictionary may be undefined (``None``). + +.. method:: GeoIPcountry(query) + +Returns a dictionary with the country code and country for the given +query. + +.. method:: GeoIP.country_code(query) + +Returns only the country code corresponding to the query. + +.. method:: GeoIP.country_name(query) + +Returns only the country name corresponding to the query. + +Coordinate Retrieval +-------------------- + +.. method:: GeoIP.coords(query) + +Returns a coordinate tuple of (longitude, latitude). + +.. method:: GeoIP.lon_lat(query) + +Returns a coordinate tuple of (longitude, latitude). + +.. method:: GeoIP.lat_lon(query) + +Returns a coordinate tuple of (latitude, longitude), + +.. method:: GeoIP.geos(query) + +Returns a :class:`django.contrib.gis.geos.Point` object corresponding to the query. + +Database Information +-------------------- + +.. attribute:: GeoIP.country_info + +This property returns information about the GeoIP country database. + +.. attribute:: GeoIP.city_info + +This property returns information about the GeoIP city database. + +.. attribute:: GeoIP.info + +This property returns information about all GeoIP databases (both city +and country). + +GeoIP-Python API compatibility methods +---------------------------------------- + +These methods exist to ease compatibility with any code using MaxMind's +existing Python API. + +.. classmethod:: GeoIP.open(path, cache) + +This classmethod instantiates the GeoIP object from the given database path +and given cache setting. + +.. method:: GeoIP.regioin_by_addr(query) + +.. method:: GeoIP.region_by_name(query) + +.. method:: GeoIP.record_by_addr(query) + +.. method:: GeoIP.record_by_name(query) + +.. method:: GeoIP.country_code_by_addr(query) + +.. method:: GeoIP.country_code_by_name(query) + +.. method:: GeoIP.country_name_by_addr(query) + +.. method:: GeoIP.country_name_by_name(query) + +.. rubric:: Footnotes +.. [#] GeoIP(R) is a registered trademark of MaxMind, LLC of Boston, Massachusetts. diff --git a/docs/ref/contrib/gis/geoquerysets.txt b/docs/ref/contrib/gis/geoquerysets.txt new file mode 100644 index 0000000000..c413ff4157 --- /dev/null +++ b/docs/ref/contrib/gis/geoquerysets.txt @@ -0,0 +1,1256 @@ +.. _ref-geoquerysets: + +========================= +GeoQuerySet API Reference +========================= + +.. currentmodule:: django.contrib.gis.db.models + +.. class:: GeoQuerySet([model=None]) + + +.. _spatial-lookups: + +Spatial Lookups +=============== + +Just like when using the the :ref:`queryset-api`, interaction +with ``GeoQuerySet`` by :ref:`chaining filters `. +Instead of the regular Django :ref:`field-lookups`, the +spatial lookups in this section are available for :class:`GeometryField`. + +For an introduction, see the :ref:`spatial lookups introduction +`. For an overview of what lookups are +compatible with a particular spatial backend, refer to the +:ref:`spatial lookup compatibility table `. + +.. fieldlookup:: bbcontains + +bbcontains +---------- + +*Availability*: PostGIS, MySQL, SpatiaLite + +Tests if the geometry field's bounding box completely contains the lookup +geometry's bounding box. + +Example:: + + Zipcode.objects.filter(poly__bbcontains=geom) + +========== ========================== +Backend SQL Equivalent +========== ========================== +PostGIS ``poly ~ geom`` +MySQL ``MBRContains(poly, geom)`` +SpatiaLite ``MbrContains(poly, geom)`` +========== ========================== + +.. fieldlookup:: bboverlaps + +bboverlaps +---------- + +*Availability*: PostGIS, MySQL, SpatiaLite + +Tests if the geometry field's bounding box overlaps the lookup geometry's +bounding box. + +Example:: + + Zipcode.objects.filter(poly__bboverlaps=geom) + +========== ========================== +Backend SQL Equivalent +========== ========================== +PostGIS ``poly && geom`` +MySQL ``MBROverlaps(poly, geom)`` +SpatiaLite ``MbrOverlaps(poly, geom)`` +========== ========================== + +.. fieldlookup:: contained + +contained +--------- + +*Availability*: PostGIS, MySQL, SpatiaLite + +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) + +========== ========================== +Backend SQL Equivalent +========== ========================== +PostGIS ``poly @ geom`` +MySQL ``MBRWithin(poly, geom)`` +SpatiaLite ``MbrWithin(poly, geom)`` +========== ========================== + +.. fieldlookup:: gis-contains + +contains +-------- + +*Availability*: PostGIS, Oracle, MySQL, SpatiaLite + +Tests if the geometry field spatially contains the lookup geometry. + +Example:: + + Zipcode.objects.filter(poly__contains=geom) + +========== ============================ +Backend SQL Equivalent +========== ============================ +PostGIS ``ST_Contains(poly, geom)`` +Oracle ``SDO_CONTAINS(poly, geom)`` +MySQL ``MBRContains(poly, geom)`` +SpatiaLite ``Contains(poly, geom)`` +========== ============================ + +.. fieldlookup:: contains_properly + +contains_properly +----------------- + +.. versionadded:: 1.2 + +*Availability*: PostGIS + +Returns true if the lookup geometry intersects the interior of the +geometry field, but not the boundary (or exterior). [#fncontainsproperly]_ + +.. note:: + + Requires PostGIS 1.4 and above. + +Example:: + + Zipcode.objects.filter(poly__contains_properly=geom) + +========== =================================== +Backend SQL Equivalent +========== =================================== +PostGIS ``ST_ContainsProperly(poly, geom)`` +========== =================================== + +.. fieldlookup:: coveredby + +coveredby +--------- + +*Availability*: PostGIS, Oracle + +Tests if no point in the geometry field is outside the lookup geometry. +[#fncovers]_ + +Example:: + + Zipcode.objects.filter(poly__coveredby=geom) + +========== ============================= +Backend SQL Equivalent +========== ============================= +PostGIS ``ST_CoveredBy(poly, geom)`` +Oracle ``SDO_COVEREDBY(poly, geom)`` +========== ============================= + +.. fieldlookup:: covers + +covers +------ + +*Availability*: PostGIS, Oracle + +Tests if no point in the lookup geometry is outside the geometry field. +[#fncovers]_ + +Example:: + + Zipcode.objects.filter(poly__covers=geom) + +========== ========================== +Backend SQL Equivalent +========== ========================== +PostGIS ``ST_Covers(poly, geom)`` +Oracle ``SDO_COVERS(poly, geom)`` +========== ========================== + +.. fieldlookup:: crosses + +crosses +------- + +*Availability*: PostGIS, SpatiaLite + +Tests if the geometry field spatially crosses the lookup geometry. + +Example:: + + Zipcode.objects.filter(poly__crosses=geom) + +========== ========================== +Backend SQL Equivalent +========== ========================== +PostGIS ``ST_Crosses(poly, geom)`` +SpatiaLite ``Crosses(poly, geom)`` +========== ========================== + +.. fieldlookup:: disjoint + +disjoint +-------- + +*Availability*: PostGIS, Oracle, MySQL, SpatiaLite + +Tests if the geometry field is spatially disjoint from the lookup geometry. + +Example:: + + Zipcode.objects.filter(poly__disjoint=geom) + +========== ================================================= +Backend SQL Equivalent +========== ================================================= +PostGIS ``ST_Disjoint(poly, geom)`` +Oracle ``SDO_GEOM.RELATE(poly, 'DISJOINT', geom, 0.05)`` +MySQL ``MBRDisjoint(poly, geom)`` +SpatiaLite ``Disjoint(poly, geom)`` +========== ================================================= + +equals +------ + +*Availability*: PostGIS, Oracle, MySQL, SpatiaLite + +.. fieldlookup:: exact +.. fieldlookup:: same_as + +exact, same_as +-------------- + +*Availability*: PostGIS, Oracle, MySQL, SpatiaLite + +.. fieldlookup:: intersects + +intersects +---------- + +*Availability*: PostGIS, Oracle, MySQL, SpatiaLite + +Tests if the geometry field spatially intersects the lookup geometry. + +Example:: + + Zipcode.objects.filter(poly__intersects=geom) + +========== ================================================= +Backend SQL Equivalent +========== ================================================= +PostGIS ``ST_Intersects(poly, geom)`` +Oracle ``SDO_OVERLAPBDYINTERSECT(poly, geom)`` +MySQL ``MBRIntersects(poly, geom)`` +SpatiaLite ``Intersects(poly, geom)`` +========== ================================================= + +.. fieldlookup:: overlaps + +overlaps +-------- + +*Availability*: PostGIS, Oracle, MySQL, SpatiaLite + +.. fieldlookup:: relate + +relate +------ + +*Availability*: PostGIS, Oracle, SpatiaLite + +Tests if the geometry field is spatially related to the the lookup geometry by +the values given in the given pattern. This lookup requires a tuple parameter, +``(geom, pattern)``; the form of ``pattern`` will depend on the spatial backend: + +PostGIS & SpatiaLite +~~~~~~~~~~~~~~~~~~~~ +On these spatial backends the intersection pattern 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. [#fnde9im]_ + +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 SQL equivalent:: + + SELECT ... WHERE ST_Relate(poly, geom, 'T*T***FF*') + +SpatiaLite SQL equivalent:: + + SELECT ... WHERE Relate(poly, geom, 'T*T***FF*') + +Oracle +~~~~~~ + +Here the relation pattern is compreised at least one of the nine relation +strings: ``TOUCH``, ``OVERLAPBDYDISJOINT``, ``OVERLAPBDYINTERSECT``, +``EQUAL``, ``INSIDE``, ``COVEREDBY``, ``CONTAINS``, ``COVERS``, ``ON``, and +``ANYINTERACT``. Multiple strings may be combined with the logical Boolean +operator OR, for example, ``'inside+touch'``. [#fnsdorelate]_ The relation +strings are case-insensitive. + +Example:: + + Zipcode.objects.filter(poly__relate(geom, 'anyinteract')) + +Oracle SQL equivalent:: + + SELECT ... WHERE SDO_RELATE(poly, geom, 'anyinteract') + +.. fieldlookup:: touches + +touches +------- + +*Availability*: PostGIS, Oracle, MySQL, SpatiaLite + +Tests if the geometry field spatially touches the lookup geometry. + +Example:: + + Zipcode.objects.filter(poly__touches=geom) + +========== ========================== +Backend SQL Equivalent +========== ========================== +PostGIS ``ST_Touches(poly, geom)`` +MySQL ``MBRTouches(poly, geom)`` +Oracle ``SDO_TOUCH(poly, geom)`` +SpatiaLite ``Touches(poly, geom)`` +========== ========================== + +.. fieldlookup:: within + +within +------ + +*Availability*: PostGIS, Oracle, MySQL, SpatiaLite + +Tests if the geometry field is spatially within the lookup geometry. + +Example:: + + Zipcode.objects.filter(poly__within=geom) + +========== ========================== +Backend SQL Equivalent +========== ========================== +PostGIS ``ST_Within(poly, geom)`` +MySQL ``MBRWithin(poly, geom)`` +Oracle ``SDO_INSIDE(poly, geom)`` +SpatiaLite ``Within(poly, geom)`` +========== ========================== + +.. fieldlookup:: left + +left +---- + +*Availability*: PostGIS + +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 + +.. fieldlookup:: right + +right +----- + +*Availability*: PostGIS + +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 + +.. fieldlookup:: overlaps_left + +overlaps_left +------------- + +*Availability*: PostGIS + +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 + + +.. fieldlookup:: overlaps_right + +overlaps_right +-------------- + +*Availability*: PostGIS + +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 + +.. fieldlookup:: overlaps_above + +overlaps_above +-------------- + +*Availability*: PostGIS + +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 + +.. fieldlookup:: overlaps_below + +overlaps_below +-------------- + +*Availability*: PostGIS + +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 + +.. fieldlookup:: strictly_above + +strictly_above +-------------- + +*Availability*: PostGIS + +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 + +.. fieldlookup:: strictly_below + +strictly_below +-------------- + +*Availability*: PostGIS + +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 + + +.. _distance-lookups: + +Distance Lookups +================ + +*Availability*: PostGIS, Oracle, SpatiaLite + +For an overview on performing distance queries, please refer to +the :ref:`distance queries introduction `. + +Distance lookups take the following form:: + + __=(, [, 'spheroid']) + +The value passed into a distance lookup is a tuple; the first two +values are mandatory, and are the geometry to calculate distances to, +and a distance value (either a number in units of the field or a +:class:`~django.contrib.gis.measure.Distance` object). On every +distance lookup but :lookup:`dwithin`, an optional +third element, ``'spheroid'``, may be included to tell GeoDjango +to use the more accurate spheroid distance calculation functions on +fields with a geodetic coordinate system (e.g., ``ST_Distance_Spheroid`` +would be used instead of ``ST_Distance_Sphere``). + +.. fieldlookup:: distance_gt + +distance_gt +----------- + +Returns models where the distance to the geometry field from the lookup +geometry is greater than the given distance value. + +Example:: + + Zipcode.objects.filter(poly__distance_gt=(geom, D(m=5))) + +========== =============================================== +Backend SQL Equivalent +========== =============================================== +PostGIS ``ST_Distance(poly, geom) > 5`` +Oracle ``SDO_GEOM.SDO_DISTANCE(poly, geom, 0.05) > 5`` +SpatiaLite ``Distance(poly, geom) > 5`` +========== =============================================== + +.. fieldlookup:: distance_gte + +distance_gte +------------ + +Returns models where the distance to the geometry field from the lookup +geometry is greater than or equal to the given distance value. + +Example:: + + Zipcode.objects.filter(poly__distance_gte=(geom, D(m=5))) + +========== ================================================ +Backend SQL Equivalent +========== ================================================ +PostGIS ``ST_Distance(poly, geom) >= 5`` +Oracle ``SDO_GEOM.SDO_DISTANCE(poly, geom, 0.05) >= 5`` +SpatiaLite ``Distance(poly, geom) >= 5`` +========== ================================================ + +.. fieldlookup:: distance_lt + +distance_lt +----------- + +Returns models where the distance to the geometry field from the lookup +geometry is less than the given distance value. + +Example:: + + Zipcode.objects.filter(poly__distance_lt=(geom, D(m=5))) + +========== =============================================== +Backend SQL Equivalent +========== =============================================== +PostGIS ``ST_Distance(poly, geom) < 5`` +Oracle ``SDO_GEOM.SDO_DISTANCE(poly, geom, 0.05) < 5`` +SpatiaLite ``Distance(poly, geom) < 5`` +========== =============================================== + +.. fieldlookup:: distance_lte + +distance_lte +------------ + +Returns models where the distance to the geometry field from the lookup +geometry is less than or equal to the given distance value. + +Example:: + + Zipcode.objects.filter(poly__distance_lte=(geom, D(m=5))) + +========== ================================================ +Backend SQL Equivalent +========== ================================================ +PostGIS ``ST_Distance(poly, geom) <= 5`` +Oracle ``SDO_GEOM.SDO_DISTANCE(poly, geom, 0.05) <= 5`` +SpatiaLite ``Distance(poly, geom) <= 5`` +========== ================================================ + +.. fieldlookup:: dwithin + +dwithin +------- + +Returns models where the distance to the geometry field from the +lookup geometry are within the given distance from one another. + +Example:: + + Zipcode.objects.filter(poly__dwithin=(geom, D(m=5))) + +========== ====================================== +Backend SQL Equivalent +========== ====================================== +PostGIS ``ST_DWithin(poly, geom, 5)`` +Oracle ``SDO_WITHIN_DISTANCE(poly, geom, 5)`` +========== ====================================== + +.. note:: + + This lookup is not available on SpatiaLite. + +.. fieldlookup:: equals + + +``GeoQuerySet`` Methods +======================= + +``GeoQuerySet`` methods specify that a spatial operation be performed +on each patial 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. + +.. note:: + + What methods are available depend on your spatial backend. See + the :ref:`compatibility table ` + for more details. + +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. +===================== ===================================================== + +Measurement +----------- +*Availability*: PostGIS, Oracle, SpatiaLite + +``area`` +~~~~~~~~ + +.. method:: GeoQuerySet.area(**kwargs) + +Returns the area of the geographic field in an ``area`` attribute on +each element of this GeoQuerySet. + +``distance`` +~~~~~~~~~~~~ + +.. method:: GeoQuerySet.distance(geom, **kwargs) + +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 :class:`~django.contrib.gis.measure.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 +:class:`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 + :class:`~django.contrib.gis.measure.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 :ref:`ref-measure` for usage details and the list of + :ref:`supported_units`. + +__ http://code.djangoproject.com/browser/django/trunk/django/contrib/gis/tests/distapp/models.py +__ http://en.wikipedia.org/wiki/Tasmania + +``length`` +~~~~~~~~~~ + +.. method:: GeoQuerySet.length(**kwargs) + +Returns the length of the geometry field in a ``length`` attribute +(a :class:`~django.contrib.gis.measure.Distance` object) on each model in +the queryset. + +``perimeter`` +~~~~~~~~~~~~~ + +.. method:: GeoQuerySet.perimeter(**kwargs) + +Returns the perimeter of the geometry field in a ``perimeter`` attribute +(a :class:`~django.contrib.gis.measure.Distance` object) on each model in +the queryset. + +Geometry Relationships +---------------------- + +The following methods take no arguments, and attach geometry objects +each element of the :class:`GeoQuerySet` that is the result of relationship +function evaluated on the the geometry field. + +``centroid`` +~~~~~~~~~~~~ + +.. method:: GeoQuerySet.centroid(**kwargs) + +*Availability*: PostGIS, Oracle, SpatiaLite + +Returns the ``centroid`` value for the geographic field in a ``centroid`` +attribute on each element of the ``GeoQuerySet``. + +``envelope`` +~~~~~~~~~~~~ + +.. method:: GeoQuerySet.envelope(**kwargs) + +*Availability*: PostGIS, SpatiaLite + +Returns a geometry representing the bounding box of the geometry field in +an ``envelope`` attribute on each element of the ``GeoQuerySet``. + +``point_on_surface`` +~~~~~~~~~~~~~~~~~~~~ + +.. method:: GeoQuerySet.point_on_surface(**kwargs) + +*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 the queryset; otherwise sets with None. + +Geometry Editors +---------------- + +``force_rhr`` +~~~~~~~~~~~~~ + +.. method:: GeoQuerySet.force_rhr(**kwargs) + +.. versionadded:: 1.2 + +*Availability*: PostGIS + +Returns a modified version of the polygon/multipolygon in which all +of the vertices follow the Right-Hand-Rule, and attaches as a +``force_rhr`` attribute on each element of the queryset. + +``reverse_geom`` +~~~~~~~~~~~~~~~~ + +.. method:: GeoQuerySet.reverse_geom(**kwargs) + +.. versionadded:: 1.2 + +*Availability*: PostGIS, Oracle + +Reverse the coordinate order of the geometry field, and attaches as a +``reverse`` attribute on each element of the queryset. + +``scale`` +~~~~~~~~~ + +.. method:: GeoQuerySet.scale(x, y, z=0.0, **kwargs) + +*Availability*: PostGIS, SpatiaLite + +``snap_to_grid`` +~~~~~~~~~~~~~~~~ + +.. method:: GeoQuerySet.snap_to_grid(*args, **kwargs) + +.. 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. +=================== ===================================================== + +``transform`` +~~~~~~~~~~~~~ + +.. method:: GeoQuerySet.transform(srid=4326, **kwargs) + +*Availability*: PostGIS, Oracle, SpatiaLite + +The ``transform`` method transforms the geometry field of 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:: + + Unlike other ``GeoQuerySet`` methods, ``transform`` stores its output + "in-place". In other words, no new attribute for the transformed + geometry is placed on the models. + +.. 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 ... + +``translate`` +~~~~~~~~~~~~~ +.. method:: GeoQuerySet.translate(x, y, z=0.0, **kwargs) + +*Availability*: PostGIS, SpatiaLite + +Translates the geometry field to a new location using the given numeric +parameters as offsets. + +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. + +``difference`` +~~~~~~~~~~~~~~ + +.. method:: GeoQuerySet.difference(geom) + +Returns the spatial difference of the geographic field with the given +geometry in a ``difference`` attribute on each element of the +``GeoQuerySet``. + + +``intersection`` +~~~~~~~~~~~~~~~~ + +.. method:: GeoQuerySet.intersection(geom) + +Returns the spatial intersection of the geographic field with the +given geometry in an ``intersection`` attribute on each element of the +``GeoQuerySet``. + +``sym_difference`` +~~~~~~~~~~~~~~~~~~ + +.. method:: GeoQuerySet.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``. + +``union`` +~~~~~~~~~ + +.. method:: GeoQuerySet.union(geom) + +Returns the union of the geographic field with the given +geometry in an ``union`` attribute on each element of the +``GeoQuerySet``. + +Geometry 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. + +``geohash`` +~~~~~~~~~~~ + +.. method:: GeoQuerySet.geohash(preceision=20, **kwargs) + +.. versionadded:: 1.2 + +Attaches a ``geohash`` attribute to every model the the queryset +containing the `GeoHash`__ representation of the geometry. + +__ http://geohash.org/ + +``geojson`` +~~~~~~~~~~~ + +.. method:: GeoQuerySet.geojson(**kwargs) + +.. 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/ + +``gml`` +~~~~~~~ + +.. method:: GeoQuerySet.gml(**kwargs) + +*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 + +``kml`` +~~~~~~~ + +.. method:: GeoQuerySet.kml(**kwargs) + +*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/ + +``svg`` +~~~~~~~ + +.. method:: GeoQuerySet.svg(**kwargs) + +*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 +------------- + +``mem_size`` +~~~~~~~~~~~~ + +.. method:: GeoQuerySet.mem_size(**kwargs) + +*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``. + +``num_geom`` +~~~~~~~~~~~~ + +.. method:: GeoQuerySet.num_geom(**kwargs) + +*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``. + +``num_points`` +~~~~~~~~~~~~~~ + +.. method:: GeoQuerySet.num_points(**kwargs) + +*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``. + +Spatial Aggregates +================== +.. versionadded:: 1.1 + +Aggregate Methods +----------------- + +``collect`` +~~~~~~~~~~~ + +.. method:: GeoQuerySet.collect(**kwargs) + +.. 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 :meth:`GeoQuerySet.unionagg` method, +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:: GeoQuerySet.extent(**kwargs) + +*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:: GeoQuerySet.extent3d(**kwargs) + +.. 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) + +``make_line`` +~~~~~~~~~~~~~ + +.. method:: GeoQuerySet.make_line(**kwargs) + +*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`` +~~~~~~~~~~~~ + +.. method:: GeoQuerySet.unionagg(**kwargs) + +*Availability*: PostGIS, Oracle, SpatiaLite + +This method returns a :class:`~django.contrib.gis.geos.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. + +.. note:: + + If the computation time for using this method is too expensive, + consider using :meth:`GeoQuerySet.collect` instead. + +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 + +Aggregate Functions +------------------- + +Example:: + + >>> from django.contrib.gis.db.models import Extent, Union + >>> WorldBorders.objects.aggregate(Extent('mpoly'), Union('mpoly')) + +``Collect`` +~~~~~~~~~~~ + +.. class:: Collect(geo_field) + +Returns the same as the :meth:`GeoQuerySet.collect` aggregate method. + +``Extent`` +~~~~~~~~~~ +.. class:: Extent(geo_field) + + +Returns the same as the :meth:`GeoQuerySet.extent` aggregate method. + +``Extent3D`` +~~~~~~~~~~~~ + +.. class:: Extent3D(geo_field) + +.. versionadded:: 1.2 + +Returns the same as the :meth:`GeoQuerySet.extent3d` aggregate method. + +``MakeLine`` +~~~~~~~~~~~~ + +.. class:: MakeLine(geo_field) + +Returns the same as the :meth:`GeoQuerySet.make_line` aggregate method. + +``Union`` +~~~~~~~~~ + +.. class:: Union(geo_field) + +Returns the same as the :meth:`GeoQuerySet.union` aggregate method. + +.. rubric:: Footnotes +.. [#fnde9im] *See* `OpenGIS Simple Feature Specification For SQL `_, at Ch. 2.1.13.2, p. 2-13 (The Dimensionally Extended Nine-Intersection Model). +.. [#fnsdorelate] *See* `SDO_RELATE documentation `_, from Ch. 11 of the Oracle Spatial User's Guide and Manual. +.. [#fncovers] For an explanation of this routine, read `Quirks of the "Contains" Spatial Predicate `_ by Martin Davis (a PostGIS developer). +.. [#fncontainsproperly] Refer to the PostGIS ``ST_ContainsProperly`` `documentation `_ for more details. diff --git a/docs/ref/contrib/gis/geos.txt b/docs/ref/contrib/gis/geos.txt new file mode 100644 index 0000000000..06a88a88ec --- /dev/null +++ b/docs/ref/contrib/gis/geos.txt @@ -0,0 +1,911 @@ +.. _ref-geos: + +======== +GEOS API +======== + +.. module:: django.contrib.gis.geos + :synopsis: GeoDjango's high-level interface to the GEOS library. + +Background +========== + +What is GEOS? +------------- + +`GEOS`__ stands for **G**\ eometry **E**\ ngine - **O**\ pen **S**\ ource, +and is a C++ library, ported from the `Java Topology Suite`__. GEOS +implements the OpenGIS `Simple Features for SQL`__ spatial predicate functions +and spatial operators. GEOS, now an OSGeo project, was initially developed and +maintained by `Refractions Research`__ of Victoria, Canada. + +__ http://trac.osgeo.org/geos/ +__ http://sourceforge.net/projects/jts-topo-suite/ +__ http://www.opengeospatial.org/standards/sfs +__ http://www.refractions.net/ + +Features +-------- + +GeoDjango implements a high-level Python wrapper for the GEOS library, its +features include: + +* A BSD-licensed interface to the GEOS geometry routines, implemented purely + in Python using ``ctypes``. +* Loosely-coupled to GeoDjango. For example, :class:`GEOSGeometry` objects + may be used outside of a django project/application. In other words, + no need to have ``DJANGO_SETTINGS_MODULE`` set or use a database, etc. +* Mutability: :class:`GEOSGeometry` objects may be modified. +* Cross-platform and tested; compatible with Windows, Linux, Solaris, and Mac + OS X platforms. + +.. _geos-tutorial: + +Tutorial +======== + +This section contains a brief introduction and tutorial to using +:class:`GEOSGeometry` objects. + +Creating a Geometry +------------------- + +:class:`GEOSGeometry` objects may be created in a few ways. The first is +to simply instantiate the object on some spatial input -- the following +are examples of creating the same geometry from WKT, HEX, WKB, and GeoJSON:: + + >>> from django.contrib.gis.geos import GEOSGeometry + >>> pnt = GEOSGeometry('POINT(5 23)') # WKT + >>> pnt = GEOSGeometry('010100000000000000000014400000000000003740') # HEX + >>> pnt = GEOSGeometry(buffer('\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14@\x00\x00\x00\x00\x00\x007@')) + >>> pnt = GEOSGeometry('{ "type": "Point", "coordinates": [ 5.000000, 23.000000 ] }') # GeoJSON + +Another option is to use the constructor for the specific geometry type +that you wish to create. For example, a :class:`Point` object may be +created by passing in the X and Y coordinates into its constructor:: + + >>> from django.contrib.gis.geos import Point + >>> pnt = Point(5, 23) + +Finally, there are :func:`fromstr` and :func:`fromfile` factory methods, which +return a :class:`GEOSGeometry` object from an input string or a file:: + + >>> from django.contrib.gis.geos import fromstr, fromfile + >>> pnt = fromstr('POINT(5 23)') + >>> pnt = fromfile('/path/to/pnt.wkt') + >>> pnt = fromfile(open('/path/to/pnt.wkt')) + +Geometries are Pythonic +----------------------- +:class:`GEOSGeometry` objects are 'Pythonic', in other words components may +be accessed, modified, and iterated over using standard Python conventions. +For example, you can iterate over the coordinates in a :class:`Point`:: + + >>> pnt = Point(5, 23) + >>> [coord for coord in pnt] + [5.0, 23.0] + +With any geometry object, the :attr:`GEOSGeometry.coords` property +may be used to get the geometry coordinates as a Python tuple:: + + >>> pnt.coords + (5.0, 23.0) + +You can get/set geometry components using standard Python indexing +techniques. However, what is returned depends on the geometry type +of the object. For example, indexing on a :class:`LineString` +returns a coordinate tuple:: + + >>> from django.contrib.gis.geos import LineString + >>> line = LineString((0, 0), (0, 50), (50, 50), (50, 0), (0, 0)) + >>> line[0] + (0.0, 0.0) + >>> line[-2] + (50.0, 0.0) + +Whereas indexing on a :class:`Polygon` will return the ring +(a :class:`LinearRing` object) corresponding to the index:: + + >>> from django.contrib.gis.geos import Polygon + >>> poly = Polygon( ((0.0, 0.0), (0.0, 50.0), (50.0, 50.0), (50.0, 0.0), (0.0, 0.0)) ) + >>> poly[0] + + >>> poly[0][-2] # second-to-last coordinate of external ring + (50.0, 0.0) + +In addition, coordinates/components of the geometry may added or modified, +just like a Python list:: + + >>> line[0] = (1.0, 1.0) + >>> line.pop() + (0.0, 0.0) + >>> line.append((1.0, 1.0)) + >>> line.coords + ((1.0, 1.0), (0.0, 50.0), (50.0, 50.0), (50.0, 0.0), (1.0, 1.0)) + +Geometry Objects +================ + +``GEOSGeometry`` +---------------- + +.. class:: GEOSGeometry(geo_input[, srid=None]) + + :param geo_input: Geometry input value + :type geo_input: string or buffer + :param srid: spatial reference identifier + :type srid: integer + +This is the base class for all GEOS geometry objects. It initializes on the +given ``geo_input`` argument, and then assumes the proper geometry subclass +(e.g., ``GEOSGeometry('POINT(1 1)')`` will create a :class:`Point` object). + +The following input formats, along with their corresponding Python types, +are accepted: + +============= ====================== +Format Input Type +============= ====================== +WKT / EWKT ``str`` or ``unicode`` +HEX / HEXEWKB ``str`` or ``unicode`` +WKB / EWKB ``buffer`` +GeoJSON ``str`` or ``unicode`` +============= ====================== + +Properties +~~~~~~~~~~ + +.. attribute:: GEOSGeometry.coords + +Returns the coordinates of the geometry as a tuple. + +.. attribute:: GEOSGeometry.empty + +Returns whether or not the set of points in the geometry is empty. + +.. attribute:: GEOSGeometry.geom_type + +Returns a string corresponding to the type of geometry. For example:: + + >>> pnt = GEOSGeometry('POINT(5 23)') + >>> pnt.geom_type + 'Point' + +.. attribute:: GEOSGeometry.geom_typeid + +Returns the GEOS geometry type identification number. The following table +shows the value for each geometry type: + +=========================== ======== +Geometry ID +=========================== ======== +:class:`Point` 0 +:class:`LineString` 1 +:class:`LinearRing` 2 +:class:`Polygon` 3 +:class:`MultiPoint` 4 +:class:`MultiLineString` 5 +:class:`MultiPolygon` 6 +:class:`GeometryCollection` 7 +=========================== ======== + +.. attribute:: GEOSGeometry.num_coords + +Returns the number of coordinates in the geometry. + +.. attribute:: GEOSGeometry.num_geom + +Returns the number of geometries in this geometry. In other words, will +return 1 on anything but geometry collections. + +.. attribute:: GEOSGeometry.hasz + +Returns a boolean indicating whether the geometry is three-dimensional. + +.. attribute:: GEOSGeometry.ring + +Returns a boolean indicating whether the geometry is a ``LinearRing``. + +.. attribute:: GEOSGeometry.simple + +Returns a boolean indicating whether the geometry is 'simple'. A geometry +is simple if and only if it does not intersect itself (except at boundary +points). For example, a :class:`LineString` object is not simple if it +intersects itself. Thus, :class:`LinearRing` and :class`Polygon` objects +are always simple because they do cannot intersect themselves, by +definition. + +.. attribute:: GEOSGeometry.valid + +Returns a boolean indicating whether the geometry is valid. + +.. attribute:: GEOSGeometry.srid + +Property that may be used to retrieve or set the SRID associated with the +geometry. For example:: + + >>> pnt = Point(5, 23) + >>> print pnt.srid + None + >>> pnt.srid = 4326 + >>> pnt.srid + 4326 + +Output Properties +~~~~~~~~~~~~~~~~~ + +The properties in this section export the :class:`GEOSGeometry` object into +a different. This output may be in the form of a string, buffer, or even +another object. + +.. attribute:: GEOSGeometry.ewkt + +Returns the "extended" Well-Known Text of the geometry. This representation +is specific to PostGIS and is a super set of the OGC WKT standard. [#fnogc]_ +Essentially the SRID is prepended to the WKT representation, for example +``SRID=4326;POINT(5 23)``. + +.. note:: + + The output from this property does not include the 3dm, 3dz, and 4d + information that PostGIS supports in its EWKT representations. + +.. attribute:: GEOSGeometry.hex + +Returns the WKB of this Geometry in hexadecimal form. Please note +that the SRID and Z values are not included in this representation +because it is not a part of the OGC specification (use the +:attr:`GEOSGeometry.hexewkb` property instead). + +.. attribute:: GEOSGeometry.hexewkb + +.. versionadded:: 1.2 + +Returns the EWKB of this Geometry in hexadecimal form. This is an +extension of the WKB specification that includes SRID and Z values +that are a part of this geometry. + +.. note:: + + GEOS 3.1 is *required* if you want valid 3D HEXEWKB. + +.. attribute:: GEOSGeometry.json + +Returns the GeoJSON representation of the geometry. + +.. note:: + + Requires GDAL. + +.. attribute:: GEOSGeometry.geojson + +Alias for :attr:`GEOSGeometry.json`. + +.. attribute:: GEOSGeometry.kml + +Returns a `KML`__ (Keyhole Markup Language) representation of the +geometry. This should only be used for geometries with an SRID of +4326 (WGS84), but this restriction is not enforced. + +.. attribute:: GEOSGeometry.ogr + +Returns an :class:`~django.contrib.gis.gdal.OGRGeometry` object +correspondg to the GEOS geometry. + +.. note:: + + Requires GDAL. + +.. _wkb: + +.. attribute:: GEOSGeometry.wkb + +Returns the WKB (Well-Known Binary) representation of this Geometry +as a Python buffer. SRID and Z values are not included, use the +:attr:`GEOSGeometry.ewkb` property instead. + +.. _ewkb: + +.. attribute:: GEOSGeometry.ewkb + +.. versionadded:: 1.2 + +Return the EWKB representation of this Geometry as a Python buffer. +This is an extension of the WKB specification that includes any SRID +and Z values that are a part of this geometry. + +.. note:: + + GEOS 3.1 is *required* if you want valid 3D EWKB. + +.. attribute:: GEOSGeometry.wkt + +Returns the Well-Known Text of the geometry (an OGC standard). + +__ http://code.google.com/apis/kml/documentation/ + +Spatial Predicate Methods +~~~~~~~~~~~~~~~~~~~~~~~~~ + +All of the following spatial predicate methods take another +:class:`GEOSGeometry` instance (``other``) as a parameter, and +return a boolean. + +.. method:: GEOSGeometry.contains(other) + +Returns ``True`` if :meth:`GEOSGeometry.within` is ``False``. + +.. method:: GEOSGeometry.crosses(other) + +Returns ``True`` if the DE-9IM intersection matrix for the two Geometries +is ``T*T******`` (for a point and a curve,a point and an area or a line +and an area) ``0********`` (for two curves). + +.. method:: GEOSGeometry.disjoint(other) + +Returns ``True`` if the DE-9IM intersection matrix for the two geometries +is ``FF*FF****``. + +.. method:: GEOSGeometry.equals(other) + +Returns ``True`` if the DE-9IM intersection matrix for the two geometries +is ``T*F**FFF*``. + +.. method:: GEOSGeometry.equals_exact(other, tolerance=0) + +Returns true if the two geometries are exactly equal, up to a +specified tolerance. The ``tolerance`` value should be a floating +point number representing the error tolerance in the comparison, e.g., +``poly1.equals_exact(poly2, 0.001)`` will compare equality to within +one thousandth of a unit. + +.. method:: GEOSGeometry.intersects(other) + +Returns ``True`` if :meth:`GEOSGeometry.disjoint` is ``False``. + +.. method:: GEOSGeometry.overlaps(other) + +Returns true if the DE-9IM intersection matrix for the two geometries +is ``T*T***T**`` (for two points or two surfaces) ``1*T***T**`` +(for two curves). + +.. method:: GEOSGeometry.relate_pattern(other, pattern) + +Returns ``True`` if the elements in the DE-9IM intersection matrix +for this geometry and the other matches the given ``pattern`` -- +a string of nine characters from the alphabet: {``T``, ``F``, ``*``, ``0``}. + +.. method:: GEOSGeometry.touches(other) + +Returns ``True`` if the DE-9IM intersection matrix for the two geometries +is ``FT*******``, ``F**T*****`` or ``F***T****``. + +.. method:: GEOSGeometry.within(other) + +Returns ``True`` if the DE-9IM intersection matrix for the two geometries +is ``T*F**F***``. + +Topological Methods +~~~~~~~~~~~~~~~~~~~ + +.. method:: GEOSGeometry.buffer(width, quadsegs=8) + +Returns a :class:`GEOSGeometry` that represents all points whose distance +from this geometry is less than or equal to the given ``width``. The optional +``quadsegs`` keyword sets the number of segments used to approximate a +quarter circle (defaults is 8). + +.. method:: GEOSGeometry.difference(other) + +Returns a :class:`GEOSGeometry` representing the points making up this +geometry that do not make up other. + +.. method:: GEOSGeometry:intersection(other) + +Returns a :class:`GEOSGeometry` representing the points shared by this +geometry and other. + +.. method:: GEOSGeometry.relate(other) + +Returns the DE-9IM intersection matrix (a string) representing the +topological relationship between this geometry and the other. + +.. method:: GEOSGeometry.simplify(tolerance=0.0, preserve_topology=False) + +Returns a new :class:`GEOSGeometry`, simplified using the Douglas-Peucker +algorithm to the specified tolerance. A higher tolerance value implies +less points in the output. If no tolerance is tolerance provided, +it defaults to 0. + +By default, this function does not preserve topology - e.g., +:class:`Polygon` objects can be split, collapsed into lines or disappear. +:class:`Polygon` holes can be created or disappear, and lines can cross. +By specifying ``preserve_topology=True``, the result will have the same +dimension and number of components as the input, however, this is +significantly slower. + +.. method:: GEOSGeometry.sym_difference(other) + +Returns a :class:`GEOSGeometry` combining the points in this geometry +not in other, and the points in other not in this geometry. + +.. method:: GEOSGeometry.union(other) + +Returns a :class:`GEOSGeometry` representing all the points in this +geometry and the other. + +Topological Properties +~~~~~~~~~~~~~~~~~~~~~~ + +.. attribute:: GEOSGeometry.boundary + +Returns the boundary as a newly allocated Geometry object. + +.. attribute:: GEOSGeometry.centroid + +Returns a :class:`Point` object representing the geometric center of +the geometry. The point is not guaranteed to be on the interior +of the geometry. + +.. attribute:: GEOSGeometry.convex_hull + +Returns the smallest :class:`Polygon` that contains all the points in +the geometry. + +.. attribute:: GEOSGeometry.envelope + +Returns a :class:`Polygon` that represents the bounding envelope of +this geometry. + +.. attribute:: GEOSGeometry.point_on_surface + +Computes and returns a :class:`Point` guaranteed to be on the interior +of this geometry. + +Other Properties & Methods +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. attribute:: GEOSGeometry.area + +This property returns the area of the Geometry. + +.. attribute:: GEOSGeometry.extent + +This property returns the extent of this geometry as a 4-tuple, +consisting of (xmin, ymin, xmax, ymax). + +.. method:: GEOSGeometry.clone() + +This method returns a :class:`GEOSGeometry` that is a clone of the original. + +.. method:: GEOSGeometry.distance(geom) + +Returns the distance between the closest points on this geometry and the given +``geom`` (another :class:`GEOSGeometry` object). + +.. note:: + + GEOS distance calculations are linear -- in other words, GEOS does not + perform a spherical calculation even if the SRID specifies a geographic + coordinate system. + +.. attribute:: GEOSGeometry.length + +Returns the length of this geometry (e.g., 0 for a :class:`Point`, +the length of a :class:`LineString`, or the circumference of +a :class:`Polygon`). + +.. attribute:: GEOSGeometry.prepared + +.. versionadded:: 1.1 + +.. note:: + + Support for prepared geometries requires GEOS 3.1. + +Returns a GEOS ``PreparedGeometry`` for the contents of this geometry. +``PreparedGeometry`` objects are optimized for the contains, intersects, +and covers operations. Refer to the :ref:`prepared-geometries` documentation +for more information. + +.. attribute:: GEOSGeometry.srs + +Returns a :class:`~django.contrib.gis.gdal.SpatialReference` object +corresponding to the SRID of the geometry or ``None``. + +.. note:: + + Requires GDAL. + +.. method:: transform(ct, clone=False) + +Transforms the geometry according to the given coordinate transformation paramter +(``ct``), which may be an integer SRID, spatial reference WKT string, +a PROJ.4 string, a :class:`~django.contrib.gis.gdal.SpatialReference` object, or a +:class:`~django.contrib.gis.gdal.CoordTransform` object. By default, the geometry +is transformed in-place and nothing is returned. However if the ``clone`` keyword +is set, then the geometry is not modified and a transformed clone of the geometry +is returned instead. + +.. note:: + + Requires GDAL. + +``Point`` +--------- + +.. class:: Point(x, y, z=None, srid=None) + + ``Point`` objects are instantiated using arguments that represent + the component coordinates of the point or with a single sequence + coordinates. For example, the following are equivalent:: + + >>> pnt = Point(5, 23) + >>> pnt = Point([5, 23]) + +``LineString`` +-------------- + +.. class:: LineString(*args, **kwargs) + + ``LineString`` objects are instantiated using arguments that are + either a sequence of coordinates or :class:`Point` objects. + For example, the following are equivalent:: + + >>> ls = LineString((0, 0), (1, 1)) + >>> ls = LineString(Point(0, 0), Point(1, 1)) + + In addition, ``LineString`` objects may also be created by passing + in a single sequence of coordinate or :class:`Point` objects:: + + >>> ls = LineString( ((0, 0), (1, 1)) ) + >>> ls = LineString( [Point(0, 0), Point(1, 1)] ) + +``LinearRing`` +-------------- + +.. class:: LinearRing(*args, **kwargs) + + ``LinearRing`` objects are constructed in the exact same way as + :class:`LineString` objects, however the coordinates must be + *closed*, in other words, the first coordinates must be the + same as the last coordinates. For example:: + + >>> ls = LinearRing((0, 0), (0, 1), (1, 1), (0, 0)) + + Notice that ``(0, 0)`` is the first and last coordinate -- if + they were not equal, an error would be raised. + +``Polygon`` +----------- + +.. class:: Polygon(*args, **kwargs) + + ``Polygon`` objects may be instantiated by passing in one or + more parameters that represent the rings of the polygon. The + parameters must either be :class:`LinearRing` instances, or + a sequence that may be used to construct a :class:`LinearRing`:: + + >>> ext_coords = ((0, 0), (0, 1), (1, 1), (1, 0), (0, 0)) + >>> int_coords = ((0.4, 0.4), (0.4, 0.6), (0.6, 0.6), (0.6, 0.4), (0.4, 0.4)) + >>> poly = Polygon(ext_coords, int_coords) + >>> poly = Polygon(LinearRing(ext_coords), LinearRing(int_coords)) + + .. classmethod:: from_bbox(bbox) + + .. versionadded:: 1.1 + + Returns a polygon object from the given bounding-box, a 4-tuple + comprising (xmin, ymin, xmax, ymax). + + .. attribute:: num_interior_rings + + Returns the number of interior rings in this geometry. + +Geometry Collections +==================== + +``MultiPoint`` +-------------- + +.. class:: MultiPoint(*args, **kwargs) + + ``MultiPoint`` objects may be instantiated by passing in one + or more :class:`Point` objects as arguments, or a single + sequence of :class:`Point` objects:: + + >>> mp = MultiPoint(Point(0, 0), Point(1, 1)) + >>> mp = MultiPoint( (Point(0, 0), Point(1, 1)) ) + +``MultiLineString`` +------------------- + +.. class:: MultiLineString(*args, **kwargs) + + ``MultiLineString`` objects may be instantiated by passing in one + or more :class:`LineString` objects as arguments, or a single + sequence of :class:`LineString` objects:: + + >>> ls1 = LineString((0, 0), (1, 1)) + >>> ls2 = LineString((2, 2), (3, 3)) + >>> mls = MultiLineString(ls1, ls2) + >>> mls = MultiLineString([ls1, ls2]) + + .. attribute:: merged + + .. versionadded:: 1.1 + + Returns a :class:`LineString` representing the line merge of + all the components in this ``MultiLineString``. + + +``MultiPolygon`` +---------------- + +.. class:: MultiPolygon(*args, **kwargs) + + ``MultiPolygon`` objects may be instantiated by passing one or + more :class:`Polygon` objects as arguments, or a single sequence + of :class:`Polygon` objects:: + + >>> p1 = Polygon( ((0, 0), (0, 1), (1, 1), (0, 0)) ) + >>> p2 = Polygon( ((1, 1), (1, 2), (2, 2), (1, 1)) ) + >>> mp = MultiPolygon(p1, p2) + >>> mp = MultiPolygon([p1, p2]) + + .. attribute:: cascaded_union + + .. versionadded:: 1.1 + + Returns a :class:`Polygon` that is the union of all of the component + polygons in this collection. The algorithm employed is significantly + more efficient (faster) than trying to union the geometries together + individually. [#fncascadedunion]_ + + .. note:: + + GEOS 3.1 is *required* to peform cascaded unions. + +``GeometryCollection`` +---------------------- + +.. class:: GeometryCollection(*args, **kwargs) + + ``GeometryCollection`` objects may be instantiated by passing in + one or more other :class:`GEOSGeometry` as arguments, or a single + sequence of :class:`GEOSGeometry` objects:: + + >>> poly = Polygon( ((0, 0), (0, 1), (1, 1), (0, 0)) ) + >>> gc = GeometryCollection(Point(0, 0), MultiPoint(Point(0, 0), Point(1, 1)), poly) + >>> gc = GeometryCollection((Point(0, 0), MultiPoint(Point(0, 0), Point(1, 1)), poly)) + +.. _prepared-geometries: + +Prepared Geometries +=================== + +.. versionadded: 1.1 + +In order to obtain a prepared geometry, just access the +:attr:`GEOSGeometry.prepared` property. Once you have a +``PreparedGeometry`` instance its spatial predicate methods, listed below, +may be used with other ``GEOSGeometry`` objects. An operation with a prepared +geometry can be orders of magnitude faster -- the more complex the geometry +that is prepared, the larger the speedup in the operation. For more information, +please consult the `GEOS wiki page on prepared geometries `_. + +.. note:: + + GEOS 3.1 is *required* in order to use prepared geometries. + +For example:: + + >>> from django.contrib.gis.geos import Point, Polygon + >>> poly = Polygon.from_bbox((0, 0, 5, 5)) + >>> prep_poly = poly.prepared + >>> prep_poly.contains(Point(2.5, 2.5)) + True + +``PreparedGeometry`` +-------------------- + +.. class:: PreparedGeometry + + All methods on ``PreparedGeometry`` take an ``other`` argument, which + must be a :class:`GEOSGeometry` instance. + + .. method:: contains(other) + + .. method:: contains_properly(other) + + .. method:: covers(other) + + .. method:: intersects(other) + +Geometry Factories +================== + +.. function:: fromfile(file_h) + + :param file_h: input file that contains spatial data + :type file_h: a Python ``file`` object or a string path to the file + :rtype: a :class:`GEOSGeometry` corresponding to the spatial data in the file + +Example:: + + >>> from django.contrib.gis.geos import fromfile + >>> g = fromfile('/home/bob/geom.wkt') + +.. function:: fromstr(string, [,srid=None]) + + :param string: string that contains spatial data + :type string: string + :param srid: spatial reference identifier + :type srid: integer + :rtype: a :class:`GEOSGeometry` corresponding to the spatial data in the string + +Example:: + + >>> from django.contrib.gis.geos import fromstr + >>> pnt = fromstr('POINT(-90.5 29.5)', srid=4326) + +I/O Objects +=========== + +.. versionadded: 1.1 + +Reader Objects +-------------- + +The reader I/O classes simply return a :class:`GEOSGeometry` instance from the +WKB and/or WKT input given to their ``read(geom)`` method. + +.. class:: WKBReader + +Example:: + + >>> from django.contrib.gis.geos import WKBReader + >>> wkb_r = WKBReader() + >>> wkb_r.read('0101000000000000000000F03F000000000000F03F') + + +.. class:: WKTReader + +Example:: + + >>> from django.contrib.gis.geos import WKTReader + >>> wkt_r = WKTReader() + >>> wkt_r.read('POINT(1 1)') + + +Writer Objects +-------------- + +All writer objects have a ``write(geom)`` method that returns either the +WKB or WKT of the given geometry. In addition, :class:`WKBWriter` objects +also have properties that may be used to change the byte order, and or +include the SRID and 3D values (in other words, EWKB). + +.. class:: WKBWriter + +``WKBWriter`` provides the most control over its output. By default it +returns OGC-compliant WKB when it's ``write`` method is called. However, +it has properties that allow for the creation of EWKB, a superset of the +WKB standard that includes additional information. + +.. method:: WKBWriter.write(geom) + +Returns the WKB of the given geometry as a Python ``buffer`` object. +Example:: + + >>> from django.contrib.gis.geos import Point, WKBWriter + >>> pnt = Point(1, 1) + >>> wkb_w = WKBWriter() + >>> wkb_w.write(pnt) + + +.. method:: WKBWriter.write_hex(geom) + +Returns WKB of the geometry in hexadecimal. Example:: + + >>> from django.contrib.gis.geos import Point, WKBWriter + >>> pnt = Point(1, 1) + >>> wkb_w = WKBWriter() + >>> wkb_w.write_hex(pnt) + '0101000000000000000000F03F000000000000F03F' + +.. attribute:: WKBWriter.byteorder + +This property may be be set to change the byte-order of the geometry +representation. + +=============== ================================================= +Byteorder Value Description +=============== ================================================= +0 Big Endian (e.g., compatible with RISC systems) +1 Little Endian (e.g., compatible with x86 systems) +=============== ================================================= + +Example:: + + >>> from django.contrib.gis.geos import Point, WKBWriter + >>> wkb_w = WKBWriter() + >>> pnt = Point(1, 1) + >>> wkb_w.write_hex(pnt) + '0101000000000000000000F03F000000000000F03F' + >>> wkb_w.byteorder = 0 + '00000000013FF00000000000003FF0000000000000' + +.. attribute:: WKBWriter.outdim + +This property may be set to change the output dimension of the geometry +representation. In other words, if you have a 3D geometry then set to 3 +so that the Z value is included in the WKB. + +============ =========================== +Outdim Value Description +============ =========================== +2 The default, output 2D WKB. +3 Output 3D EWKB. +============ =========================== + +Example:: + + >>> from django.contrib.gis.geos import Point, WKBWriter + >>> wkb_w = WKBWriter() + >>> wkb_w.outdim + 2 + >>> pnt = Point(1, 1, 1) + >>> wkb_w.write_hex(pnt) # By default, no Z value included: + '0101000000000000000000F03F000000000000F03F' + >>> wkb_w.outdim = 3 # Tell writer to include Z values + >>> wkb_w.write_hex(pnt) + '0101000080000000000000F03F000000000000F03F000000000000F03F' + +.. attribute:: WKBWriter.srid + +Set this property with a boolean to indicate whether the SRID of the +geometry should be included with the WKB representation. Example:: + + >>> from django.contrib.gis.geos import Point, WKBWriter + >>> wkb_w = WKBWriter() + >>> pnt = Point(1, 1, srid=4326) + >>> wkb_w.write_hex(pnt) # By default, no SRID included: + '0101000000000000000000F03F000000000000F03F' + >>> wkb_w.srid = True # Tell writer to include SRID + >>> wkb_w.write_hex(pnt) + '0101000020E6100000000000000000F03F000000000000F03F' + +.. class:: WKTWriter + +.. method:: WKTWriter.write(geom) + +Returns the WKT of the given geometry. Example:: + + >>> from django.contrib.gis.geos import Point, WKTWriter + >>> pnt = Point(1, 1) + >>> wkt_w = WKTWriter() + >>> wkt_w.write(pnt) + 'POINT (1.0000000000000000 1.0000000000000000)' + + +.. rubric:: Footnotes +.. [#fnogc] *See* `PostGIS EWKB, EWKT and Canonical Forms `_, PostGIS documentation at Ch. 4.1.2. +.. [#fncascadedunion] For more information, read Paul Ramsey's blog post about `(Much) Faster Unions in PostGIS 1.4 `_ and Martin Davis' blog post on `Fast polygon merging in JTS using Cascaded Union `_. + +Settings +======== + +.. setting:: GEOS_LIBRARY_PATH + +GEOS_LIBRARY_PATH +----------------- + +A string specifying the location of the GEOS C library. Typically, +this setting is only used if the GEOS C library is in a non-standard +location (e.g., ``/home/bob/lib/libgeos_c.so``). + +.. note:: + + The setting must be the *full* path to the **C** shared library; in + other words you want to use ``libgeos_c.so``, not ``libgeos.so``. diff --git a/docs/ref/contrib/gis/index.txt b/docs/ref/contrib/gis/index.txt new file mode 100644 index 0000000000..074fa3a7b6 --- /dev/null +++ b/docs/ref/contrib/gis/index.txt @@ -0,0 +1,33 @@ +.. _ref-contrib-gis: + +========= +GeoDjango +========= + +.. versionadded:: 1.0 + +.. module:: django.contrib.gis + :synopsis: Geographic Information System (GIS) extensions for Django + +GeoDjango intends to be a world-class geographic web framework. Its goal is to +make it as easy as possible to build GIS web applications and harness the power +of spatially enabled data. + +.. toctree:: + :maxdepth: 2 + + tutorial + install + model-api + db-api + geoquerysets + measure + geos + gdal + utils + commands + admin + feeds + sitemaps + testing + deployment diff --git a/docs/ref/contrib/gis/install.txt b/docs/ref/contrib/gis/install.txt new file mode 100644 index 0000000000..3f378fe924 --- /dev/null +++ b/docs/ref/contrib/gis/install.txt @@ -0,0 +1,1190 @@ +.. _ref-gis-install: + +====================== +GeoDjango Installation +====================== + +Overview +======== +In general, GeoDjango installation requires: + +1. :ref:`python24` and :ref:`django` +2. :ref:`spatial_database` +3. :ref:`geospatial_libs` + +Details for each of the requirements and installation instructions +are provided in the sections below. In addition, platform-specific +instructions are available for: + +* :ref:`macosx` +* :ref:`ubuntudebian` +* :ref:`windows` + +.. admonition:: Use the Source + + Because GeoDjango takes advantage of the latest in the open source geospatial + software technology, recent versions of the libraries are necessary. + If binary packages aren't available for your platform, + :ref:`installation from source ` + may be required. When compiling the libraries from source, please follow the + directions closely, especially if you're a beginner. + +Requirements +============ + +.. _python24: + +Python 2.4+ +----------- +Because of heavy use of the decorator syntax, Python 2.4 is minimum +version supported by GeoDjango. Python 2.5+ is recommended because the +`ctypes`__ module comes included; otherwise, 2.4 users will need to +`download and install ctypes`__. + +__ http://docs.python.org/lib/module-ctypes.html +__ http://sourceforge.net/projects/ctypes/files/ + +.. _django: + +Django +------ + +Because GeoDjango is included with Django, please refer to Django's +:ref:`installation instructions ` for details on how to install. + +.. _spatial_database: + +Spatial Database +---------------- +PostgreSQL (with PostGIS), MySQL, Oracle, and SQLite (with SpatiaLite) are +the spatial databases currently supported. + +.. note:: + + PostGIS is recommended, because it is the most mature and feature-rich + open source spatial database. + +The geospatial libraries required for a GeoDjango installation depends +on the spatial database used. The following lists the library requirements, +supported versions, and any notes for each of the supported database backends: + +================== ============================== ================== ========================================================== +Database Library Requirements Supported Versions Notes +================== ============================== ================== ========================================================== +PostgreSQL GEOS, PROJ.4, PostGIS 8.1+ Requires PostGIS. +MySQL GEOS 5.x Not OGC-compliant; limited functionality. +Oracle GEOS 10.2, 11 XE not supported; not tested with 9. +SQLite GEOS, GDAL, PROJ.4, SpatiaLite 3.6.+ Requires SpatiaLite 2.3+, pysqlite2 2.5+, and Django 1.1. +================== ============================== ================== ========================================================== + +.. _geospatial_libs: + +Geospatial Libraries +-------------------- +GeoDjango uses and/or provides interfaces for the the following open source +geospatial libraries: + +======================== ==================================== ================================ ========================== +Program Description Required Supported Versions +======================== ==================================== ================================ ========================== +:ref:`GEOS ` Geometry Engine Open Source Yes 3.2, 3.1, 3.0 +`PROJ.4`_ Cartographic Projections library Yes (PostgreSQL and SQLite only) 4.7, 4.6, 4.5, 4.4 +:ref:`GDAL ` Geospatial Data Abstraction Library No (but, required for SQLite) 1.6, 1.5, 1.4 +:ref:`GeoIP ` IP-based geolocation library No 1.4 +`PostGIS`__ Spatial extensions for PostgreSQL Yes (PostgreSQL only) 1.5, 1.4, 1.3 +`SpatiaLite`__ Spatial extensions for SQLite Yes (SQLite only) 2.4, 2.3 +======================== ==================================== ================================ ========================== + +.. admonition:: Install GDAL + + While :ref:`gdalbuild` is technically not required, it is *recommended*. + Some features of GeoDjango (including the :ref:`ref-layermapping` and the geographic + admin) depend on its functionality. + +.. note:: + + The GeoDjango interfaces to GEOS, GDAL, and GeoIP may be used + independently of Django. In other words, no database or settings file + required -- just import them as normal from :mod:`django.contrib.gis`. + +.. _PROJ.4: http://trac.osgeo.org/proj/ +__ http://postgis.refractions.net/ +__ http://www.gaia-gis.it/spatialite/index.html + +.. _build_from_source: + +Building from Source +==================== + +When installing from source on UNIX and GNU/Linux systems, please follow +the installation instructions carefully, and install the libraries in the +given order. If using MySQL or Oracle as the spatial database, only GEOS +is required. + +.. note:: + + On Linux platforms, it may be necessarry to run the ``ldconfig`` + command after installing each library. For example:: + + $ sudo make install + $ sudo ldconfig + +.. note:: + + OS X users are required to install `Apple Developer Tools`_ in order + to compile software from source. This is typically included on your + OS X installation DVDs. + +.. _Apple Developer Tools: http://developer.apple.com/tools/xcode/ + +.. _geosbuild: + +GEOS +---- + +GEOS is a C++ library for performing geometric operations, and is the default +internal geometry representation used by GeoDjango (it's behind the "lazy" +geometries). Specifically, the C API library is called (e.g., ``libgeos_c.so``) +directly from Python using ctypes. + +First, download GEOS 3.2 from the refractions website and untar the source +archive:: + + $ wget http://download.osgeo.org/geos/geos-3.2.0.tar.bz2 + $ tar xjf geos-3.2.0.tar.bz2 + +Next, change into the directory where GEOS was unpacked, run the configure +script, compile, and install:: + + $ cd geos-3.2.0 + $ ./configure + $ make + $ sudo make install + $ cd .. + +Troubleshooting +^^^^^^^^^^^^^^^ + +Can't find GEOS Library +~~~~~~~~~~~~~~~~~~~~~~~ + +When GeoDjango can't find GEOS, this error is raised:: + + ImportError: Could not find the GEOS library (tried "geos_c"). Try setting GEOS_LIBRARY_PATH in your settings. + +The most common solution is to properly configure your :ref:`libsettings` *or* set +:ref:`geoslibrarypath` in your settings. + +If using a binary package of GEOS (e.g., on Ubuntu 8.10), you may need to :ref:`binutils`. + +.. _geoslibrarypath: + +``GEOS_LIBRARY_PATH`` +~~~~~~~~~~~~~~~~~~~~~ + +If your GEOS library is in a non-standard location, or you don't want to +modify the system's library path then the :setting:`GEOS_LIBRARY_PATH` setting +may be added to your Django settings file with the full path to the GEOS +C library. For example:: + + GEOS_LIBRARY_PATH = '/home/bob/local/lib/libgeos_c.so' + +.. note:: + + The setting must be the *full* path to the **C** shared library; in + other words you want to use ``libgeos_c.so``, not ``libgeos.so``. + +.. _proj4: + +PROJ.4 +------ + +`PROJ.4`_ is a library for converting geospatial data to different coordinate +reference systems. + +First, download the PROJ.4 source code and datum shifting files [#]_:: + + $ wget http://download.osgeo.org/proj/proj-4.7.0.tar.gz + $ wget http://download.osgeo.org/proj/proj-datumgrid-1.5.zip + +Next, untar the source code archive, and extract the datum shifting files in the +``nad`` subdirectory. This must be done *prior* to configuration:: + + $ tar xzf proj-4.7.0.tar.gz + $ cd proj-4.7.0/nad + $ unzip ../../proj-datumgrid-1.5.zip + $ cd .. + +Finally, configure, make and install PROJ.4:: + + $ ./configure + $ make + $ sudo make install + $ cd .. + +.. _postgis: + +PostGIS +------- + +`PostGIS`__ adds geographic object support to PostgreSQL, turning it +into a spatial database. :ref:`geosbuild` and :ref:`proj4` should be +installed prior to building PostGIS. + +.. note:: + + The `psycopg2`_ module is required for use as the database adaptor + when using GeoDjango with PostGIS. + +.. _psycopg2: http://initd.org/projects/psycopg2 + +First download the source archive, and extract:: + + $ wget http://postgis.refractions.net/download/postgis-1.5.1.tar.gz + $ tar xzf postgis-1.5.1.tar.gz + $ cd postgis-1.5.1 + +Next, configure, make and install PostGIS:: + + $ ./configure + +Finally, make and install:: + + $ make + $ sudo make install + $ cd .. + +.. note:: + + GeoDjango does not automatically create a spatial database. Please + consult the section on :ref:`spatialdb_template` for more information. + +__ http://postgis.refractions.net/ + +.. _gdalbuild: + +GDAL +---- + +`GDAL`__ is an excellent open source geospatial library that has support for +reading most vector and raster spatial data formats. Currently, GeoDjango only +supports :ref:`GDAL's vector data ` capabilities [#]_. +:ref:`geosbuild` and :ref:`proj4` should be installed prior to building GDAL. + +First download the latest GDAL release version and untar the archive:: + + $ wget http://download.osgeo.org/gdal/gdal-1.7.1.tar.gz + $ tar xzf gdal-1.7.1.tar.gz + $ cd gdal-1.7.1 + +Configure, make and install:: + + $ ./configure + $ make # Go get some coffee, this takes a while. + $ sudo make install + $ cd .. + +.. note:: + + Because GeoDjango has it's own Python interface, the preceding instructions + do not build GDAL's own Python bindings. The bindings may be built by + adding the ``--with-python`` flag when running ``configure``. See + `GDAL/OGR In Python`__ for more information on GDAL's bindings. + +If you have any problems, please see the troubleshooting section below for +suggestions and solutions. + +__ http://trac.osgeo.org/gdal/ +__ http://trac.osgeo.org/gdal/wiki/GdalOgrInPython + +.. _gdaltrouble: + +Troubleshooting +^^^^^^^^^^^^^^^ + +Can't find GDAL Library +~~~~~~~~~~~~~~~~~~~~~~~ + +When GeoDjango can't find the GDAL library, the ``HAS_GDAL`` flag +will be false:: + + >>> from django.contrib.gis import gdal + >>> gdal.HAS_GDAL + False + +The solution is to properly configure your :ref:`libsettings` *or* set +:ref:`gdallibrarypath` in your settings. + +.. _gdallibrarypath: + +``GDAL_LIBRARY_PATH`` +~~~~~~~~~~~~~~~~~~~~~ + +If your GDAL library is in a non-standard location, or you don't want to +modify the system's library path then the :setting:`GDAL_LIBRARY_PATH` +setting may be added to your Django settings file with the full path to +the GDAL library. For example:: + + GDAL_LIBRARY_PATH = '/home/sue/local/lib/libgdal.so' + +.. _gdaldata: + +Can't find GDAL data files (``GDAL_DATA``) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When installed from source, GDAL versions 1.5.1 and below have an autoconf bug +that places data in the wrong location. [#]_ This can lead to error messages +like this:: + + ERROR 4: Unable to open EPSG support file gcs.csv. + ... + OGRException: OGR failure. + +The solution is to set the ``GDAL_DATA`` environment variable to the location of the +GDAL data files before invoking Python (typically ``/usr/local/share``; use +``gdal-config --datadir`` to find out). For example:: + + $ export GDAL_DATA=`gdal-config --datadir` + $ python manage.py shell + +If using Apache, you may need to add this environment variable to your configuration +file:: + + SetEnv GDAL_DATA /usr/local/share + +.. _spatialite: + +SpatiaLite +---------- +.. versionadded:: 1.1 + +.. note:: + + Mac OS X users should follow the instructions in the :ref:`kyngchaos` section, + as it is much easier than building from source. + +`SpatiaLite`__ adds spatial support to SQLite, turning it into a full-featured +spatial database. Because SpatiaLite has special requirements, it typically +requires SQLite and pysqlite2 (the Python SQLite DB-API adaptor) to be built from +source. :ref:`geosbuild` and :ref:`proj4` should be installed prior to building +SpatiaLite. + +After installation is complete, don't forget to read the post-installation +docs on :ref:`create_spatialite_db`. + +__ http://www.gaia-gis.it/spatialite/index.html + +.. _sqlite: + +SQLite +^^^^^^ + +Typically, SQLite packages are not compiled to include the `R*Tree module`__ -- +thus it must be compiled from source. First download the latest amalgamation +source archive from the `SQLite download page`__, and extract:: + + $ wget http://www.sqlite.org/sqlite-amalgamation-3.6.22.tar.gz + $ tar xzf sqlite-amalgamation-3.6.22.tar.gz + $ cd sqlite-3.6.22 + +Next, run the ``configure`` script -- however the ``CFLAGS`` environment variable +needs to be customized so that SQLite knows to build the R*Tree module:: + + $ CFLAGS="-DSQLITE_ENABLE_RTREE=1" ./configure + $ make + $ sudo make install + $ cd .. + +.. note:: + + If using Ubuntu, installing a newer SQLite from source can be very difficult + because it links to the existing ``libsqlite3.so`` in ``/usr/lib`` which + many other packages depend on. Unfortunately, the best solution at this time + is to overwrite the existing library by adding ``--prefix=/usr`` to the + ``configure`` command. + +__ http://www.sqlite.org/rtree.html +__ http://www.sqlite.org/download.html + +.. _spatialitebuild : + +SpatiaLite Library (``libspatialite``) and Tools (``spatialite``) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +After SQLite has been built with the R*Tree module enabled, get the latest +SpatiaLite library source and tools bundle from the `download page`__:: + + $ wget http://www.gaia-gis.it/spatialite/libspatialite-amalgamation-2.3.1.tar.gz + $ wget http://www.gaia-gis.it/spatialite/spatialite-tools-2.3.1.tar.gz + $ tar xzf libspatialite-amalgamation-2.3.1.tar.gz + $ tar xzf spatialite-tools-2.3.1.tar.gz + +Prior to attempting to build, please read the important notes below to see if +customization of the ``configure`` command is necessary. If not, then run the +``configure`` script, make, and install for the SpatiaLite library:: + + $ cd libspatialite-amalgamation-2.3.1 + $ ./configure # May need to modified, see notes below. + $ make + $ sudo make install + $ cd .. + +Finally, do the same for the SpatiaLite tools:: + + $ cd spatialite-tools-2.3.1 + $ ./configure # May need to modified, see notes below. + $ make + $ sudo make install + $ cd .. + +.. note:: + + If you've installed GEOS and PROJ.4 from binary packages, you will have to specify + their paths when running the ``configure`` scripts for *both* the library and the + tools (the configure scripts look, by default, in ``/usr/local``). For example, + on Debian/Ubuntu distributions that have GEOS and PROJ.4 packages, the command would be:: + + $ ./configure --with-proj-include=/usr/include --with-proj-lib=/usr/lib --with-geos-include=/usr/include --with-geos-lib=/usr/lib + +.. note:: + + For Mac OS X users building from source, the SpatiaLite library *and* tools + need to be linked into the existing ``iconv`` library. While this happens + automatically on Linux, the ``configure`` scripts need to know about the + specific location on Mac OS X (via modification of the ``CFLAGS`` and + ``LDFLAGS`` environment variables prior to configuration):: + + $ CFLAGS=-I/usr/include LDFLAGS="-L/usr/lib -liconv" ./configure + +__ http://www.gaia-gis.it/spatialite/sources.html + +.. _pysqlite2: + +pysqlite2 +^^^^^^^^^ + +Because SpatiaLite must be loaded as an external extension, it requires the +``enable_load_extension`` method, which is only available in versions 2.5+. +Thus, download pysqlite2 2.5, and untar:: + + $ wget http://pysqlite.googlecode.com/files/pysqlite-2.5.6.tar.gz + $ tar xzf pysqlite-2.5.6.tar.gz + $ cd pysqlite-2.5.6 + +Next, use a text editor (e.g., ``emacs`` or ``vi``) to edit the ``setup.cfg`` file +to look like the following:: + + [build_ext] + #define= + include_dirs=/usr/local/include + library_dirs=/usr/local/lib + libraries=sqlite3 + #define=SQLITE_OMIT_LOAD_EXTENSION + +.. note:: + + The important thing here is to make sure you comment out the the + ``define=SQLITE_OMIT_LOAD_EXTENSION`` flag and that the ``include_dirs`` + and ``library_dirs`` settings are uncommented and set to the appropriate + path if the SQLite header files and libraries are not in ``/usr/include`` + and ``/usr/lib``, respectively. + +After modifying ``setup.cfg`` appropriately, then run the ``setup.py`` script +to build and install:: + + $ sudo python setup.py install + +Post-Installation +================= + +.. _spatialdb_template: + +Creating a Spatial Database Template for PostGIS +------------------------------------------------ + +Creating a spatial database with PostGIS is different than normal because +additional SQL must be loaded to enable spatial functionality. Because of +the steps in this process, it's better to create a database template that +can be reused later. + +First, you need to be able to execute the commands as a privileged database +user. For example, you can use the following to become the ``postgres`` user:: + + $ sudo su - postgres + +.. note:: + + The location *and* name of the PostGIS SQL files (e.g., from + ``POSTGIS_SQL_PATH`` below) depends on the version of PostGIS. + PostGIS versions 1.3 and below use ``/contrib/lwpostgis.sql``, whereas + versions 1.4 and 1.5 use ``/contrib/postgis-1.4/postgis.sql`` and + ``/contrib/postgis-1.5/postgis.sql``, respectively. + + The example below assumes 1.5, thus you may need to modify + ``POSTGIS_SQL_PATH`` and the name of the SQL file for the specific + version of PostGIS you are using. + +Once you're a database super user, then you may execute the following commands +to create a PostGIS spatial database template. If running Ubuntu :ref:`ibex` +or Debian :ref:`lenny`, please refer to their specific documentation for +modifications to these commands:: + + $ POSTGIS_SQL_PATH=`pg_config --sharedir`/contrib/postgis-1.5 + # Creating the template spatial database. + $ createdb -E UTF8 template_postgis + $ createlang -d template_postgis plpgsql # Adding PLPGSQL language support. + # Allows non-superusers the ability to create from this template + $ psql -d postgres -c "UPDATE pg_database SET datistemplate='true' WHERE datname='template_postgis';" + # Loading the PostGIS SQL routines + $ psql -d template_postgis -f $POSTGIS_SQL_PATH/postgis.sql + $ psql -d template_postgis -f $POSTGIS_SQL_PATH/spatial_ref_sys.sql + # Enabling users to alter spatial tables. + $ psql -d template_postgis -c "GRANT ALL ON geometry_columns TO PUBLIC;" + $ psql -d template_postgis -c "GRANT ALL ON spatial_ref_sys TO PUBLIC;" + + + + +These commands may be placed in a shell script for later use; for convenience +the following scripts are available: + +=============== ========================================== +PostGIS Version Shell Script +=============== ========================================== +1.3 :download:`create_template_postgis-1.3.sh` +1.4 :download:`create_template_postgis-1.4.sh` +1.5 :download:`create_template_postgis-1.5.sh` +=============== ========================================== + +Afterwards, you may create a spatial database by simply specifying +``template_postgis`` as the template to use (via the ``-T`` option):: + + $ createdb -T template_postgis + +.. note:: + + While the ``createdb`` command does not require database super-user privileges, + it must be executed by a database user that has permissions to create databases. + You can create such a user with the following command:: + + $ createuser --createdb + +.. _create_spatialite_db: + +Creating a Spatial Database for SpatiaLite +------------------------------------------- + +After the SpatiaLite library and tools have been installed, it is now possible +to create spatial database for use with GeoDjango. In order to do this, download +the spatial database initialization SQL from the `SpatiaLite Resources`__ page:: + + $ wget http://www.gaia-gis.it/spatialite/init_spatialite-2.3.sql.gz + $ gunzip init_spatialite-2.3.sql.gz + +Now, the ``spatialite`` command can be used to initialize a spatial database:: + + $ spatialite geodjango.db < init_spatialite-2.3.sql + +.. note:: + + The parameter ``geodjango.db`` is the *filename* of the SQLite database + you want to use. Use the same in the :setting:`DATABASE_NAME` + inside your ``settings.py``. + + +__ http://www.gaia-gis.it/spatialite/resources.html + + +Add ``django.contrib.gis`` to ``INSTALLED_APPS`` +------------------------------------------------ + +Like other Django contrib applications, you will *only* need to add +:mod:`django.contrib.gis` to :setting:`INSTALLED_APPS` in your settings. +This is the so that ``gis`` templates can be located -- if not done, then +features such as the geographic admin or KML sitemaps will not function properly. + +.. _addgoogleprojection: + +Add Google Projection to ``spatial_ref_sys`` table +-------------------------------------------------- + +.. versionchanged:: 1.2 + +.. note:: + + If running PostGIS 1.4 and above, the entry is already included in the + default ``spatial_ref_sys`` table. You can skip this step. + +In order to conduct database transformations to the so-called "Google" +projection (a spherical mercator projection used by Google Maps), +an entry must be added to your spatial database's ``spatial_ref_sys`` table. +Invoke the Django shell from your project and execute the +``add_srs_entry`` function:: + + $ python manage shell + >>> from django.contrib.gis.utils import add_srs_entry + >>> add_srs_entry(900913) + +.. note:: + + In Django 1.1 the name of this function is ``add_postgis_srs``. + +This adds an entry for the 900913 SRID to the ``spatial_ref_sys`` (or equivalent) +table, making it possible for the spatial database to transform coordinates in +this projection. You only need to execute this command *once* per spatial database. + +Troubleshooting +=============== + +If you can't find the solution to your problem here then participate in the +community! You can: + +* Join the ``#geodjango`` IRC channel on FreeNode (may be accessed on the + web via `Mibbit`__). Please be patient and polite -- while you may not + get an immediate response, someone will attempt to answer your question + as soon as they see it. +* Ask your question on the `GeoDjango`__ mailing list. +* File a ticket on the `Django trac`__ if you think there's a bug. Make + sure to provide a complete description of the problem, versions used, + and specify the component as "GIS". + +__ http://www.mibbit.com/?server=irc.freenode.net&channel=%23geodjango +__ http://groups.google.com/group/geodjango +__ http://code.djangoproject.com/simpleticket + +.. _libsettings: + +Library Environment Settings +---------------------------- + +By far, the most common problem when installing GeoDjango is that the +external shared libraries (e.g., for GEOS and GDAL) cannot be located. [#]_ +Typically, the cause of this problem is that the operating system isn't aware +of the directory where the libraries built from source were installed. + +In general, the library path may be set on a per-user basis by setting +an environment variable, or by configuring the library path for the entire +system. + +``LD_LIBRARY_PATH`` environment variable +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A user may set this environment variable to customize the library paths +they want to use. The typical library directory for software +built from source is ``/usr/local/lib``. Thus, ``/usr/local/lib`` needs +to be included in the ``LD_LIBRARY_PATH`` variable. For example, the user +could place the following in their bash profile:: + + export LD_LIBRARY_PATH=/usr/local/lib + +Setting System Library Path +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +On GNU/Linux systems, there is typically a file in ``/etc/ld.so.conf``, which may include +additional paths from files in another directory, such as ``/etc/ld.so.conf.d``. +As the root user, add the custom library path (like ``/usr/local/lib``) on a +new line in ``ld.so.conf``. This is *one* example of how to do so:: + + $ sudo echo /usr/local/lib >> /etc/ld.so.conf + $ sudo ldconfig + +For OpenSolaris users, the system library path may be modified using the +``crle`` utility. Run ``crle`` with no options to see the current configuration +and use ``crle -l`` to set with the new library path. Be *very* careful when +modifying the system library path:: + + # crle -l $OLD_PATH:/usr/local/lib + +.. _binutils: + +Install ``binutils`` +^^^^^^^^^^^^^^^^^^^^ + +GeoDjango uses the ``find_library`` function (from the ``ctypes.util`` Python +module) to discover libraries. The ``find_library`` routine uses a program +called ``objdump`` (part of the ``binutils`` package) to verify a shared +library on GNU/Linux systems. Thus, if ``binutils`` is not installed on your +Linux system then Python's ctypes may not be able to find your library even if +your library path is set correctly and geospatial libraries were built perfectly. + +The ``binutils`` package may be installed on Debian and Ubuntu systems using the +following command:: + + $ sudo apt-get install binutils + +Similarly, on Red Hat and CentOS systems:: + + $ sudo yum install binutils + +Platform Specific Instructions +============================== + +.. _macosx: + +Mac OS X +-------- + +Because of the variety of packaging systems available for OS X, users have +several different options for installing GeoDjango. These options are: + +* :ref:`kyngchaos` +* :ref:`fink` +* :ref:`macports` +* :ref:`build_from_source` + +.. note:: + + Currently, the easiest and recommended approach for installing GeoDjango + on OS X is to use the KyngChaos packages. + +This section also includes instructions for installing an upgraded version +of :ref:`macosx_python` from packages provided by the Python Software +Foundation, however, this is not required. + +.. _macosx_python: + +Python +^^^^^^ + +Although OS X comes with Python installed, users can use framework +installers (`2.5`__ and `2.6`__ are available) provided by +the Python Software Foundation. An advantage to using the installer is +that OS X's Python will remain "pristine" for internal operating system +use. + +__ http://python.org/ftp/python/2.5.4/python-2.5.4-macosx.dmg +__ http://python.org/ftp/python/2.6.2/python-2.6.2-macosx2009-04-16.dmg + +.. note:: + + You will need to modify the ``PATH`` environment variable in your + ``.profile`` file so that the new version of Python is used when + ``python`` is entered at the command-line:: + + export PATH=/Library/Frameworks/Python.framework/Versions/Current/bin:$PATH + +.. _kyngchaos: + +KyngChaos Packages +^^^^^^^^^^^^^^^^^^ + +William Kyngesburye provides a number of `geospatial library binary packages`__ +that make it simple to get GeoDjango installed on OS X without compiling +them from source. However, the `Apple Developer Tools`_ are still necessary +for compiling the Python database adapters :ref:`psycopg2_kyngchaos` (for PostGIS) +and :ref:`pysqlite2_kyngchaos` (for SpatiaLite). + +.. note:: + + SpatiaLite users should consult the :ref:`spatialite_kyngchaos` section + after installing the packages for additional instructions. + +Download the framework packages for: + +* UnixImageIO +* PROJ +* GEOS +* SQLite3 (includes the SpatiaLite library) +* GDAL + +Install the packages in the order they are listed above, as the GDAL and SQLite +packages require the packages listed before them. Afterwards, you can also +install the KyngChaos binary packages for `PostgreSQL and PostGIS`__. + +After installing the binary packages, you'll want to add the following to +your ``.profile`` to be able to run the package programs from the command-line:: + + export PATH=/Library/Frameworks/UnixImageIO.framework/Programs:$PATH + export PATH=/Library/Frameworks/PROJ.framework/Programs:$PATH + export PATH=/Library/Frameworks/GEOS.framework/Programs:$PATH + export PATH=/Library/Frameworks/SQLite3.framework/Programs:$PATH + export PATH=/Library/Frameworks/GDAL.framework/Programs:$PATH + export PATH=/usr/local/pgsql/bin:$PATH + +__ http://www.kyngchaos.com/wiki/software:frameworks +__ http://www.kyngchaos.com/wiki/software:postgres + +.. note:: + + Use of these binaries requires Django 1.0.3 and above. If you are + using a previous version of Django (like 1.0.2), then you will have + to add the the following in your settings:: + + GEOS_LIBRARY_PATH='/Library/Frameworks/GEOS.framework/GEOS' + GDAL_LIBRARY_PATH='/Library/Frameworks/GDAL.framework/GDAL' + +.. _psycopg2_kyngchaos: + +psycopg2 +~~~~~~~~ + +After you've installed the KyngChaos binaries and modified your ``PATH``, as +described above, ``psycopg2`` may be installed using the following command:: + + $ sudo python easy_install psycopg2 + +.. note:: + + To use ``easy_install`` you'll need to install Python's `setuptools`_. + +.. _setuptools: http://pypi.python.org/pypi/setuptools + +.. _pysqlite2_kyngchaos: + +pysqlite2 +~~~~~~~~~ + +Follow the :ref:`pysqlite2` source install instructions, however, +when editing the ``setup.cfg`` use the following instead:: + + [build_ext] + #define= + include_dirs=/Library/Frameworks/SQLite3.framework/unix/include + library_dirs=/Library/Frameworks/SQLite3.framework/unix/lib + libraries=sqlite3 + #define=SQLITE_OMIT_LOAD_EXTENSION + +.. _spatialite_kyngchaos: + +SpatiaLite +~~~~~~~~~~ + +When :ref:`create_spatialite_db`, the ``spatialite`` program is required. +However, instead of attempting to compile the SpatiaLite tools from source, +download the `SpatiaLite Binaries`__ for OS X, and install ``spatialite`` in a +location available in your ``PATH``. For example:: + + $ curl -O http://www.gaia-gis.it/spatialite/spatialite-tools-osx-x86-2.3.1.tar.gz + $ tar xzf spatialite-tools-osx-x86-2.3.1.tar.gz + $ cd spatialite-tools-osx-x86-2.3.1/bin + $ sudo cp spatialite /Library/Frameworks/SQLite3.framework/Programs + +Finally, for GeoDjango to be able to find the KyngChaos SpatiaLite library, +add the following to your ``settings.py``:: + + SPATIALITE_LIBRARY_PATH='/Library/Frameworks/SQLite3.framework/SQLite3' + +__ http://www.gaia-gis.it/spatialite/binaries.html + +.. _fink: + +Fink +^^^^ + +`Kurt Schwehr`__ has been gracious enough to create GeoDjango packages for users +of the `Fink`__ package system. The following packages are available, depending +on which version of Python you want to use: + +* ``django-gis-py26`` +* ``django-gis-py25`` +* ``django-gis-py24`` + +__ http://schwehr.org/blog/ +__ http://www.finkproject.org/ + +.. _macports: + +MacPorts +^^^^^^^^ + +`MacPorts`__ may be used to install GeoDjango prerequisites on Macintosh +computers running OS X. Because MacPorts still builds the software from source, +the `Apple Developer Tools`_ are required. + +Summary:: + + $ sudo port install postgresql83-server + $ sudo port install geos + $ sudo port install proj + $ sudo port install postgis + $ sudo port install gdal + $ sudo port install libgeoip + +.. note:: + + You will also have to modify the ``PATH`` in your ``.profile`` so + that the MacPorts programs are accessible from the command-line:: + + export PATH=/opt/local/bin:/opt/local/lib/postgresql83/bin + + In addition, add the ``FALLBACK_DYLD_LIBRARY_PATH`` setting so that + the libraries can be found by Python:: + + export FALLBACK_DYLD_LIBRARY_PATH=/opt/local/lib:/opt/local/lib/postgresql83 + +__ http://www.macports.org/ + +.. _ubuntudebian: + +Ubuntu & Debian GNU/Linux +------------------------- + +.. _ubuntu: + +Ubuntu +^^^^^^ + +.. _heron: + +8.04 and lower +~~~~~~~~~~~~~~ + +The 8.04 (and lower) versions of Ubuntu use GEOS v2.2.3 in their binary packages, +which is incompatible with GeoDjango. Thus, do *not* use the binary packages +for GEOS or PostGIS and build some prerequisites from source, per the instructions +in this document; however, it is okay to use the PostgreSQL binary packages. + +For more details, please see the Debian instructions for :ref:`etch` below. + +.. _ibex: + +8.10 +~~~~ + +Use the synaptic package manager to install the following packages:: + + $ sudo apt-get install binutils libgdal1-1.5.0 postgresql-8.3-postgis postgresql-server-dev-8.3 python-psycopg2 python-setuptools + +Afterwards, you may install Django with Python's ``easy_install`` script (the +Ubuntu package ``python-django`` uses an older version missing several +important bug fixes for GeoDjango):: + + $ sudo easy_install Django + +That's it! For the curious, the required binary prerequisites packages are: + +* ``binutils``: for ctypes to find libraries +* ``postgresql-8.3`` +* ``postgresql-server-dev-8.3``: for ``pg_config`` +* ``postgresql-8.3-postgis``: for PostGIS 1.3.3 +* ``libgeos-3.0.0``, and ``libgeos-c1``: for GEOS 3.0.0 +* ``libgdal1-1.5.0``: for GDAL 1.5.0 library +* ``proj``: for PROJ 4.6.0 -- but no datum shifting files, see note below +* ``python-psycopg2`` +* ``python-setuptools``: for ``easy_install`` + +Optional packages to consider: + +* ``libgeoip1``: for :ref:`GeoIP ` support +* ``gdal-bin``: for GDAL command line programs like ``ogr2ogr`` +* ``python-gdal`` for GDAL's own Python bindings -- includes interfaces for raster manipulation + +.. note:: + + The Ubuntu ``proj`` package does not come with the datum shifting files + installed, which will cause problems with the geographic admin because + the ``null`` datum grid is not available for transforming geometries to the + spherical mercator projection. A solution is to download the + datum-shifting files, create the grid file, and install it yourself:: + + $ wget http://download.osgeo.org/proj/proj-datumgrid-1.4.tar.gz + $ mkdir nad + $ cd nad + $ tar xzf ../proj-datumgrid-1.4.tar.gz + $ nad2bin null < null.lla + $ sudo cp null /usr/share/proj + + Otherwise, the Ubuntu ``proj`` package is fine for general use as long as you + do not plan on doing any database transformation of geometries to the + Google projection (900913). + +.. note:: + + The PostGIS SQL files are not placed the PostgreSQL share directory in the + Ubuntu packages. Use the :download:`create_template_postgis-debian.sh` script + instead when :ref:`spatialdb_template`. + +.. _debian: + +Debian +------ + +.. _etch: + +4.0 (Etch) +^^^^^^^^^^ +The situation here is the same as that of Ubuntu :ref:`heron` -- in other words, +some packages must be built from source to work properly with GeoDjango. + +Binary Packages +~~~~~~~~~~~~~~~ +The following command will install acceptable binary packages, as well as +the development tools necessary to build the rest of the requirements:: + + $ sudo apt-get install binutils bzip2 gcc g++ flex make postgresql-8.1 postgresql-server-dev-8.1 python-ctypes python-psycopg2 python-setuptools + +Required package information: + +* ``binutils``: for ctypes to find libraries +* ``bzip2``: for decompressing the source packages +* ``gcc``, ``g++``, ``make``: GNU developer tools used to compile the libraries +* ``flex``: required to build PostGIS +* ``postgresql-8.1`` +* ``postgresql-server-dev-8.1``: for ``pg_config`` +* ``python-ctypes``: Python 2.4 needs to have ctypes installed separately +* ``python-psycopg2`` +* ``python-setuptools``: for ``easy_install`` + +Optional packages: + +* ``libgeoip``: for :ref:`GeoIP ` support + +Source Packages +~~~~~~~~~~~~~~~ +You will still have to install :ref:`geosbuild`, :ref:`proj4`, +:ref:`postgis`, and :ref:`gdalbuild` from source. Please follow the +directions carefully. + +.. _lenny: + +5.0 (Lenny) +^^^^^^^^^^^ +This version is comparable to Ubuntu :ref:`ibex`, so the command +is very similar:: + + $ sudo apt-get install binutils libgdal1-1.5.0 postgresql-8.3 postgresql-8.3-postgis postgresql-server-dev-8.3 python-psycopg2 python-setuptools + +This assumes that you are using PostgreSQL version 8.3. Else, replace ``8.3`` +in the above command with the appropriate PostgreSQL version. + +.. note:: + + Please read the note in the Ubuntu :ref:`ibex` install documentation + about the ``proj`` package -- it also applies here because the package does + not include the datum shifting files. + +.. _post_install: + +Post-installation Notes +~~~~~~~~~~~~~~~~~~~~~~~ + +If the PostgreSQL database cluster was not initiated after installing, then it +can be created (and started) with the following command:: + + $ sudo pg_createcluster --start 8.3 main + +Afterwards, the ``/etc/init.d/postgresql-8.3`` script should be used to manage +the starting and stopping of PostgreSQL. + +In addition, the SQL files for PostGIS are placed in a different location on +Debian 5.0 . Thus when :ref:`spatialdb_template` either: + +* Create a symbolic link to these files:: + + $ sudo ln -s /usr/share/postgresql-8.3-postgis/{lwpostgis,spatial_ref_sys}.sql /usr/share/postgresql/8.3 + + If not running PostgreSQL 8.3, then replace ``8.3`` in the command above with the correct version. + +* Or use the :download:`create_template_postgis-debian.sh` to create the spatial database. + +.. _windows: + +Windows XP +---------- + +Python +^^^^^^ + +First, download the `Python 2.6 installer`__ from the Python website. Next, +execute the installer and use defaults, e.g., keep 'Install for all users' +checked and the installation path set as ``C:\Python26``. + +.. note:: + + You may already have a version of Python installed in ``C:\python`` as ESRI + products sometimes install a copy there. *You should still install a + fresh version of Python 2.6.* + +__ http://python.org/ftp/python/2.6.2/python-2.6.2.msi + +PostgreSQL +^^^^^^^^^^ + +First, select a mirror and download the latest `PostgreSQL 8.3 installer`__ from +the EnterpriseDB website. + +.. note:: + + PostgreSQL 8.3 is required because PostGIS is not available yet for 8.4. + +After downloading, simply click on the installer, follow the +on-screen directions, and keep the default options (e.g., keep the installation +path as ``C:\Program Files\PostgreSQL\8.3``). + +.. note:: + + This PostgreSQL installation process will create both a new windows user to be the + 'postgres service account' and a special 'postgres superuser' to own the database + cluster. You will be prompted to set a password for both users (make sure to write + them down!). To see basic details on the 'service user' account right click on + 'My Computer' and select 'Manage' or go to: Control Panel -> Administrative Tools -> + Computer Management -> System Tools -> Local Users and Groups. + +If installed successfully, the PostgreSQL server will run in the background each time +the system as started as a Windows service. When finished, the installer should launch +the Application Stack Builder (ASB) -- use this to install PostGIS, see instructions +below for more details. A 'PostgreSQL 8.3' start menu group should be created that +contains shortcuts for the ASB and 'Command Prompt', which launches a terminal window +in the PostgreSQL directory. + +__ http://www.enterprisedb.com/products/pgdownload.do#windows + +PostGIS +^^^^^^^ + +From the Application Stack Builder (Programs -> PostgreSQL 8.3), select +'PostgreSQL Database Server 8.3 on port 5432' from the drop down menu. Next, +select 'PostGIS 1.3.6 for PostgreSQL 8.3' from the 'Spatial Extensions' tree +in the list. Select only the default options during install (do not uncheck +the option to create a default PostGIS database). + +.. note:: + + You will be prompted to enter your 'postgres superuser' password in the + 'Database Connection Information' dialog. + +psycopg2 +^^^^^^^^ + +The ``psycopg2`` Python module provides the interface between Python and the +PostgreSQL database. Download the `Windows installer`__ (v2.0.10) and run +using the default settings. [#]_ + +__ http://www.stickpeople.com/projects/python/win-psycopg/psycopg2-2.0.10.win32-py2.6-pg8.3.7-release.exe + +GeoDjango Installer +^^^^^^^^^^^^^^^^^^^ + +Download the `GeoDjango Installer`__; this was created [#]_ to simplify the rest +of the process for installing GeoDjango on Windows platforms. The installer +automatically installs Django 1.1, GDAL 1.6.0, PROJ 4.6.1 (including datum grid +files), and configures the necessary environment variables. + +Once the installer has completed, log out and log back in so that the +modifications to the system environment variables take effect, and you +should be good to go. + +.. note:: + + The installer modifies the system ``Path`` environment variable to + include ``C:\Program Files\PostgreSQL\8.3\bin`` and + ``C:\Program Files\GeoDjango\bin``. This is required so that Python + may find the GEOS DLL provided by PostGIS and the GDAL DLL provided + by the installer. The installer also sets the ``GDAL_DATA`` and + ``PROJ_LIB`` environment variables. + +__ http://geodjango.org/windows/GeoDjango_Installer.exe + +.. rubric:: Footnotes +.. [#] The datum shifting files are needed for converting data to and from certain projections. + For example, the PROJ.4 string for the `Google projection (900913) `_ + requires the ``null`` grid file only included in the extra datum shifting files. + It is easier to install the shifting files now, then to have debug a problem caused by their absence later. +.. [#] Specifically, GeoDjango provides support for the `OGR `_ library, a component of GDAL. +.. [#] See `GDAL ticket #2382 `_. +.. [#] GeoDjango uses the `find_library `_ + routine from ``ctypes.util`` to locate shared libraries. +.. [#] The ``psycopg2`` Windows installers are packaged and maintained by + `Jason Erickson `_. +.. [#] The source code for the installer is available in the `nsis_installer `_ + GeoDjango mercurial repository. diff --git a/docs/ref/contrib/gis/layermapping.txt b/docs/ref/contrib/gis/layermapping.txt new file mode 100644 index 0000000000..bb5fc3f92e --- /dev/null +++ b/docs/ref/contrib/gis/layermapping.txt @@ -0,0 +1,219 @@ +.. _ref-layermapping: + +==================================== +``LayerMapping`` data import utility +==================================== + +.. module:: django.contrib.gis.utils.layermapping + :synopsis: Spatial data import utility for GeoDjango models. + +.. currentmodule:: django.contrib.gis.utils + +The :class:`LayerMapping` class provides a way to map the contents of +vector spatial data files (e.g. shapefiles) intoto GeoDjango models. + +This utility grew out of the author's personal needs to eliminate +the code repetition that went into pulling geometries and fields out of +a vector layer, converting to another coordinate system (e.g. WGS84), and +then inserting into a GeoDjango model. + +.. note:: + + Use of :class:`LayerMapping` requires GDAL. + +.. warning :: + + GIS data sources, like shapefiles, may be very large. If you find + that :class:`LayerMapping` is using too much memory, set + ``DEBUG=False`` in your settings. When ``DEBUG=True`` Django automatically + logs *every* SQL query -- thus, when SQL statements contain geometries, it is + easy to consume more memory than usual. + +Example +======= + +1. You need a GDAL-supported data source, like a shapefile (here we're using + a simple polygon shapefile, ``test_poly.shp``, with three features):: + + >>> from django.contrib.gis.gdal import DataSource + >>> ds = DataSource('test_poly.shp') + >>> layer = ds[0] + >>> print layer.fields # Exploring the fields in the layer, we only want the 'str' field. + ['float', 'int', 'str'] + >>> print len(layer) # getting the number of features in the layer (should be 3) + 3 + >>> print layer.geom_type # Should be 'Polygon' + Polygon + >>> print layer.srs # WGS84 in WKT + GEOGCS["GCS_WGS_1984", + DATUM["WGS_1984", + SPHEROID["WGS_1984",6378137,298.257223563]], + PRIMEM["Greenwich",0], + UNIT["Degree",0.017453292519943295]] + +2. Now we define our corresponding Django model (make sure to use ``syncdb``):: + + from django.contrib.gis.db import models + + class TestGeo(models.Model): + name = models.CharField(max_length=25) # corresponds to the 'str' field + poly = models.PolygonField(srid=4269) # we want our model in a different SRID + objects = models.GeoManager() + def __unicode__(self): + return 'Name: %s' % self.name + +3. Use :class:`LayerMapping` to extract all the features and place them in the + database:: + + >>> from django.contrib.gis.utils import LayerMapping + >>> from geoapp.models import TestGeo + >>> mapping = {'name' : 'str', # The 'name' model field maps to the 'str' layer field. + 'poly' : 'POLYGON', # For geometry fields use OGC name. + } # The mapping is a dictionary + >>> lm = LayerMapping(TestGeo, 'test_poly.shp', mapping) + >>> lm.save(verbose=True) # Save the layermap, imports the data. + Saved: Name: 1 + Saved: Name: 2 + Saved: Name: 3 + +Here, :class:`LayerMapping` just transformed the three geometries from the +shapefile in their original spatial reference system (WGS84) to the spatial +reference system of the GeoDjango model (NAD83). If no spatial reference +system is defined for the layer, use the ``source_srs`` keyword with a +:class:`django.contrib.gis.gdal.SpatialReference` object to specify one. + +``LayerMapping`` API +==================== + +.. class:: LayerMapping(model, data_source, mapping[, layer=0, source_srs=None, encoding=None, transaction_mode='commit_on_success', transform=True, unique=True, using='default']) + +The following are the arguments and keywords that may be used during +instantiation of ``LayerMapping`` objects. + +================= ========================================================= +Argument Description +================= ========================================================= +``model`` The geographic model, *not* an instance. + +``data_source`` The path to the OGR-supported data source file + (e.g., a shapefile). Also accepts + :class:`django.contrib.gis.gdal.DataSource` instances. + +``mapping`` A dictionary: keys are strings corresponding to + the model field, and values correspond to + string field names for the OGR feature, or if the + model field is a geographic then it should + correspond to the OGR geometry type, + e.g., ``'POINT'``, ``'LINESTRING'``, ``'POLYGON'``. +================= ========================================================= + +===================== ===================================================== +Keyword Arguments +===================== ===================================================== +``layer`` The index of the layer to use from the Data Source + (defaults to 0) + +``source_srs`` Use this to specify the source SRS manually (for + example, some shapefiles don't come with a '.prj' + file). An integer SRID, WKT or PROJ.4 strings, and + :class:`django.contrib.gis.gdal.SpatialReference` + objects are accepted. + +``encoding`` Specifies the character set encoding of the strings + in the OGR data source. For example, ``'latin-1'``, + ``'utf-8'``, and ``'cp437'`` are all valid encoding + parameters. + +``transaction_mode`` May be ``'commit_on_success'`` (default) or + ``'autocommit'``. + +``transform`` Setting this to False will disable coordinate + transformations. In other words, geometries will + be inserted into the database unmodified from their + original state in the data source. + +``unique`` Setting this to the name, or a tuple of names, + from the given model will create models unique + only to the given name(s). Geometries will from + each feature will be added into the collection + associated with the unique model. Forces + the transaction mode to be ``'autocommit'``. + +``using`` New in version 1.2. Sets the database to use when + importing spatial data. Default is ``'default'`` +===================== ===================================================== + +``save()`` Keyword Arguments +---------------------------- + +.. method:: LayerMapping.save([verbose=False, fid_range=False, step=False, progress=False, silent=False, stream=sys.stdout, strict=False]) + +The ``save()`` method also accepts keywords. These keywords are +used for controlling output logging, error handling, and for importing +specific feature ranges. + +=========================== ================================================= +Save Keyword Arguments Description +=========================== ================================================= +``fid_range`` May be set with a slice or tuple of + (begin, end) feature ID's to map from + the data source. In other words, this + keyword enables the user to selectively + import a subset range of features in the + geographic data source. + +``progress`` When this keyword is set, status information + will be printed giving the number of features + processed and successfully saved. By default, + progress information will be printed every 1000 + features processed, however, this default may + be overridden by setting this keyword with an + integer for the desired interval. + +``silent`` By default, non-fatal error notifications are + printed to ``sys.stdout``, but this keyword may + be set to disable these notifications. + +``step`` If set with an integer, transactions will + occur at every step interval. For example, if + ``step=1000``, a commit would occur after the + 1,000th feature, the 2,000th feature etc. + + +``stream`` Status information will be written to this file + handle. Defaults to using ``sys.stdout``, but + any object with a ``write`` method is supported. + +``strict`` Execution of the model mapping will cease upon + the first error encountered. The default value + (``False``) + behavior is to attempt to continue. + +``verbose`` If set, information will be printed + subsequent to each model save + executed on the database. +=========================== ================================================= + +Troubleshooting +=============== + +Running out of memory +--------------------- + +As noted in the warning at the top of this section, Django stores all SQL +queries when ``DEBUG=True``. Set ``DEBUG=False`` in your settings, and this +should stop excessive memory use when running ``LayerMapping`` scripts. + +MySQL: ``max_allowed_packet`` error +----------------------------------- + +If you encounter the following error when using ``LayerMapping`` and MySQL:: + + OperationalError: (1153, "Got a packet bigger than 'max_allowed_packet' bytes") + +Then the solution is to increase the value of the ``max_allowed_packet`` +setting in your MySQL configuration. For example, the default value may +be something low like one megabyte -- the setting may be modified in MySQL's +configuration file (``my.cnf``) in the ``[mysqld]`` section:: + + max_allowed_packet = 10M diff --git a/docs/ref/contrib/gis/measure.txt b/docs/ref/contrib/gis/measure.txt new file mode 100644 index 0000000000..8b9629ef80 --- /dev/null +++ b/docs/ref/contrib/gis/measure.txt @@ -0,0 +1,180 @@ +.. _ref-measure: + +=================== +Measurement Objects +=================== + +.. module:: django.contrib.gis.measure + :synopsis: GeoDjango's distance and area measurment objects. + +The :mod:`django.contrib.gis.measure` module contains objects that allow +for convenient representation of distance and area units of measure. [#]_ +Specifically, it implements two objects, :class:`Distance` and +:class:`Area` -- both of which may be accessed via the +:class:`D` and :class:`A` convenience aliases, respectively. + +Example +======= + +:class:`Distance` objects may be instantiated using a keyword argument indicating the +context of the units. In the example below, two different distance objects are +instantiated in units of kilometers (``km``) and miles (``mi``):: + + >>> from django.contrib.gis.measure import Distance, D + >>> d1 = Distance(km=5) + >>> print d1 + 5.0 km + >>> d2 = D(mi=5) # `D` is an alias for `Distance` + >>> print d2 + 5.0 mi + +Conversions are easy, just access the preferred unit attribute to get a +converted distance quantity:: + + >>> print d1.mi # Converting 5 kilometers to miles + 3.10685596119 + >>> print d2.km # Converting 5 miles to kilometers + 8.04672 + +Moreover, arithmetic operations may be performed between the distance +objects:: + + >>> print d1 + d2 # Adding 5 miles to 5 kilometers + 13.04672 km + >>> print d2 - d1 # Subtracting 5 kilometers from 5 miles + 1.89314403881 mi + +Two :class:`Distance` objects multiplied together will yield an :class:`Area` +object, which uses squared units of measure:: + + >>> a = d1 * d2 # Returns an Area object. + >>> print a + 40.2336 sq_km + +To determine what the attribute abbreviation of a unit is, the ``unit_attname`` +class method may be used:: + + >>> print Distance.unit_attname('US Survey Foot') + survey_ft + >>> print Distance.unit_attname('centimeter') + cm + +.. _supported_units: + +Supported units +=============== + +================================= ======================================== +Unit Attribute Full name or alias(es) +================================= ======================================== +``km`` Kilometre, Kilometer +``mi`` Mile +``m`` Meter, Metre +``yd`` Yard +``ft`` Foot, Foot (International) +``survey_ft`` U.S. Foot, US survey foot +``inch`` Inches +``cm`` Centimeter +``mm`` Millimetre, Millimeter +``um`` Micrometer, Micrometre +``british_ft`` British foot (Sears 1922) +``british_yd`` British yard (Sears 1922) +``british_chain_sears`` British chain (Sears 1922) +``indian_yd`` Indian yard, Yard (Indian) +``sears_yd`` Yard (Sears) +``clarke_ft`` Clarke's Foot +``chain`` Chain +``chain_benoit`` Chain (Benoit) +``chain_sears`` Chain (Sears) +``british_chain_benoit`` British chain (Benoit 1895 B) +``british_chain_sears_truncated`` British chain (Sears 1922 truncated) +``gold_coast_ft`` Gold Coast foot +``link`` Link +``link_benoit`` Link (Benoit) +``link_sears`` Link (Sears) +``clarke_link`` Clarke's link +``fathom`` Fathom +``rod`` Rod +``nm`` Nautical Mile +``nm_uk`` Nautical Mile (UK) +``german_m`` German legal metre +================================= ======================================== + +.. note:: + + :class:`Area` attributes are the same as :class:`Distance` attributes, + except they are prefixed with ``sq_`` (area units are square in nature). + For example, ``Area(sq_m=2)`` creates an :class:`Area` object + representing two square meters. + +Measurement API +=============== + +``Distance`` +------------ + +.. class:: Distance(**kwargs) + + To initialize a distance object, pass in a keyword corresponding to + the desired :ref:`unit attribute name ` set with + desired value. For example, the following creates a distance + object representing 5 miles:: + + >>> dist = Distance(mi=5) + + .. method:: __getattr__(unit_att) + + Returns the distance value in units corresponding to the given unit + attribute. For example:: + + >>> print dist.km + 8.04672 + + .. classmethod:: unit_attname(unit_name) + + Returns the distance unit attribute name for the given full unit name. + For example:: + + >>> Distance.unit_attname('Mile') + 'mi' + +.. class:: D + + Alias for :class:`Distance` class. + +``Area`` +-------- + +.. class:: Area(**kwargs) + + To initialize a distance object, pass in a keyword corresponding to + the desired :ref:`unit attribute name ` set with + desired value. For example, the following creates a distance + object representing 5 square miles:: + + >>> a = Area(sq_mi=5) + + .. method:: __getattr__(unit_att) + + Returns the area value in units corresponding to the given unit + attribute. For example:: + + >>> print a.sq_km + 12.949940551680001 + + .. classmethod:: unit_attname(unit_name) + + Returns the area unit attribute name for the given full unit name. + For example:: + + >>> Area.unit_attname('Kilometer') + 'sq_km' + +.. class:: A + + Alias for :class:`Area` class. + +.. rubric:: Footnotes +.. [#] `Robert Coup `_ is the initial author of the measure objects, + and was inspired by Brian Beck's work in `geopy `_ + and Geoff Biggs' PhD work on dimensioned units for robotics. diff --git a/docs/ref/contrib/gis/model-api.txt b/docs/ref/contrib/gis/model-api.txt new file mode 100644 index 0000000000..6b7b20d478 --- /dev/null +++ b/docs/ref/contrib/gis/model-api.txt @@ -0,0 +1,266 @@ +.. _ref-gis-model-api: + +=================== +GeoDjango Model API +=================== + +.. module:: django.contrib.gis.db.models + :synopsis: GeoDjango model and field API. + +This document explores the details of the GeoDjango Model API. Throughout this +section, we'll be using the following geographic model of a `ZIP code`__ as our +example:: + + from django.contrib.gis.db import models + + class Zipcode(models.Model): + code = models.CharField(max_length=5) + poly = models.PolygonField() + objects = models.GeoManager() + +__ http://en.wikipedia.org/wiki/ZIP_code + +Geometry Field Types +==================== + +Each of the following geometry field types correspond with the +OpenGIS Simple Features specification [#fnogc]_. + +``GeometryField`` +----------------- + +.. class:: GeometryField + +``PointField`` +-------------- + +.. class:: PointField + +``LineStringField`` +------------------- + +.. class:: LineStringField + +``PolygonField`` +---------------- + +.. class:: PolygonField + +``MultiPointField`` +------------------- + +.. class:: MultiPointField + +``MultiLineStringField`` +------------------------ + +.. class:: MultiLineStringField + +``MultiPolygonField`` +--------------------- + +.. class:: MultiPolygonField + +``GeometryCollectionField`` +--------------------------- + +.. class:: GeometryCollectionField + +.. _geometry-field-options: + +Geometry Field Options +====================== + +In addition to the regular :ref:`common-model-field-options` available for +Django model fields, geometry fields have the following additional options. +All are optional. + +``srid`` +-------- + +.. attribute:: GeometryField.srid + +Sets the SRID [#fnogcsrid]_ (Spatial Reference System Identity) of the geometry field to +the given value. Defaults to 4326 (also known as `WGS84`__, units are in degrees +of longitude and latitude). + +__ http://en.wikipedia.org/wiki/WGS84 + +.. _selecting-an-srid: + +Selecting an SRID +^^^^^^^^^^^^^^^^^ + +Choosing an appropriate SRID for your model is an important decision that the +developer should consider carefully. The SRID is an integer specifier that +corresponds to the projection system that will be used to interpret the data +in the spatial database. [#fnsrid]_ Projection systems give the context to the +coordinates that specify a location. Although the details of `geodesy`__ are +beyond the scope of this documentation, the general problem is that the earth +is spherical and representations of the earth (e.g., paper maps, web maps) +are not. + +Most people are familiar with using latitude and longitude to reference a +location on the earth's surface. However, latitude and longitude are angles, +not distances. [#fnharvard]_ In other words, while the shortest path between two points on +a flat surface is a straight line, the shortest path between two points on a curved +surface (such as the earth) is an *arc* of a `great circle`__. [#fnthematic]_ Thus, +additional computation is required to obtain distances in planar units (e.g., +kilometers and miles). Using a geographic coordinate system may introduce +complications for the developer later on. For example, PostGIS does not +have the capability to perform distance calculations between non-point +geometries using geographic coordinate systems, e.g., constructing a query to +find all points within 5 miles of a county boundary stored as WGS84. [#fndist]_ + +Portions of the earth's surface may projected onto a two-dimensional, or +Cartesian, plane. Projected coordinate systems are especially convenient +for region-specific applications, e.g., if you know that your database will +only cover geometries in `North Kansas`__, then you may consider using projection +system specific to that region. Moreover, projected coordinate systems are +defined in Cartesian units (such as meters or feet), easing distance +calculations. + +.. note:: + + If you wish to peform arbitrary distance queries using non-point + geometries, consider using PostGIS 1.5 and enabling the + :attr:`GeometryField.geography` keyword to use the + :ref:`geography database type ` instead. + +Additional Resources: + +* `spatialreference.org`__: A Django-powered database of spatial reference + systems. +* `The State Plane Coordinate System`__: A website covering the various + projection systems used in the United States. Much of the U.S. spatial + data encountered will be in one of these coordinate systems rather than + in a geographic coordinate system such as WGS84. + +__ http://en.wikipedia.org/wiki/Geodesy +__ http://en.wikipedia.org/wiki/Great_circle +__ http://www.spatialreference.org/ref/epsg/2796/ +__ http://spatialreference.org/ +__ http://welcome.warnercnr.colostate.edu/class_info/nr502/lg3/datums_coordinates/spcs.html + +``spatial_index`` +----------------- + +.. attribute:: GeometryField.spatial_index + +Defaults to ``True``. Creates a spatial index for the given geometry +field. + +.. note:: + + This is different from the ``db_index`` field option because spatial + indexes are created in a different manner than regular database + indexes. Specifically, spatial indexes are typically created using + a variant of the R-Tree, while regular database indexes typically + use B-Trees. + +``dim`` +------- + +.. versionadded:: 1.2 + +.. attribute:: GeometryField.dim + +This option may be used for customizing the coordinate dimension of the +geometry field. By default, it is set to 2, for representing two-dimensional +geometries. For spatial backends that support it, it may be set to 3 for +three-dimensonal support. + +.. note:: + + At this time 3D support requires that GEOS 3.1 be installed, and is + limited only to the PostGIS spatial backend. + +``geography`` +------------- + +.. versionadded:: 1.2 + +.. attribute:: GeometryField.geography + +If set to ``True``, this option will use create a database column of +type geography, rather than geometry. Please refer to the +:ref:`geography type ` section below for more +details. + +.. note:: + + Geography support is limited only to PostGIS 1.5+, and will + force the SRID to be 4326. + +.. _geography-type: + +Geography Type +^^^^^^^^^^^^^^ + +In PostGIS 1.5, the geography type was introduced -- it provides +provides native support for spatial features represented with geographic +coordinates (e.g., WGS84 longitude/latitude). [#fngeography]_ +Unlike the plane used by a geometry type, the geography type uses a spherical +representation of its data. Distance and measurement operations +performed on a geography column automatically employ great circle arc +calculations and return linear units. In other words, when ``ST_Distance`` +is called on two geographies, a value in meters is returned (as opposed +to degrees if called on a geometry column in WGS84). + +Because geography calculations involve more mathematics, only a subset of the +PostGIS spatial lookups are available for the geography type. Practically, +this means that in addition to the :ref:`distance lookups ` +only the following additional :ref:`spatial lookups ` are +available for geography columns: + +* :lookup:`bboverlaps` +* :lookup:`exact`, and :lookup:`same_as` +* :lookup:`coveredby` +* :lookup:`covers` +* :lookup:`intersects` + +For more information, the PostGIS documentation contains a helpful section on +determining `when to use geography data type over geometry data type +`_. + + + +``GeoManager`` +============== + +.. currentmodule:: django.contrib.gis.db.models +.. class:: GeoManager + +In order to conduct geographic queries, each geographic model requires +a ``GeoManager`` model manager. This manager allows for the proper SQL +construction for geographic queries; thus, without it, all geographic filters +will fail. It should also be noted that ``GeoManager`` is required even if the +model does not have a geographic field itself, e.g., in the case of a +``ForeignKey`` relation to a model with a geographic field. For example, +if we had an ``Address`` model with a ``ForeignKey`` to our ``Zipcode`` +model:: + + from django.contrib.gis.db import models + from django.contrib.localflavor.us.models import USStateField + + class Address(models.Model): + num = models.IntegerField() + street = models.CharField(max_length=100) + city = models.CharField(max_length=100) + state = USStateField() + zipcode = models.ForeignKey(Zipcode) + objects = models.GeoManager() + +The geographic manager is needed to do spatial queries on related ``Zipcode`` objects, +for example:: + + qs = Address.objects.filter(zipcode__poly__contains='POINT(-104.590948 38.319914)') + +.. rubric:: Footnotes +.. [#fnogc] OpenGIS Consortium, Inc., `Simple Feature Specification For SQL `_, Document 99-049 (May 5, 1999). +.. [#fnogcsrid] *See id.* at Ch. 2.3.8, p. 39 (Geometry Values and Spatial Reference Systems). +.. [#fnsrid] Typically, SRID integer corresponds to an EPSG (`European Petroleum Survey Group `_) identifier. However, it may also be associated with custom projections defined in spatial database's spatial reference systems table. +.. [#fnharvard] Harvard Graduate School of Design, `An Overview of Geodesy and Geographic Referencing Systems `_. This is an excellent resource for an overview of principles relating to geographic and Cartesian coordinate systems. +.. [#fnthematic] Terry A. Slocum, Robert B. McMaster, Fritz C. Kessler, & Hugh H. Howard, *Thematic Cartography and Geographic Visualization* (Prentice Hall, 2nd edition), at Ch. 7.1.3. +.. [#fndist] This isn't impossible using GeoDjango; you could for example, take a known point in a projected coordinate system, buffer it to the appropriate radius, and then perform an intersection operation with the buffer transformed to the geographic coordinate system. +.. [#fngeography] Please refer to the `PostGIS Geography Type `_ documentation for more details. diff --git a/docs/ref/contrib/gis/ogrinspect.txt b/docs/ref/contrib/gis/ogrinspect.txt new file mode 100644 index 0000000000..03ce6e58d3 --- /dev/null +++ b/docs/ref/contrib/gis/ogrinspect.txt @@ -0,0 +1,20 @@ +.. _ref-ogrinspect: + +============== +OGR Inspection +============== + +.. module:: django.contrib.gis.utils.ogrinspect + :synopsis: Utilities for inspecting OGR data sources. + +.. currentmodule:: django.contrib.gis.utils + +``ogrinspect`` +============== + +.. function:: ogrinspect(data_source, model_name[, **kwargs]) + +``mapping`` +=========== + +.. function:: mapping(data_source, [geom_name='geom', layer_key=0, multi_geom=False]) diff --git a/docs/ref/contrib/gis/sitemaps.txt b/docs/ref/contrib/gis/sitemaps.txt new file mode 100644 index 0000000000..75bddd3b86 --- /dev/null +++ b/docs/ref/contrib/gis/sitemaps.txt @@ -0,0 +1,27 @@ +=================== +Geographic Sitemaps +=================== + +Google's sitemap protocol has been recently extended to support geospatial +content. [#]_ This includes the addition of the ```` child element +````, which tells Google that the content located at the URL is +geographic in nature. [#]_ + +Example +======= + +Reference +========= + +``KMLSitemap`` +-------------- + +``KMZSitemap`` +-------------- + +``GeoRSSSitemap`` +----------------- + +.. rubric:: Footnotes +.. [#] Google, Inc., `What is a Geo Sitemap? `_. +.. [#] Google, Inc., `Submit Your Geo Content to Google `_. diff --git a/docs/ref/contrib/gis/testing.txt b/docs/ref/contrib/gis/testing.txt new file mode 100644 index 0000000000..b2513f670b --- /dev/null +++ b/docs/ref/contrib/gis/testing.txt @@ -0,0 +1,181 @@ +====================== +Testing GeoDjango Apps +====================== + +.. versionchanged:: 1.2 + +In Django 1.2, the addition of :ref:`spatial-backends` +simplified the process of testing GeoDjango applications. Specifically, testing +GeoDjango applications is now the same as :ref:`topics-testing`. + +Included in this documentation are some additional notes and settings +for :ref:`testing-postgis` and :ref:`testing-spatialite` users. + +.. note:: + + Django 1.1 users are still required to use a custom :setting:`TEST_RUNNER`. + See the :ref:`testing-1.1` section for more details. + +.. _testing-postgis: + +PostGIS +======= + +Settings +-------- + +.. note:: + + The settings below have sensible defaults, and shouldn't require manual setting. + +.. setting:: POSTGIS_TEMPLATE + +``POSTGIS_TEMPLATE`` +^^^^^^^^^^^^^^^^^^^^ + +.. versionadded:: 1.1 + +.. versionchanged:: 1.2 + +This setting may be used to customize the name of the PostGIS template +database to use. In Django versions 1.2 and above, it automatically +defaults to ``'template_postgis'`` (the same name used in the +:ref:`installation documentation `). + +.. note:: + + Django 1.1 users will still have to define the :setting:`POSTGIS_TEMPLATE` + with a value, for example:: + + POSTGIS_TEMPLATE='template_postgis' + +.. setting:: POSTGIS_VERSION + +``POSTGIS_VERSION`` +^^^^^^^^^^^^^^^^^^^ +.. versionadded:: 1.1 + +When GeoDjango's spatial backend initializes on PostGIS, it has to perform +a SQL query to determine the version. Setting the version manually +prevents this query to the database:: + + POSTGIS_VERSION=('1.3.6', 1, 3, 6) + +Obtaining Sufficient Privileges +------------------------------- + +Depending on your configuration, this section describes several methods to +configure a database user with sufficient privileges to run tests for +GeoDjango applications on PostgreSQL. If your +:ref:`spatial database template ` +was created like in the instructions, then your testing database user +only needs to have the ability to create databases. In other configurations, +you may be required to use a database superuser. + +Create Database User +^^^^^^^^^^^^^^^^^^^^ +To make database user with the ability to create databases, use the +following command:: + + $ createuser --createdb -R -S + +The ``-R -S`` flags indicate that we do not want the user to have the ability +to create additional users (roles) or to be a superuser, respectively. + +Alternatively, you may alter an existing user's role from the SQL shell +(assuming this is done from an existing superuser account):: + + postgres# ALTER ROLE CREATEDB NOSUPERUSER NOCREATEROLE; + +Create Database Superuser +^^^^^^^^^^^^^^^^^^^^^^^^^ +This may be done at the time the user is created, for example:: + + $ createuser --superuser + +Or you may alter the user's role from the SQL shell (assuming this +is done from an existing superuser account):: + + postgres# ALTER ROLE SUPERUSER; + + +Create Local PostgreSQL Database +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +1. Initialize database: ``initdb -D /path/to/user/db`` + +2. If there's already a Postgres instance on the machine, it will need + to use a different TCP port than 5432. Edit ``postgresql.conf`` (in + ``/path/to/user/db``) to change the database port (e.g. ``port = 5433``). + +3. Start this database ``pg_ctl -D /path/to/user/db start`` + +Windows +------- +On Windows platforms the pgAdmin III utility may also be used as +a simple way to add superuser privileges to your database user. + +By default, the PostGIS installer on Windows includes a template +spatial database entitled ``template_postgis``. + +.. _testing-spatialite: + +SpatiaLite +========== + +.. versionadded:: 1.1 + +You will need to download the `initialization SQL`__ script for SpatiaLite:: + + $ wget http://www.gaia-gis.it/spatialite/init_spatialite-2.3.zip + $ unzip init_spatialite-2.3.zip + +If ``init_spatialite-2.3.sql`` is in the same path as your project's ``manage.py``, +then all you have to do is:: + + $ python manage.py test + +Settings +-------- + +.. setting:: SPATIALITE_SQL + +``SPATIALITE_SQL`` +^^^^^^^^^^^^^^^^^^ +.. versionadded:: 1.1 + +By default, the GeoDjango test runner looks for the SpatiaLite SQL in the +same directory where it was invoked (by default the same directory where +``manage.py`` is located). If you want to use a different location, then +you may add the following to your settings:: + + SPATIALITE_SQL='/path/to/init_spatialite-2.3.sql' + +__ http://www.gaia-gis.it/spatialite/init_spatialite-2.3.zip + +.. _testing-1.1: + +Testing GeoDjango Applications in 1.1 +===================================== + +In Django 1.1, to accommodate the extra steps required to scaffalod a +spatial database automatically, a test runner customized for GeoDjango +must be used. To use this runner, configure :setting:`TEST_RUNNER` as follows:: + + TEST_RUNNER='django.contrib.gis.tests.run_tests' + +.. note:: + + In order to create a spatial database, the :setting:`DATABASE_USER` setting + (or :setting:`TEST_DATABASE_USER`, if optionally defined on Oracle) requires + elevated privileges. When using PostGIS or MySQL, the database user + must have at least the ability to create databases. When testing on Oracle, + the user should be a superuser. + +GeoDjango Test Suite +==================== + +To run GeoDjango's own internal test suite, configure the +:setting:`TEST_RUNNER` setting as follows:: + + TEST_RUNNER='django.contrib.gis.tests.run_gis_tests' diff --git a/docs/ref/contrib/gis/tutorial.txt b/docs/ref/contrib/gis/tutorial.txt new file mode 100644 index 0000000000..fcf3e77d93 --- /dev/null +++ b/docs/ref/contrib/gis/tutorial.txt @@ -0,0 +1,758 @@ +================== +GeoDjango Tutorial +================== + +Introduction +============ + +GeoDjango is an add-on for Django that turns it into a world-class geographic +web framework. GeoDjango strives to make at as simple as possible to create +geographic web applications, like location-based services. Some features include: + +* Django model fields for `OGC`_ geometries. +* Extensions to Django's ORM for the querying and manipulation of spatial data. +* Loosely-coupled, high-level Python interfaces for GIS geometry operations and + data formats. +* Editing of geometry fields inside the admin. + +This tutorial assumes a familiarity with Django; thus, if you're brand new to +Django please read through the :ref:`regular tutorial ` to introduce +yourself with basic Django concepts. + +.. note:: + + GeoDjango has special prerequisites overwhat is required by Django -- + please consult the :ref:`installation documentation ` + for more details. + +This tutorial is going to guide you through guide the user through the creation +of a geographic web application for viewing the `world borders`_. [#]_ Some of +the code used in this tutorial is taken from and/or inspired by the +`GeoDjango basic apps`_ project. [#]_ + +.. note:: + + Proceed through the tutorial sections sequentially for step-by-step + instructions. + +.. _OGC: http://www.opengeospatial.org/ +.. _world borders: http://thematicmapping.org/downloads/world_borders.php +.. _GeoDjango basic apps: http://code.google.com/p/geodjango-basic-apps/ + +Setting Up +========== + +Create a Spatial Database +------------------------- + +.. note:: + + MySQL and Oracle users can skip this section because spatial types + are already built into the database. + +First, a spatial database needs to be created for our project. If using +PostgreSQL and PostGIS, then the following commands will +create the database from a :ref:`spatial database template `:: + + $ createdb -T template_postgis geodjango + +.. note:: + + This command must be issued by a database user that has permissions to + create a database. Here is an example set of commands to create such + a user:: + + $ sudo su - postgres + $ createuser --createdb geo + $ exit + + Replace ``geo`` to correspond to the system login user name will be + connecting to the database. For example, ``johndoe`` if that is the + system user that will be running GeoDjango. + +Users of SQLite and SpatiaLite should consult the instructions on how +to create a :ref:`SpatiaLite database `. + +Create GeoDjango Project +------------------------ + +Use the ``django-admin.py`` script like normal to create a ``geodjango`` project:: + + $ django-admin.py startproject geodjango + +With the project initialized, now create a ``world`` Django application within +the ``geodjango`` project:: + + $ cd geodjango + $ python manage.py startapp world + +Configure ``settings.py`` +------------------------- + +The ``geodjango`` project settings are stored in the ``settings.py`` file. Edit +the database connection settings appropriately:: + + DATABASES = { + 'default': { + 'ENGINE': 'django.contrib.gis.db.backends.postgis', + 'NAME': 'geodjango', + 'USER': 'geo', + } + } + +.. note:: + + These database settings are for Django 1.2 and above. + +In addition, modify the :setting:`INSTALLED_APPS` setting to include +:mod:`django.contrib.admin`, :mod:`django.contrib.gis`, +and ``world`` (our newly created application):: + + INSTALLED_APPS = ( + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.sites', + 'django.contrib.admin', + 'django.contrib.gis', + 'world' + ) + +Geographic Data +=============== + +.. _worldborders: + +World Borders +------------- + +The world borders data is available in this `zip file`__. Create a data directory +in the ``world`` application, download the world borders data, and unzip. +On GNU/Linux platforms the following commands should do it:: + + $ mkdir world/data + $ cd world/data + $ wget http://thematicmapping.org/downloads/TM_WORLD_BORDERS-0.3.zip + $ unzip TM_WORLD_BORDERS-0.3.zip + $ cd ../.. + +The world borders ZIP file contains a set of data files collectively known as +an `ESRI Shapefile`__, one of the most popular geospatial data formats. When +unzipped the world borders data set includes files with the following extensions: + +* ``.shp``: Holds the vector data for the world borders geometries. +* ``.shx``: Spatial index file for geometries stored in the ``.shp``. +* ``.dbf``: Database file for holding non-geometric attribute data + (e.g., integer and character fields). +* ``.prj``: Contains the spatial reference information for the geographic + data stored in the shapefile. + +__ http://thematicmapping.org/downloads/TM_WORLD_BORDERS-0.3.zip +__ http://en.wikipedia.org/wiki/Shapefile + +Use ``ogrinfo`` to examine spatial data +--------------------------------------- + +The GDAL ``ogrinfo`` utility is excellent for examining metadata about +shapefiles (or other vector data sources):: + + $ ogrinfo world/data/TM_WORLD_BORDERS-0.3.shp + INFO: Open of `world/data/TM_WORLD_BORDERS-0.3.shp' + using driver `ESRI Shapefile' successful. + 1: TM_WORLD_BORDERS-0.3 (Polygon) + +Here ``ogrinfo`` is telling us that the shapefile has one layer, and that +layer contains polygon data. To find out more we'll specify the layer name +and use the ``-so`` option to get only important summary information:: + + $ ogrinfo -so world/data/TM_WORLD_BORDERS-0.3.shp TM_WORLD_BORDERS-0.3 + INFO: Open of `world/data/TM_WORLD_BORDERS-0.3.shp' + using driver `ESRI Shapefile' successful. + + Layer name: TM_WORLD_BORDERS-0.3 + Geometry: Polygon + Feature Count: 246 + Extent: (-180.000000, -90.000000) - (180.000000, 83.623596) + Layer SRS WKT: + GEOGCS["GCS_WGS_1984", + DATUM["WGS_1984", + SPHEROID["WGS_1984",6378137.0,298.257223563]], + PRIMEM["Greenwich",0.0], + UNIT["Degree",0.0174532925199433]] + FIPS: String (2.0) + ISO2: String (2.0) + ISO3: String (3.0) + UN: Integer (3.0) + NAME: String (50.0) + AREA: Integer (7.0) + POP2005: Integer (10.0) + REGION: Integer (3.0) + SUBREGION: Integer (3.0) + LON: Real (8.3) + LAT: Real (7.3) + +This detailed summary information tells us the number of features in the layer +(246), the geographical extent, the spatial reference system ("SRS WKT"), +as well as detailed information for each attribute field. For example, +``FIPS: String (2.0)`` indicates that there's a ``FIPS`` character field +with a maximum length of 2; similarly, ``LON: Real (8.3)`` is a floating-point +field that holds a maximum of 8 digits up to three decimal places. Although +this information may be found right on the `world borders`_ website, this shows +you how to determine this information yourself when such metadata is not +provided. + +Geographic Models +================= + +Defining a Geographic Model +--------------------------- + +Now that we've examined our world borders data set using ``ogrinfo``, we can +create a GeoDjango model to represent this data:: + + from django.contrib.gis.db import models + + class WorldBorders(models.Model): + # Regular Django fields corresponding to the attributes in the + # world borders shapefile. + name = models.CharField(max_length=50) + area = models.IntegerField() + pop2005 = models.IntegerField('Population 2005') + fips = models.CharField('FIPS Code', max_length=2) + iso2 = models.CharField('2 Digit ISO', max_length=2) + iso3 = models.CharField('3 Digit ISO', max_length=3) + un = models.IntegerField('United Nations Code') + region = models.IntegerField('Region Code') + subregion = models.IntegerField('Sub-Region Code') + lon = models.FloatField() + lat = models.FloatField() + + # GeoDjango-specific: a geometry field (MultiPolygonField), and + # overriding the default manager with a GeoManager instance. + mpoly = models.MultiPolygonField() + objects = models.GeoManager() + + # So the model is pluralized correctly in the admin. + class Meta: + verbose_name_plural = "World Borders" + + # Returns the string representation of the model. + def __unicode__(self): + return self.name + +Two important things to note: + +1. The ``models`` module is imported from :mod:`django.contrib.gis.db`. +2. The model overrides its default manager with + :class:`~django.contrib.gis.db.models.GeoManager`; this is *required* + to perform spatial queries. + +When declaring a geometry field on your model the default spatial reference system +is WGS84 (meaning the `SRID`__ is 4326) -- in other words, the field coordinates are in +longitude/latitude pairs in units of degrees. If you want the coordinate system to be +different, then SRID of the geometry field may be customized by setting the ``srid`` +with an integer corresponding to the coordinate system of your choice. + +__ http://en.wikipedia.org/wiki/SRID + +Run ``syncdb`` +-------------- + +After you've defined your model, it needs to be synced with the spatial database. +First, let's look at the SQL that will generate the table for the ``WorldBorders`` +model:: + + $ python manage.py sqlall world + +This management command should produce the following output:: + + BEGIN; + CREATE TABLE "world_worldborders" ( + "id" serial NOT NULL PRIMARY KEY, + "name" varchar(50) NOT NULL, + "area" integer NOT NULL, + "pop2005" integer NOT NULL, + "fips" varchar(2) NOT NULL, + "iso2" varchar(2) NOT NULL, + "iso3" varchar(3) NOT NULL, + "un" integer NOT NULL, + "region" integer NOT NULL, + "subregion" integer NOT NULL, + "lon" double precision NOT NULL, + "lat" double precision NOT NULL + ) + ; + SELECT AddGeometryColumn('world_worldborders', 'mpoly', 4326, 'MULTIPOLYGON', 2); + ALTER TABLE "world_worldborders" ALTER "mpoly" SET NOT NULL; + CREATE INDEX "world_worldborders_mpoly_id" ON "world_worldborders" USING GIST ( "mpoly" GIST_GEOMETRY_OPS ); + COMMIT; + +If satisfied, you may then create this table in the database by running the +``syncdb`` management command:: + + $ python manage.py syncdb + Creating table world_worldborders + Installing custom SQL for world.WorldBorders model + +The ``syncdb`` command may also prompt you to create an admin user; go ahead and +do so (not required now, may be done at any point in the future using the +``createsuperuser`` management command). + +Importing Spatial Data +====================== + +This section will show you how to take the data from the world borders +shapefile and import it into GeoDjango models using the :ref:`ref-layermapping`. +There are many different different ways to import data in to a +spatial database -- besides the tools included within GeoDjango, you +may also use the following to populate your spatial database: + +* `ogr2ogr`_: Command-line utility, included with GDAL, that + supports loading a multitude of vector data formats into + the PostGIS, MySQL, and Oracle spatial databases. +* `shp2pgsql`_: This utility is included with PostGIS and only supports + ESRI shapefiles. + +.. _ogr2ogr: http://www.gdal.org/ogr/ogr2ogr.html +.. _shp2pgsql: http://postgis.refractions.net/documentation/manual-1.5/ch04.html#shp2pgsql_usage + +.. _gdalinterface: + +GDAL Interface +-------------- + +Earlier we used the the ``ogrinfo`` to explore the contents of the world borders +shapefile. Included within GeoDjango is an interface to GDAL's powerful OGR +library -- in other words, you'll be able explore all the vector data sources +that OGR supports via a Pythonic API. + +First, invoke the Django shell:: + + $ python manage.py shell + +If the :ref:`worldborders` data was downloaded like earlier in the +tutorial, then we can determine the path using Python's built-in +``os`` module:: + + >>> import os + >>> from geodjango import world + >>> world_shp = os.path.abspath(os.path.join(os.path.dirname(world.__file__), + ... 'data/TM_WORLD_BORDERS-0.3.shp')) + +Now, the world borders shapefile may be opened using GeoDjango's +:class:`~django.contrib.gis.gdal.DataSource` interface:: + + >>> from django.contrib.gis.gdal import * + >>> ds = DataSource(world_shp) + >>> print ds + / ... /geodjango/world/data/TM_WORLD_BORDERS-0.3.shp (ESRI Shapefile) + +Data source objects can have different layers of geospatial features; however, +shapefiles are only allowed to have one layer:: + + >>> print len(ds) + 1 + >>> lyr = ds[0] + >>> print lyr + TM_WORLD_BORDERS-0.3 + +You can see what the geometry type of the layer is and how many features it +contains:: + + >>> print lyr.geom_type + Polygon + >>> print len(lyr) + 246 + +.. note:: + + Unfortunately the shapefile data format does not allow for greater + specificity with regards to geometry types. This shapefile, like + many others, actually includes ``MultiPolygon`` geometries in its + features. You need to watch out for this when creating your models + as a GeoDjango ``PolygonField`` will not accept a ``MultiPolygon`` + type geometry -- thus a ``MultiPolygonField`` is used in our model's + definition instead. + +The :class:`~django.contrib.gis.gdal.Layer` may also have a spatial reference +system associated with it -- if it does, the ``srs`` attribute will return a +:class:`~django.contrib.gis.gdal.SpatialReference` object:: + + >>> srs = lyr.srs + >>> print srs + GEOGCS["GCS_WGS_1984", + DATUM["WGS_1984", + SPHEROID["WGS_1984",6378137.0,298.257223563]], + PRIMEM["Greenwich",0.0], + UNIT["Degree",0.0174532925199433]] + >>> srs.proj4 # PROJ.4 representation + '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs ' + +Here we've noticed that the shapefile is in the popular WGS84 spatial reference +system -- in other words, the data uses units of degrees longitude and latitude. + +In addition, shapefiles also support attribute fields that may contain +additional data. Here are the fields on the World Borders layer: + + >>> print lyr.fields + ['FIPS', 'ISO2', 'ISO3', 'UN', 'NAME', 'AREA', 'POP2005', 'REGION', 'SUBREGION', 'LON', 'LAT'] + +Here we are examining the OGR types (e.g., whether a field is an integer or +a string) associated with each of the fields: + + >>> [fld.__name__ for fld in lyr.field_types] + ['OFTString', 'OFTString', 'OFTString', 'OFTInteger', 'OFTString', 'OFTInteger', 'OFTInteger', 'OFTInteger', 'OFTInteger', 'OFTReal', 'OFTReal'] + +You can iterate over each feature in the layer and extract information from both +the feature's geometry (accessed via the ``geom`` attribute) as well as the +feature's attribute fields (whose **values** are accessed via ``get()`` +method):: + + >>> for feat in lyr: + ... print feat.get('NAME'), feat.geom.num_points + ... + Guernsey 18 + Jersey 26 + South Georgia South Sandwich Islands 338 + Taiwan 363 + +:class:`~django.contrib.gis.gdal.Layer` objects may be sliced:: + + >>> lyr[0:2] + [, ] + +And individual features may be retrieved by their feature ID:: + + >>> feat = lyr[234] + >>> print feat.get('NAME') + San Marino + +Here the boundary geometry for San Marino is extracted and looking +exported to WKT and GeoJSON:: + + >>> geom = feat.geom + >>> print geom.wkt + POLYGON ((12.415798 43.957954,12.450554 ... + >>> print geom.json + { "type": "Polygon", "coordinates": [ [ [ 12.415798, 43.957954 ], [ 12.450554, 43.979721 ], ... + + +``LayerMapping`` +---------------- + +We're going to dive right in -- create a file called ``load.py`` inside the +``world`` application, and insert the following:: + + import os + from django.contrib.gis.utils import LayerMapping + from models import WorldBorders + + world_mapping = { + 'fips' : 'FIPS', + 'iso2' : 'ISO2', + 'iso3' : 'ISO3', + 'un' : 'UN', + 'name' : 'NAME', + 'area' : 'AREA', + 'pop2005' : 'POP2005', + 'region' : 'REGION', + 'subregion' : 'SUBREGION', + 'lon' : 'LON', + 'lat' : 'LAT', + 'mpoly' : 'MULTIPOLYGON', + } + + world_shp = os.path.abspath(os.path.join(os.path.dirname(__file__), 'data/TM_WORLD_BORDERS-0.3.shp')) + + def run(verbose=True): + lm = LayerMapping(WorldBorders, world_shp, world_mapping, + transform=False, encoding='iso-8859-1') + + lm.save(strict=True, verbose=verbose) + +A few notes about what's going on: + +* Each key in the ``world_mapping`` dictionary corresponds to a field in the + ``WorldBorders`` model, and the value is the name of the shapefile field + that data will be loaded from. +* The key ``mpoly`` for the geometry field is ``MULTIPOLYGON``, the + geometry type we wish to import as. Even if simple polygons are encountered + in the shapefile they will automatically be converted into collections prior + to insertion into the database. +* The path to the shapefile is not absolute -- in other words, if you move the + ``world`` application (with ``data`` subdirectory) to a different location, + then the script will still work. +* The ``transform`` keyword is set to ``False`` because the data in the + shapefile does not need to be converted -- it's already in WGS84 (SRID=4326). +* The ``encoding`` keyword is set to the character encoding of string values in + the shapefile. This ensures that string values are read and saved correctly + from their original encoding system. + +Afterwards, invoke the Django shell from the ``geodjango`` project directory:: + + $ python manage.py shell + +Next, import the ``load`` module, call the ``run`` routine, and watch ``LayerMapping`` +do the work:: + + >>> from world import load + >>> load.run() + + +.. _ogrinspect-intro: + +Try ``ogrinspect`` +------------------ +Now that you've seen how to define geographic models and import data with the +:ref:`ref-layermapping`, it's possible to further automate this process with +use of the :djadmin:`ogrinspect` management command. The :djadmin:`ogrinspect` +command introspects a GDAL-supported vector data source (e.g., a shapefile) and +generates a model definition and ``LayerMapping`` dictionary automatically. + +The general usage of the command goes as follows:: + + $ python manage.py ogrinspect [options] [options] + +Where ``data_source`` is the path to the GDAL-supported data source and +``model_name`` is the name to use for the model. Command-line options may +be used to further define how the model is generated. + +For example, the following command nearly reproduces the ``WorldBorders`` model +and mapping dictionary created above, automatically:: + + $ python manage.py ogrinspect world/data/TM_WORLD_BORDERS-0.3.shp WorldBorders --srid=4326 --mapping --multi + +A few notes about the command-line options given above: + +* The ``--srid=4326`` option sets the SRID for the geographic field. +* The ``--mapping`` option tells ``ogrinspect`` to also generate a + mapping dictionary for use with :class:`~django.contrib.gis.utils.LayerMapping`. +* The ``--multi`` option is specified so that the geographic field is a + :class:`~django.contrib.gis.db.models.MultiPolygonField` instead of just a + :class:`~django.contrib.gis.db.models.PolygonField`. + +The command produces the following output, which may be copied +directly into the ``models.py`` of a GeoDjango application:: + + # This is an auto-generated Django model module created by ogrinspect. + from django.contrib.gis.db import models + + class WorldBorders(models.Model): + fips = models.CharField(max_length=2) + iso2 = models.CharField(max_length=2) + iso3 = models.CharField(max_length=3) + un = models.IntegerField() + name = models.CharField(max_length=50) + area = models.IntegerField() + pop2005 = models.IntegerField() + region = models.IntegerField() + subregion = models.IntegerField() + lon = models.FloatField() + lat = models.FloatField() + geom = models.MultiPolygonField(srid=4326) + objects = models.GeoManager() + + # Auto-generated `LayerMapping` dictionary for WorldBorders model + worldborders_mapping = { + 'fips' : 'FIPS', + 'iso2' : 'ISO2', + 'iso3' : 'ISO3', + 'un' : 'UN', + 'name' : 'NAME', + 'area' : 'AREA', + 'pop2005' : 'POP2005', + 'region' : 'REGION', + 'subregion' : 'SUBREGION', + 'lon' : 'LON', + 'lat' : 'LAT', + 'geom' : 'MULTIPOLYGON', + } + +Spatial Queries +=============== + +Spatial Lookups +--------------- +GeoDjango extends the Django ORM and allows the use of spatial lookups. +Let's do an example where we find the ``WorldBorder`` model that contains +a point. First, fire up the management shell:: + + $ python manage.py shell + +Now, define a point of interest [#]_:: + + >>> pnt_wkt = 'POINT(-95.3385 29.7245)' + +The ``pnt_wkt`` string represents the point at -95.3385 degrees longitude, +and 29.7245 degrees latitude. The geometry is in a format known as +Well Known Text (WKT), an open standard issued by the Open Geospatial +Consortium (OGC). [#]_ Import the ``WorldBorders`` model, and perform +a ``contains`` lookup using the ``pnt_wkt`` as the parameter:: + + >>> from world.models import WorldBorders + >>> qs = WorldBorders.objects.filter(mpoly__contains=pnt_wkt) + >>> qs + [] + +Here we retrieved a ``GeoQuerySet`` that has only one model: the one +for the United States (which is what we would expect). Similarly, +a :ref:`GEOS geometry object ` may also be used -- here the ``intersects`` +spatial lookup is combined with the ``get`` method to retrieve +only the ``WorldBorders`` instance for San Marino instead of a queryset:: + + >>> from django.contrib.gis.geos import Point + >>> pnt = Point(12.4604, 43.9420) + >>> sm = WorldBorders.objects.get(mpoly__intersects=pnt) + >>> sm + + +The ``contains`` and ``intersects`` lookups are just a subset of what's +available -- the :ref:`ref-gis-db-api` documentation has more. + +Automatic Spatial Transformations +--------------------------------- +When querying the spatial database GeoDjango automatically transforms +geometries if they're in a different coordinate system. In the following +example, the coordinate will be expressed in terms of `EPSG SRID 32140`__, +a coordinate system specific to south Texas **only** and in units of +**meters** and not degrees:: + + >>> from django.contrib.gis.geos import * + >>> pnt = Point(954158.1, 4215137.1, srid=32140) + +Note that ``pnt`` may also constructed with EWKT, an "extended" form of +WKT that includes the SRID:: + + >>> pnt = GEOSGeometry('SRID=32140;POINT(954158.1 4215137.1)') + +When using GeoDjango's ORM, it will automatically wrap geometry values +in transformation SQL, allowing the developer to work at a higher level +of abstraction:: + + >>> qs = WorldBorders.objects.filter(mpoly__intersects=pnt) + >>> qs.query.as_sql() # Generating the SQL + ('SELECT "world_worldborders"."id", "world_worldborders"."name", "world_worldborders"."area", + "world_worldborders"."pop2005", "world_worldborders"."fips", "world_worldborders"."iso2", + "world_worldborders"."iso3", "world_worldborders"."un", "world_worldborders"."region", + "world_worldborders"."subregion", "world_worldborders"."lon", "world_worldborders"."lat", + "world_worldborders"."mpoly" FROM "world_worldborders" + WHERE ST_Intersects("world_worldborders"."mpoly", ST_Transform(%s, 4326))', + (,)) + >>> qs # printing evaluates the queryset + [] + +__ http://spatialreference.org/ref/epsg/32140/ + +Lazy Geometries +--------------- +Geometries come to GeoDjango in a standardized textual representation. Upon +access of the geometry field, GeoDjango creates a `GEOS geometry object `, +exposing powerful functionality, such as serialization properties for +popular geospatial formats:: + + >>> sm = WorldBorders.objects.get(name='San Marino') + >>> sm.mpoly + + >>> sm.mpoly.wkt # WKT + MULTIPOLYGON (((12.4157980000000006 43.9579540000000009, 12.4505540000000003 43.9797209999999978, ... + >>> sm.mpoly.wkb # WKB (as Python binary buffer) + + >>> sm.mpoly.geojson # GeoJSON (requires GDAL) + '{ "type": "MultiPolygon", "coordinates": [ [ [ [ 12.415798, 43.957954 ], [ 12.450554, 43.979721 ], ... + +This includes access to all of the advanced geometric operations provided by +the GEOS library:: + + >>> pnt = Point(12.4604, 43.9420) + >>> sm.mpoly.contains(pnt) + True + >>> pnt.contains(sm.mpoly) + False + +``GeoQuerySet`` Methods +----------------------- + + +Putting your data on the map +============================ + +Google +------ + +Geographic Admin +---------------- + +GeoDjango extends :ref:`Django's admin application ` to +enable support for editing geometry fields. + +Basics +^^^^^^ + +GeoDjango also supplements the Django admin by allowing users to create +and modify geometries on a JavaScript slippy map (powered by `OpenLayers`_). + +Let's dive in again -- create a file called ``admin.py`` inside the +``world`` application, and insert the following:: + + from django.contrib.gis import admin + from models import WorldBorders + + admin.site.register(WorldBorders, admin.GeoModelAdmin) + +Next, edit your ``urls.py`` in the ``geodjango`` project folder to look +as follows:: + + from django.conf.urls.defaults import * + from django.contrib.gis import admin + + admin.autodiscover() + + urlpatterns = patterns('', + (r'^admin/(.*)', include(admin.site.urls)), + ) + +Start up the Django development server:: + + $ python manage.py runserver + +Finally, browse to ``http://localhost:8000/admin/``, and log in with the admin +user created after running ``syncdb``. Browse to any of the ``WorldBorders`` +entries -- the borders may be edited by clicking on a polygon and dragging +the vertexes to the desired position. + +.. _OpenLayers: http://openlayers.org/ +.. _Open Street Map: http://openstreetmap.org/ +.. _Vector Map Level 0: http://earth-info.nga.mil/publications/vmap0.html +.. _Metacarta: http://metacarta.com + +.. _osmgeoadmin-intro: + +``OSMGeoAdmin`` +^^^^^^^^^^^^^^^ + +With the :class:`~django.contrib.gis.admin.OSMGeoAdmin`, GeoDjango uses +a `Open Street Map`_ layer in the admin. +This provides more context (including street and thoroughfare details) than +available with the :class:`~django.contrib.gis.admin.GeoModelAdmin` +(which uses the `Vector Map Level 0`_ WMS data set hosted at `Metacarta`_). + +First, there are some important requirements and limitations: + +* :class:`~django.contrib.gis.admin.OSMGeoAdmin` requires that the + :ref:`spherical mercator projection be added ` + to the to be added to the ``spatial_ref_sys`` table (PostGIS 1.3 and + below, only). +* The PROJ.4 datum shifting files must be installed (see the + :ref:`PROJ.4 installation instructions ` for more details). + +If you meet these requirements, then just substitute in the ``OSMGeoAdmin`` +option class in your ``admin.py`` file:: + + admin.site.register(WorldBorders, admin.OSMGeoAdmin) + +.. rubric:: Footnotes + +.. [#] Special thanks to Bjørn Sandvik of `thematicmapping.org `_ for providing and maintaining this data set. +.. [#] GeoDjango basic apps was written by Dane Springmeyer, Josh Livni, and Christopher Schmidt. +.. [#] Here the point is for the `University of Houston Law Center `_ . +.. [#] Open Geospatial Consortium, Inc., `OpenGIS Simple Feature Specification For SQL `_, Document 99-049. diff --git a/docs/ref/contrib/gis/utils.txt b/docs/ref/contrib/gis/utils.txt new file mode 100644 index 0000000000..8b14802831 --- /dev/null +++ b/docs/ref/contrib/gis/utils.txt @@ -0,0 +1,32 @@ +.. _ref-gis-utils: + +=================== +GeoDjango Utilities +=================== + +.. module:: django.contrib.gis.utils + :synopsis: GeoDjango's collection of utilities. + +The :mod:`django.contrib.gis.utils` module contains various utilities that are +useful in creating geospatial web applications. + +.. toctree:: + :maxdepth: 2 + + geoip + layermapping + ogrinspect + +GeoIP +===== + +Interface to the MaxMind GeoIP library for performing IP-based geolocation +from GeoDjango. See :ref:`GeoIP reference ` documentation for +more information. + +LayerMapping +============ + +The :class:`~django.contrib.gis.utils.LayerMapping` simplifies the process +of importing spatial data and attributes into your GeoDjango models. + diff --git a/docs/ref/contrib/index.txt b/docs/ref/contrib/index.txt index 2d15c25dfe..649128e989 100644 --- a/docs/ref/contrib/index.txt +++ b/docs/ref/contrib/index.txt @@ -32,6 +32,7 @@ those packages have. databrowse flatpages formtools/index + gis/index humanize localflavor messages @@ -111,6 +112,14 @@ Splits forms across multiple Web pages. See the :ref:`form wizard documentation `. +gis +==== + +A world-class geospatial framework built on top of Django, that enables +storage, manipulation and display of spatial data. + +See the :ref:`ref-contrib-gis` documentation for more. + humanize ======== diff --git a/docs/topics/db/managers.txt b/docs/topics/db/managers.txt index d7f5569c91..4569775652 100644 --- a/docs/topics/db/managers.txt +++ b/docs/topics/db/managers.txt @@ -296,11 +296,12 @@ manager that Django creates for you -- either as a default manager on a model with no managers, or to use temporarily when accessing related objects. Sometimes this default class won't be the right choice. One example is in the -`django.contrib.gis` application that ships with Django itself. All `gis` -models must use a special manager class (``GeoManager``) because they need a -special queryset (``GeoQuerySet``) to be used for interacting with the -database. It turns out that models which require a special manager like this -need to use the same manager class wherever an automatic manager is created. +:mod:`django.contrib.gis` application that ships with Django itself. All ``gis`` +models must use a special manager class (:class:`~django.contrib.gis.db.models.GeoManager`) +because they need a special queryset (:class:`~django.contrib.gis.db.models.GeoQuerySet`) +to be used for interacting with the database. It turns out that models which require +a special manager like this need to use the same manager class wherever an automatic +manager is created. Django provides a way for custom manager developers to say that their manager class should be used for automatic managers whenever it is the default manager