QGIS Temporal Controller – Interpolating Points in Chronological Order

qgis

This question follows on from the method shared by @Babel at Interpolating points with QGIS native Temporal Controller.

I have successfully used the above method to create interpolated lines moving between my points. However as seen in the gif below it has not created one line moving from point to point but rather multiple lines. I cannot seem to find a reason for this.

enter image description here

My data looks like the below, some days have more than one point, some days have no points. I don't think this is the issue however. I am using the Date_time field to animate the data, in place of 'arrival_time' in Babel's method.

enter image description here

At the link below is my project and data as both csv and gpkg.
Project and data


At this imgur link is the gif output using a Fixed Time Range, showing my original issue of multiple points and lines being generated at once. At this second link is the result after implementing @Babel's Sort Order and Temporal Control fixes below. Both methods are using a 4 hour event duration and a four hour step.

As you'll see, whilst the fixes do have the points now rendering in the right order however it still isn't generating one continuous solid line moving point-to-point.


I've made some progress. For the gif below I have the following settings – my steps are set to 4 hours, Event Duration is set to 1 day.

enter image description here

My code is as the below. I am using two geometry generators, one for the plane symbol and one for the dotted line with the end_point function removed.:

with_variable (
'zone',
0,  -- change this value to add/subtract hours to/from attribute named arrival_time to transform local time zone to UTC
with_variable(
    'arrival',
    Date_time + to_interval (@zone  || ' hours'),
    with_variable(
        'next',
        attribute (get_feature_by_id (@layer, id2+1), 'Date_time'),
        with_variable (
            'mapstart',
            @map_start_time + to_interval ((hour (@map_end_time - @map_start_time)/2 ) || ' hours'),
            with_variable (
                'line',
                make_line (
                    $geometry,
                    geometry( get_feature_by_id (@layer, id2+1))
                ),
                case 
                when 
                    @mapstart < @next and @mapstart > Date_time +  @frame_duration 
                then 
                    end_point(
                        line_substring (
                            @line,
                            0,
                            length (@line) * 
                            hour ( @map_start_time + (hour (@frame_duration )/2)  || ' hours' - @arrival ) /
                            hour (  @next + to_interval (@zone  || ' hours') - @arrival)
                        
                    )
                    )
                
            end
            )
        )
    )
)

)

There is obviously still something not quite right however as the line is still not travelling point-to-point.

Best Answer

There seem to be several problems. See below for each and how to deal with it:

  • Sort order
  • Configuration of Temporal Control
  • Time zones

enter image description here

Be aware that the lines are not geodetic lines, but simply connect the dots with a straight line in the projection/crs used. This is especially true for long connections like from New Zealand to the US.

Sort order

The expression in the linked answer is based on the variable @next, created with the expression attribute (get_feature_by_id (@layer, $id+1), 'arrival_time'). So this variable returns for each feature the value of the field Date_time from the next feature - next here meaning in the internal order ($id: the order features were initially added to the layer).

However, in your case, this order does not correspond to the chronological order of your Date_time field. If I sort your Date_time filds, the first entry is 1/1/83 1 pm with id=229, the second is 1/1/83 6pm with id=138.

The expression, however, gets the next feature based on id, thus id=230. This corresponds to a value in Data_time field of 12/25/83 1 pm.

So create a new field id2 with this expression to get the correct sort order:

array_find (
    array_sort( array_agg( Date_time)),
    Date_time
)

Then in geomtry generator replace $id with id2.

Configuration of temporal control

In layer properties, you configured temporal control to Redraw layer Only. However, you should select Single Field with Date/Time and select the Date_time field. Select a Limits condition (either include or exclude end) and set Event duration accordingly.

Changing expression (sort order, part 2)

See answer by @Kasper - with this, it works for me using Single field with date/time, Event duration: 1 day, step 4 hours . So the whole expression looks like:

with_variable (
'zone',
0,  -- change this value to add/subtract hours to/from attribute named arrival_time to transform local time zone to UTC
with_variable(
    'arrival',
    Date_time + to_interval (@zone  || ' hours'),
    with_variable(
        'next',
        attribute (get_feature (@layer, 'ID',ID+1), 'Date_time'),
        with_variable (
            'mapstart',
            @map_start_time + to_interval ((hour (@map_end_time - @map_start_time)/2 ) || ' hours'),
            with_variable (
                'line',
                make_line (
                    $geometry,
                    geometry( get_feature (@layer, 'ID',ID+1))
                ),
                case 
                when 
                    @mapstart < @next and @mapstart > Date_time +  @frame_duration 
                then 
                    
                        end_point (
                            line_substring (
                                @line,
                                0,
                                length (@line) * 
                                hour ( @map_start_time + (hour (@frame_duration )/2)  || ' hours' - @arrival ) /
                                hour (  @next + to_interval (@zone  || ' hours') - @arrival)
                            )
                    )
                    end
                )
            )
        )
    )
)

Time Zone

Maybe you also have to tweek the time zone. In my local installation, the Date_time field is recognized as Central European Time, whereas variables like @map_start_time are in UTC. If you have a larger difference from your local time zone to UTC, this might affect results. This is why I created the variable @zone at the beginning of the expression. Set the value in line 3 to compensate the difference between your local time zone and UTC.