The topological relationships such as ST_Intersects
and the distance relationships such as ST_DWithin
can be generalized for temporal points. The arguments of these generalized functions are either a temporal point and a base type (that is, a geometry
or a geography
) or two temporal points. Furthermore, both arguments must be of the same base type, that is, these functions do not allow to mix a temporal geometry point (or a geometry) and a temporal geography point (or a geography).
There are three versions of the spatial relationships:
The ever relationships determine whether the topological or distance relationship is ever satisfied (see the section called “Ever and Always Comparisons”) and returns a boolean
. Examples are the eIntersects
and eDwithin
functions.
The always relationships determine whether the topological or distance relationship is always satisfied (see the section called “Ever and Always Comparisons”) and returns a boolean
. Examples are the aIntersects
and aDwithin
functions.
The temporal relationships compute the topological or distance relationship at each instant and results in a tbool
. Examples are the tIntersects
and tDwithin
functions.
For example, the following query
SELECT eIntersects(geometry 'Polygon((1 1,1 3,3 3,3 1,1 1))', tgeompoint '[Point(0 2)@2001-01-01, Point(4 2)@2001-01-05)'); -- t
tests whether the temporal point ever intersects the geometry. In this case, the query is equivalent to the following one
SELECT ST_Intersects(geometry 'Polygon((1 1,1 3,3 3,3 1,1 1))', geometry 'Linestring(0 2,4 2)');
where the second geometry is obtained by applying the trajectory
function to the temporal point.
In contrast, the query
SELECT tIntersects(geometry 'Polygon((1 1,1 3,3 3,3 1,1 1))', tgeompoint '[Point(0 2)@2001-01-01, Point(4 2)@2001-01-05)'); -- {[f@2001-01-01, t@2001-01-02, t@2001-01-04], (f@2001-01-04, f@2001-01-05)}
computes at each instant whether the temporal point intersects the geometry. Similarly, the following query
SELECT eDwithin(tgeompoint '[Point(3 1)@2001-01-01, Point(5 1)@2001-01-03)', tgeompoint '[Point(3 1)@2001-01-01, Point(1 1)@2001-01-03)', 2); -- t
tests whether the distance between the temporal points was ever less than or equal to 2, while the following query
SELECT tDwithin(tgeompoint '[Point(3 1)@2001-01-01, Point(5 1)@2001-01-03)', tgeompoint '[Point(3 1)@2001-01-01, Point(1 1)@2001-01-03)', 2); -- {[t@2001-01-01, t@2001-01-02], (f@2001-01-02, f@2001-01-03)}
computes at each instant whether the distance between the temporal points is less than or equal to 2.
The ever or always relationships are sometimes used in combination with a spatiotemporal index when computing the temporal relationships. For example, the following query
SELECT T.TripId, R.RegionId, tIntersects(T.Trip, R.Geom) FROM Trips T, Regions R WHERE eIntersects(T.Trip, R.Geom)
which verifies whether a trip T
(which is a temporal point) intersects a region R
(which is a geometry), will benefit from a spatiotemporal index on the column T.Trip
since the eIntersects
function will automatically perform the bounding box comparison T.Trip && R.Geom
. This is further explained later in this document.
Not all spatial relationships available in PostGIS have a meaningful generalization for temporal points. A generalized version of the following relationships are defined for temporal geometric points: eIntersects
, eDisjoint
, eDwithin
, eContains
, and eTouches
, while for temporal geographic points only the three first ones are defined. Furthermore, not all combinations of parameters are meaningful for a given generalized function. For example, while tContains(geometry, tpoint)
is meaningful, tContains(tpoint, geometry)
is meaningful only when the geometry is a single point, and tContains(tpoint, tpoint)
is equivalent to tintersects(tpoint, geometry)
. For this reason, only the first combination of parameters is defined for eContains
, aContains
, and tContains
.
Finally, it is worth noting that the temporal relationships allow to mix 2D/3D geometries but in that case, the computation is only performed on 2D.
We present next the ever and always spatial relationships. These relationships automatically include a bounding box comparison that makes use of any spatial indexes that are available on the arguments.
Ever or always contains
eContains(geo,tgeompoint) → boolean
aContains(geo,tgeompoint) → boolean
This function returns true if the temporal point is ever or always at the interior of the geometry. Recall that a geometry does not contain things in its boundary and thus, polygons and lines do not contain lines and points lying in their boundary. Please refer to the documentation of the ST_Contains function in PostGIS.
SELECT eContains(geometry 'Linestring(1 1,3 3)', tgeompoint '[Point(4 2)@2001-01-01, Point(2 4)@2001-01-02]'); -- false SELECT eContains(geometry 'Linestring(1 1,3 3,1 1)', tgeompoint '[Point(4 2)@2001-01-01, Point(2 4)@2001-01-03]'); -- true SELECT eContains(geometry 'Polygon((1 1,1 3,3 3,3 1,1 1))', tgeompoint '[Point(0 1)@2001-01-01, Point(4 1)@2001-01-02]'); -- false SELECT eContains(geometry 'Polygon((1 1,1 3,3 3,3 1,1 1))', tgeompoint '[Point(1 4)@2001-01-01, Point(4 1)@2001-01-04]'); -- true
Is ever or always disjoint
eDisjoint({geo,tgeompoint},{geo,tgeompoint}) → boolean
aDisjoint({geo,tpoint},{geo,tpoint}) → boolean
SELECT eDisjoint(geometry 'Polygon((0 0,0 1,1 1,1 0,0 0))', tgeompoint '[Point(0 0)@2001-01-01, Point(1 1)@2001-01-03)'); -- false SELECT eDisjoint(geometry 'Polygon((0 0 0,0 1 1,1 1 1,1 0 0,0 0 0))', tgeompoint '[Point(0 0 1)@2001-01-01, Point(1 1 0)@2001-01-03)'); -- true
Is ever or always at distance within
eDwithin({geo,tpoint},{geo,tpoint},float) → boolean
aDwithin({geo,tgeompoint},{geo,tgeompoint},float) → boolean
SELECT eDwithin(geometry 'Point(1 1 1)', tgeompoint '[Point(0 0 0)@2001-01-01, Point(1 1 0)@2001-01-02]', 1); -- true SELECT eDwithin(geometry 'Polygon((0 0 0,0 1 1,1 1 1,1 0 0,0 0 0))', tgeompoint '[Point(0 2 2)@2001-01-01,Point(2 2 2)@2001-01-02]', 1); -- false
Ever or always intersects
eIntersects({geo,tpoint},{geo,tpoint}) → boolean
aIntersects({geo,tgeompoint},{geo,tgeompoint}) → boolean
SELECT eIntersects(geometry 'Polygon((0 0 0,0 1 0,1 1 0,1 0 0,0 0 0))', tgeompoint '[Point(0 0 1)@2001-01-01, Point(1 1 1)@2001-01-03)'); -- false SELECT eIntersects(geometry 'Polygon((0 0 0,0 1 1,1 1 1,1 0 0,0 0 0))', tgeompoint '[Point(0 0 1)@2001-01-01, Point(1 1 1)@2001-01-03)'); -- true
Ever or always touches
eTouches({geo,tgeompoint},{geo,tgeompoint}) → boolean
aTouches({geo,tgeompoint},{geo,tgeompoint}) → boolean
SELECT eTouches(geometry 'Polygon((0 0,0 1,1 1,1 0,0 0))', tgeompoint '[Point(0 0)@2001-01-01, Point(0 1)@2001-01-03)'); -- true
We present next the temporal spatial relationships. A common requirement regarding them is to restrict the result of the relationship to the instants when the value of the result is true or false. As an example, the following query computes for each trip the time spent traveling in the Brussels municipality.
SELECT TripId, duration(atValue(tintersects(T.trip, M.geom), True)) FROM Trips T, Municipality M WHERE M.Name = "Brussels" AND atValue(tintersects(T.trip, M.geom), True) IS NOT NULL;
To simplify query writing, the temporal spatial relationships have an optional last parameter, which if given applies the atValue
function (see the section called “Restrictions”) to the result of the relationship. In this way, the above query can be written as follows.
SELECT TripId, duration(tintersects(T.trip, M.geom, True)) FROM Trips T, Municipality M WHERE M.Name = "Brussels" AND tintersects(T.trip, M.geom, True) IS NOT NULL;
Temporal contains
tContains(geometry,tgeompoint,atValue boolean=NULL) → tbool
SELECT tContains(geometry 'Linestring(1 1,3 3)', tgeompoint '[Point(4 2)@2001-01-01, Point(2 4)@2001-01-02]'); -- {[f@2001-01-01, f@2001-01-02]} SELECT tContains(geometry 'Linestring(1 1,3 3,1 1)', tgeompoint '[Point(4 2)@2001-01-01, Point(2 4)@2001-01-03]'); -- {[f@2001-01-01, t@2001-01-02], (f@2001-01-02, f@2001-01-03]} SELECT tContains(geometry 'Polygon((1 1,1 3,3 3,3 1,1 1))', tgeompoint '[Point(0 1)@2001-01-01, Point(4 1)@2001-01-02]'); -- {[f@2001-01-01, f@2001-01-02]} SELECT tContains(geometry 'Polygon((1 1,1 3,3 3,3 1,1 1))', tgeompoint '[Point(1 4)@2001-01-01, Point(4 1)@2001-01-04]'); -- {[f@2001-01-01, f@2001-01-02], (t@2001-01-02, f@2001-01-03, f@2001-01-04]}
Temporal disjoint
tDisjoint({geo,tpoint},{geo,tpoint},atValue boolean=NULL) → tbool
The function only supports 3D or geographies for two temporal points
SELECT tDisjoint(geometry 'Polygon((1 1,1 2,2 2,2 1,1 1))', tgeompoint '[Point(0 0)@2001-01-01, Point(3 3)@2001-01-04)'); -- {[t@2001-01-01, f@2001-01-02, f@2001-01-03], (t@2001-01-03, t@2001-01-04]} SELECT tDisjoint(tgeompoint '[Point(0 3)@2001-01-01, Point(3 0)@2001-01-05)', tgeompoint '[Point(0 0)@2001-01-01, Point(3 3)@2001-01-05)'); -- {[t@2001-01-01, f@2001-01-03], (t@2001-01-03, t@2001-01-05)}
Temporal distance within
tDwithin({geompoint,tgeompoint},{geompoint,tgeompoint},float,atValue boolean=NULL)
→ tbool
SELECT tDwithin(geometry 'Point(1 1)', tgeompoint '[Point(0 0)@2001-01-01, Point(2 2)@2001-01-03)', sqrt(2)); -- {[t@2001-01-01, t@2001-01-03)} SELECT tDwithin(tgeompoint '[Point(1 0)@2001-01-01, Point(1 4)@2001-01-05]', tgeompoint 'Interp=Step;[Point(1 2)@2001-01-01, Point(1 3)@2001-01-05]', 1); -- {[f@2001-01-01, t@2001-01-02, t@2001-01-04], (f@2001-01-04, t@2001-01-05]}
Temporal intersects
tIntersects({geo,tpoint},{geo,tpoint},atValue boolean=NULL) → tbool
The function only supports 3D or geographies for two temporal points
SELECT tIntersects(geometry 'MultiPoint(1 1,2 2)', tgeompoint '[Point(0 0)@2001-01-01, Point(3 3)@2001-01-04)'); /* {[f@2001-01-01, t@2001-01-02], (f@2001-01-02, t@2001-01-03], (f@2001-01-03, f@2001-01-04]} */ SELECT tIntersects(tgeompoint '[Point(0 3)@2001-01-01, Point(3 0)@2001-01-05)', tgeompoint '[Point(0 0)@2001-01-01, Point(3 3)@2001-01-05)'); -- {[f@2001-01-01, t@2001-01-03], (f@2001-01-03, f@2001-01-05)}
Temporal touches
tTouches({geo,tgeompoint},{geo,tgeompoint},atValue boolean=NULL) → tbool
SELECT tTouches(geometry 'Polygon((1 0,1 2,2 2,2 0,1 0))', tgeompoint '[Point(0 0)@2001-01-01, Point(3 0)@2001-01-04)'); -- {[f@2001-01-01, t@2001-01-02, t@2001-01-03], (f@2001-01-03, f@2001-01-04]}