Skip to content

Instantly share code, notes, and snippets.

@loretoparisi
Created April 10, 2019 16:21
Show Gist options
  • Save loretoparisi/d9272754d59d5c660f0f24c5d5330ac1 to your computer and use it in GitHub Desktop.
Save loretoparisi/d9272754d59d5c660f0f24c5d5330ac1 to your computer and use it in GitHub Desktop.
Generate a random HSV palette of non overlapping colors
function randomHSVPalette(options) {
function random(min, max) {
return min + Math.random() * (max - min);
}
function HSVtoXYZ(hsv) {
var h = hsv[0];
var s = hsv[1];
var v = hsv[2];
var angle = h * Math.PI * 2;
return [Math.sin(angle) * s * v,
Math.cos(angle) * s * v,
v
];
}
function distSq(a, b) {
var dx = a[0] - b[0];
var dy = a[1] - b[1];
var dz = a[2] - b[2];
return dx * dx + dy * dy + dz * dz;
}
if (!options) {
options = {};
}
var numColors = options.numColors || 10;
var hRange = options.hRange || [0, 1];
var sRange = options.sRange || [0, 1];
var vRange = options.vRange || [0, 1];
var exclude = options.exclude || [
[0, 0, 0],
[0, 0, 1]
];
var points = exclude.map(HSVtoXYZ);
var result = [];
while (result.length < numColors) {
var bestHSV;
var bestXYZ;
var bestDist = 0;
for (var i = 0; i < 100; i++) {
var hsv = [random(hRange[0], hRange[1]), random(sRange[0], sRange[1]), random(vRange[0], vRange[1])];
var xyz = HSVtoXYZ(hsv);
var minDist = 100;
points.forEach(function(point) {
minDist = Math.min(minDist, distSq(xyz, point));
});
if (minDist > bestDist) {
bestHSV = hsv;
bestXYZ = xyz;
bestDist = minDist;
}
}
points.push(bestXYZ);
result.push(bestHSV);
}
return result;
}
@loretoparisi
Copy link
Author

Usage

// with default values:
randomHSVPalette({ hRange:[0,1], sRange:[0,1], vRange: [0,1], exclude:[[0, 0, 0], [0, 0, 1]]})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment