GEOS API

Background

What is GEOS?

GEOS stands for Geometry Engine - Open Source, and is a C++ port of the Java Topology Suite, implementing 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.

Why the new API?

  1. The GEOS SWIG wrapper is no longer maintained, and requires the installation of SWIG. [1]
  2. The 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 [2] package was used to wrap the 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. For example, GEOS geometry objects may be used outside a django project/application (no need to have DJANGO_SETTINGS_MODULE set, etc.)
  • Mutability. GEOS Geometry objects may be modified.
  • Cross-platform and tested. GeoDjango GEOS geometries are well-tested and compatible with Windows, Linux, Solaris, and Mac OS X platforms.

Geometry Objects

Point

The Point object may be initialized with either a tuple, or individual parameters. For example:

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

Methods

Point(x, y, z=None)
x
y
z

LineString and LinearRing

LineString objects initialize on a given sequence. For example, the constructor may take lists, tuples, 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:

>>> 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 objects are subclasses of LineString; however, an error will be raised if the points used during initialization are not closed (the first point is equal to the last point):

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

Methods

LineString(coords)
x
y
z

Polygon

Polygons are composed of an exterior ring (the shell), and may also have interior rings that denote areas excluded from the exterior.

Methods

Polygon(rings)
from_bbox(bbox)
shell, exterior_ring
num_interior_rings

Geometry Collections

MultiPoint

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

Methods

cascaded_union

New in Django 1.1: Requires GEOS 3.1

GeometryCollection

API

Creation

GEOSGeometry(geo_input, srid=None)

Geometries may be created using the GEOSGeometry constructor; geo_input may be any of the following types of data:

Input Type Python Type Example
WKT str / unicode 'POINT(5 23)'
EWKT str / unicode 'SRID=4326;POINT(5 23)'
HEX str / unicode '010100000000000000000014400000000000003740'
HEXEWKB str / unicode ''0101000020E610000000000000000014400000000000003740'
GeoJSON str / unicode '{ "type": "Point", "coordinates": [ 5.000000, 23.000000 ] }'
WKB buffer buffer('\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14@\x00\x00\x00\x00\x00\x007@')

While this may seem like an acronym soup, all are standardized geospatial data formats or extensions thereof.

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.

fromfile(file_h)

This factory creates a GEOS geometry from the given file name or an open file handle (1.1 only):

>>> from django.contrib.gis.geos import fromfile
>>> g = fromfile('/home/bob/geom.wkt')

fromstr(string)

GEOS geometry objects may be created from strings using the fromstr() factory, or using the constructor for each geometry object (as described above):

>>> from django.contrib.gis.geos import fromstr
>>> pnt = fromstr('POINT(-90.5 29.5)', srid=4326)

It should be noted that fromstr is a shortcut to the constructor for the base GEOSGeometry object.

Geometry Properties

empty

Returns whether or not the set of points in the geometry is empty.

geom_type

Returns a string corresponding to the type of geometry. For example:

>>> pnt = GEOSGeometry('POINT(5 23)')
>>> pnt.geom_type
'Point'

geom_typeid

Returns the GEOS geometry type identification number. The following table shows the value for each geometry type:

Geometry ID
Point 0
LineString 1
LinearRing 2
Polygon 3
MultiPoint 4
MultiLineString 5
MultiPolygon 6
GeometryCollection 7

hasz

Returns a boolean indicating whether the geometry is three-dimensional.

num_coords, num_points

Returns the total number of coordinates in this geometry. For polygons and collections, this is the cumulative number of all coordinates from the component geometries.

ring

Returns a boolean indicating whether the geometry is a LinearRing.

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. Thus, LinearRing and Polygon objects are always simple because they do not intersect themselves.

valid

Returns a boolean indicating whether the geometry is valid.

Output Properties

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. [8] Essentially the SRID is prepended to the WKT representation, for example SRID=4326;POINT(5 23). Please note that this does not include the 3dm, 3dz, and 4d information that PostGIS supports in its EWKT representations.

hex

Returns the HEXEWKB PostGIS canonical representation of the geometry. This representation is specific to PostGIS, and is not a standard.

json, geojson

Returns the GeoJSON representation of the geometry. Requires GDAL.

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.

ogr

Returns an OGRGeometry object from the data in the GEOSGeometry.

wkb

Returns the Well-Known Binary of the geometry (an OGC standard). The WKB data is returned Python buffer object.

wkt

Returns the Well-Known Text of the geometry (an OGC standard).

Spatial Predicate Methods

All of the following spatial predicate methods take another GEOS Geometry instance (other) as an argument.

contains(other)

Returns True if within(other) is False.

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

disjoint(other)

Returns true if the DE-9IM intersection matrix for the two Geometries is FF*FF****.

equals(other)

Returns true if the DE-9IM intersection matrix for the two Geometries is T*F**FFF*.

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.

intersects(other)

Returns True if disjoint(other) is False.

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

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

touches(other)

Returns true if the DE-9IM intersection matrix for the two Geometries is FT*******, F**T***** or F***T****.

within(other)

Returns true if the DE-9IM intersection matrix for the two Geometries is T*F**F***.

Topological Methods

buffer(width, quadsegs=8)

Returns a geometry 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).

difference(other)

Returns a geometry representing the points making up this geometry that do not make up other.

intersection(other)

Returns a geometry representing the points shared by this geometry and other.

relate(other)

Returns the DE-9IM intersection matrix for this geometry and the other.

simplify(tolerance=0.0, preserve_topology=False)

Returns the geometry, simplified using the Douglas-Peucker algorithm to the specified tolerance (higher tolerance => less points). If no tolerance provided, defaults to 0.

By default, this function does not preserve topology - e.g. polygons can be split, collapse to lines or disappear 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. This is significantly slower.

sym_difference(other)

Returns a set combining the points in this geometry not in other, and the points in other not in this geometry.

union(other)

Returns a Geometry representing all the points in this Geometry and other.

Topological Properties

boundary

Returns the boundary as a newly allocated Geometry object.

centroid

The centroid is equal to the centroid of the set of component Geometries of highest dimension (since the lower-dimension geometries contribute zero “weight” to the centroid).

convex_hull

Returns the smallest convex Polygon that contains all the points in the Geometry.

envelope

Returns a Polygon that represents the bounding envelope of this geometry.

point_on_surface

Computes and returns a Point guaranteed to be on the interior of this geometry.

Other Properties & Methods

extent

This property returns the extent of this geometry as a 4-tuple, consisting of (xmin, ymin, xmax, ymax).

area

This property returns the area of the Geometry.

distance(geom)

Returns the distance between the closest points on this Geometry and the given geom (another GEOSGeometry object). GEOS distance calculations are linear – in other words, GEOS will not perform a spherical calculation even if the SRID is in a geographic coordinate system.

length

Returns the length of this Geometry (e.g., 0 for point or the circumference of a Polygon).

prepared

New in Django 1.1: 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.

srs

Returns an OGR SpatialReference object corresponding to the SRID of the geometry or None. Requires GDAL.

transform(ct, clone=False)

Transforms the geometry according to the given transformation object, which may be an integer SRID, spatial reference WKT string, a PROJ.4 string, or a SpatialReference 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 is returned instead. Requires GDAL.

Footnotes

[1]See Sean Gillies, Geometries for Python (blog post explaining rationale for abandoning GEOS support); see also Sean’s message on the geos-devel mailing list, Mar. 5, 2007
[2]See generally Python’s ctypes documentation, at Ch. 14.14.
[3]Specifically, GEOSGeometry was introduced in revision 5008 on April 15th, 2007.
[4]See Sean Gillies, Geometries for Python Update, April 16th 2007 (“The ctypes-based geometry module in r5008 looks kickass. I’m checking it out now.”).
[5]Sean Gillies, Proposal to launch the Shapely Project, May 1, 2007.
[6]Justin Bronn, RE: Proposal to launch the Shapely project, May 1, 2007.
[7]Sean Gillies, Proposal to change Shapely license from LGPL to BSD, Nov. 20, 2007.
[8]See PostGIS EWKB, EWKT and Canonical Forms, PostGIS documentation at Ch. 4.1.2.