Color: as many unique color (vectors) as objects?

On 28/02/2014 at 14:45, xxxxxxxx wrote:

Hi everyone,

I want to assign every object a unique Color in the editor, the script works so far, but I am having trouble spacing and feeding the color vector with adequate numbers to have enough differentiation and not to exceed the 3 integers.

lets say I have 254*254*254 = 16387064 Colors at my disposal and I have 2Mio Objects. How do i feed the vector with a spacing (color differentiation) while having 3 parameters.

The cherry on top would be to exclude black, and white.

  
counter = 2000000 # e.g. Number of Objects   
step = (1/float(counter)) # somehow gives me a step but not robust   
  
def getcolor (step, counter, secondcounter) :   
    colorvec = (step * secondcounter)   
    color = c4d.Vector(colorvec , colorvec , colorvec) # of course this alters all three vectors which limits me in color spacing ....   
    return color   

thanks for your help in advance.
mogh

On 28/02/2014 at 18:18, xxxxxxxx wrote:

Give this a try.
It should theoretically generate a ton of unique colors.

import c4d  
import random  
  
def main() :  
    
  #Create a list array to hold all of the vector colors  
  colors = []  
  
  num_Colors = 100   #<--- Change this number as desired  
    
  #Generate lots of colors values between 0-255 using random  
  #Then test to see if the color already exist in the colors list  
  #If the color already exists..start the loop over again  
  #If the color is not in the list...Add it to the list  
  for i in xrange(num_Colors) :  
      vec = c4d.Vector(random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))  
  
      if vec in colors: continue  
      else: colors.append(vec)  
        
  print colors  
  
if __name__=='__main__':  
  main()

-ScottA

On 01/03/2014 at 13:20, xxxxxxxx wrote:

Hi ScottA,

i tried this because your script didn't produce valid color vectors, found some similar script for random colors which had this division by 256 incorporated, don't know if this is the real deal but it gives me colors.

Anyway i still have trouble to exclude black and white, when the script finds the vec in the list it continues but does not add another value it seems, hence I get index out of range errors.

any idea?

def random_unique_colors(howmany) : #Create a list array to hold all of the vector colors   
    colors = []   
    white = c4d.Vector(1,1,1)   
    black = c4d.Vector(0,0,0)   
    for i in xrange(howmany) :   
        vec = c4d.Vector(random.randint(0, 255)/256.0, random.randint(0, 255)/256.0, random.randint(0, 255)/256.0)   
        if vec in colors or vec == white or vec == black: continue   
        else: colors.append(vec)   
    return colors

On 01/03/2014 at 14:07, xxxxxxxx wrote:

Sorry to bother,
i tried it with 70.000 Objects and not getting nearly as many colors in the list - something is definitely wrong and slow.

I guess i really need some sort of "step" solution.

On 01/03/2014 at 15:37, xxxxxxxx wrote:

If you want values between 0-1 instead of 0-255. Then try it like this:

import c4d  
import random  
  
def main() :  
    
  #Create a list array to hold all of the vector colors  
  colors = []  
  
  num_Colors = 100   #<--- Change this number as desired  
    
  #Generate lots of colors values between 0-255 using random  
  #Then test to see if the color already exist in the colors list  
  #If the color already exists..start the loop over again  
  #If the color is not in the list...Add it to the list  
  for i in xrange(num_Colors) :  
      vec = c4d.Vector(float(random.randint(0, 255)/100.0), float(random.randint(0, 255)/100.0), float(random.randint(0, 255)/100.0))  
  
      if vec in colors: continue  
      else: colors.append(vec)  
        
  print colors  
  
if __name__=='__main__':  
  main()

This is going to be very slow because
a.) It's generating huge amounts of data
b.) It's looking through the list for already existing values every iteration of the loop. Which takes longer...depending on how many vectors are in the list.

I'm sure there's faster more optimized ways to generate large numbers of vectors. I just came up with this code off the top of my head.
If you don't mind the generated colors being sequential. Simply incrementing the values per loop iteration, and deleting all the random and the "if vec in colors:"  code I used, will speed it up a lot.
I just assumed that you didn't want the color values to be sequential.

-ScottA

On 02/03/2014 at 04:59, xxxxxxxx wrote:

Hi
If you want to limit the color range it might be easier to start in HSV.

  
import c4d   
from random import randint, randrange   
from c4d import utils   
  
def main() :   
    howMany = 1000   
    colors = []   
  
    # Change min/max to limit hue range ( degrees )   
    hueMin = 0   
    hueMax = 360       
       
    # Change min/max to limit saturation range ( % )   
    saturationMin = 0   
    saturationMax = 100   
       
    # Change min/max lo limit value range ( % )   
    valueMin = 0   
    valueMax = 100   
       
    for i in xrange(howMany) :   
        h = float(randrange( hueMin, hueMax )) / 360   
        s = float(randrange( saturationMin, saturationMax )) / 100   
        v = float(randrange( valueMin, valueMax )) / 100   
  
        # Convert hsv to rgb and append new value to list   
        colors.append(c4d.utils.HSVToRGB( c4d.Vector(h, s, v) ))   
  
    print colors   
  
if __name__=='__main__':   
    main()

I'm not sure if all these colors are completely unique.

Cheers
Bonsak

PS How do i set the line spacing inside the code block?

On 02/03/2014 at 05:06, xxxxxxxx wrote:

Thanks for all your answers,

I came up with a quiet dirty method manipulating a string, but it works good and isn't to slow after all.

I do not need random! I need unique and well spaced colors because I am trying to code a object visibility plugin.

def unique_colors(howmany) : #Create a list array to hold all of the vector colors   
    if howmany == 0:   
        return False   
       
    colors = []   
    step = 999999998 / howmany # 0.999 0.999 0.999 divided by the objectcount   
    largestring = 1000000001 + (step/2) # puts the range in the middle betweeen black and white   
  
    for i in xrange(howmany) :          
        r = float(str(largestring)[1:-6])/1000   
        g = float(str(largestring)[4:-3])/1000   
        b = float(str(largestring)[7:])/1000   
        colors.append(c4d.Vector(r , g, b))   
        largestring = largestring + step   
    return colors   

On 02/03/2014 at 12:33, xxxxxxxx wrote:

I see. So you need a narrow range of hues, or the full spectrum devided evenly among the members?

Cheers
Bonsak

On 02/03/2014 at 13:02, xxxxxxxx wrote:

I need full spectrum devided evenly among the members, without black and white to prevent errors with the background.

kind regards
mogh

On 18/03/2014 at 13:57, xxxxxxxx wrote:

Still searching for a clean solution,

found this but can't implement it

http://stackoverflow.com/questions/470690/how-to-automatically-generate-n-distinct-colors

kind regards

On 10/04/2014 at 03:27, xxxxxxxx wrote:

found something:

g = itertools.product(range(1,255), repeat=3) # range excluding 0 and 256   
for x in manycolors:   
    color = g.next()   

this creates as many colors as often you call g.next()

kind regards