Spatial databases can not only store geometry, they also provide the capabilities to compare relationships between geometries. Answering questions such as “Which are the closet bike racks to a park?” or “Where are the intersections of subway lines and streets?” is only possible by comparing geometries representing the bike racks, streets, and subway lines.
The next sections describe the various geometry comparison functions available with PostGIS.
ST_Equals(geometry A, geometry B) tests the spatial equality of two geometries. ST_Equals returns TRUE if two geometries of the same type have identical x,y coordinate values, that is if the secondary shape is equal (identical) to the first shape.
Objects are equal to themselves.
SELECT ST_Equals( 'POINT(0 0)', 'POINT(0 0)' );
st_equals ----------- t
Objects are equal to other objects that cover the same space (but might have different representations):
SELECT ST_Equals( 'LINESTRING(0 0,1 1)', 'LINESTRING(1 1,0.5 0.5,0 0)' );
st_equals ----------- t
There are other equality tests in PostGIS as well, that test for identical representations or bounds equality, refer to Equality for more information.
ST_Intersects, ST_Crosses, and ST_Overlaps test whether the interiors of the geometries intersect.
ST_Intersects(geometry A, geometry B) returns TRUE if the intersection any part of geometry A touches or overlaps with geometry B.
The opposite of ST_Intersects is ST_Disjoint(geometry A , geometry B). If two geometries are disjoint, they do not intersect, and vice-versa.
It is usually more efficient to test “not intersects” than to test “disjoint” because the intersects tests can be spatially indexed, while the disjoint test cannot.
For multipoint/polygon, multipoint/linestring, linestring/linestring, linestring/polygon, and linestring/multipolygon comparisons, ST_Crosses(geometry A, geometry B) returns TRUE if the intersection results in a geometry whose dimension is one less than the maximum dimension of the two source geometries. The intersection set must also be interior to both source geometries.
ST_Overlaps(geometry A, geometry B) compares two geometries of the same dimension and returns TRUE if the intersection set results in a geometry different from both but of the same dimension.
For example, again using the New York City subways and neighborhoods as an example, it is possible to determine a subway station’s neighborhood using the ST_Intersects function.
SELECT name, ST_AsText(the_geom) FROM nyc_subway_stations WHERE name = 'Broad St';
SELECT name, boroname FROM nyc_neighborhoods WHERE ST_Intersects(the_geom, ST_GeomFromText('POINT(583571 4506714)',26918));
name | boroname --------------------+----------- Financial District | Manhattan
ST_Touches(geometry A, geometry B) tests whether two geometries touch at their boundaries, but do not intersect in their interiors. ST_Touches will return TRUE if either of the geometries’ boundaries intersect, or if only one of the geometry’s interiors intersects the other’s boundary.
Although ST_Within and ST_Contains both test whether one geometry is fully within the other, ST_Within tests for the exact opposite result of ST_Contains.
ST_Within(geometry A, geometry B) returns TRUE if the first geometry is completely within the second geometry. ST_Contains(geometry A, geometry B) returns TRUE if the second geometry is completely contained by the first geometry.
Identifying features that are within a certain distance of other features is a common requirement in spatial analysis. The ST_Distance(geometry A, geometry B) calculates the (shortest) distance between two geometries and returns the answer as a number (float). This is useful for actually reporting back the distance between objects.
SELECT ST_Distance( ST_GeometryFromText('POINT(0 5)'), ST_GeometryFromText('LINESTRING(-2 2, 2 2)'));
To test whether two objects are within a distance of one another, the ST_DWithin function provides an spatial index-accelerated TRUE/FALSE test. This will help answer questions such as “how many trees are within a 500 meter buffer of the road?”. You don’t have to calculate an actual buffer, you just have to test the distance relationship.
The following example will identify the streets within 10 meters of a given subway stop:
SELECT name FROM nyc_streets WHERE ST_DWithin( the_geom, ST_GeomFromText('POINT(583571 4506714)',26918), 10 );
name -------------- Wall St Broad St Nassau St
For more information about geometry functions in PostGIS, please refer to the PostGIS Reference