public void Render() { try { double CanvasWidth = (ActualWidth - 24) * Zoom; double CanvasHeight = Height - 14; CanvasPlot.Children.Clear(); if (CanvasWidth <= 0 || CanvasHeight <= 0) { return; } #region Determine axis range ValueMin = double.MaxValue; ValueMax = -double.MaxValue; if (!double.IsNaN(AxisMin)) { ValueMin = AxisMin; } else if (Points != null && Points.Count > 0) { foreach (var point in Points) { if (!double.IsNaN(point.Value)) { ValueMin = Math.Min(ValueMin, point.Value); } } } else { ValueMin = 0; } if (!double.IsNaN(AxisMax)) { ValueMax = AxisMax; } else if (Points != null && Points.Count > 0 && Points.Any(v => !double.IsNaN(v.Value))) { foreach (var point in Points) { if (!double.IsNaN(point.Value)) { ValueMax = Math.Max(ValueMax, point.Value); } } } else { ValueMax = 1; } double Range = ValueMax - ValueMin; if (ValueMin == ValueMax) // Range = 0, probably only one point { ValueMax += 1; ValueMin -= 1; } else // Make sure there are a few pixels left to draw the points at the extremes { if (double.IsNaN(AxisMax)) { ValueMax += Range / CanvasHeight * PointRadius; } if (double.IsNaN(AxisMin)) { ValueMin -= Range / CanvasHeight * PointRadius; } } Range = ValueMax - ValueMin; Dispatcher.Invoke(() => { string FloatFormat = "F0"; if (Math.Max(ValueMax, ValueMin) < 100) { FloatFormat = "F1"; } if (Math.Max(ValueMax, ValueMin) < 10) { FloatFormat = "F2"; } TextLineBottom.Text = ValueMin.ToString(FloatFormat, CultureInfo.InvariantCulture); TextLineCenter.Text = ((ValueMin + ValueMax) * 0.5).ToString(FloatFormat, CultureInfo.InvariantCulture); TextLineTop.Text = ValueMax.ToString(FloatFormat, CultureInfo.InvariantCulture); }); #endregion #region Adjust range highlight double RangeHighlightClampedMin = Math.Max(ValueMin, RangeHighlightMin); double RangeHighlightClampedMax = Math.Min(ValueMax, RangeHighlightMax); PanelRangeHighlight.Margin = new Thickness(0, 7 + (ValueMax - RangeHighlightClampedMax) / Range * CanvasHeight, 0, 0); PanelRangeHighlight.Height = Math.Max(0, RangeHighlightClampedMax - RangeHighlightClampedMin) / Range * CanvasHeight; #endregion if (Range < 0 || Points == null || Points.Count == 0) { ImagePlot.Source = null; return; } float[] HistogramBins = new float[50]; DrawingGroup DGroup = new DrawingGroup(); using (DrawingContext DContext = DGroup.Open()) { DContext.PushClip(new RectangleGeometry(new Rect(new Size(CanvasWidth, CanvasHeight)))); Pen OutlinePen = new Pen(Brushes.Transparent, 0); OutlinePen.Freeze(); SolidColorBrush BackgroundBrush = new SolidColorBrush(Colors.Transparent); BackgroundBrush.Freeze(); DContext.DrawRectangle(BackgroundBrush, OutlinePen, new Rect(new Size(CanvasWidth, CanvasHeight))); SolidColorBrush[] ColorBrushes = PointColors.Count > 0 ? PointColors.Select(c => { SolidColorBrush Brush = new SolidColorBrush(Color.FromArgb(255, c.R, c.G, c.B)); Brush.Freeze(); return(Brush); }).ToArray() : new[] { new SolidColorBrush(Color.FromArgb(150, Colors.DeepSkyBlue.R, Colors.DeepSkyBlue.G, Colors.DeepSkyBlue.B)) }; StepX = (CanvasWidth - PointRadius * 2) / Points.Count; OffsetX = StepX / 2 + PointRadius; StepY = CanvasHeight / Range; PointCenters = new System.Windows.Point[Points.Count]; for (int i = 0; i < Points.Count; i++) { if (double.IsNaN(Points[i].Value)) { continue; } double X = i * StepX + OffsetX; double Y = (ValueMax - Points[i].Value) * StepY; DContext.DrawEllipse(ColorBrushes[Points[i].ColorID], OutlinePen, new System.Windows.Point(X, Y), PointRadius, PointRadius); PointCenters[i] = new System.Windows.Point(X, Y); HistogramBins[Math.Max(0, Math.Min(HistogramBins.Length - 1, (int)((Points[i].Value - ValueMin) / Range * (HistogramBins.Length - 1) + 0.5)))]++; } } DrawingImage Plot = new DrawingImage(DGroup); Plot.Freeze(); Dispatcher.Invoke(() => ImagePlot.Source = Plot); Dispatcher.Invoke(() => { float[] HistogramConv = new float[HistogramBins.Length]; float[] ConvKernel = { 0.11f, 0.37f, 0.78f, 1f, 0.78f, 0.37f, 0.11f }; for (int i = 0; i < HistogramBins.Length; i++) { float Sum = 0; float Samples = 0; for (int j = 0; j < ConvKernel.Length; j++) { int ij = i - 3 + j; if (ij < 0 || ij >= HistogramBins.Length) { continue; } Sum += ConvKernel[j] * HistogramBins[ij]; Samples += ConvKernel[j]; } HistogramConv[i] = Sum / Samples; } float HistogramMax = MathHelper.Max(HistogramConv); if (HistogramMax > 0) { HistogramConv = HistogramConv.Select(v => v / HistogramMax * 16).ToArray(); } Polygon HistogramPolygon = new Polygon() { Stroke = Brushes.Transparent, Fill = Brushes.Gray, Opacity = 0.15 }; PointCollection HistogramPoints = new PointCollection(HistogramConv.Length); HistogramPoints.Add(new System.Windows.Point(16, 0)); HistogramPoints.Add(new System.Windows.Point(16, CanvasHeight)); for (int i = 0; i < HistogramConv.Length; i++) { double X = 15 - HistogramConv[i]; double Y = CanvasHeight - (i / (float)(HistogramConv.Length - 1) * CanvasHeight); HistogramPoints.Add(new System.Windows.Point(X, Y)); } HistogramPolygon.Points = HistogramPoints; CanvasHistogram.Children.Clear(); CanvasHistogram.Children.Add(HistogramPolygon); Canvas.SetRight(HistogramPolygon, 0); }); } catch { } }
public void Render() { try { double CanvasWidth = ActualWidth; double CanvasHeight = ActualHeight; double FullRange = AxisMax * 2; CanvasPlot.Children.Clear(); if (double.IsNaN(AxisMax)) { return; } if (CanvasWidth <= 0 || CanvasHeight <= 0) { return; } if (Points == null || Points.Count == 0) { ImagePlot.Source = null; return; } DrawingGroup DGroup = new DrawingGroup(); using (DrawingContext DContext = DGroup.Open()) { DContext.PushClip(new RectangleGeometry(new Rect(new Size(CanvasWidth, CanvasHeight)))); Pen OutlinePen = new Pen(Brushes.Transparent, 0); OutlinePen.Freeze(); SolidColorBrush BackgroundBrush = new SolidColorBrush(Colors.Transparent); BackgroundBrush.Freeze(); DContext.DrawRectangle(BackgroundBrush, OutlinePen, new Rect(new Size(CanvasWidth, CanvasHeight))); SolidColorBrush[] ColorBrushes = PointColors.Count > 0 ? PointColors.Select(c => { SolidColorBrush Brush = new SolidColorBrush(Color.FromArgb(120, c.R, c.G, c.B)); Brush.Freeze(); return(Brush); }).ToArray() : new[] { new SolidColorBrush(Color.FromArgb(150, Colors.DeepSkyBlue.R, Colors.DeepSkyBlue.G, Colors.DeepSkyBlue.B)) }; PointCenters = new System.Windows.Point[Points.Count]; for (int i = 0; i < Points.Count; i++) { if (double.IsNaN(Points[i].X) || double.IsNaN(Points[i].Y)) { continue; } //if (Math.Abs(Points[i].X) > AxisMax || Math.Abs(Points[i].Y) > AxisMax) // continue; double X = Points[i].X / FullRange * CanvasWidth + CanvasWidth / 2; double Y = Points[i].Y / FullRange * CanvasHeight + CanvasHeight / 2; DContext.DrawEllipse(ColorBrushes[Points[i].ColorID], OutlinePen, new System.Windows.Point(X, Y), PointRadius, PointRadius); PointCenters[i] = new System.Windows.Point(X, Y); } } DrawingImage Plot = new DrawingImage(DGroup); Plot.Freeze(); Dispatcher.Invoke(() => ImagePlot.Source = Plot); } catch { } }