@macrostrat/column-components
Version:
React rendering primitives for stratigraphic columns
84 lines (83 loc) • 2.4 kB
JavaScript
import Color from "../Color.js";
import clip_rgb from "../utils/clip_rgb.js";
import "../utils/type.js";
const { pow, sqrt, PI, cos, sin, atan2 } = Math;
const average = (colors, mode = "lrgb", weights = null) => {
const l = colors.length;
if (!weights) weights = Array.from(new Array(l)).map(() => 1);
const k = l / weights.reduce(function(a, b) {
return a + b;
});
weights.forEach((w, i) => {
weights[i] *= k;
});
colors = colors.map((c) => new Color(c));
if (mode === "lrgb") {
return _average_lrgb(colors, weights);
}
const first = colors.shift();
const xyz = first.get(mode);
const cnt = [];
let dx = 0;
let dy = 0;
for (let i = 0; i < xyz.length; i++) {
xyz[i] = (xyz[i] || 0) * weights[0];
cnt.push(isNaN(xyz[i]) ? 0 : weights[0]);
if (mode.charAt(i) === "h" && !isNaN(xyz[i])) {
const A = xyz[i] / 180 * PI;
dx += cos(A) * weights[0];
dy += sin(A) * weights[0];
}
}
let alpha = first.alpha() * weights[0];
colors.forEach((c, ci) => {
const xyz2 = c.get(mode);
alpha += c.alpha() * weights[ci + 1];
for (let i = 0; i < xyz.length; i++) {
if (!isNaN(xyz2[i])) {
cnt[i] += weights[ci + 1];
if (mode.charAt(i) === "h") {
const A = xyz2[i] / 180 * PI;
dx += cos(A) * weights[ci + 1];
dy += sin(A) * weights[ci + 1];
} else {
xyz[i] += xyz2[i] * weights[ci + 1];
}
}
}
});
for (let i = 0; i < xyz.length; i++) {
if (mode.charAt(i) === "h") {
let A = atan2(dy / cnt[i], dx / cnt[i]) / PI * 180;
while (A < 0) A += 360;
while (A >= 360) A -= 360;
xyz[i] = A;
} else {
xyz[i] = xyz[i] / cnt[i];
}
}
alpha /= l;
return new Color(xyz, mode).alpha(alpha > 0.99999 ? 1 : alpha, true);
};
const _average_lrgb = (colors, weights) => {
const l = colors.length;
const xyz = [0, 0, 0, 0];
for (let i = 0; i < colors.length; i++) {
const col = colors[i];
const f = weights[i] / l;
const rgb = col._rgb;
xyz[0] += pow(rgb[0], 2) * f;
xyz[1] += pow(rgb[1], 2) * f;
xyz[2] += pow(rgb[2], 2) * f;
xyz[3] += rgb[3] * f;
}
xyz[0] = sqrt(xyz[0]);
xyz[1] = sqrt(xyz[1]);
xyz[2] = sqrt(xyz[2]);
if (xyz[3] > 0.9999999) xyz[3] = 1;
return new Color(clip_rgb(xyz));
};
export {
average as default
};
//# sourceMappingURL=average.js.map