Files
DynamicDataDisplay/Common/Palettes/UniformLinearPalette.cs
2024-02-23 00:46:06 -05:00

134 lines
3.1 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media;
using System.ComponentModel;
using System.Windows.Markup;
using Microsoft.Research.DynamicDataDisplay.Common.Auxiliary;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
namespace Microsoft.Research.DynamicDataDisplay.Common.Palettes
{
public class UniformPaletteColorStep
{
public Color Color { get; set; }
}
[ContentProperty("ColorSteps_XAML")]
public sealed class UniformLinearPalette : IPalette, ISupportInitialize
{
private double[] points;
private ObservableCollection<Color> colors = new ObservableCollection<Color>();
public ObservableCollection<Color> ColorSteps
{
get { return colors; }
}
private List<UniformPaletteColorStep> colorSteps_XAML = new List<UniformPaletteColorStep>();
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[EditorBrowsable(EditorBrowsableState.Never)]
public List<UniformPaletteColorStep> ColorSteps_XAML
{
get { return colorSteps_XAML; }
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
private void RaiseChanged()
{
Changed.Raise(this);
}
public event EventHandler Changed;
public UniformLinearPalette() { }
public UniformLinearPalette(params Color[] colors)
{
if (colors == null) throw new ArgumentNullException("colors");
if (colors.Length < 2) throw new ArgumentException(Strings.Exceptions.PaletteTooFewColors);
this.colors = new ObservableCollection<Color>(colors);
FillPoints(colors.Length);
}
private void FillPoints(int size)
{
points = new double[size];
for (int i = 0; i < size; i++)
{
points[i] = i / (double)(size - 1);
}
}
private bool increaseBrightness = true;
[DefaultValue(true)]
public bool IncreaseBrightness
{
get { return increaseBrightness; }
set { increaseBrightness = value; }
}
public Color GetColor(double t)
{
Verify.AssertIsFinite(t);
Verify.IsTrue(0 <= t && t <= 1);
if (t <= 0)
return colors[0];
else if (t >= 1)
return colors[colors.Count - 1];
else
{
int i = 0;
while (points[i] < t)
i++;
double ratio = (points[i] - t) / (points[i] - points[i - 1]);
Verify.IsTrue(0 <= ratio && ratio <= 1);
Color c0 = colors[i - 1];
Color c1 = colors[i];
Color res = Color.FromRgb(
(byte)(c0.R * ratio + c1.R * (1 - ratio)),
(byte)(c0.G * ratio + c1.G * (1 - ratio)),
(byte)(c0.B * ratio + c1.B * (1 - ratio)));
// Increasing saturation and brightness
if (increaseBrightness)
{
HsbColor hsb = res.ToHsbColor();
//hsb.Saturation = 0.5 * (1 + hsb.Saturation);
hsb.Brightness = 0.5 * (1 + hsb.Brightness);
return hsb.ToArgbColor();
}
else
{
return res;
}
}
}
#region ISupportInitialize Members
bool beganInit = false;
public void BeginInit()
{
beganInit = true;
}
public void EndInit()
{
if (beganInit)
{
colors = new ObservableCollection<Color>(colorSteps_XAML.Select(step => step.Color));
FillPoints(colors.Count);
}
}
#endregion
}
}