Advertisements

Movement data in GIS #7: animated trajectories with TimeManager

In this post, we use TimeManager to visualize the position of a moving object over time along a trajectory. This is another example of what is possible thanks to QGIS’ geometry generator feature. The result can look like this:

What makes this approach interesting is that the trajectory is stored in PostGIS as a LinestringM instead of storing individual trajectory points. So there is only one line feature loaded in QGIS:

(In part 2 of this series, we already saw how a geometry generator can be used to visualize speed along a trajectory.)

The layer is added to TimeManager using t_start and t_end attributes to define the trajectory’s temporal extent.

TimeManager exposes an animation_datetime() function which returns the current animation timestamp, that is, the timestamp that is also displayed in the TimeManager dock, as well as on the map (if we don’t explicitly disable this option).

Once TimeManager is set up, we can edit the line style to add a point marker to visualize the position of the moving object at the current animation timestamp. To do that, we interpolate the position along the trajectory segments. The first geometry generator expression splits the trajectory in its segments:

The second geometry generator expression interpolates the position on the segment that contains the current TimeManager animation time:

The WHEN statement compares the trajectory segment’s start and end times to the current TimeManager animation time. Afterwards, the line_interpolate_point function is used to draw the point marker at the correct position along the segment:

CASE 
WHEN (
m(end_point(geometry_n($geometry,@geometry_part_num)))
> second(age(animation_datetime(),to_datetime('1970-01-01 00:00')))
AND
m(start_point(geometry_n($geometry,@geometry_part_num)))
<= second(age(animation_datetime(),to_datetime('1970-01-01 00:00')))
)
THEN
line_interpolate_point( 
  geometry_n($geometry,@geometry_part_num),
  1.0 * (
    second(age(animation_datetime(),to_datetime('1970-01-01 00:00')))
	- m(start_point(geometry_n($geometry,@geometry_part_num)))
  ) / (
    m(end_point(geometry_n($geometry,@geometry_part_num)))
	- m(start_point(geometry_n($geometry,@geometry_part_num)))
  ) 
  * length(geometry_n($geometry,@geometry_part_num))
)
END

Here is the animation result for a part of the trajectory between 08:00 and 09:00:


Read more:

Advertisements
12 comments
  1. K said:

    How can I create a LinestringM out of a line and a separate point layer with points exactly on the line and a timestamp as attribute?

    • Interesting … where does the line come from? Is it a routing network? If not, wouldn’t it be enough to just deal with, i.e. connect, the points?

      • K said:

        I used QuickOSM to download a bus route relation, then I filtered the way layer so that it only shows the roads and then i dissolved that so that I have a simple continuous line from bus route start to bus route end (theres a roundabout in it though, not sure how it affects that).

        I also got a point layer with the points “on” that line, I filtered it so that the layer now only contains the stops that the bus I’m looking at stops at. Then I joined a csv file to it that contains the overall time spent up to each stop in seconds (first stop 0 seconds, next stop 240, etc. up to the last stop 1440 seconds).
        Example: http://puu.sh/xazze/d04aae0e9c.png

        Here are the two shapefiles: http://puu.sh/xazEV/57a5467156.zip

        What should I do next?

  2. Mike said:

    Hi, I’d really like to be able to replicate this but having trouble displaying the marker on the screen when TimeManager runs.

    My layer looks like this…

    id;t_start;t_end;newline
    100;2016-01-01 08:00:00;2016-01-01 08:02:00;LINESTRING(546805 261201, 545883 260197, 544799 261344, 544343 261491)

    I add the layer to Time Manager no problem and I think I’ve followed your instructions to the letter re applying the two geomertry generator steps.

    When I click play TimeManager runs at specified intervals from 08:00 to 08:02 but the marker is not displayed on screen.

    Anything obvious I could be missing?

    Thanks

    • Hi Mike! If your file contains ordinary linestring features instead of linestringM, it can not work.

  3. Thanks for responding. I couldn’t see how the measure value in the linestringM was being used so wrongly assumed a regular linestring was fine. Please could you explain why it needs to be a linestringM and how the measure value is used by this example? I’ve read back through your earlier posts on this subject and can see how the measure value is used when producing the plot which breaks down the trajectory into segments then colours them by speed, but from what I can tell for this example it assumes a constant speed between the start and end of the entire trajectory – the speed of the marker in the animation doesn’t reflect the specified speed on each individual segment of the trajectory.

    I changed my layer to the below but am still not seeing the marker when I run Time Manager.

    id;t_start;t_end;newline
    100;2016-01-01 08:00;2016-01-01 08:02;LINESTRINGM(546805 261201 10, 545883 260197 10, 544799 261344 10, 544343 261491 10)

    • from what I can tell for this example it assumes a constant speed between the start and end of the entire trajectory

      That’s incorrect. The expression that you see above is evaluated on the level of each individual trajectory segment and not on the entire trajectory.

      In your example, the m value is always 10, so it’s always 1970-01-01 00:00:10. That’s inconsistent with the t_start and t_end values you specified.

      • Mike said:

        I understand now and have it working – thanks!!

  4. Mike said:

    Hi, is it possible to include the fadeout effect in this example as per your ‘Trajectory animations with fadeout effect’ post?

    For the fadeout feature to work I understand you have to activate ‘accumulate features’ in the layer settings, but does this work if an end time is specified as required to interpolate the position in this example?

    • That’s a good question! I’ll have to think about how this can be achieved. I don’t doubt that it can, but will have to try how it performs.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: