Add more functions for Gradient
This commit is contained in:
Родитель
41a19f03b9
Коммит
999b11ead0
|
@ -5,25 +5,73 @@ using SomeChartsUi.themes.themes;
|
|||
namespace SomeChartsUi.themes.colors;
|
||||
|
||||
public class Gradient {
|
||||
public GradientPoint[] colors = Array.Empty<GradientPoint>();
|
||||
private GradientPoint[] _points = Array.Empty<GradientPoint>();
|
||||
|
||||
public Gradient() { }
|
||||
public Gradient(GradientPoint[] colors) => this.colors = colors;
|
||||
public Gradient(params GradientPoint[] colors) => _points = colors.OrderBy(v => v.time).ToArray();
|
||||
public Gradient(params (float t, indexedColor c)[] colors) => _points = colors.Select(v => new GradientPoint(v.t, v.c)).OrderBy(v => v.time).ToArray();
|
||||
|
||||
public Gradient(params indexedColor[] colors) {
|
||||
float step = 1f / colors.Length;
|
||||
_points = colors.Select((v, i) => new GradientPoint(i * step, v)).OrderBy(v => v.time).ToArray();
|
||||
}
|
||||
|
||||
/// <summary>evaluate at specific time (0-1)</summary>
|
||||
public indexedColor Eval(float t, palette? p = null) {
|
||||
int len = colors.Length;
|
||||
if (len == 0) return theme.black_ind;
|
||||
if (len == 1 || t <= colors[0].time) return colors[0].col;
|
||||
if (t >= colors[^1].time) return colors[^1].col;
|
||||
public color Eval(float t, palette? p = null) {
|
||||
int len = _points.Length;
|
||||
if (len == 0) return theme.globalTheme.black;
|
||||
if (len == 1 || t <= _points[0].time) return _points[0].col.GetColor(p);
|
||||
if (t >= _points[^1].time) return _points[^1].col.GetColor(p);
|
||||
|
||||
int pos = 0;
|
||||
for (; pos < len; pos++)
|
||||
if (colors[pos].time >= t) break;
|
||||
if (_points[pos].time >= t) break;
|
||||
|
||||
float normalizedTime = (t - colors[pos - 1].time) / (colors[pos].time - colors[pos - 1].time);
|
||||
return indexedColor.Lerp(colors[pos - 1].col, colors[pos].col, normalizedTime, p);
|
||||
float normalizedTime = (t - _points[pos - 1].time) / (_points[pos].time - _points[pos - 1].time);
|
||||
return indexedColor.Lerp(_points[pos - 1].col, _points[pos].col, normalizedTime, p);
|
||||
}
|
||||
|
||||
public int FindCeil(float t) {
|
||||
int len = _points.Length;
|
||||
if (len == 0) return -1;
|
||||
if (len == 1 || t <= _points[0].time) return 0;
|
||||
if (t >= _points[^1].time) return len - 1;
|
||||
|
||||
int pos = 0;
|
||||
for (; pos < len; pos++)
|
||||
if (_points[pos].time >= t) break;
|
||||
return pos;
|
||||
}
|
||||
|
||||
public int FindNearest(float t) {
|
||||
int i = FindCeil(t);
|
||||
if (i == 0) return i;
|
||||
|
||||
float t0 = _points[i - 1].time;
|
||||
float t1 = _points[i].time;
|
||||
|
||||
return math.abs(t0 - t) > math.abs(t1 - t) ? i : i - 1;
|
||||
}
|
||||
|
||||
public void Add(GradientPoint p) => _points = _points.Append(p).OrderBy(v => v.time).ToArray();
|
||||
|
||||
public void Remove(GradientPoint p) {
|
||||
List<GradientPoint> l = _points.ToList();
|
||||
l.Remove(p);
|
||||
_points = l.ToArray();
|
||||
}
|
||||
|
||||
public void Clear() => _points = Array.Empty<GradientPoint>();
|
||||
|
||||
public void Replace(int at, GradientPoint p) {
|
||||
_points[at] = p;
|
||||
_points = _points.OrderBy(v => v.time).ToArray();
|
||||
}
|
||||
|
||||
public color this[float t] => Eval(t);
|
||||
public color this[float t, palette? p] => Eval(t, p);
|
||||
|
||||
public static Gradient FromColor(indexedColor col, float startAlpha = 0f, float endAlpha = 1f) => new((startAlpha, col), (endAlpha, col));
|
||||
}
|
||||
|
||||
public readonly record struct GradientPoint(float time, indexedColor col) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче