In primo luogo, si richiede l'interpolazione lineare ma non si specifica che il colore B si trova sulla linea tra il colore A e il colore C; questo è necessario. Secondo, non hai specificato, ma ho intenzione di semplificare l'ipotesi che il colore B sia il punto medio della linea tra il colore A e il colore C; il seguente codice viene facilmente modificato se questo non è vero. Infine, ho cambiato la tua ipotesi che il parametro sia un numero intero compreso tra zero e cento per essere un doppio tra zero e uno. Il codice è più facile da scrivere e più facile da capire in quest'ultimo caso, e può ancora essere usato con il primo (dividi i tuoi input di un centinaio).
class ColorInterpolator {
delegate byte ComponentSelector(Color color);
static ComponentSelector _redSelector = color => color.R;
static ComponentSelector _greenSelector = color => color.G;
static ComponentSelector _blueSelector = color => color.B;
public static Color InterpolateBetween(
Color endPoint1,
Color endPoint2,
double lambda) {
if (lambda < 0 || lambda > 1) {
throw new ArgumentOutOfRangeException("lambda");
}
Color color = Color.FromRgb(
InterpolateComponent(endPoint1, endPoint2, lambda, _redSelector),
InterpolateComponent(endPoint1, endPoint2, lambda, _greenSelector),
InterpolateComponent(endPoint1, endPoint2, lambda, _blueSelector)
);
return color;
}
static byte InterpolateComponent(
Color endPoint1,
Color endPoint2,
double lambda,
ComponentSelector selector) {
return (byte)(selector(endPoint1)
+ (selector(endPoint2) - selector(endPoint1)) * lambda);
}
}
Come si modifica questo se il colore B non è il punto intermedio tra il colore A e il colore C? Il modo più semplice è il seguente. Se il parametro (che io chiamo "lambda
") è inferiore a 0.5
, moltiplicare lo lambda
di due e restituire il colore interpolato tra il colore A e il colore B. Se il parametro è maggiore di 0.5
, moltiplicare lo lambda
per due e sottrarre uno (le mappe [0.5, 1]
su [0, 1]
) e restituire il colore interpolato tra il colore B e il colore C.
Se non ti piace il requisito che il colore B vivi sulla linea tra il colore A e il colore C, allora puoi usare esattamente la modifica che Ho appena descritto di fare un'interpolazione lineare-parziale tra i colori.
Infine, non è stato specificato se si desidera interpolare il cosiddetto valore alfa ("A" in "ARGB"). Il codice sopra è facilmente modificabile per gestire anche questa situazione. Aggiungere un altro ComponentSelector
definito come color => color.A
, utilizzare InterpolateComponent
per interpolare questo valore e utilizzare il sovraccarico Color.FromArgb(int, int, int, int)
di Color.FromArgb
.
non può essere lineare con tre punti casuali – RBarryYoung