8

I have a layer with a timestamp column. I want the color of the labels with the same hour to be identical. I used this:

CASE
    WHEN hour("time") = 9 THEN color_rgb(rand(0, 255), rand(0, 255), rand(0, 255))
    WHEN hour("time") = 10 THEN color_rgb(rand(0, 255), rand(0, 255), rand(0, 255))
    WHEN hour("time") = 11 THEN color_rgb(rand(0, 255), rand(0, 255), rand(0, 255))
    WHEN hour("time") = 12 THEN color_rgb(rand(0, 255), rand(0, 255), rand(0, 255))
END

But it generates random colors for all labels as in the image.

enter image description here

I could use the following expression, but I want it to be random. I don't want to specify a different color for each hour manually.

CASE
    WHEN hour("time") = 9 THEN '255,0,0'
    WHEN hour("time") = 10 THEN '0,255,0'
    WHEN hour("time") = 11 THEN '0,0,255'
    WHEN hour("time") = 12 THEN '0,255,255'
END

enter image description here

How can I make the color of the label in each rectangle (in the first image) the same, but random? I hope there is a shorter way. The column includes other hours as well.

4
  • 4
    Could you create 24 random colors and store them in an array, then call them according to their index after your THEN operators in place of ''color_rgb(rand(0, 255), rand(0, 255), rand(0, 255))''?
    – Kartograaf
    Commented Mar 7, 2022 at 21:57
  • 1
    Does this post help? gis.stackexchange.com/questions/385158/…
    – Binx
    Commented Mar 7, 2022 at 21:59
  • 2
    @Zman3 No, I don't mean a randomness in every refreshing of map canvas. Commented Mar 7, 2022 at 22:38
  • @Kartograaf it is too long. Commented Mar 7, 2022 at 22:41

4 Answers 4

13
  1. Use Categorized symbology
  2. Value: hour("time"), Color ramp: 'Random colors'

enter image description here

  1. In Labels tab, use @symbol_color for the color data-defined override

enter image description here

6

One option is to color the geometry (i.e. categorized by hour...) and then to use @symbol_color as the color data-defined override. In the example below I used a size of 0 on the point so we don't see them (and then I can style the point as I wish, maybe as a 2nd layer)

enter image description here

2
  • 1
    What do you mean by "to color the geometry". I tried but all labels still have the same color. Commented Mar 7, 2022 at 23:01
  • 1
    come on, if you want to set label color by hour, maybe the geometry should be colored by hour too. See the answer that plagiarized mine.
    – JGH
    Commented Mar 8, 2022 at 13:52
4

The problem is that because you don't assign a seed for rand function the color for any given value (e.g. 10) will be dynamically changing each time is invoked the label expression.

so use:

rand(0, 255, <fixed number for each hour seed>)  
4

Let's analyze your code:

WHEN hour("time") = X THEN color_rgb(rand(0, 255), rand(0, 255), rand(0, 255))

When the hour of the current time is X what this does is it creates a color with random RGB values. The Red value is random, the Green value is random, and the Blue value is random. Every time it executes each of the Red, Green and Blue values is random, and will be different each time it's called, even if called with the exact same time, so your code can't possibly work as intended. What you need to do is to ensure that you get the same random color for a given hour.

If getting a random color for each of the 24 hours, with different days having the same random color for the same hours, and if rand works with a seed as shown above, and if hour("time") returns an integer, (a lot of if's, but I'm not familiar with this environment) then you could do something like the following:

color = color_rgb(
   rand(0, 255, hour("time")*10), 
   rand(0, 255, hour("time")*20), 
   rand(0, 255, hour("time")*30)
)

Note that you don't have to use a case statement at all, it's 1 line of code! There is a possible subtle race condition here if hour("time") is using the time of the call, as opposed to a fixed time calculated before getting into this code, where getting the hour multiple times could end up with the first call being in hour X and the second or third call being in hour X+1, creating a totally new color that doesn't match the colors for either hour X or hour X+1... To guarantee the random values are the same efficient you could get hour("time") once and use it repeatedly, rather than getting it each time (again, assuming that hour("time") gets the current time)...

This uses the hour value (multiplied by a different multiplier for each of R, G and B else the R, G and B values will be identical and you'll get shades of gray) as the seed for the random numbers. So, when the code is executed and the hour is X the same R, G and B seeds will be used and will generate the same random numbers for each of R, G and B values for that time.

If you want the colors for each hour to be different every day you could do something like this (again, assuming day("time") returns an integer):

color = color_rgb(
   rand(0, 255, hour("time")*day("time")*10), 
   rand(0, 255, hour("time")*day("time")*20), 
   rand(0, 255, hour("time")*day("time")*30)
)

In this case the colors will be the same for each hour on the same day of the month, but otherwise different each day...

1
  • Thank you for the detailed explanation. Commented Mar 8, 2022 at 22:38

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.