It seems like you want to select a random range that is between 45 and 90 wide and falls within a hue. Do you want ranges that can be centered on red? Hue is circular, so ranges from say 315-45 should be possible. Imagine yourself first picking a curved stick of random length 45-90, then placing it somewhere along the edge of a color wheel. Your current approach is to then chop off the right-hand side of the stick if it crosses over the line of absolute red (0/360). This means you have an unusually small number of ranges including the value 0/360, and an unusually large number of those have red as the last color-almost none have red as the first color. Do you want the possible results to be equally distributed?
This method gives you a normal distribution on 0-360 – so, almost no pure red, ever, but it is balanced.
float half = random(45, 90) / 2.0; // half the range width
float center = random(0 + half, 360 - half);
float start = center - half;
float end = center + half;
Or you could just pick a random range.
float start = random(0, 360);
float end = (start + random(45, 90))%360;
This can give values like “[340, 20]” … but you might actually want that. If you intend to interpolate, you could also just skip the modulo and save “340, 380” as the range – interpolate, then use modulo before passing to a color function.
int[] range = new int[]{200, 400};
colorMode(HSB);
background(255);
for (int i=0; i<width; i++) {
float c = lerp(range[0], range[1], i/(float)width);
stroke(c%360, 255, 255);
line(i, 0, i, height);
}
Another way to think about the constrain approach is that you have created a normal distribution from 0-405 (360+45) and then cropped it on the right side.
This shows the alternative to just make the result equally distributed – choose the size of the range first, then choose a valid random placement for your range based on its size. Now there are no hue ranges that cross red from either side.
/**
* DistributeRandomRanges
* 2020-01-06 Processing 3.4
* https://discourse.processing.org/t/minimum-and-maximum-random-numbers/16888/4
*/
int[] hits;
int[] hits2;
void setup() {
size(360, 360);
hits = new int[360];
hits2 = new int[360];
}
void draw() {
background(255);
PVector r = randomRange();
for (int i=int(r.x); i<int(r.y); i++) {
hits[i] = hits[i]+1;
}
PVector r2 = randomRange2();
for (int i=int(r2.x); i<int(r2.y); i++) {
hits2[i] = hits2[i]+1;
}
// draw current ranges
stroke(255, 0, 0, 128);
line(r.x, 20, r.y, 20);
rect(width-45, 0, 45, height); // problem on this end, see left edge
stroke(0, 0, 255, 128);
line(r2.x, 30, r2.y, 30);
// draw cumulative graph of results
for (int i=0; i<width; i++) {
stroke(255, 0, 0, 128);
line(i, height, i, height-hits[i]);
stroke(0, 0, 255, 128);
line(i, height, i, height-hits2[i]);
}
}
PVector randomRange() { // @kll
float rangemin=45, rangemax=90;
float start, end;
start = random(0, 360-rangemin);
end = constrain(random(start+rangemin, start+rangemax), 0, 360); // thanks @Tiemen
return new PVector(start, end);
}
PVector randomRange2() { // @jeremydouglass
// the right hand side is correctly distributed
float half = random(45, 90) / 2.0;
float center = random(0 + half, 360 - half);
float start = center - half;
float end = center + half;
return new PVector(start, end);
}