Help sought writing a loop construct

A

Anand Hariharan

The problem simply put is as follows:

I have a list of entities each of which needs to be assigned a unique
triplet of values, each in the range [0.0, 1.0]. The triplet (0.0,
0.0, 0.0) is not allowed.

So, I came with this ('NUMENTITIES' is defined as a compile time
constant):

--- BEGIN ---

#include <math.h>
#include <stdio.h>
#include <float.h>
#include <assert.h>

int main(void)
{
const double Num = pow(NUMENTITIES + 1, (1.0/3.0));
const double FloorNum = floor(Num);
const double Step = Num / ( Num == FloorNum ? FloorNum - 1 :
FloorNum );

double r = 0.0, g = 0.0, b = Step;
int i;

printf("Num = %f, Step = %f\n", Num, Step);

for ( i = 1 ; i <= NUMENTITIES ; ++i )
{
printf("[%d] (%f, %f, %f)\n", i, (r/Num), (g/Num), (b/Num));

b += Step;
if ( b > Num + DBL_EPSILON )
{
b = 0;
g += Step;
if ( g > Num + DBL_EPSILON )
{
g = 0;
r += Step;
if ( r > Num + DBL_EPSILON && i != NUMENTITIES )
{
break;
}
}
}
}

assert( i == NUMENTITIES + 1 );
return 0;
}

--- END ---

This seems to do an adequate job. For example, for NUMENTITIES=8, it
generates:

Num = 2.080084, Step = 1.040042
[1] (0.000000, 0.000000, 0.500000)
[2] (0.000000, 0.000000, 1.000000)
[3] (0.000000, 0.500000, 0.000000)
[4] (0.000000, 0.500000, 0.500000)
[5] (0.000000, 0.500000, 1.000000)
[6] (0.000000, 1.000000, 0.000000)
[7] (0.000000, 1.000000, 0.500000)
[8] (0.000000, 1.000000, 1.000000)


No two triplet of values are the same, so the objective is met.
However, the 'r' component of the triplet is not used at all.

Am hoping that many of you will be able to tell me how to design a
loop construct so that I get a more 'uniform' distribution of values
that uses all three components.

Advance wishes to all for a happy & prosperous new year! :)
- Anand


PS: Feel free to show attitude (e.g., suggest that a high school kid
should be able to do it, but not actually offer any solution or
constructive criticism) but be rest assured this is not homework.
 
B

Bartc

Anand Hariharan said:
The problem simply put is as follows:

I have a list of entities each of which needs to be assigned a unique
triplet of values, each in the range [0.0, 1.0]. The triplet (0.0,
0.0, 0.0) is not allowed.
Num = 2.080084, Step = 1.040042
[1] (0.000000, 0.000000, 0.500000)
[2] (0.000000, 0.000000, 1.000000)
[3] (0.000000, 0.500000, 0.000000)
[4] (0.000000, 0.500000, 0.500000)
[5] (0.000000, 0.500000, 1.000000)
[6] (0.000000, 1.000000, 0.000000)
[7] (0.000000, 1.000000, 0.500000)
[8] (0.000000, 1.000000, 1.000000)


No two triplet of values are the same, so the objective is met.
However, the 'r' component of the triplet is not used at all.
Am hoping that many of you will be able to tell me how to design a
loop construct so that I get a more 'uniform' distribution of values
that uses all three components.

By using a bigger NUMENTITIES, you will eventually get some action in the
first column.

But, if the step size was 1.0 rather than 0.5, you'd simply be counting in
tertiary (001, 002, 010, 011, 012, 020, etc). Each successive value will be
unique (until you hit 222), but is not very interesting.

Do you have examples of a distribution that is more acceptable? What is this
for anyway, it seems colour graphics of some kind.
 
B

Ben Bacarisse

Anand Hariharan said:
I have a list of entities each of which needs to be assigned a unique
triplet of values, each in the range [0.0, 1.0]. The triplet (0.0,
0.0, 0.0) is not allowed.

So, I came with this ('NUMENTITIES' is defined as a compile time
constant):
This seems to do an adequate job. For example, for NUMENTITIES=8, it
generates:

Num = 2.080084, Step = 1.040042
[1] (0.000000, 0.000000, 0.500000)
[2] (0.000000, 0.000000, 1.000000)
[3] (0.000000, 0.500000, 0.000000)
[4] (0.000000, 0.500000, 0.500000)
[5] (0.000000, 0.500000, 1.000000)
[6] (0.000000, 1.000000, 0.000000)
[7] (0.000000, 1.000000, 0.500000)
[8] (0.000000, 1.000000, 1.000000)

No two triplet of values are the same, so the objective is met.
However, the 'r' component of the triplet is not used at all.

Am hoping that many of you will be able to tell me how to design a
loop construct so that I get a more 'uniform' distribution of values
that uses all three components.

I needed something like this once. In a very simple graphics package
I wanted a method for the user to be able choose the 'i'th colour from
'n' spread round the spectrum -- the fully saturated colour ring. It
turns out to be one the few reasonably commented bits of my code so
here it is:

void Pen::set(int number, int out_of)
{
float posn = float(number) / out_of;

// Each of the RGB values rises and falls in the same way
// but exactly 120 degrees out of phase with the others.
// Since the whole ring is represented by the interval 0 to 1
// 120 degrees is 1/3.

// This picture might help. Look at it while reading the
// code for the cval function below.

// ______ ______
// \ / RED
// \ /
// \______/
// ______
// / \ / GREEN
// / \ /
// ___/ \______/
// ______
// \ / \ BLUE
// \ / \
// \______/ \___
//
// | | | |
// 0 0.33 0.66 1.0

set(cval(posn + 1.0/3.0), cval(posn), cval(posn + 2.0/3.0));
}

The final line is a call to an RGB colour setting method:

Pen::set(double red, double green, double blue);
 
T

Thad Smith

Anand said:
The problem simply put is as follows:

I have a list of entities each of which needs to be assigned a unique
triplet of values, each in the range [0.0, 1.0]. The triplet (0.0,
0.0, 0.0) is not allowed. ---- Code snipped ----
This seems to do an adequate job. For example, for NUMENTITIES=8, it
generates:

Num = 2.080084, Step = 1.040042
[1] (0.000000, 0.000000, 0.500000)
[2] (0.000000, 0.000000, 1.000000)
[3] (0.000000, 0.500000, 0.000000)
[4] (0.000000, 0.500000, 0.500000)
[5] (0.000000, 0.500000, 1.000000)
[6] (0.000000, 1.000000, 0.000000)
[7] (0.000000, 1.000000, 0.500000)
[8] (0.000000, 1.000000, 1.000000)


No two triplet of values are the same, so the objective is met.
However, the 'r' component of the triplet is not used at all.

Am hoping that many of you will be able to tell me how to design a
loop construct so that I get a more 'uniform' distribution of values
that uses all three components.

Good, you are refining your requirements. Can you describe --or better,
quantify -- your desired uniform distribution? Can you define and use
"distance between points"?
 
A

Anand Hariharan

The problem simply put is as follows:

I have a list of entities each of which needs to be assigned a unique
triplet of values, each in the range [0.0, 1.0].  The triplet (0.0,
0.0, 0.0) is not allowed.
(...)

Advance wishes to all for a happy & prosperous new year! :)
- Anand


Sincere thanks to all those who responded.

I was so 'hung-up' on being able to write this as some kind of a loop
that I didn't see there are other ways to approach the same problem.

Happy new year wishes once again,
- Anand
 
A

Anand Hariharan

Anand Hariharan said:
The problem simply put is as follows:
I have a list of entities each of which needs to be assigned a
unique
triplet of values, each in the range [0.0, 1.0].  The triplet
(0.0, 0.0, 0.0) is not allowed.

First, let's work in whole numbers, since it'll be a lot easier,
conceptually speaking. We can always convert later.

Let us assume we can have any of 256 different values in the range
0-255 for any attribute. So we can calculate a three-attribute
unique hash like this:

(A1 << 16) | (A2 << 8) | A3

Alternatively, given a hash value, we can extract attribute values
from it like this:

A1 = (hash & 0xFF0000) >> 16
A2 = (hash & 0xFF00) >> 8
A3 = hash & 0xFF

(If all three are 0, just ++ one of them.)

Now, you have a maximum of NUM_ENTITIES attribute tuples. You want
them to be unique, and presumably you also want them to be
reasonably well spaced out. So this is easy - just divide the
largest possible 24-bit value, 16777215 if memory serves, by
NUM_ENTITIES (or, if you'd like to play a little safe, by
NUM_ENTITIES + 1). Call this value G, say.

Then all you have to do is go through each entity in turn, doing
something like this:

for(e = 0, h = 1; e < NUM_ENTITIES; e++, h += G)
{
  entity[e].attrA = ((h & 0xFF0000) >> 16  ) / 256.0;
  entity[e].attrB = ((h & 0xFF00) >> 8     ) / 256.0;
  entity[e].attrC = ( h & 0xFF             ) / 256.0;

}

This will give you pretty nigh-on perfect spread. If you'd like a
less perfect spread, remember that you can perturb h through up to
G/2 or so, randomly, if you wish.

Starting h at 1 should avoid the 0, 0, 0 taboo.

Even though there are 256 distinct whole numbers in [0, 255], I think
the values are "better" (?) if divided by 255 since the range I want
is [0.0, 1.0]. Also, I think it is "more correct" (??) dividing by
NUM_ENTITIES than NUM_ENTITIES+1. (I realise these are weasely and
vacuous statements, but I write simply after reading your post and
thinking about it for a couple of minutes, not actually implementing
it.)

What I am unable to appreciate is how a whole number spread across
2^24 translates to a uniform bit-wise spread (especially in the left-
most octet). Again, I write this in a rush and am not sure if I
phrased my question sensibly.

thank you for your response,
- Anand
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top