class ColorScaleSequential {
constructor(surface, trajectory, { nStep = 100, scale = 1 } = {}) {
if (!(surface instanceof ColorSurface)) {
throw "surface must be a ColorSurface";
}
if (!(trajectory instanceof ColorTrajectory)) {
throw "trajectory must be a ColorTrajectory";
}
this.surface = surface;
this.trajectory = trajectory;
this.nStep = nStep;
const indices = d3.ticks(0, 1, nStep);
const distances = indices
.map(this.trajectory.spline)
.map((x) => [x.luminance, x.chroma, this.surface.fnSurface(x.luminance)])
.map(colorUtils.fromPolar)
.map((x, i, arr) => {
return i == 0 ? 0 : math.distance(x, arr[i - 1]);
});
const cumulativeDistances = math.cumsum(distances);
this.distance = cumulativeDistances.slice(-1)[0];
const normalizedDistances = cumulativeDistances.map(
(x) => x / this.distance
);
const rescaleFunction = (x) => scale * x;
const transferFunction = NaturalCubicSpline(normalizedDistances, indices);
this.sRgbInterp = _.flow([
rescaleFunction,
transferFunction,
this.trajectory.spline,
(x) => [x.luminance, x.chroma, this.surface.fnSurface(x.luminance)],
fromPolar,
this.surface.space.from100,
this.surface.space.toSRgb,
this.surface.space.clampChromaSRgb
]);
this.hexInterp = _.flow([this.sRgbInterp, colorUtils.hexFromSRgb]);
}
// use arrow notation to preserve "this"
data100 = (x) => {
const sRgb = this.sRgbInterp(x);
const lab = _.flow([this.surface.space.fromSRgb, this.surface.space.to100])(
sRgb
);
const lch = toPolar(lab);
return {
x: x,
luminance: lch[0],
chroma: lch[1],
hue: lch[2],
a: lab[1],
b: lab[2],
hex: hexFromSRgb(sRgb)
};
};
data100Points = (nStepPoints) => {
return d3
.range(0, 1, 1 / nStepPoints)
.concat(1)
.map(this.data100);
};
plotMarks100Points = ({
negateChroma: negateChroma,
nStepPoints = 10,
strokePoints = "#777777",
rPoints = 10
} = {}) => {
const data = this.data100Points(nStepPoints).map(negChroma(negateChroma));
return [
Plot.dot(data, {
x: "chroma",
y: "luminance",
r: rPoints,
fill: "hex",
stroke: strokePoints
})
];
};
plotMarks100 = ({
negateChroma: negateChroma,
nStepSpline = 100,
strokeSpline = "#777777",
rControlPoints = 10,
nStepPoints = 10,
strokePoints = "#777777",
rPoints = 10
} = {}) => {
return [
...this.surface.plotMarks100({ negateChroma }),
...this.trajectory.plotMarks100({
negateChroma,
nStepSpline,
strokeSpline,
rControlPoints
}),
...this.plotMarks100Points({
negateChroma,
nStepPoints,
strokePoints,
rPoints
})
];
};
}