Table of Contents
The temporal points that we have considered so far represent the movement of objects that can move freely on space since it is assumed that they can change their position from one location to the next one without any motion restriction. This is the case for animals and for flying objects such as planes or drones. However, in many cases, objects do not move freely in space but rather within spatially embedded networks such as routes or railways. In this case, it is necessary to take the embedded networks into account while describing the movements of these moving objects. Temporal network points account for these requirements.
Compared with the free-space temporal points, network-based points have the following advantages:
Network points provide road constraints that reflect the real movements of moving objects.
The geometric information is not stored with the moving point, but once and for all in the fixed networks. In this way, the location representations and interpolations are more precise.
Network points are more efficient in terms of data storage, location update, formulation of query, as well as indexing. These are discussed later in this document.
Temporal network points are based on pgRouting, a PostgreSQL extension for developing network routing applications and doing graph analysis. Therefore, temporal network points asume that the underlying network is defined in a table named ways
, which has at least three columns: gid
containing the unique route identifier, length
containing the route length, and the_geom
containing the route geometry.
There are two static network types, npoint
(short for network point) and nsegment
(short for network segment), which represent, respectively, a point and a segment of a route. An npoint
value is composed of a route identifier and a float number in the range [0,1] determining a relative position of the route, where 0 corresponds to the begining of the route and 1 to the end of the route. An nsegment
value is composed of a route identifier and two float numbers in the range [0,1] determining the start and end relative positions. A nsegment
value whose start and end positions are equal corresponds to an npoint
value.
The npoint
type serves as base type for defining the temporal network point type tnpoint
. The tnpoint
type has similar functionality as the temporal point type tgeompoint
with the exception that it only considers two dimensions. Thus, all functions and operators described before for the tgeompoint
type are also applicable for the tnpoint
type. In addition, there are specific functions defined for the tnpoint
type.
An npoint
value is a couple of the form (rid,position)
where rid
is a bigint
value representing a route identifier and position
is a float
value in the range [0,1] indicating its relative position. The values 0 and 1 of position
denote, respectively, the starting and the ending position of the route. The road distance between an npoint
value and the starting position of route with identifier rid
is computed by multiplying position
by length, where length
is the route length. Examples of input of network point values are as follows:
SELECT npoint 'Npoint(76, 0.3)'; SELECT npoint 'Npoint(64, 1.0)';
The constructor function for network points has one argument for the route identifier and one argument for the relative position. An example of a network point value defined with the constructor function is as follows:
SELECT npoint(76, 0.3);
An nsegment
value is a triple of the form (rid,startPosition,endPosition)
where rid
is a bigint
value representing a route identifier and startPosition
and endPosition
are float
values in the range [0,1] such that startPosition ≤ endPosition
. Semantically, a network segment represents a set of network points (rid,position)
with startPosition ≤ position ≤ endPosition
. If startPosition=0
and endPosition=1
, the network segment is equivalent to the entire route. If startPosition=endPosition
, the network segment represents into a single network point. Examples of input of network point values are as follows:
SELECT nsegment 'Nsegment(76, 0.3, 0.5)'; SELECT nsegment 'Nsegment(64, 0.5, 0.5)'; SELECT nsegment 'Nsegment(64, 0.0, 1.0)'; SELECT nsegment 'Nsegment(64, 1.0, 0.0)'; -- converted to nsegment 'Nsegment(64, 0.0, 1.0)';
As can be seen in the last example, the startPosition
and endPosition
values will be inverted to ensure that the condition startPosition ≤ endPosition
is always satisfied. The constructor function for network segments has one argument for the route identifier and two optional arguments for the start and end positions. Examples of network segment values defined with the constructor function are as follows:
SELECT nsegment(76, 0.3, 0.3); SELECT nsegment(76); -- start and end position assumed to be 0 and 1 respectively SELECT nsegment(76, 0.5); -- end position assumed to be 1
Values of the npoint
type can be converted to the nsegment
type using an explicit CAST
or using the ::
notation as shown next.
SELECT npoint(76, 0.33)::nsegment;
Values of static network types must satisfy several constraints so that they are well defined. These constraints are given next.
The route identifier rid
must be found in column gid
of table ways
.
The position
, startPosition
, and endPosition
values must be in the range [0,1]. An error is raised whenever one of these constraints are not satisfied.
Examples of incorrect static network type values are as follows.
-- incorrect rid value SELECT npoint 'Npoint(87.5, 1.0)'; -- incorrect position value SELECT npoint 'Npoint(87, 2.0)'; -- rid value not found in the ways table SELECT npoint 'Npoint(99999999, 1.0)';
We give next the functions and operators for the static network types.
Round the position(s) of the network point or the network segment to the number of decimal places
round({npoint,nsegment},integer=0) → {npoint,nsegment}
SELECT round(npoint(76, 0.123456789), 6); -- NPoint(76,0.123457) SELECT round(nsegment(76, 0.123456789, 0.223456789), 6); -- NSegment(76,0.123457,0.223457)
Return the route identifier
route({npoint,nsegment}) → bigint
SELECT route(npoint 'Npoint(63, 0.3)'); -- 63 SELECT route(nsegment 'Nsegment(76, 0.3, 0.3)'); -- 76
Return the position
getPosition(npoint) → float
SELECT getPosition(npoint 'Npoint(63, 0.3)'); -- 0.3
Return the start/end position
startPosition(nsegment) → float
endPosition(nsegment) → float
SELECT startPosition(nsegment 'Nsegment(76, 0.3, 0.5)'); -- 0.3 SELECT endPosition(nsegment 'Nsegment(76, 0.3, 0.5)'); -- 0.5
Values of the npoint
and nsegment
types can be converted to the geometry
type using an explicit CAST
or using the ::
notation as shown next.
Convert a network point to a geometry
{npoint,nsegment}::geometry
SELECT ST_AsText(npoint(76, 0.33)::geometry); -- POINT(21.6338731332283 50.0545869554067) SELECT ST_AsText(nsegment(76, 0.33, 0.66)::geometry); -- LINESTRING(21.6338731332283 50.0545869554067,30.7475989651999 53.9185062927473) SELECT ST_AsText(nsegment(76, 0.33, 0.33)::geometry); -- POINT(21.6338731332283 50.0545869554067)
Similarly, geometry
values of subtype point
or linestring
(restricted to two points) can be converted, respectively, to npoint
and nsegment
values using an explicit CAST
or using the ::
notation. For this, the route that intersects the given points must be found, where a tolerance of 0.00001 units (depending on the coordinate system) is assumed so a point and a route that are close are considered to intersect. If no such route is found, a null value is returned.
Convert a geometry to a network point
geometry::{npoint,nsegment}
SELECT geometry 'SRID=5676;Point(279.269156511873 811.497076880187)'::npoint; -- NPoint(3,0.781413) SELECT geometry 'SRID=5676;LINESTRING(406.729536784738 702.58583437902, 383.570801314823 845.137059419277)'::nsegment; -- NSegment(3,0.6,0.9) SELECT geometry 'SRID=5676;Point(279.3 811.5)'::npoint; -- NULL SELECT geometry 'SRID=5676;LINESTRING(406.7 702.6,383.6 845.1)'::nsegment; -- NULL
Two npoint
values may be have different route identifiers but may represent the same spatial point at the intersection of the two routes. Function equals
is used for testing spatial equality of network points.
Spatial equality for network points
equals(npoint, npoint)::Boolean
WITH inter(geom) AS ( SELECT st_intersection(t1.the_geom, t2.the_geom) FROM ways t1, ways t2 WHERE t1.gid = 1 AND t2.gid = 2), fractions(f1, f2) AS ( SELECT ST_LineLocatePoint(t1.the_geom, i.geom), ST_LineLocatePoint(t2.the_geom, i.geom) FROM ways t1, ways t2, inter i WHERE t1.gid = 1 AND t2.gid = 2) SELECT equals(npoint(1, f1), npoint(2, f2)) FROM fractions; -- true
The comparison operators (=, <, and so on) for static network types require that the left and right arguments be of the same type. Excepted the equality and inequality, the other comparison operators are not useful in the real world but allow B-tree indexes to be constructed on static network types.
Are the values equal?
{npoint,nsegment} = {npoint,nsegment}
SELECT npoint 'Npoint(3, 0.5)' = npoint 'Npoint(3, 0.5)'; -- true SELECT nsegment 'Nsegment(3, 0.5, 0.5)' = nsegment 'Nsegment(3, 0.5, 0.6)'; -- false
Are the values different?
{npoint,nsegment} <> {npoint,nsegment}
SELECT npoint 'Npoint(3, 0.5)' <> npoint 'Npoint(3, 0.6)'; -- true SELECT nsegment 'Nsegment(3, 0.5, 0.5)' <> nsegment 'Nsegment(3, 0.5, 0.5)'; -- false
Is the first value less than the second one?
{npoint,nsegment} < {npoint,nsegment}
SELECT nsegment 'Nsegment(3, 0.5, 0.5)' < nsegment 'Nsegment(3, 0.5, 0.6)'; -- true
Is the first value greater than the second one?
{npoint,nsegment} > {npoint,nsegment}
SELECT nsegment 'Nsegment(3, 0.5, 0.5)' > nsegment 'Nsegment(2, 0.5, 0.5)'; -- true
Is the first value less than or equal to the second one?
{npoint,nsegment} <= {npoint,nsegment}
SELECT npoint 'Npoint(1, 0.5)' <= npoint 'Npoint(2, 0.5)'; -- true
Is the first value greater than or equal to the second one?
{npoint,nsegment} >= {npoint,nsegment}
SELECT npoint 'Npoint(1, 0.6)' >= npoint 'Npoint(1, 0.5)'; -- true