[[TOC()]]
= GEOS Geometries =
== Background ==
=== What is GEOS? ===
[http://geos.refractions.net/ GEOS] stands for '''G'''eometry '''E'''ngine - '''O'''pen '''S'''ource, and is a C++ port of the [http://www.jump-project.org/project.php?PID=JTS&SID=OVER Java Topology Suite], implementing the OpenGIS [http://www.opengeospatial.org/standards/sfs Simple Features for SQL] spatial predicate functions and spatial operators. GEOS is developed and maintained by [http://www.refractions.net/ Refractions Research] of Victoria, Canada.
=== Why the new API? ===
1. The GEOS SWIG wrapper is no longer maintained, and requires the installation of SWIG.
* ''See'' Sean Gillies, ''[http://zcologia.com/news/150/geometries-for-python/ Geometries for Python]'' (blog post explaining rationale for abandoning GEOS support); ''see also'' Sean's message on the [http://geos.refractions.net/pipermail/geos-devel/2007-March/002851.html GEOS-Devel Mailing List] (Mar. 5, 2007).
2. The [http://trac.gispython.org/projects/PCL/browser/PCL/trunk/PCL-Core/cartography/geometry PCL implementation] is over 2K+ lines of C and would make PCL a requisite package for the GeoDjango application stack.
3. Cross-platform compatibility.
Thus, the Python {{{ctypes}}} package was used to wrap the [http://geos.refractions.net/ro/doxygen_docs/html/geos__c_8h-source.html GEOS C API] to bring the rich capabilities of GEOS to Python and !GeoDjango.
''Features'':
* A BSD-licensed interface to the GEOS geometry routines, implemented purely in Python using {{{ctypes}}}.
* Loosely-coupled to !GeoDjango, ''e.g.'', GEOS geometry objects may be used outside a django project/application (no need to have {{{DJANGO_SETTINGS_MODULE}}} set).
* Mutability. GEOS Geometry objects may be modified, and memory is safely re-used when possible.
* Cross-platform and tested. !GeoDjango GEOS geometries are well-tested and compatible with Windows, Linux, Solaris, and Mac OSX platforms.
=== Related Work ===
Upon learning of the GEOS Geometry work in GeoDjango in May, 2007, Sean Gillies began implementation of PCL's {{{ctypes}}} interface to GEOS, called [http://trac.gispython.org/projects/PCL/wiki/ShapeLy ShapeLy]. !ShapeLy is still evolving, ''e.g.'', it lacks support for the full GEOS API, mutable geometries, and fully-functional constructors for Polygons and !GeometryCollections. However, the PCL team is implementing exciting features including a geometry interface (similar to NumPy's [http://numpy.scipy.org/array_interface.shtml array interface]) and excellent GeoJSON support.
Because !ShapeLy is licensed under the LGPL, I (Justin Bronn) declined to merge the projects. ''See'' [http://lists.gispython.org/pipermail/community/2007-May/000964.html Proposal to launch the Shapely project], GISPython.com mailing list.
== Geometry Objects ==
'''Note:''' The images shown below are courtesy of the [http://www.jump-project.org/project.php?PID=JTS&SID=OVER Java Topology Suite (JTS) webpage], Copyright (C) 2003, [http://www.jump-project.org/ The JUMP-Project . Org].
=== Point ===
{{{
#!html
}}}
The {{{Point}}} object may be initialized with either a tuple, or individual parameters. For example:
{{{
#!python
>>> from django.contrib.gis.geos import Point
>>> p = Point((5, 23)) # 2D point, passed in as a tuple
>>> p = Point(5, 23, 8) # 3D point, passed in with individual parameters
}}}
=== !LineString ===
{{{
#!html
}}}
{{{LineString}}} objects initialize on a given sequence. For example, the constructor may take lists, tuples, [http://numpy.scipy.org/ NumPy] arrays of X,Y[,Z] pairs, or {{{Point}}} objects. If {{{Point}}} objects are used, ownership of the points is ''not'' transferred to the {{{LineString}}} object. Examples:
{{{
#!python
>>> from django.contrib.gis.geos import LineString, Point
>>> ls = LineString((1, 1), (2, 2))
>>> ls = LineString([(1, 1), (2, 2)])
>>> ls = LineString(Point(1, 1), Point(2, 2))
>>> from numpy import array
>>> ls = LineString(array([(1, 1), (2, 2)]))
}}}
=== !LinearRing ===
{{{
#!html
}}}
{{{LinearRing}}} objects are subclasses of {{{LineString}}} objects, however, an error will be thrown if the points used during initialization do not form a closed linestring.
{{{
#!python
>>> from django.contrib.gis.geos import LinearRing
>>> lr = LinearRing((0, 0), (0, 1), (1, 1), (1, 0), (0, 0))
>>> lr = LinearRing((0, 0), (0, 1))
GEOS_ERROR: IllegalArgumentException: points must form a closed linestring
...
}}}
=== Polygon ===
{{{
#!html
}}}
== Geometry Collections ==
=== !MultiPoint ===
{{{
#!python
>>> from django.contrib.gis.geos import Point
>>> from django.contrib.gis.geos import MultiPoint
>>> p1 = Point((0,0))
>>> p2 = Point((1,2))
>>> mp = MultiPoint(p1, p2)
>>> mp
>>> mp[0].wkt
'POINT (0.0000000000000000 0.0000000000000000)'
>>> len(mp)
2
>>> [ p.wkt for p in mp ]
['POINT (0.0000000000000000 0.0000000000000000)', 'POINT (1.0000000000000000 2.0000000000000000)']
>>> mp.ring
False
}}}
=== !MultiLineString ===
=== !MultiPolygon ===
=== !GeometryCollection ===
== API ==
=== Creation ===
GEOS geometry objects may be created from strings using the {{{fromstr()}}} factory, or using the constructor for each geometry object (as described above).
{{{
#!python
>>> from django.contrib.gis.geos import fromstr
>>> pnt = fromstr('POINT(-90.5 29.5)', srid=4326)
}}}
The {{{srid}}} keyword may be used to set the spatial reference system identifier number for the geometry. This will be used to conduct any needed transformations for spatial lookups and geographic model creation. It should be noted that {{{fromstr}}} is a shortcut to the constructor for the base {{{GEOSGeometry}}} object.
=== Output Properties ===
* {{{wkt}}}
* Returns the Well-Known Text of the geometry (an OGC standard).
* {{{hex}}}
* Returns the HEXEWKB PostGIS canonical representation of the geometry. This representation is specific to PostGIS, and is not a standard.
* {{{kml}}}
* Returns a [http://code.google.com/apis/kml/documentation/ KML] (Keyhole Markup Language) representation of the geometry. Should only be used for geometries with an SRID of 4326 (WGS84), but this restriction is not enforced.
=== Spatial Predicate Properties ===
* {{{empty}}}
* Returns whether or not the set of points in the geometry is empty.
* {{{valid}}}
* Returns a boolean indicating whether the geometry is valid.
* {{{simple}}}
* A Geometry is simple if and only if the only self-intersections are at boundary points. For example, a {{{LineString}}} object is not simple if it intersects itself (like the one pictured above). Thus, {{{LinearRing}}} and {{{Polygon}}} objects are always simple because they do not intersect themselves.
* {{{ring}}}
* Returns a boolean indicating whether the geometry is a {{{LinearRing}}}.
* {{{hasz}}}
* Returns a boolean indicating whether the geometry is three-dimensional.
=== Spatial Predicate Methods ===
All of the following spatial predicate methods take another GEOS Geometry instance as an argument (referred to below as {{{other}}}).
* {{{contains(other)}}}
* {{{crosses(other)}}}
* {{{disjoint(other)}}}
* {{{equals(other)}}}
* {{{equals_exact(other)}}}
* {{{intersects(other)}}}
* {{{overlaps(other)}}}
* {{{relate_pattern(other)}}}
* {{{within(other)}}}
=== Topological Methods ===
* {{{buffer()}}}
* {{{difference()}}}
* {{{intersection()}}}
* {{{relate()}}}
* {{{sym_difference()}}}
* {{{union()}}}
=== Topological Properties ===
* {{{area}}}
* {{{boundary}}}
* {{{centroid}}}
* {{{convex_hull}}}
* {{{envelope}}}
* {{{point_on_surface}}}