What follows is the translation of Java code I found here, in the VisualizeCoords class. It returns an array reference holding the given number of array references. Each RGB tuple has a value from 0 to 1  simply multiply by 255 to get the "normal" value.
sub get_distinct_colors {
use POSIX 'ceil';
my $n = shift;
my $discrete = ceil($n ** (1/3));
my @vals = map 1  (($_1) / $discrete), 1 .. $discrete;
my @colors;
my ($r, $g, $b) = (0,0,0);
for my $i (1 .. $n) {
push @colors, [@vals[$r,$g,$b]];
if (++$b == $discrete) {
if (++$g == $discrete) {
$r = ($r + 1) % $discrete;
$g = 0;
}
$b = 0;
}
}
return \@colors;
}
_____________________________________________________
Jeff japhy Pinyan,
P.L., P.M., P.O.D, X.S.:
Perl,
regex,
and perl
hacker
How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart
Re: Generating Visually Distinct Colors
by Roy Johnson (Monsignor) on Mar 22, 2005 at 04:52 UTC

Nicely translated. I wanted to make it read a little nicer, and came up with this equivalent code:
sub my_gdc {
use POSIX 'ceil';
my $n = shift;
my $discrete = ceil($n ** (1/3));
my @colors;
GENERATE:
for my $r (0..$discrete1) {
for my $g (0..$discrete1) {
for my $b (0..$discrete1) {
push @colors, [map {1$_/$discrete} $r, $g, $b];
last GENERATE if @colors >= $n;
}
}
}
\@colors;
}
and then I wanted to use a single loop and came up with this:
sub my_gdc1 {
use POSIX 'ceil';
my $n = shift;
my $discrete = ceil($n ** (1/3));
my @colors = ([1,1,1]);
for my $i (1..$n1) {
push @colors, [map {1($_%$discrete)/$discrete}
$i/($discrete**2),
$i/$discrete,
$i];
}
\@colors;
}
Caution: Contents may have been coded under pressure.
 [reply] [d/l] [select] 
Re: Generating Visually Distinct Colors
by iblech (Friar) on Mar 22, 2005 at 15:36 UTC

#!/usr/bin/perl6
use v6;
# ceil() not yet implemented in Pugs
sub ceil ($n) { int($n) + ($n > int($n) ?? 1 :: 0) }
my $n = 10;
my $discrete = ceil($n ** (1/3));
my $r = any 0..$discrete1;
my $g = any 0..$discrete1;
my $b = any 0..$discrete1;
# Now $r,$g,$b are Junctions containing all the possible values of
# red/green/blue.
$r = int( (1$r/$discrete) * 255 );
$g = int( (1$g/$discrete) * 255 );
$b = int( (1$b/$discrete) * 255 );
# $color is a Junction containing all colors as "(red, green, blue)".
my $color = "($r, $g, $b)";
# Finally, print $color.
for $color > $x { say $x }
Update: Handrolled ceil was wrong, fixed (thanks japhy!).  [reply] [d/l] 

Um, what's with that ceil() function? int($x+2)? I'd feel much safer with
sub ceil (Num $x) { $x == int($x) ?? $x :: int($x+1) }
I'm pretty sure that's the appropriate P6 code.
_____________________________________________________
Jeff japhy Pinyan,
P.L., P.M., P.O.D, X.S.:
Perl,
regex,
and perl
hacker
How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart
 [reply] [d/l] [select] 

 [reply] [d/l] [select] 


 [reply] 
Re: Generating Visually Distinct Colors
by sfink (Deacon) on Mar 22, 2005 at 18:07 UTC

I implemented something like this for an application I wrote once. The algorithm you're implementing chooses N evenlyspaced 3D grid points in the RGB color space. I found that this didn't give a terribly good result, because our eyes are far from being equally sensitive to changes in red, green, and blue at different points in the color space.
Anyone know of a better algorithm? As a first cut, probably using HSV space would be better, but you wouldn't want to sample it evenly  you'd probably use a whole bunch of gradations in hue, but only a few in saturation and value.
I probably just ought to spend some quality time with Google. Given how important this is for things like MPEG encoding, I'm sure somebody's come up with a color space that approximates an even spreading of perceptual differences. Well, "approximates" it for "most" people, or something.
Then you'd just have to implement a "red/green colorblind" mode that a user could select, with a very different sampling space...
 [reply] 

 [reply] 
Re: Generating Visually Distinct Colors
by cosimo (Hermit) on Mar 23, 2005 at 12:18 UTC

I usually use something like this to generate colors for sections of histogram or pie charts.
sub getColor
{
my $index = shift; # Numerical index (integer from 0 to ..
+.)
my @color; # Color components
my @hue_matrix = (
#
# R G B Component to modify(0=R, 1=G, 2=B)
#    
# V V V V Add or subtract the offset
#  from (r,g,b) triplet
# V
[ 255, 0, 0, 2, 1 ], # Sector 1 R > R+B
[ 255, 0, 255, 0, 1 ], # Sector 2 R+B > B
[ 0, 0, 255, 1, 1 ], # ... B > Cyan
[ 0, 255, 255, 2, 1 ], # ... Cyan> G
[ 0, 255, 0, 0, 1 ], # ... ...
[ 255, 255, 0, 1, 1 ],
[ 255, 0, 0, 2, 1 ]
);
# Select a "spectrum sector", according to my hue matrix
my $sector = $hue_matrix[ int($index / 42) % @hue_matrix ];
# Calculate an offset to be applied to starting color
my $offset = ($index % 42) * 6;
@color = @$sector[0..2];
# Modify selected component to generate a "continuous gradient"
$color[$sector>[3]] += ($sector>[4] > 0 ? $offset : $offset);
return(@color);
}
# Generate visually distinct colors...
print '<HTML><BODY>', "\n";
# How much distinct you decide with this factor
my $distinct_factor = 10;
for( 1 .. 30 )
{
printf(
"<TABLE BGCOLOR=#%02X%02X%02X><TR><TD>" . ' ' x 20 . "</T
+D></TR></TABLE>\n",
getColor($distinct_factor * $_)
);
}
print '</BODY></HTML>';
# Or you can choose getColor() parameter at random...
The final result is:
... that of course is not perfect, but adjusting the $distinct_factor can provide satisfying results.
Update: Sorry, it was missing the last piece of code...
 [reply] [d/l] [select] 
Re: Generating Visually Distinct Colors
by iblech (Friar) on Mar 23, 2005 at 13:39 UTC

japhy, you might find Coloring IRC logs nicely interesting, too.
This is the algorithm my IRC bot iblechbot uses, too (screenshot).
First, a raw IRC log is read to find out which nicks were online (and talked) at the same time. This information is used to build a interference graph. Then, using the graph, all nicks get distict colors.
Because of the interference graph, the colors used are reduced to a minimum:
 10:00  A joins  color: 1/3 # notice: three colors needed
 10:03  B joins  color: 2/3
 10:05  C joins  color: 3/3
 (Time passes...)
 20:00  D joins  color: 1/2 # notice: only two colors used here
 20:02  E joins  color: 2/2
Using the colornum/total_num_of_colors information, the actual color pair (foreground, background) is built:
 [reply] [d/l] 

