5

I made a geopackage to plan Aids-to-Navigation for maritime environments. In my database I have a few fields that describe the character of the lights that are to be placed on the planned A-to-N's. These are the fields used in the S-57 standard.

e.g.: A south cardinal bouy (it' s a type of AtoN) has a standard lightcharacter: 6 quick flashes + one long flash in a total period of 15 seconds. this is coded as (italic text not in database:

LITCHR: 25 - Quickflash + Longflash;

SIGPER: 15 - 15 seconds;

SIGGRP: (6+1);

SIGSEQ: 0.5(0.5)0.5(0.5)0.5(0.5)0.5(0.5)0.5(0.5)0.5(2.5)3(4)

The SIGSEQ (signal sequence) is the total flashsequence of the light with the format: light(eclipse), so 0.5(0.5) is half a second lit, half a second dark. The total amount of the SIGSEQ should add up to be as much as the SIGPER.

Is is possible in QGIS to make a SVG marker blink as the intended lightcharacter?! If yes I would like to know where I have to look to make this happen.

SVG marker i want to make blink view of project

  • Not as a core feature, but maybe there's a plugin. For example, MMQGIS says it does "simple animation." Or maybe you can creatively use QVisualize plugin, which displays features one-by-one, with a time delay that you specify. There's also QGIS Full Motion Video, which "allows to analyze, visualize and process videos inside the QGIS environment." – csk Jan 28 at 21:06
  • 1
    Indeed very interesting question. You could try using data defined override and add something like this: Case When second(now()) > 0 AND second(now()) <= 30 Then '#990000' When second(now()) > 30 AND second(now()) <= 60 Then '#00FF00' end. I will take a look at what is possible with this... – MrXsquared Jan 28 at 21:08
  • 1
    I have no idea if QGIS can display SMIL in SVG files, but it might be something to look into as the animations would be internal to the symbols themselves and could therefore be set as rule-based symbols, no plugin needed. – Gabriel C. Jan 28 at 21:18
  • 1
    possible with python. a blog from 2014 so it's been around for a few years. python 3 syntax for qgis3 would be needed to adapt all of that for your needs nathanw.net/2014/10/29/animated-qgis-map-canvas-item – SaultDon Jan 28 at 21:43
3

I played around for a bit with @MrXsquared's idea and there is a way to do it with the expression builder. I have tried various ways of defining the patterns and I was successful even for irregular ones, although I'm not 100% satisfied. Another issue is that for huge layers with large numbers of features, this is probably not viable to refresh at 10hz...

Simple patterns like Flashing and Occulting are easy to write, but the particular example you used, a cardinal south buoy, gets tedious real quick. I'll get to that one further below.

Bear in mind I assume the SVGs you use can have their basic parameters set inside QGIS (outline color, outline weight, fill color). Check here if you'd like to do that.

To get flashing signals, first set the stage by using Rule-based symbology on your layer. Edit the rules and go to the marker section, highlighting the symbol layer and going to the fill color expression builder. As an example, the rules for flashing and occulting are basically the same, with the alpha channel values reversed:

  • Flashing: if(second(now()) % 5,'#00FF0000','#FFFF0000')
  • Occulting: if(second(now()) % 5,'#FFFF0000','#00FF0000')

Symbols with the above rules will flash/occult red, 12 times per minute. Just edit the hex color values and modulo for the various lights in new rules.

Then go to Layer properties | Rendering and set the refresh layer at interval to 0.10, ticking the checkbox. After applying the changes, your symbols should be flashing in the map canvas.

Now for the Q(6) + LFl. 15s example, I haven't found a way to simplify the expression. I was able to make it work by explicitly specifying on which map canvas updates I wanted the alpha to be opaque or transparent. It wouldn't have made for a particularly long string if the flashing hadn't been under a second, but now I had to tell QGIS every 0.1 second if it needed to be lit, over the course of 1 minute. That's a lot of values. I just built the first 15s pattern in Excel, transposed it +15 3 more times, concatenated everything in 1 cell and copy-pasted it in my rule, which looks like this:

  • Q(6) + LFl. 15s: if(round(format_date(now(),'s.z'), 1) IN (0,0.1,0.2,0.3,0.4,0.5,1,1.1,1.2,1.3,1.4,1.5,2,2.1,2.2,2.3,2.4,2.5,3,3.1,3.2,3.3,3.4,3.5,4,4.1,4.2,4.3,4.4,4.5,5,5.1,5.2,5.3,5.4,5.5,8,8.1,8.2,8.3,8.4,8.5,8.6,8.7,8.8,8.9,9,9.1,9.2,9.3,9.4,9.5,9.6,9.7,9.8,9.9,10,10.1,10.2,10.3,10.4,10.5,15,15.1,15.2,15.3,15.4,15.5,16,16.1,16.2,16.3,16.4,16.5,17,17.1,17.2,17.3,17.4,17.5,18,18.1,18.2,18.3,18.4,18.5,19,19.1,19.2,19.3,19.4,19.5,20,20.1,20.2,20.3,20.4,20.5,23,23.1,23.2,23.3,23.4,23.5,23.6,23.7,23.8,23.9,24,24.1,24.2,24.3,24.4,24.5,24.6,24.7,24.8,24.9,25,25.1,25.2,25.3,25.4,25.5,30,30.1,30.2,30.3,30.4,30.5,31,31.1,31.2,31.3,31.4,31.5,32,32.1,32.2,32.3,32.4,32.5,33,33.1,33.2,33.3,33.4,33.5,34,34.1,34.2,34.3,34.4,34.5,35,35.1,35.2,35.3,35.4,35.5,38,38.1,38.2,38.3,38.4,38.5,38.6,38.7,38.8,38.9,39,39.1,39.2,39.3,39.4,39.5,39.6,39.7,39.8,39.9,40,40.1,40.2,40.3,40.4,40.5,45,45.1,45.2,45.3,45.4,45.5,46,46.1,46.2,46.3,46.4,46.5,47,47.1,47.2,47.3,47.4,47.5,48,48.1,48.2,48.3,48.4,48.5,49,49.1,49.2,49.3,49.4,49.5,50,50.1,50.2,50.3,50.4,50.5,53,53.1,53.2,53.3,53.4,53.5,53.6,53.7,53.8,53.9,54,54.1,54.2,54.3,54.4,54.5,54.6,54.7,54.8,54.9,55,55.1,55.2,55.3,55.4,55.5),'#FFFFFFFF','#00FFFFFF')

This is terribly ugly, I know, but it works, flashes white on the specified pattern. If you're more comfortable with Python than I am, this can probably be circumvented in the function editor. Here's what some dummy data looks like on my canvas:

enter image description here

  • Was ending up with the same thing. But I failed changing the refresh rate of map canvas. Now QGIS crashes everytime I hit OK button in settings menu (no matter if I change settings or not). So I want to add this warning: Do not change refresh rate in Settings --> Options but as described in this answer in Layer Properties; This works just fine. – MrXsquared Jan 28 at 21:55
  • To shorten up things you can use if(second(now()) % 5,'red','blue') – MrXsquared Jan 28 at 22:04
  • Definitely could have. I should tidy up this answer a bit. The only issue I see with all this is that it won't permit a blinking shorter than 1 second, I fear. – Gabriel C. Jan 28 at 22:10
  • Indeed. Only expression available in QGIS that works with milliseconds is epoch(). But not sure yet how an expression using this could look like in the end. Maybe this could be done with a custom python script in function editor. – MrXsquared Jan 28 at 22:18
  • Using if(epoch(now()) % 5,'red','blue') and setting refresh rate to 0,05 seems to "work", but it also seems like QGIS comes to its limit as the blinking is no longer consistently. Wouldnt really recommend. Edit: should be % 500 i think. But this seems to not work at all.. – MrXsquared Jan 28 at 22:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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