Chapter 11. Temporal Network Points

Table of Contents

Static Network Types
Constructors
Transformations
Accessors
Spatial Operations
Comparisons
Temporal Network Points
Validity of Temporal Network Points
Constructors
Conversions
Operations
Aggregations
Indexing

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:

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.

Static Network Types

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.

Constructors

  • Constructor for network points

    npoint(bigint,double precision) → npoint

    SELECT npoint(76, 0.3);
    
  • Constructor for network segments

    nsegment(bigint,double precision,double precision) → nsegment

    SELECT nsegment(76, 0.3, 0.5);
    

Transformations

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

Accessors

  • 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
    

Spatial Operations

  • Return the spatial reference identifier

    srid({npoint,nsegment}) → integer

    SELECT SRID(npoint 'Npoint(76, 0.3)');
    -- 5676
    SELECT SRID(nsegment 'Nsegment(76, 0.3, 0.5)');
    -- 5676
    

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
    

Comparisons

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