Control Random Color's HSV values - particularly Saturation

Hey all,

Working on a Python script, and I have a Random Color assigned to a new layer – but I’d like to be able to specify ranges of its HSV values (eg. Set a Pastel-type look with Saturation=15-25)

Thinking maybe I need to find a way to define the HSV of the color, and then convert to argb…?

Snippet of script below.

Thx,
Alan

#Create Random Color

def randomcolor():
          red = int(255*random.random())
          green = int(255*random.random())
          blue = int(255*random.random())
          return Color.FromArgb(red,green,blue)

#Define new layers (with names to be used throughout script)

bbox_layer_name = rs.AddLayer("bbox"+new_element, Color.FromArgb(20, 0, 0, 0), parent=new_element)
crv_layer_name = rs.AddLayer("crv"+new_element, Color.Red, parent=new_element)
sol_layer_name = rs.AddLayer("sol"+new_element, randomcolor(), parent=new_element)

I’m interested in this as well as often times with random RGB you get fairly muddled colors and I want to keep them in the brighter, saturated range.

You can make randomly saturated HSL/HSV colors directly and cast them to RGB like so:


230802_RandomlySaturatedColors_00.gh (6.8 KB)

2 Likes

Maybe refrain from answering questions about it then (and tell ChatGPT to read the docs!).

1 Like

These might also be useful:

RandomSaturatedColor.py (430 Bytes)
RandomLightColor.py (541 Bytes)
RandomLightColor2.py (574 Bytes)
RandomLightColor3.py (639 Bytes)

(no ChatGPT involved…)

2 Likes

I have a background in other languages just not GHPython. As I read the code it seemed like it provided a decent framework to work from and the script worked well, it also answered Alan’s questions so I posted it. Sure there may be more optimized ways to do things but I don’t think there’s anything wrong with using chatGPT to get ideas to move forward with. I’ve deleted it now, sorry for any offense it may have caused.

And I apologise for getting ChatGPT-triggered again, my bad :face_with_open_eyes_and_hand_over_mouth:

2 Likes

Beautifully simple, thank you

1 Like

Thanks, @AndersDeleuran and @Helvetosaur That’s what I’d expect the succinct scripts to look like. :wink:

And thanks @michaelkreft I do appreciate the help.

Thanks @AndersDeleuran ,

I ended up tweaking your solution a bit to allow a few additional controls, Saturation, Count, Seed, and ability to sort the color list by value.

I’m not quite happy with the value sorting as it appears (at least visually to me) that the sorting is slightly off (the V values are correct, but i think i need to take the saturation into account as well?)

My idea is to be able to generate a “random” color pallet and for now it’s close enough for my intent.

Thanks for sharing as always!

import random
import Rhino as rc

def generate_random_colors(C, H, S, V, Se):

    # Assign specific inputs if provided, otherwise use defaults
    C = C if C is not None else 4
    H = H if H is not None else .5
    S = S if S is not None else .5
    V = V if V is not None else .5
    Se = Se if Se is not None else 235
    
    Rc = []

    if Se is not None:
        random.seed(Se)

    for i in range(C):
        rand_S = random.uniform(S, 1.0)
        rand_V = random.uniform(V, 1.0)
        hsv = rc.Display.ColorHSV(H, rand_S, rand_V)
        rgb = hsv.ToArgbColor()
        Rc.append((rgb, rand_V))  # Store both the RGB color and the corresponding V value

    # Sort Rc by V value in descending order
    RcS = sorted(Rc, key=lambda x: x[1], reverse=True)

    # Extract the sorted RGB colors from the RcS list
    RcS = [item[0] for item in RcS]
    
    # Get RGB Colors from Rc list
    Rc = [item[0] for item in Rc]

    return Rc, RcS

Rc, RcS = generate_random_colors(C, H, S, V, Se)

Graph Space:

Model Space:

1 Like

@AndersDeleuran I get a problem flag (I’m using VSCode) that “H” and “V” are not defined.

(EDITED…)
In @Helvetosaur script for “RandomLightColor.py” he has the following snippet:

for obj in objs:
     h=random.random()
     s=random.random()
     v=random.uniform(0.6,1.0)

Seems this one from Mitch should do the trick (tho I’m creating layers and setting their display colors, instead of objects.)

Thx
Alan

random.random() creates random values between 0 and 1.0, which is what the h, s and v arguments are looking for.
random.uniform(a,b) creates values between a and b and thus serves to limit the range. By supplying 0.6 to 1 as a range, the values (brightness) stay in the upper range.

From the Python docs:

random.random()

Return the next random floating point number in the range 0.0 <= X < 1.0

random.uniform(a, b )

Return a random floating point number N such that a <= N <= b for a <= b and b <= N <= a for b < a.

One could use the same strategy to limit the range of hues (h) or saturation (s)…

The script can be modified to do layer colors…

RandomLightColorSelLayers.py (633 Bytes)

1 Like

Yes those are defined as input parameters to the GHPython component I posted. You can just define these variables and their values within your script :slightly_smiling_face:

1 Like

Hi Mitch, thanks for the help, here.

I added your snippet to my script (updating to LayerColor, as you did) and I’ve been working for a few minutes on a new problem: My intended new layer (“sol”+new_element…) isn’t being created. I believe I’m able to use the def as a parameter inside my rs.AddLayer(), correct?

Maybe it’s because I’m not “selecting” a layer to change, but creating one?

#Create Random Light Color

def random_color_light():
    h=random.random()
    s=random.uniform(0.2,0.3)
    v=random.uniform(0.3,0.8)
    rs.LayerColor(layer,Rhino.Display.ColorHSV(h,s,v).ToArgbColor())

#Create Layers named per user-submitted new_element

rs.AddLayer(name=new_element, parent=overall_parent)
bbox_layer_name = rs.AddLayer("bbox"+new_element, Color.FromArgb(20, 0, 0, 0), parent=new_element)
crv_layer_name = rs.AddLayer("crv"+new_element, Color.Red, parent=new_element)
sol_layer_name = rs.AddLayer("sol"+new_element, random_color_light(), parent=new_element)

EDIT: Ah, maybe b/c I don’t have the “for Layer in Layers…”

So you are trying to generate a random color for a single new layer you are adding to the document?

Yes, tho (probably separate topic) I’m planning on scripting it so the user can choose how many “sol” layers for the layer tree, and then each of those layers would get their own color

Yes maybe, it’s gets a bit “visual” if you will. I just took the liberty to simplify things a bit by using default function arguments and sorting by the HSV Value property directly, might help:


230803_MakeRandomlySaturatedColors_00.gh (4.2 KB)

Edit: If you’re trying to generate a controlled gradient, perhaps something like this is more appropriate:

1 Like

I’m moving my original question, including some add’l question about Layers

1 Like

Beautiful, thank you for sharing!

1 Like

Sorry Alan :sweat_smile: