diff --git a/docs/AIS.xml b/docs/AIS.xml index c82b238..2187662 100644 --- a/docs/AIS.xml +++ b/docs/AIS.xml @@ -304,9 +304,9 @@ WHERE length(Trip) = 0 OR length(Trip) >= 1500000; Let's have a look at the speed of the ships. There are two speed values in the data; the speed calculated from the spatiotemporal trajectory speed(Trip), and the SOG attribute. Optimally, the two will be the same. A small variance would still be OK, because of sensor errors. Note that both are temporal floats. In the next query, we compare the averages of the two speed values for every ship: -SELECT ABS(twavg(SOG) * 1.852 - twavg(speed(Trip))* 3.6 ) SpeedDifference +SELECT ABS(twAvg(SOG) * 1.852 - twAvg(speed(Trip))* 3.6 ) SpeedDifference FROM Ships WHERE SOG IS NOT NULL AND - ABS(twavg(SOG) * 1.852 - twavg(speed(Trip))* 3.6 ) > 10.0 + ABS(twAvg(SOG) * 1.852 - twAvg(speed(Trip))* 3.6 ) > 10.0 ORDER BY SpeedDifference DESC; speeddifference @@ -325,13 +325,13 @@ ORDER BY SpeedDifference DESC; - The twavg computes a time-weighted average of a temporal float. It basically computes the area under the curve, then divides it by the time duration of the temporal float. By doing so, the speed values that remain for longer durations affect the average more than those that remain for shorter durations. Note that SOG is in knot, and Speed(Trip) is in m/s. The query converts both to km/h. + The twAvg computes a time-weighted average of a temporal float. It basically computes the area under the curve, then divides it by the time duration of the temporal float. By doing so, the speed values that remain for longer durations affect the average more than those that remain for shorter durations. Note that SOG is in knot, and Speed(Trip) is in m/s. The query converts both to km/h. The query shows the first 10 ship trajectories of the 82 in the table that have a difference of more than 10 km/h. These trajectories are shown in . Again they look like noise, so we remove them with the following query DELETE FROM Ships -WHERE ABS(twavg(SOG) * 1.852 - twavg(speed(Trip))* 3.6 ) > 10; +WHERE ABS(twAvg(SOG) * 1.852 - twAvg(speed(Trip))* 3.6 ) > 10;
Ship trajectories with big difference between <varname>speed(Trip)</varname> and <varname>SOG</varname> @@ -342,9 +342,9 @@ WHERE ABS(twavg(SOG) * 1.852 - twavg(speed(Trip))* 3.6 ) > 10; Now we do a similar comparison between the calculated azimuth from the spatiotemporal trajectory, and the attribute COG: -SELECT ABS(twavg(COG) - twavg(azimuth(Trip)) * 180.0/pi()) AzimuthDifference +SELECT ABS(twAvg(COG) - twAvg(azimuth(Trip)) * 180.0/pi()) AzimuthDifference FROM Ships -WHERE ABS(twavg(COG) - twavg(azimuth(Trip)) * 180.0/pi()) > 45.0 +WHERE ABS(twAvg(COG) - twAvg(azimuth(Trip)) * 180.0/pi()) > 45.0 ORDER BY AzimuthDifference DESC; azimuthdifference @@ -386,7 +386,7 @@ WITH Ports(Rodby, Puttgarden) AS ( ST_MakeEnvelope(644339, 6042108, 644896, 6042487, 25832) ) SELECT S.*, Rodby, Puttgarden FROM Ports P, Ships S -WHERE eintersects(S.Trip, P.Rodby) AND eintersects(S.Trip, P.Puttgarden); +WHERE eIntersects(S.Trip, P.Rodby) AND eIntersects(S.Trip, P.Puttgarden); -- Total query runtime: 462 msec -- 4 rows retrieved. @@ -402,7 +402,7 @@ WHERE eintersects(S.Trip, P.Rodby) AND eintersects(S.Trip, P.Puttgarden);
- This query creates two envelope geometries that represent the locations of the two ports, then intersects them with the spatiotemporal trajectories of the ships. The eintersects function checks whether a temporal point ever intersects a geometry. To speed up the query, a spatiotemporal GiST index is first built on the Trip attribute. The query identified four Ships that commuted between the two ports, . To count how many one way trips each of them did, we extend the previous query as follows: + This query creates two envelope geometries that represent the locations of the two ports, then intersects them with the spatiotemporal trajectories of the ships. The eIntersects function checks whether a temporal point ever intersects a geometry. To speed up the query, a spatiotemporal GiST index is first built on the Trip attribute. The query identified four Ships that commuted between the two ports, . To count how many one way trips each of them did, we extend the previous query as follows: WITH Ports(Rodby, Puttgarden) AS ( SELECT ST_MakeEnvelope(651135, 6058230, 651422, 6058548, 25832), @@ -410,7 +410,7 @@ WITH Ports(Rodby, Puttgarden) AS ( SELECT MMSI, (numSequences(atGeometry(S.Trip, P.Rodby)) + numSequences(atGeometry(S.Trip, P.Puttgarden)))/2.0 AS NumTrips FROM Ports P, Ships S -WHERE eintersects(S.Trip, P.Rodby) AND eintersects(S.Trip, P.Puttgarden); +WHERE eIntersects(S.Trip, P.Rodby) AND eIntersects(S.Trip, P.Puttgarden); mmsi | numtrips -----------+--------------------- @@ -435,16 +435,16 @@ BeltShips AS ( SELECT MMSI, atGeometry(S.Trip, B.Belt) AS Trip, trajectory(atGeometry(S.Trip, B.Belt)) AS Traj FROM Ships S, B - WHERE eintersects(S.Trip, B.Belt) ) + WHERE eIntersects(S.Trip, B.Belt) ) SELECT S1.MMSI, S2.MMSI, S1.Traj, S2.Traj, shortestLine(S1.trip, S2.trip) Approach FROM BeltShips S1, BeltShips S2 -WHERE S1.MMSI > S2.MMSI AND edwithin(S1.trip, S2.trip, 300); +WHERE S1.MMSI > S2.MMSI AND eDwithin(S1.trip, S2.trip, 300); -- Total query runtime: 28.5 secs -- 7 rows retrieved. - The query first defines the area of interest as an envelope, the red dashed line in ). It then restricts/crops the trajectories to only this envelope using the atGeometry function. The main query then find pairs of different trajectories that ever came within a distance of 300 meters to one another (the dwithin). For these trajectories, it computes the spatial line that connects the two instants where the two trajectories were closest to one another (the shortestLine function). shows the green trajectories that came close to the blue trajectories, and their shortest connecting line in solid red. Most of the approaches occur at the entrance of the Rødby port, which looks normal. But we also see two interesting approaches, that may indicate danger of collision away from the port. They are shown with more zoom in and + The query first defines the area of interest as an envelope, the red dashed line in ). It then restricts/crops the trajectories to only this envelope using the atGeometry function. The main query then find pairs of different trajectories that ever came within a distance of 300 meters to one another (the eDwithin). For these trajectories, it computes the spatial line that connects the two instants where the two trajectories were closest to one another (the shortestLine function). shows the green trajectories that came close to the blue trajectories, and their shortest connecting line in solid red. Most of the approaches occur at the entrance of the Rødby port, which looks normal. But we also see two interesting approaches, that may indicate danger of collision away from the port. They are shown with more zoom in and
Ship that come closer than 300 meters to one another diff --git a/docs/GTFS.xml b/docs/GTFS.xml index 7974973..648cffe 100644 --- a/docs/GTFS.xml +++ b/docs/GTFS.xml @@ -424,7 +424,7 @@ FROM trip_points t JOIN ( SELECT service_id, MIN(date) AS date FROM service_dates GROUP BY service_id) s ON t.service_id = s.service_id; - In the inner query of the INSERT statement, we select the first date of a service in the service_dates table and then we join the resulting table with the trip_points table to compute the arrival time at each point composing the trips. Notice that we filter the first date of each trip for optimization purposes because in the next step below we use the shift function to compute the trips to all other dates. Alternatively, we could join the two tables but this will be considerably slower for big GTFS files. + In the inner query of the INSERT statement, we select the first date of a service in the service_dates table and then we join the resulting table with the trip_points table to compute the arrival time at each point composing the trips. Notice that we filter the first date of each trip for optimization purposes because in the next step below we use the shiftTime function to compute the trips to all other dates. Alternatively, we could join the two tables but this will be considerably slower for big GTFS files. @@ -447,10 +447,10 @@ GROUP BY trip_id, service_id, route_id, date; INSERT INTO trips_mdb(trip_id, service_id, route_id, date, trip) SELECT trip_id, t.service_id, route_id, d.date, - shift(trip, make_interval(days => d.date - t.date)) + shiftTime(trip, make_interval(days => d.date - t.date)) FROM trips_mdb t JOIN service_dates d ON t.service_id = d.service_id AND t.date <> d.date; - In the first INSERT statement we group the rows in the trips_input table by trip_id and date while keeping the route_id atribute, use the array_agg function to construct an array containing the temporal points composing the trip ordered by time, and compute the trip from this array using the function tgeompointseq. As explained above, table trips_input only contains the first date of a trip. In the second INSERT statement we add the trips for all the other dates with the function shift. + In the first INSERT statement we group the rows in the trips_input table by trip_id and date while keeping the route_id atribute, use the array_agg function to construct an array containing the temporal points composing the trip ordered by time, and compute the trip from this array using the function tgeompointSeq. As explained above, table trips_input only contains the first date of a trip. In the second INSERT statement we add the trips for all the other dates with the function shiftTime. diff --git a/docs/location_history.xml b/docs/location_history.xml index 6c6b35d..d809360 100644 --- a/docs/location_history.xml +++ b/docs/location_history.xml @@ -95,7 +95,7 @@ UPDATE locations_mdb SET trajectory = trajectory(trip); We convert the longitude and latitude values into standard coordinates values by dividing them by 107. These can be converted into PostGIS points in the WGS84 coordinate system with the functions ST_Point and ST_SetSRID. Also, we convert the timestamp values in miliseconds to timestamptz values. We can now apply the function - tgeompointinst to create a tgeompoint of instant duration from the point and the timestamp, collect all temporal points of a day into an array with the function array_agg, and finally, create a temporal point containing all the locations of a day using function tgeompointseq. We added to the table a trajectory attribute to visualize the location history in QGIS is given in . + tgeompoint to create a tgeompoint of instant duration from the point and the timestamp, collect all temporal points of a day into an array with the function array_agg, and finally, create a temporal point containing all the locations of a day using function tgeompointSeq. We added to the table a trajectory attribute to visualize the location history in QGIS is given in .
Visualization of the Google location history loaded into MobilityDB.