| 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 | |