/// <summary> /// Raises the <see cref="VirtualRangeChanged"/> event. /// </summary> /// <param name="minimumX">The minimum x.</param> /// <param name="maximumX">The maximum x.</param> /// <param name="minimumY">The minimum y.</param> /// <param name="maximumY">The maximum y.</param> protected virtual void OnVirtualRangeChanged(GraphDataPoint minimumX, GraphDataPoint maximumX, GraphDataPoint minimumY, GraphDataPoint maximumY) { var range = new RangeChangedEventArgs(minimumX, maximumX, minimumY, maximumY); VirtualRangeChanged?.Invoke(this, range); }
/// <summary> /// Raises the <see cref="EffectiveRangeChanged"/> event. /// </summary> /// <param name="minimumX">The minimum x.</param> /// <param name="maximumX">The maximum x.</param> /// <param name="minimumY">The minimum y.</param> /// <param name="maximumY">The maximum y.</param> protected virtual void OnEffectiveRangeChanged(GraphDataPoint minimumX, GraphDataPoint maximumX, GraphDataPoint minimumY, GraphDataPoint maximumY) { EffectiveRangeChanged?.Invoke(this, new RangeChangedEventArgs(minimumX, maximumX, minimumY, maximumY)); }
/// <summary> /// The rendering thread method. /// </summary> private void RenderThreadMethod() { while (true) { if (!IsPaused) { var pending_list = _pending_series_collection.BlockDequeue(); foreach (var pending_series in pending_list) { if (pending_series.IsClearSeries) { _pending_series_collection = new GraphDataQueue <List <PendingSeries> >(); _to_render.Clear(); break; } if (_to_render.ContainsKey(pending_series.Series)) { var s = _to_render[pending_series.Series]; s.XX.AddRange(pending_series.XX); s.YY.AddRange(pending_series.YY); } else { _to_render[pending_series.Series] = pending_series; } } if (DateTime.Now > _last_render_time.AddMilliseconds(RefreshRate.TotalMilliseconds) && _to_render.Count > 0) { GraphDataPoint min_x = _range.MaximumX - _range.MaximumX; GraphDataPoint max_x = _range.MaximumX; GraphDataPoint min_y = _range.MinimumY; GraphDataPoint max_y = _range.MaximumY; min_x = _to_render.First().Value.XX.First(); max_x = _to_render.First().Value.XX.Last(); if (_range.AutoY) { min_y = _to_render.Select(x => x.Value).SelectMany(x => x.YY).Min(); max_y = _to_render.Select(x => x.Value).SelectMany(x => x.YY).Max(); } if (min_y == max_y) { min_y = _range.MinimumY; max_y = _range.MaximumY; } EffectiveMinimumX = min_x; EffectiveMaximumX = max_x; EffectiveMinimumY = min_y; EffectiveMaximumY = max_y; VirtualMinimumX = EffectiveMinimumX; VirtualMaximumX = EffectiveMaximumX; VirtualMinimumY = EffectiveMinimumY; VirtualMaximumY = EffectiveMaximumY; _last_render_time = DateTime.Now; if (Surface != null) { var surface_size = Surface.GetSize(); var zoom_rect = Surface.GetZoomRect(); Surface.BeginDraw(); if (zoom_rect.Width > 0 && zoom_rect.Height > 0) { var zoom_rect_top_percentage = zoom_rect.Top / surface_size.Height; var zoom_rect_bottom_percentage = zoom_rect.Bottom / surface_size.Height; var zoom_rect_left_percentage = zoom_rect.Left / surface_size.Width; var zoom_rect_right_percentage = zoom_rect.Right / surface_size.Width; VirtualMinimumY = EffectiveMaximumY - GraphDataPointHelper.ComputeAbsolutePosition(EffectiveMinimumY, EffectiveMaximumY, zoom_rect_bottom_percentage); VirtualMaximumY = EffectiveMaximumY - GraphDataPointHelper.ComputeAbsolutePosition(EffectiveMinimumY, EffectiveMaximumY, zoom_rect_top_percentage); VirtualMinimumX = GraphDataPointHelper.ComputeAbsolutePosition(EffectiveMinimumX, EffectiveMaximumX, zoom_rect_left_percentage); VirtualMaximumX = GraphDataPointHelper.ComputeAbsolutePosition(EffectiveMinimumX, EffectiveMaximumX, zoom_rect_right_percentage); GraphTransform transform = new GraphTransform(); var scale_x = (float)(surface_size.Width / zoom_rect.Width); var scale_y = (float)(surface_size.Height / zoom_rect.Height); var translate_x = (float)-zoom_rect.Left * scale_x; var translate_y = (float)-zoom_rect.Top * scale_y; transform = new GraphTransform(); transform.TranslateX = translate_x; transform.TranslateY = translate_y; transform.ScaleX = scale_x; transform.ScaleY = scale_y; Surface.SetTransform(transform); } List <Tuple <TDataSeries, IEnumerable <PointF> > > to_draw = new List <Tuple <TDataSeries, IEnumerable <PointF> > >(); var to_render = _to_render.Select(x => x.Value).ToList(); foreach (var item in to_render) { var points = Renderer.Render(Surface, item.Series, _range, item.XX, item.YY, min_x, max_x, min_y, max_y); to_draw.Add(new Tuple <TDataSeries, IEnumerable <PointF> >(item.Series, points)); } for (int i = 0; i < to_draw.Count; i++) { if (to_draw[i].Item2.Count() > 2) { if (to_draw[i].Item1.IsVisible) { Renderer.Draw(Surface, to_draw[i].Item1, to_draw[i].Item2, i, to_draw.Count); } } } Surface.EndDraw(); } OnEffectiveRangeChanged(EffectiveMinimumX, EffectiveMaximumX, EffectiveMinimumY, EffectiveMaximumY); OnVirtualRangeChanged(VirtualMinimumX, VirtualMaximumX, VirtualMinimumY, VirtualMaximumY); } } else { Thread.Sleep(RefreshRate); } } }
private void Render() { if (_to_render.Count > 0) { GraphDataPoint min_x = _range.MaximumX - _range.MaximumX; GraphDataPoint max_x = _range.MaximumX; GraphDataPoint min_y = _range.MinimumY; GraphDataPoint max_y = _range.MaximumY; if (_to_render.Count > 0 && _to_render.First().Value.XX.Count > 0) { min_x = _to_render.First().Value.XX.First(); max_x = _to_render.First().Value.XX.Last(); } else { return; } if (_range.AutoY) { min_y = _to_render.Select(x => x.Value).SelectMany(x => x.YY).Min(); max_y = _to_render.Select(x => x.Value).SelectMany(x => x.YY).Max(); } if (min_y == max_y) { if (_range.AutoYFallbackMode == GraphRangeAutoYFallBackMode.MinMax) { min_y = _range.MinimumY; max_y = _range.MaximumY; } else if (_range.AutoYFallbackMode == GraphRangeAutoYFallBackMode.Margins) { min_y -= _range.AutoYFallbackMargins; max_y += _range.AutoYFallbackMargins; } } EffectiveMinimumX = min_x; EffectiveMaximumX = max_x; EffectiveMinimumY = min_y; EffectiveMaximumY = max_y; VirtualMinimumX = EffectiveMinimumX; VirtualMaximumX = EffectiveMaximumX; VirtualMinimumY = EffectiveMinimumY; VirtualMaximumY = EffectiveMaximumY; _last_render_time = DateTime.Now; if (Surface != null) { var surface_size = Surface.GetSize(); var zoom_rect = Surface.GetZoomRect(); if (surface_size.Width > 0 && surface_size.Height > 0) { Surface.BeginDraw(); if (zoom_rect.Width > 0 && zoom_rect.Height > 0) { var zoom_rect_top_percentage = zoom_rect.Top / surface_size.Height; var zoom_rect_bottom_percentage = zoom_rect.Bottom / surface_size.Height; var zoom_rect_left_percentage = zoom_rect.Left / surface_size.Width; var zoom_rect_right_percentage = zoom_rect.Right / surface_size.Width; VirtualMinimumY = EffectiveMaximumY - GraphDataPointHelper.ComputeAbsolutePosition(EffectiveMinimumY, EffectiveMaximumY, zoom_rect_bottom_percentage); VirtualMaximumY = EffectiveMaximumY - GraphDataPointHelper.ComputeAbsolutePosition(EffectiveMinimumY, EffectiveMaximumY, zoom_rect_top_percentage); VirtualMinimumX = GraphDataPointHelper.ComputeAbsolutePosition(EffectiveMinimumX, EffectiveMaximumX, zoom_rect_left_percentage); VirtualMaximumX = GraphDataPointHelper.ComputeAbsolutePosition(EffectiveMinimumX, EffectiveMaximumX, zoom_rect_right_percentage); GraphTransform transform = new GraphTransform(); var scale_x = (float)(surface_size.Width / zoom_rect.Width); var scale_y = (float)(surface_size.Height / zoom_rect.Height); var translate_x = (float)-zoom_rect.Left * scale_x; var translate_y = (float)-zoom_rect.Top * scale_y; transform = new GraphTransform(); transform.TranslateX = translate_x; transform.TranslateY = translate_y; transform.ScaleX = scale_x; transform.ScaleY = scale_y; Surface.SetTransform(transform); } List <Tuple <TDataSeries, IEnumerable <PointF> > > to_draw = new List <Tuple <TDataSeries, IEnumerable <PointF> > >(); var to_render = _to_render.Select(x => x.Value).ToList(); foreach (var item in to_render) { if (item.YY.Count > 0) { item.Series.CurrentValue = item.YY.Last().GetValue(); } var points = Renderer.Render(Surface, item.Series, _range, item.XX, item.YY, min_x, max_x, min_y, max_y); to_draw.Add(new Tuple <TDataSeries, IEnumerable <PointF> >(item.Series, points)); } for (int i = 0; i < to_draw.Count; i++) { if (to_draw[i].Item2.Count() > 2) { if (to_draw[i].Item1.IsVisible) { Renderer.Draw(Surface, to_draw[i].Item1, to_draw[i].Item2, i, to_draw.Count); } } } Surface.EndDraw(); } } OnEffectiveRangeChanged(EffectiveMinimumX, EffectiveMaximumX, EffectiveMinimumY, EffectiveMaximumY); OnVirtualRangeChanged(VirtualMinimumX, VirtualMaximumX, VirtualMinimumY, VirtualMaximumY); } }
/// <summary> /// Arranges the series of data points and returns a series of drawing points. /// </summary> /// <param name="surface">The target graph surface.</param> /// <param name="series">The instance of the current rendered data series.</param> /// <param name="range">Instance of graph range.</param> /// <param name="xx">Collection of x coordinates.</param> /// <param name="yy">Collection of y coordinates.</param> /// <param name="minimumX">The minimum x coordinates value.</param> /// <param name="maximumX">The maximum x coordinates value.</param> /// <param name="minimumY">The minimum y coordinates value.</param> /// <param name="maximumY">The maximum y coordinates value.</param> /// <returns></returns> public abstract IEnumerable <PointF> Render(IGraphSurface <TDataSeries> surface, TDataSeries series, IGraphRange range, List <GraphDataPoint> xx, List <GraphDataPoint> yy, GraphDataPoint minimumX, GraphDataPoint maximumX, GraphDataPoint minimumY, GraphDataPoint maximumY);