/// <summary> /// Renders frame and returns it as a render result. /// </summary> /// <param name="state">Render task state for rendering frame.</param> /// <returns>Render result of rendered frame.</returns> protected virtual RenderResult RenderFrame(RenderTaskState state) { //if (!state.IsCancelled) // return new RenderResult(HeatMap.BuildHeatMap(state.Transform.ScreenRect, new DataRect(state.Transform.ViewportRect), DataSource.X, DataSource.Y, DataSource.Data, 0)); //else return(null); }
private void EnqueueTask(long id /*Func<RenderTaskState, RenderResult> task*/) { if (runningTasks.Count < maxTasks) { Size screenSize = new Size(Math.Abs(LeftFromX(ActualPlotRect.XMax) - LeftFromX(ActualPlotRect.XMin)), Math.Abs(TopFromY(ActualPlotRect.YMax) - TopFromY(ActualPlotRect.YMin))); RenderTaskState state = new RenderTaskState(ActualPlotRect, screenSize); state.Id = id; state.Bounds = ComputeBounds(); runningTasks.Add(state); if (!DesignerProperties.GetIsInDesignMode(this)) { ThreadPool.QueueUserWorkItem(s => { var rr = RenderFrame((RenderTaskState)s); Dispatcher.BeginInvoke(new RenderFunc(OnTaskCompleted), rr, s); }, state); } else { var rr = RenderFrame(state); OnTaskCompleted(rr, state); } } else { tasks.Enqueue(id); } }
private void OnTaskCompleted(RenderResult r, RenderTaskState state) { if (r != null && !state.IsCanceled) { WriteableBitmap wr = new WriteableBitmap((int)r.Output.Width, (int)r.Output.Height, 96, 96, PixelFormats.Bgra32, null); // Calculate the number of bytes per pixel. int bytesPerPixel = (wr.Format.BitsPerPixel + 7) / 8; // Stride is bytes per pixel times the number of pixels. // Stride is the byte width of a single rectangle row. int stride = wr.PixelWidth * bytesPerPixel; wr.WritePixels(new Int32Rect(0, 0, wr.PixelWidth, wr.PixelHeight), r.Image, stride, 0); outputImage.Source = wr; Canvas.SetLeft(outputImage, r.Output.Left); Canvas.SetTop(outputImage, r.Output.Top); imageCartesianRect = r.Visible; imageSize = new Size(r.Output.Width, r.Output.Height); outputImage.RenderTransform = null; } RaiseTaskCompletion(state.Id); runningTasks.Remove(state); while (tasks.Count > 1) { long id = tasks.Dequeue(); RaiseTaskCompletion(id); } if (tasks.Count > 0 && runningTasks.Count < maxTasks) { EnqueueTask(tasks.Dequeue()); } InvalidateMeasure(); }
/// <summary> /// Renders frame and returns it as a render result. /// </summary> /// <param name="state">Render task state for rendering frame.</param> /// <returns>Render result of rendered frame.</returns> protected override RenderResult RenderFrame(RenderTaskState state) { if (state == null) { throw new ArgumentNullException("state"); } if (!state.Bounds.IsEmpty && !state.IsCanceled && data != null) { //DataRect dataRect = new DataRect(state.Transform.Visible); //Rect output = state.Transform.Screen; DataRect dataRect = state.ActualPlotRect; DataRect output = new DataRect(0, 0, state.ScreenSize.Width, state.ScreenSize.Height); DataRect bounds = state.Bounds; if (dataRect.XMin >= bounds.XMax || dataRect.XMax <= bounds.XMin || dataRect.YMin >= bounds.YMax || dataRect.YMax <= bounds.YMin) { return(null); } double left = 0; double xmin = dataRect.XMin; double scale = output.Width / dataRect.Width; if (xmin < bounds.XMin) { left = (bounds.XMin - dataRect.XMin) * scale; xmin = bounds.XMin; } double width = output.Width - left; double xmax = dataRect.XMax; if (xmax > bounds.XMax) { width -= (dataRect.XMax - bounds.XMax) * scale; xmax = bounds.XMax; } scale = output.Height / dataRect.Height; double top = 0; double ymax = dataRect.YMax; if (ymax > bounds.YMax) { top = (dataRect.YMax - bounds.YMax) * scale; ymax = bounds.YMax; } double height = output.Height - top; double ymin = dataRect.YMin; if (ymin < bounds.YMin) { height -= (bounds.YMin - dataRect.YMin) * scale; ymin = bounds.YMin; } if (xmin < bounds.XMin) { xmin = bounds.XMin; } if (xmax > bounds.XMax) { xmax = bounds.XMax; } if (ymin < bounds.YMin) { ymin = bounds.YMin; } if (ymax > bounds.YMax) { ymax = bounds.YMax; } DataRect visibleData = new DataRect(xmin, ymin, xmax, ymax); // Capture data to local variable double[,] localData; double[] localX, localY; long localDataVersion; IPalette localPalette; double localMV; Range localDataRange; bool getMaxMin = false; lock (locker) { localData = data; localX = xArr; localY = yArr; localDataVersion = dataVersion; localPalette = palette; localMV = missingValue; localDataRange = dataRange; if (palette.IsNormalized && dataVersion != dataRangeVersion) { getMaxMin = true; } } if (getMaxMin) { localDataRange = Double.IsNaN(missingValue) ? HeatmapBuilder.GetMaxMin(data) : HeatmapBuilder.GetMaxMin(data, missingValue); lock (locker) { if (dataVersion == localDataVersion) { dataRangeVersion = dataVersion; dataRange = localDataRange; } else { return(null); // New data was passed to Plot method so this render task is obsolete } } } if (paletteRangeUpdateRequired) { Dispatcher.BeginInvoke(new Action <long>(UpdatePaletteRange), localDataVersion); } return(new RenderResult(HeatmapBuilder.BuildHeatMap(new Rect(0, 0, width, height), visibleData, localX, localY, localData, localMV, localPalette, localDataRange), visibleData, new Point(left, top), width, height)); } else { return(null); } }
protected virtual RenderTaskState PrepareRenderTaskState(long id, Size screenSize) { RenderTaskState state = new RenderTaskState(ActualPlotRect, screenSize); state.Id = id; state.Bounds = ComputeBounds(); return state; }