3

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.

6
  • I'm not exactly sure what exactly you want to achieve based on your data. Maybe you can explain a little bit more about what the expected result shold be like.
    – Babel
    Nov 22, 2022 at 16:10
  • I want to animate just one interpolated line, moving from point to point in chronological order by the Date_time field. Nov 22, 2022 at 16:17
  • See updated answer
    – Babel
    Dec 1, 2022 at 15:01
  • Great, thanks for feedback! What was finally the problem that solved your issue? Did you have to change timezone?
    – Babel
    Dec 1, 2022 at 15:56
  • Some of my points were out of order still, which didn't help. I also still had get_feature_by_id in one place rather than get_feature. But all your tips got me over the finish line, just need to play with my symbology and pretty things up now! Dec 1, 2022 at 16:02

2 Answers 2

3
+50

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.

5
  • This is better, thank you. I thought I could just use another field I had named ID. I've responded elsewhere with what I want my final resul to look like. Nov 22, 2022 at 16:18
  • Ah, indeed, you already have a field ID that looks correct. The other problem seems to be Configuration of temporal control, see updated answer
    – Babel
    Nov 22, 2022 at 16:42
  • Hmmm, that seems to have stopped some of my geometry generators working, I'll play around with it and update again accordingly. Nov 23, 2022 at 10:09
  • Updated my original post, still experiencing some issues. Nov 23, 2022 at 13:32
  • I tested your project and replaced the get_feature_by_id (@layer, $id+1) which does not get the layer by 'ID', by get_feature(@layer, 'ID',"ID"+1): this does indeed only draw/animate one line at a time
    – Kasper
    Nov 30, 2022 at 18:18
3

If I understand what you want to achieve (one line at a time, from ID N to N+1 and so on 'ID' now being the items sorted by ascending date)

If you just replace the get_feature_by_id (@layer, $id+1) from your sample project by the following everywhere in your code, it works:

get_feature(@layer,'ID' , "ID" +1)

I have added a dynamic label on your markers to display each location's "ID" along the animation.

Here are a few frame extracts, as you can see an animated line goes from 196 to 197, 197 to 198 and so on:

From 196: enter image description here

From 197: enter image description here

From 198: enter image description here

From 199: enter image description here

2
  • For some reason my geometries aren't displaying now. Just to check, are you using 'Redraw only' or 'Single field with date/time'? Neither seem to be working for me currently, but wantd to check all the settings are the same after i've done some playing around. @Kasper Dec 1, 2022 at 10:53
  • @MattHouston: I am using redraw -only
    – Kasper
    Dec 1, 2022 at 17:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.