Advertisement
Guest User

OxyPaletteEditor

a guest
May 21st, 2015
55
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 21.48 KB | None | 0 0
  1. using OxyPlot;
  2. using OxyPlot.Annotations;
  3. using OxyPlot.Axes;
  4. using OxyPlot.Series;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.ComponentModel;
  8. using System.Data;
  9. using System.Drawing;
  10. using System.Linq;
  11. using System.Text;
  12. using System.Threading.Tasks;
  13. using System.Windows.Forms;
  14.  
  15. namespace TRUSTIE
  16. {
  17.     /// <summary>   Editor for color palette. </summary>
  18.     ///
  19.     /// <remarks>   James, 23/04/2015. </remarks>
  20.     public partial class OxyPaletteEditor : Form
  21.     {
  22.         #region Events
  23.  
  24.         /// <summary>   Palette changed. </summary>
  25.         ///
  26.         /// <remarks>   James, 20/05/2015. </remarks>
  27.         public delegate void PaletteChanged();
  28.         /// <summary>   Event queue for all listeners interested in OnPaletteChanged events. </summary>
  29.         public event PaletteChanged OnPaletteChanged;
  30.         /// <summary>   Invalid color changed. </summary>
  31.         ///
  32.         /// <remarks>   James, 20/05/2015. </remarks>
  33.         public delegate void InvalidColorChanged();
  34.         /// <summary>   Event queue for all listeners interested in OnInvalidColorChanged events. </summary>
  35.         public event InvalidColorChanged OnInvalidColorChanged;
  36.  
  37.         #endregion
  38.  
  39.         #region Private Members
  40.  
  41.         /// <summary>   The model. </summary>
  42.         private PlotModel model = new PlotModel
  43.         {
  44.             FixedXYScalingRatio = 1,
  45.             PlotAreaBorderThickness = new OxyThickness(0),
  46.             PlotMargins = new OxyThickness(0, 0, 0, 0)
  47.         };
  48.         /// <summary>   The Axis to process. </summary>
  49.         private CategoryAxis xAxis = new CategoryAxis
  50.         {
  51.             GapWidth = 0,
  52.             MaximumPadding = 0,
  53.             MinorTickSize = 0,
  54.             Position = AxisPosition.Bottom,
  55.             TickStyle = OxyPlot.Axes.TickStyle.None
  56.         };
  57.         /// <summary>   The Axis to process. </summary>
  58.         private LinearAxis yAxis = new LinearAxis
  59.         {
  60.             AbsoluteMinimum = 0,
  61.             MinimumPadding = 0,
  62.             MaximumPadding = 0,
  63.             MinorTickSize = 0,
  64.             Position = AxisPosition.Left,
  65.             TextColor = OxyColors.Transparent,
  66.             TickStyle = OxyPlot.Axes.TickStyle.None
  67.         };
  68.         /// <summary> The axis.</summary>
  69.         private LinearColorAxis cAxis = new LinearColorAxis { IsAxisVisible = false };
  70.         /// <summary>   The cursor i. </summary>
  71.         private LineAnnotation cursor_i = new LineAnnotation
  72.         {
  73.             Color = OxyColors.White,
  74.             LineStyle = OxyPlot.LineStyle.Solid,
  75.             Type = LineAnnotationType.Vertical
  76.         };
  77.         /// <summary>   The cursor f. </summary>
  78.         private LineAnnotation cursor_f = new LineAnnotation
  79.         {
  80.             Color = OxyColors.White,
  81.             LineStyle = OxyPlot.LineStyle.Solid,
  82.             Type = LineAnnotationType.Vertical
  83.         };
  84.         /// <summary>   The roi. </summary>
  85.         private ImageAnnotation roi;
  86.         /// <summary>   The histogram. </summary>
  87.         private ColumnSeries histogram = new ColumnSeries { IsVisible = true };
  88.         /// <summary>   The colormap. </summary>
  89.         private HeatMapSeries colormap = new HeatMapSeries { Interpolate = false };
  90.         /// <summary>   The current. </summary>
  91.         private OxyPalette current;
  92.         /// <summary>   The previous. </summary>
  93.         private OxyPalette previous;
  94.         /// <summary>   The initial. </summary>
  95.         private OxyPalette initial;
  96.         /// <summary>   The selected color. </summary>
  97.         private object selectedColor;
  98.         /// <summary>   The data bins. </summary>
  99.         Dictionary<double, int> data_bins = new Dictionary<double, int>(4096);
  100.         /// <summary>   The anchor. </summary>
  101.         private double anchor = 0;
  102.         /// <summary>   The dx. </summary>
  103.         private double dx;
  104.  
  105.         #endregion
  106.  
  107.         /// <summary>   Constructor. </summary>
  108.         ///
  109.         /// <remarks>   James, 23/04/2015. </remarks>
  110.         ///
  111.         /// <param name="min">      (Optional) The minimum. </param>
  112.         /// <param name="max">      (Optional) The maximum. </param>
  113.         /// <param name="data">     (Optional) The data. </param>
  114.         /// <param name="initial">  (Optional) The current. </param>
  115.         public OxyPaletteEditor(double min = -50, double max = 50, double[,] data = null, OxyPalette initial = null)
  116.         {
  117.             InitializeComponent();
  118.  
  119.             this.SuspendLayout();
  120.  
  121.             model.Axes.Add(xAxis);
  122.             model.Axes.Add(yAxis);
  123.             model.Axes.Add(cAxis);
  124.  
  125.             colormap.X0 = min;
  126.             colormap.X1 = max;
  127.             colormap.Y0 = 0;
  128.             colormap.Y1 = 1;
  129.             xAxis.Minimum = min;
  130.             xAxis.Maximum = max;
  131.             yAxis.Minimum = 0;
  132.             cAxis.Minimum = min;
  133.             cAxis.Maximum = max;
  134.             this.cAxis.Palette = initial;
  135.  
  136.             dx = 4096.0 / Math.Abs(max - min);
  137.  
  138.             this.initial = OxyPalette.Interpolate(4096, initial.Colors.ToArray());
  139.  
  140.             colormap.Data = new double[4096, 1];
  141.  
  142.             if (data != null)
  143.             {
  144.                 this.ResetData(min, max, data);
  145.             }
  146.             else
  147.             {
  148.                 this.Close();
  149.             }
  150.             //this.model.Series.Add(colormap);
  151.             //this.PlotHistogram.Model = CreateHistogram(100000, 200);
  152.  
  153.             this.model.Series.Add(histogram);
  154.             this.model.MouseDown += model_MouseDown;
  155.             this.model.MouseUp += model_MouseUp;
  156.             this.model.MouseMove += model_MouseMove;
  157.             this.model.PlotType = PlotType.XY;
  158.             this.PlotHistogram.Model = this.model;
  159.  
  160.             if (initial != null)
  161.             {
  162.                 this.Palette = initial;
  163.             }
  164.             else // For the time being
  165.             {
  166.                 this.Palette = OxyPalettes.Gray(4096);
  167.             }
  168.  
  169.             ColorPickerSolid.AddStandardColors();
  170.             ColorPickerGradient.AddStandardGradients();
  171.  
  172.             this.ResumeLayout();
  173.         }
  174.  
  175.         public static PlotModel CreateHistogram(int n, int binCount)
  176.         {
  177.             var bins = new Dictionary<string, int>(binCount);
  178.             for (int i = 0; i < binCount; i++)
  179.             {
  180.                 bins.Add(Convert.ToString(i), 0);
  181.             }
  182.  
  183.             var r = new Random(31);
  184.             for (int i = 0; i < n; i++)
  185.             {
  186.                 int value = r.Next(binCount);
  187.                 bins[Convert.ToString(value)]++;
  188.             }
  189.  
  190.             var temp = new PlotModel { Title = string.Format("Histogram (bins={0}, n={1})", binCount, n), Subtitle = "Pseudorandom numbers" };
  191.             var series1 = new ColumnSeries { ItemsSource = bins, ValueField = "Value" };
  192.             if (binCount < 100)
  193.             {
  194.                 series1.LabelFormatString = "{0}";
  195.             }
  196.  
  197.             temp.Series.Add(series1);
  198.  
  199.             temp.Axes.Add(new CategoryAxis { Position = AxisPosition.Bottom, ItemsSource = bins, LabelField = "Key", GapWidth = 0 });
  200.             temp.Axes.Add(new LinearAxis { Position = AxisPosition.Left, MinimumPadding = 0, MaximumPadding = 0.1, AbsoluteMinimum = 0 });
  201.  
  202.             return temp;
  203.         }
  204.  
  205.         #region Public Properties
  206.        
  207.         /// <summary>   Gets or sets the palette. </summary>
  208.         ///
  209.         /// <value> The palette. </value>
  210.         public OxyPalette Palette
  211.         {
  212.             get
  213.             {
  214.                 return current;
  215.             }
  216.             set
  217.             {
  218.                 this.current = OxyPalette.Interpolate(4096, value.Colors.ToArray());
  219.                 this.previous = OxyPalette.Interpolate(4096, value.Colors.ToArray());
  220.                 this.ResetPalette();
  221.             }
  222.         }
  223.  
  224.         /// <summary>   Gets or sets the invalid. </summary>
  225.         ///
  226.         /// <value> The invalid. </value>
  227.         public OxyColor Invalid
  228.         {
  229.             get;
  230.             set;
  231.         }
  232.  
  233.         #endregion
  234.  
  235.         #region Public Methods
  236.  
  237.         /// <summary>   Resets the data. </summary>
  238.         ///
  239.         /// <remarks>   James, 20/05/2015. </remarks>
  240.         ///
  241.         /// <param name="min">  The minimum. </param>
  242.         /// <param name="max">  The maximum. </param>
  243.         /// <param name="data"> The data. </param>
  244.         public void ResetData(double min, double max, double[,] data)
  245.         {
  246.             xAxis.Minimum = min;
  247.             xAxis.Maximum = max;
  248.             cAxis.Minimum = min;
  249.             cAxis.Maximum = max;
  250.  
  251.             colormap.X0 = min;
  252.             colormap.X1 = max;
  253.  
  254.             dx = 4096.0 / Math.Abs(max - min);
  255.            
  256.             for (int i = 0; i < 4096; i++)
  257.             {
  258.                 double div = Math.Round(min + ((Math.Abs(max - min) / 4096.0) * Convert.ToDouble(i)), 2);
  259.                 data_bins.Add(div, 0);
  260.                 colormap.Data[i, 0] = div;
  261.             }
  262.  
  263.             List<double> keys = data_bins.Keys.ToList();
  264.             for (long i = 0; i < data.LongLength; i++)
  265.             {
  266.                 int keyindex = keys.BinarySearch
  267.                 (
  268.                     data[i % data.GetLength(0), i / data.GetLength(0)],
  269.                     Comparer<double>.Create
  270.                     (
  271.                         (a, b) =>
  272.                         {
  273.                             if (Math.Abs(a - b) < ((Math.Abs(max - min) / 4096.0) / 2))
  274.                             {
  275.                                 return 0;
  276.                             }
  277.                             else if (a > b)
  278.                             {
  279.                                 return 1;
  280.                             }
  281.                             else
  282.                             {
  283.                                 return -1;
  284.                             }
  285.                         }
  286.                     )
  287.                 );
  288.                 if (keyindex > -1)
  289.                 {
  290.                     data_bins[keys[keyindex]]++;
  291.                 }
  292.             }
  293.  
  294.             this.xAxis.ItemsSource = data_bins;
  295.             this.xAxis.LabelField = "Key";
  296.             this.histogram.ItemsSource = data_bins;
  297.             this.histogram.ValueField = "Value";
  298.             this.yAxis.Maximum = data_bins.Max(b => b.Value);
  299.             this.colormap.Y1 = this.yAxis.Maximum;
  300.         }
  301.  
  302.         #endregion
  303.  
  304.         #region Private Methods
  305.  
  306.         /// <summary>   Gets mouse point. </summary>
  307.         ///
  308.         /// <remarks>   James, 20/05/2015. </remarks>
  309.         ///
  310.         /// <param name="p">    The ScreenPoint to process. </param>
  311.         ///
  312.         /// <returns>   The mouse point. </returns>
  313.         private DataPoint GetMousePoint(ScreenPoint p)
  314.         {
  315.             return this.histogram.InverseTransform(p);
  316.         }
  317.  
  318.         /// <summary>   Resets the palette. </summary>
  319.         ///
  320.         /// <remarks>   James, 20/05/2015. </remarks>
  321.         private void ResetPalette()
  322.         {
  323.             this.current = OxyPalette.Interpolate(4096, this.initial.Colors.ToArray());
  324.             this.previous = OxyPalette.Interpolate(4096, this.initial.Colors.ToArray());
  325.  
  326.             if (this.OnPaletteChanged != null) this.OnPaletteChanged();
  327.  
  328.             //this.model.Annotations.ToList().RemoveAll(a => a is ImageAnnotation);
  329.             //OxyColor[,] colors = new OxyColor[4096, 1];
  330.             //for (int i = 0; i < 4096; i++)
  331.             //{
  332.             //    colors[i, 0] = OxyColor.FromArgb(255, this.initial.Colors[i].R, this.initial.Colors[i].G, this.initial.Colors[i].B);
  333.             //}
  334.            
  335.             //this.model.Annotations.Add
  336.             //(
  337.             //    new ImageAnnotation
  338.             //    {
  339.             //        X = new PlotLength(this.xAxis.Minimum, PlotLengthUnit.Data),
  340.             //        Y = new PlotLength(this.yAxis.Minimum, PlotLengthUnit.Data),
  341.             //        Layer = AnnotationLayer.BelowSeries,
  342.             //        ImageSource = OxyImage.Create(colors, ImageFormat.Png),
  343.             //        Height = new PlotLength(1, PlotLengthUnit.RelativeToPlotArea),
  344.             //        Width = new PlotLength(Math.Abs(this.xAxis.Maximum - this.xAxis.Minimum), PlotLengthUnit.Data),
  345.             //        Interpolate = false,
  346.             //        HorizontalAlignment = OxyPlot.HorizontalAlignment.Left,
  347.             //        VerticalAlignment = VerticalAlignment.Bottom
  348.             //    }
  349.             //);
  350.  
  351.             this.model.InvalidatePlot(true);
  352.         }
  353.  
  354.         #endregion
  355.  
  356.         #region Event Handlers
  357.  
  358.         /// <summary>   Event handler. Called by model for mouse down events. </summary>
  359.         ///
  360.         /// <remarks>   James, 20/05/2015. </remarks>
  361.         ///
  362.         /// <param name="sender">   Source of the event. </param>
  363.         /// <param name="e">        Oxy mouse down event information. </param>
  364.         private void model_MouseDown(object sender, OxyMouseDownEventArgs e)
  365.         {
  366.             if (e.ChangedButton == OxyMouseButton.Left && selectedColor != null)
  367.             {
  368.                 DataPoint p = this.GetMousePoint(e.Position);
  369.                 if
  370.                 (
  371.                     p.X >= this.xAxis.Minimum &&
  372.                     p.X <= this.xAxis.Maximum &&
  373.                     p.Y >= this.yAxis.Minimum &&
  374.                     p.Y <= this.yAxis.Maximum
  375.                 )
  376.                 {
  377.                     cursor_i.X = p.X;
  378.                     cursor_f.X = p.X;
  379.                     anchor = p.X;
  380.                     this.model.Annotations.Add(cursor_i);
  381.                     this.model.Annotations.Add(cursor_f);
  382.                     //this.model.Annotations.Add
  383.                     //(
  384.                     //    new ImageAnnotation
  385.                     //    {
  386.                     //        X = new PlotLength(cursor_i.X, PlotLengthUnit.Data),
  387.                     //        Y = new PlotLength(0, PlotLengthUnit.Data),
  388.                     //        Layer = AnnotationLayer.BelowSeries,
  389.                     //        Height = new PlotLength(1, PlotLengthUnit.RelativeToPlotArea),
  390.                     //        Width = new PlotLength(p.X - cursor_i.X, PlotLengthUnit.Data),
  391.                     //        Interpolate = false,
  392.                     //        HorizontalAlignment = OxyPlot.HorizontalAlignment.Left,
  393.                     //        VerticalAlignment = VerticalAlignment.Bottom
  394.                     //    }
  395.                     //);
  396.                     //roi = this.model.Annotations.Last(a => a is ImageAnnotation) as ImageAnnotation;
  397.                     e.Handled = true;
  398.                 }
  399.             }
  400.         }
  401.  
  402.         /// <summary>   Event handler. Called by model for mouse move events. </summary>
  403.         ///
  404.         /// <remarks>   James, 20/05/2015. </remarks>
  405.         ///
  406.         /// <param name="sender">   Source of the event. </param>
  407.         /// <param name="e">        Oxy mouse event information. </param>
  408.         private void model_MouseMove(object sender, OxyMouseEventArgs e)
  409.         {
  410.             if (selectedColor != null && cursor_i.Parent == this.model)
  411.             {
  412.                 DataPoint p = this.GetMousePoint(e.Position);
  413.                 if
  414.                 (
  415.                     p.X >= this.xAxis.Minimum &&
  416.                     p.X <= this.xAxis.Maximum &&
  417.                     p.Y >= this.yAxis.Minimum &&
  418.                     p.Y <= this.yAxis.Maximum
  419.                 )
  420.                 {                    
  421.                     //if (roi != null)
  422.                     //{
  423.                     double diff = Math.Abs(p.X - anchor);
  424.                     int length = Convert.ToInt32(diff * dx);
  425.                     bool shorter = false;
  426.                     if (p.X >= anchor)
  427.                     {
  428.                         shorter = diff < Math.Abs(cursor_f.X - anchor);
  429.                         cursor_f.X = p.X;
  430.                     }
  431.                     else
  432.                     {
  433.                         shorter = diff < Math.Abs(cursor_i.X - anchor);
  434.                         cursor_i.X = p.X;
  435.                     }
  436.  
  437.                     if (shorter)
  438.                     {
  439.                         this.current = OxyPalette.Interpolate(4096, this.previous.Colors.ToArray());
  440.                     }
  441.  
  442.                     //OxyColor[,] imgData = new OxyColor[length, 1];
  443.                     int start = Convert.ToInt32(Math.Abs(cursor_i.X - this.xAxis.Minimum) * dx);
  444.  
  445.                     if (selectedColor is Color)
  446.                     {
  447.                         for (int i = 0; i < length; i++)
  448.                         {
  449.                             Color color = (Color)selectedColor;
  450.                             //imgData[i, 0] =
  451.                             this.current.Colors[start + i] = OxyColor.FromArgb(255, color.R, color.G, color.B);
  452.                         }                        
  453.                     }
  454.                     else if (selectedColor is Color[])
  455.                     {
  456.                         Color[] gradient = selectedColor as Color[];
  457.                         OxyColor[] colors = new OxyColor[gradient.Length];
  458.                         for (int i = 0; i < gradient.Length; i++)
  459.                         {
  460.                             colors[i] = OxyColor.FromArgb(255, gradient[i].R, gradient[i].G, gradient[i].B);
  461.                         }
  462.                         OxyColor[] data = OxyPalette.Interpolate(length, colors).Colors.ToArray();
  463.                         for (int i = 0; i < length; i++)
  464.                         {
  465.                             //imgData[i, 0] =
  466.                             this.current.Colors[start + i] = data[i];
  467.                         }
  468.                     }
  469.  
  470.                     this.model.InvalidatePlot(true);
  471.                        
  472.                     if (this.OnPaletteChanged != null) this.OnPaletteChanged();
  473.  
  474.                     //if (p.X == cursor_i.X)
  475.                     //{
  476.                     //    roi.X = new PlotLength(p.X, PlotLengthUnit.Data);
  477.                     //}
  478.                     //roi.Width = new PlotLength(diff, PlotLengthUnit.Data);
  479.                     //Task.Run(() => { roi.ImageSource = OxyImage.Create(imgData, ImageFormat.Png); });
  480.                 }
  481.                 e.Handled = true;
  482.                 //}
  483.             }
  484.         }
  485.  
  486.         /// <summary>   Event handler. Called by model for mouse up events. </summary>
  487.         ///
  488.         /// <remarks>   James, 20/05/2015. </remarks>
  489.         ///
  490.         /// <param name="sender">   Source of the event. </param>
  491.         /// <param name="e">        Oxy mouse event information. </param>
  492.         private void model_MouseUp(object sender, OxyMouseEventArgs e)
  493.         {
  494.             this.model.Annotations.Remove(cursor_i);
  495.             this.model.Annotations.Remove(cursor_f);
  496.             this.previous = OxyPalette.Interpolate(4096, this.current.Colors.ToArray());
  497.             this.model.InvalidatePlot(true);
  498.             e.Handled = true;
  499.         }
  500.  
  501.         #endregion
  502.  
  503.         /// <summary>
  504.         /// Event handler. Called by ColorPickerSolid for selected index changed events.
  505.         /// </summary>
  506.         ///
  507.         /// <remarks>   James, 20/05/2015. </remarks>
  508.         ///
  509.         /// <param name="sender">   Source of the event. </param>
  510.         /// <param name="e">        Event information. </param>
  511.         private void ColorPickerSolid_SelectedIndexChanged(object sender, EventArgs e)
  512.         {
  513.             if (this.current != null)
  514.             {
  515.                 this.selectedColor = ColorPickerSolid.SelectedItem.Color;
  516.             }
  517.         }
  518.  
  519.         /// <summary>
  520.         /// Event handler. Called by ColorPickerGradient for selected index changed events.
  521.         /// </summary>
  522.         ///
  523.         /// <remarks>   James, 20/05/2015. </remarks>
  524.         ///
  525.         /// <param name="sender">   Source of the event. </param>
  526.         /// <param name="e">        Event information. </param>
  527.         private void ColorPickerGradient_SelectedIndexChanged(object sender, EventArgs e)
  528.         {
  529.             if (this.current != null)
  530.             {
  531.                 this.selectedColor = ColorPickerGradient.SelectedItem.Colors;
  532.             }
  533.         }
  534.  
  535.         /// <summary>   Event handler. Called by ButtonReset for click events. </summary>
  536.         ///
  537.         /// <remarks>   James, 20/05/2015. </remarks>
  538.         ///
  539.         /// <param name="sender">   Source of the event. </param>
  540.         /// <param name="e">        Event information. </param>
  541.         private void ButtonReset_Click(object sender, EventArgs e)
  542.         {
  543.             if (this.initial != null)
  544.             {
  545.                 this.ResetPalette();
  546.                 this.model.InvalidatePlot(true);
  547.             }
  548.         }
  549.  
  550.         /// <summary>   Event handler. Called by ButtonColorUndefined for click events. </summary>
  551.         ///
  552.         /// <remarks>   James, 20/05/2015. </remarks>
  553.         ///
  554.         /// <param name="sender">   Source of the event. </param>
  555.         /// <param name="e">        Event information. </param>
  556.         private void ButtonColorUndefined_Click(object sender, EventArgs e)
  557.         {
  558.             if (this.ColorDialog.ShowDialog() == DialogResult.OK)
  559.             {
  560.                 this.Invalid = OxyColor.FromArgb
  561.                 (
  562.                     this.ColorDialog.Color.A,
  563.                     this.ColorDialog.Color.R,
  564.                     this.ColorDialog.Color.G,
  565.                     this.ColorDialog.Color.B
  566.                 );
  567.                 if (this.OnInvalidColorChanged != null) this.OnInvalidColorChanged();
  568.             }
  569.         }
  570.     }
  571. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement