| 234 |  | * This is done without the 'next generation' SWIG Python bindings. The compilation flag to enable the new bindings is {{{--with-ngpython}}}. | 
          
            | 235 |  | *  ''Note'': As of 1.4.1, {{{ngpython}}} bindings don't work with Python 2.5.  While it's listed as fixed on trunk per their ticket [http://trac.osgeo.org/gdal/ticket/1379 1379], I've still had issues with using the trunk.  A {{{ctypes}}} interface, for needed GeoDjango functionality, is forthcoming. | 
          
            | 236 |  |  | 
          
            | 237 |  | = Model API = | 
          
            | 238 |  | == Fields == | 
          
            | 239 |  |  | 
          
            | 240 |  | The following geometry-enabled fields are available: | 
          
            | 241 |  | * {{{PointField}}} | 
          
            | 242 |  | * {{{LineStringField}}} | 
          
            | 243 |  | * {{{PolygonField}}} | 
          
            | 244 |  | * {{{MultiPointField}}} | 
          
            | 245 |  | * {{{MultiLineStringField}}} | 
          
            | 246 |  | * {{{MultiPolygonField}}} | 
          
            | 247 |  | * {{{GeometryCollectionField}}} | 
          
            | 248 |  |  | 
          
            | 249 |  | == Field Keywords == | 
          
            | 250 |  | * Field keywords are used during model creation, for example: | 
          
            | 251 |  | {{{ | 
          
            | 252 |  | #!python | 
          
            | 253 |  | from django.contrib.gis.db import models | 
          
            | 254 |  |  | 
          
            | 255 |  | class Zip(models.Model, models.GeoMixin): | 
          
            | 256 |  | code = models.IntegerField() | 
          
            | 257 |  | poly = models.PolygonField(srid=-1) | 
          
            | 258 |  |  | 
          
            | 259 |  | object = models.GeoManager() | 
          
            | 260 |  | }}} | 
          
            | 261 |  |  | 
          
            | 262 |  | * {{{srid}}} | 
          
            | 263 |  | * Sets the SRID (Spatial Reference System Identity) of geometry to the given value.  Defaults to 4326 (WGS84).  ''See'' Open GIS Consortium, Inc., ''[http://www.opengis.org/docs/99-049.pdf OpenGIS Simple Feature Specification For SQL]'', Document 99-049 (May 5, 1999), at  Ch. 2.3.8 (Geometry Values and Spatial Reference Systems, pg. 39). | 
          
            | 264 |  | * {{{index}}} | 
          
            | 265 |  | * Defaults to True.  Creates a GiST index for the given geometry.  Update the index with the PostgreSQL command {{{VACUUM ANALYZE}}} (may take a while to execute depending on how large your geographic-enabled tables are). | 
          
            | 266 |  |  | 
          
            | 267 |  | == Creating and Saving Models with Geometry Fields == | 
          
            | 268 |  | Here is an example of how to create a geometry object (assuming the {{{Zip}}} model example above): | 
          
            | 269 |  |  | 
          
            | 270 |  | {{{ | 
          
            | 271 |  | #!python | 
          
            | 272 |  | >>> from zipcode.models import Zip | 
          
            | 273 |  | >>> z = Zip(code=77096, poly='POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))') | 
          
            | 274 |  | >>> z.save() | 
          
            | 275 |  | }}} | 
          
            | 276 |  |  | 
          
            | 277 |  | Geometries are represented as '''strings''' in either of the formats WKT (Well Known Text) or HEXEWKB (PostGIS specific, essentially a WKB geometry in hexadecimal).  For example: | 
          
            | 278 |  | * WKT Polygon: {{{'POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))'}}} | 
          
            | 279 |  | * ''See'' Open GIS Consortium, Inc., ''[http://www.opengis.org/docs/99-049.pdf OpenGIS Simple Feature Specification For SQL]'', Document 99-049 (May 5, 1999), at  Ch. 3.2.5 (SQL Textual Representation of Geometry, pg. 53). | 
          
            | 280 |  | * HEXEWKB Polygon: '{{{0103000000010000000 ... 00000000000002440'}}} | 
          
            | 281 |  | * ''See'' [http://postgis.refractions.net/docs/ch04.html#id2904792 "PostGIS EWKB, EWKT and Canonical Forms"], PostGIS documentation at Ch. 4.1.2. | 
          
            | 282 |  |  | 
          
            | 283 |  | = Database API = | 
          
            | 284 |  |  | 
          
            | 285 |  | '''Note:''' The following database lookup types can only be used with on geographic fields with {{{filter()}}}.  Filters on 'normal' fields (e.g. {{{CharField}}}) may be chained with those on geographic fields.  Thus, geographic queries take the following form (assuming the {{{Zip}}} model used in the [GeoDjango#ModelAPI Model API] section above): | 
          
            | 286 |  |  | 
          
            | 287 |  | {{{ | 
          
            | 288 |  | #!python | 
          
            | 289 |  | >>> qs = Zip.objects.filter(<geo field A>__<geo lookup type>=<geo string B>) | 
          
            | 290 |  | >>> qs = Zip.objects.exclude(...) | 
          
            | 291 |  | }}} | 
          
            | 292 |  |  | 
          
            | 293 |  | == PostGIS Operator Field Lookup Types == | 
          
            | 294 |  |  | 
          
            | 295 |  | * ''See generally'', [http://postgis.refractions.net/docs/ch06.html#id2854381 "Operators", PostGIS Documentation at Ch. 6.2.2] | 
          
            | 296 |  | * '''Note:'''  This API is subject to some change -- we're open to suggestions. | 
          
            | 297 |  | * {{{overlaps_left}}} | 
          
            | 298 |  | * Returns true if A's bounding box overlaps or is to the left of B's bounding box. | 
          
            | 299 |  | * PostGIS equivalent "{{{&<}}}" | 
          
            | 300 |  | * {{{overlaps_right}}} | 
          
            | 301 |  | * Returns true if A's bounding box overlaps or is to the right of B's bounding box. | 
          
            | 302 |  | * PostGIS equivalent "{{{&>}}}" | 
          
            | 303 |  | * {{{left}}} | 
          
            | 304 |  | * Returns true if A's bounding box is strictly to the left of B's bounding box. | 
          
            | 305 |  | * PostGIS equivalent "{{{<<}}}" | 
          
            | 306 |  | * {{{right}}} | 
          
            | 307 |  | * Returns true if A's bounding box is strictly to the right of B's bounding box. | 
          
            | 308 |  | * PostGIS equivalent "{{{>>}}}" | 
          
            | 309 |  | * {{{overlaps_below}}} | 
          
            | 310 |  | * Returns true if A's bounding box overlaps or is below B's bounding box. | 
          
            | 311 |  | * PostGIS equivalent "{{{&<|}}}" | 
          
            | 312 |  | * {{{overlaps_above}}} | 
          
            | 313 |  | * Returns true if A's bounding box overlaps or is above B's bounding box. | 
          
            | 314 |  | * PostGIS equivalent "{{{|&>}}}" | 
          
            | 315 |  | * {{{strictly_below}}} | 
          
            | 316 |  | * Returns true if A's bounding box is strictly below B's bounding box. | 
          
            | 317 |  | * PostGIS equivalent "{{{<<|}}}" | 
          
            | 318 |  | * {{{strictly_above}}} | 
          
            | 319 |  | * Returns true if A's bounding box is strictly above B's bounding box. | 
          
            | 320 |  | * PostGIS equivalent "{{{|>>}}}" | 
          
            | 321 |  | * {{{same_as}}} or {{{exact}}} | 
          
            | 322 |  | * The "same as" operator. It tests actual geometric equality of two features. So if A and B are the same feature, vertex-by-vertex, the operator returns true. | 
          
            | 323 |  | * PostGIS equivalent "{{{~=}}}" | 
          
            | 324 |  | * {{{contained}}} | 
          
            | 325 |  | * Returns true if A's bounding box is completely contained by B's bounding box. | 
          
            | 326 |  | * PostGIS equivalent "{{{@}}}" | 
          
            | 327 |  | * {{{bbcontains}}} | 
          
            | 328 |  | * Returns true if A's bounding box completely contains B's bounding box. | 
          
            | 329 |  | * PostGIS equivalent "{{{~}}}" | 
          
            | 330 |  | * {{{bboverlaps}}} | 
          
            | 331 |  | * Returns true if A's bounding box overlaps B's bounding box. | 
          
            | 332 |  | * PostGIS equivalent "{{{&&}}}" | 
          
            | 333 |  |  | 
          
            | 334 |  | == PostGIS GEOS Function Field Lookup Types == | 
          
            | 335 |  | * ''See generally'' [http://postgis.refractions.net/docs/ch06.html#id2615853 "Geometry Relationship Functions", PostGIS Documentation at Ch. 6.1.2]. | 
          
            | 336 |  | * This documentation will be updated completely with the content from the aforementioned PostGIS docs. | 
          
            | 337 |  | * ~~{{{distance}}}~~ | 
          
            | 338 |  | * '''Warning:''' This function lookup type does not work, and will be moved to a routine as part of {{{GeoManager}}}. | 
          
            | 339 |  | * Return the cartesian distance between two geometries in projected units. | 
          
            | 340 |  | * PostGIS equivalent {{{Distance(geometry, geometry)}}} | 
          
            | 341 |  | * {{{equals}}} | 
          
            | 342 |  | * Requires GEOS | 
          
            | 343 |  | * Returns 1 (TRUE) if the given Geometries are "spatially equal". | 
          
            | 344 |  | * Use this for a 'better' answer than '='. equals('LINESTRING(0 0, 10 10)','LINESTRING(0 0, 5 5, 10 10)') is true. | 
          
            | 345 |  | * PostGIS equivalent {{{Equals(geometry, geometry)}}}, OGC SPEC s2.1.1.2 | 
          
            | 346 |  | * {{{disjoint}}} | 
          
            | 347 |  | * Requires GEOS | 
          
            | 348 |  | * Returns 1 (TRUE) if the Geometries are "spatially disjoint". | 
          
            | 349 |  | * PostGIS equivalent {{{Disjoint(geometry, geometry)}}} | 
          
            | 350 |  | * {{{intersects}}} | 
          
            | 351 |  | * PostGIS equivalent {{{Intersects(geometry, geometry)}}} | 
          
            | 352 |  | * {{{touches}}} | 
          
            | 353 |  | * PostGIS equivalent {{{Touches(geometry, geometry)}}} | 
          
            | 354 |  | * {{{crosses}}} | 
          
            | 355 |  | * PostGIS equivalent {{{Crosses(geometry, geometry)}}} | 
          
            | 356 |  | * {{{overlaps}}} | 
          
            | 357 |  | * PostGIS equivalent {{{Overlaps(geometry, geometry)}}} | 
          
            | 358 |  | * {{{contains}}} | 
          
            | 359 |  | * PostGIS equivalent {{{Contains(geometry, geometry)}}} | 
          
            | 360 |  | * {{{intersects}}} | 
          
            | 361 |  | * PostGIS equivalent {{{Intersects(geometry, geometry)}}} | 
          
            | 362 |  | * {{{relate}}} | 
          
            | 363 |  | * PostGIS equivelent {{{Relate(geometry, geometry)}}} | 
          
            | 364 |  |  | 
          
            | 365 |  | == Extra Instance Methods == | 
          
            | 366 |  |  | 
          
            | 367 |  | A model with geometry fields will get the following methods, substitute {{{GEOM}}} with the name of the geometry field: | 
          
            | 368 |  |  | 
          
            | 369 |  | == get_GEOM_geos == | 
          
            | 370 |  | Returns a {{{GEOSGeometry}}} instance for the geometry.  For example (using the {{{District}}} model from above): | 
          
            | 371 |  |  | 
          
            | 372 |  | {{{ | 
          
            | 373 |  | #!python | 
          
            | 374 |  | >>> from django.contrib.gis.geos import GEOSGeometry | 
          
            | 375 |  | >>> dist = District.objects.get(name='Houston ISD') | 
          
            | 376 |  | >>> geom = dist.get_poly_geos() | 
          
            | 377 |  | >>> print geom.centroid.wkt | 
          
            | 378 |  | POINT(-95.231713 29.723235) | 
          
            | 379 |  | >>> print geom.area | 
          
            | 380 |  | 0.08332 | 
          
            | 381 |  | >>> print geom.geom_type | 
          
            | 382 |  | Polygon | 
          
            | 383 |  | >>> print geom.centroid.geom_type | 
          
            | 384 |  | Point | 
          
            | 385 |  | >>> print geom.intersects(GEOSGeometry('POINT(-95.395223 29.798088)')) | 
          
            | 386 |  | False | 
          
            | 387 |  | }}} | 
          
            | 388 |  |  | 
          
            | 389 |  | == get_GEOM_wkt == | 
          
            | 390 |  |  | 
          
            | 391 |  | Returns the OGC WKT (Well Known Text) for the geometry.  For example (using the {{{School}}} model from above): | 
          
            | 392 |  |  | 
          
            | 393 |  | {{{ | 
          
            | 394 |  | #!python | 
          
            | 395 |  | >>> skool = School.objects.get(name='PSAS') | 
          
            | 396 |  | >>> print skool.get_point_wkt() | 
          
            | 397 |  | POINT(-95.460822 29.745463) | 
          
            | 398 |  | }}} | 
          
            | 399 |  |  | 
          
            | 400 |  | == get_GEOM_centroid == | 
          
            | 401 |  |  | 
          
            | 402 |  | This routine will return the centroid of the geometry.  For example (using the {{{District}}} model from above): | 
          
            | 403 |  |  | 
          
            | 404 |  | {{{ | 
          
            | 405 |  | #!python | 
          
            | 406 |  | >>> dist = District.objects.get(name='Houston ISD') | 
          
            | 407 |  | >>> print dist.get_poly_centroid() | 
          
            | 408 |  | POINT(-95.231713 29.723235) | 
          
            | 409 |  | }}} | 
          
            | 410 |  |  | 
          
            | 411 |  | == get_GEOM_area == | 
          
            | 412 |  |  | 
          
            | 413 |  | This routine will return the area of the geometry field. | 
          
            | 414 |  |  | 
          
            | 415 |  | {{{ | 
          
            | 416 |  | #!python | 
          
            | 417 |  | >>> dist = District.objects.get(name='Houston ISD') | 
          
            | 418 |  | >>> print dist.get_poly_area() | 
          
            | 419 |  | 0.08332 | 
          
            | 420 |  | }}} | 
          
            | 421 |  |  | 
          
            | 422 |  | '''Note''': Units are in the projected units of the coordinate system.  In the example above, the units are in degrees since we're using WGS84.  ~~The units system needs to be figured out here, since I don't know what these units represent~~. | 
          
            |  | 229 | * As of r5397 there's a {{{ctypes}}} layer for GDAL/OGR, no python bindings needed. | 
          
            |  | 230 |  |