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