/// <summary> /// Gets the source image to display in the dynamic layer. Override this to generate /// or modify images. /// </summary> /// <param name="extent">The extent of the image being request.</param> /// <param name="width">The width of the image being request.</param> /// <param name="height">The height of the image being request.</param> /// <param name="onComplete">The method to call when the image is ready.</param> /// <seealso cref="OnProgress"/> protected override void GetSource(Envelope extent, int width, int height, DynamicLayer.OnImageComplete onComplete) { if (!IsInitialized) { onComplete(null, -1, -1, null); return; } if (renderThread != null && renderThread.IsBusy) { renderThread.CancelAsync(); //render already running. Cancel current process. while (renderThread.IsBusy) //wait for thread to cancel { #if SILVERLIGHT Thread.Sleep(10); #else System.Windows.Forms.Application.DoEvents(); #endif } } //Accessing a GradientStop collection from a non-UI thread is not allowed, //so we used a private class gradient collection List <ThreadSafeGradientStop> stops = new List <ThreadSafeGradientStop>(Gradient.Count); foreach (GradientStop stop in Gradient) { stops.Add(new ThreadSafeGradientStop() { Color = stop.Color, Offset = stop.Offset }); } //Gradients must be sorted by offset stops.Sort((ThreadSafeGradientStop g1, ThreadSafeGradientStop g2) => { return(g1.Offset.CompareTo(g2.Offset)); }); List <HeatPoint> points = new List <HeatPoint>(); double res = (extent.Width / width) / Resolution; //adjust extent to include points slightly outside the view so pan won't affect the outcome Envelope extent2 = new Envelope(extent.XMin - Intensity * res, extent.YMin - Intensity * res, extent.XMax + Intensity * res, extent.YMax + Intensity * res); //get points within the extent and transform them to pixel space foreach (MapPoint p in HeatMapPoints) { if (p.X >= extent2.XMin && p.Y >= extent2.YMin && p.X <= extent2.XMax && p.Y <= extent2.YMax) { points.Add(new HeatPoint() { X = (int)Math.Round((p.X - extent.XMin) / res), Y = (int)Math.Round((extent.YMax - p.Y) / res) }); } } //Start the render thread renderThread.RunWorkerAsync( new object[] { extent, width, height, this.Intensity, this.Resolution, stops, points, onComplete }); }
/// <summary> /// Stops loading of any pending images /// </summary> protected override void Cancel() { enqueueExport = null; enqueueOnComplete = null; if (renderThread != null && renderThread.IsBusy) { renderThread.CancelAsync(); } base.Cancel(); }
/// <summary> /// Handles the RunWorkerCompleted event of the renderThread control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.ComponentModel.RunWorkerCompletedEventArgs"/> instance containing the event data.</param> private void renderThread_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (e.Cancelled) { if (enqueueExport != null) //cancelled because new image was requested. Create new image { GetSource(enqueueExport, enqueueOnComplete); enqueueExport = null; enqueueOnComplete = null; } return; } enqueueExport = null; enqueueOnComplete = null; if (e.Result == null) { return; } object[] result = (object[])e.Result; int width = (int)result[1]; int height = (int)result[2]; Envelope extent = (Envelope)result[3]; OnImageComplete onComplete = (OnImageComplete)result[4]; #if SILVERLIGHT BitmapImage image = new BitmapImage(); PngEncoder ei = (PngEncoder)result[0]; image.SetSource(ei.GetImageStream()); #else List <Color> colors = new List <Color>(); colors.Add(Colors.Violet); colors.Add(Colors.Yellow); BitmapPalette palette = new BitmapPalette(colors); System.Windows.Media.PixelFormat pf = System.Windows.Media.PixelFormats.Bgra32; int stride = width * (pf.BitsPerPixel / 8); BitmapSource image = BitmapSource.Create(width, height, 96, 96, pf, palette, (int[])result[0], stride); #endif onComplete(image, new ImageResult(extent)); }
/// <summary> /// Gets the source image to display in the dynamic layer. Override this to generate /// or modify images. /// </summary> /// <param name="properties">The image export properties.</param> /// <param name="onComplete">The method to call when the image is ready.</param> /// <seealso cref="ESRI.ArcGIS.Client.DynamicLayer.OnProgress"/> protected override void GetSource(DynamicLayer.ImageParameters properties, DynamicLayer.OnImageComplete onComplete) { if (!IsInitialized || HeatMapPoints == null || HeatMapPoints.Count == 0) { onComplete(null, null); return; } Envelope extent = properties.Extent; int width = properties.Width; int height = properties.Height; if (renderThread != null && renderThread.IsBusy) { renderThread.CancelAsync(); //render already running. Cancel current process, and queue up new enqueueExport = new ImageParameters(extent, width, height); enqueueOnComplete = onComplete; return; } //Accessing a GradientStop collection from a non-UI thread is not allowed, //so we used a private class gradient collection List <ThreadSafeGradientStop> stops = new List <ThreadSafeGradientStop>(Gradient.Count); foreach (GradientStop stop in Gradient) { stops.Add(new ThreadSafeGradientStop() { Color = stop.Color, Offset = stop.Offset }); } //Gradients must be sorted by offset stops.Sort((ThreadSafeGradientStop g1, ThreadSafeGradientStop g2) => { return(g1.Offset.CompareTo(g2.Offset)); }); List <HeatPoint> points = new List <HeatPoint>(); double res = extent.Width / width; //adjust extent to include points slightly outside the view so pan won't affect the outcome Envelope extent2 = new Envelope(extent.XMin - Intensity * res, extent.YMin - Intensity * res, extent.XMax + Intensity * res, extent.YMax + Intensity * res); //get points within the extent and transform them to pixel space foreach (MapPoint p in HeatMapPoints) { if (Map != null && Map.WrapAroundIsActive) { // Note : this should work even if WrapAround is not active but it's probably less performant if (p.Y >= extent2.YMin && p.Y <= extent2.YMax) { Point screenPoint = Map.MapToScreen(p, true); if (!double.IsNaN(width) && Map.FlowDirection == FlowDirection.RightToLeft) { screenPoint.X = width - screenPoint.X; } if (screenPoint.X >= -Intensity && screenPoint.X <= width + Intensity) { points.Add(new HeatPoint() { X = (int)Math.Round(screenPoint.X), Y = (int)Math.Round(screenPoint.Y) }); } } } else { if (p.X >= extent2.XMin && p.Y >= extent2.YMin && p.X <= extent2.XMax && p.Y <= extent2.YMax) { points.Add(new HeatPoint() { X = (int)Math.Round((p.X - extent.XMin) / res), Y = (int)Math.Round((extent.YMax - p.Y) / res) }); } } } //Start the render thread renderThread.RunWorkerAsync( new object[] { extent, width, height, (int)Math.Round(this.Intensity), stops, points, onComplete }); }
protected override void GetSource(DynamicLayer.ImageParameters properties, DynamicLayer.OnImageComplete onComplete) { throw new NotImplementedException(); }
/// <summary> /// Handles the RunWorkerCompleted event of the renderThread control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.ComponentModel.RunWorkerCompletedEventArgs"/> instance containing the event data.</param> private void renderThread_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (e.Cancelled) { if (enqueueExport != null) //cancelled because new image was requested. Create new image { GetSource(enqueueExport, enqueueOnComplete); enqueueExport = null; enqueueOnComplete = null; } return; } enqueueExport = null; enqueueOnComplete = null; if (e.Result == null) return; object[] result = (object[])e.Result; int width = (int)result[1]; int height = (int)result[2]; Envelope extent = (Envelope)result[3]; OnImageComplete onComplete = (OnImageComplete)result[4]; #if SILVERLIGHT BitmapImage image = new BitmapImage(); PngEncoder ei = (PngEncoder)result[0]; image.SetSource(ei.GetImageStream()); #else List<Color> colors = new List<Color>(); colors.Add(Colors.Violet); colors.Add(Colors.Yellow); BitmapPalette palette = new BitmapPalette(colors); System.Windows.Media.PixelFormat pf = System.Windows.Media.PixelFormats.Bgra32; int stride = width * (pf.BitsPerPixel / 8); BitmapSource image = BitmapSource.Create(width, height, 96, 96, pf, palette, (int[])result[0], stride); #endif onComplete(image, new ImageResult(extent)); }
/// <summary> /// Gets the source image to display in the dynamic layer. Override this to generate /// or modify images. /// </summary> /// <param name="properties">The image export properties.</param> /// <param name="onComplete">The method to call when the image is ready.</param> /// <seealso cref="ESRI.ArcGIS.Client.DynamicLayer.OnProgress"/> protected override void GetSource(DynamicLayer.ImageParameters properties, DynamicLayer.OnImageComplete onComplete) { if (!IsInitialized || HeatMapPoints == null || HeatMapPoints.Count == 0) { onComplete(null, null); return; } Envelope extent = properties.Extent; int width = properties.Width; int height = properties.Height; if (renderThread != null && renderThread.IsBusy) { renderThread.CancelAsync(); //render already running. Cancel current process, and queue up new enqueueExport = new ImageParameters(extent, width, height); enqueueOnComplete = onComplete; return; } //Accessing a GradientStop collection from a non-UI thread is not allowed, //so we used a private class gradient collection List<ThreadSafeGradientStop> stops = new List<ThreadSafeGradientStop>(Gradient.Count); foreach (GradientStop stop in Gradient) { stops.Add(new ThreadSafeGradientStop() { Color = stop.Color, Offset = stop.Offset }); } //Gradients must be sorted by offset stops.Sort((ThreadSafeGradientStop g1, ThreadSafeGradientStop g2) => { return g1.Offset.CompareTo(g2.Offset); }); List<HeatPoint> points = new List<HeatPoint>(); double res = extent.Width / width; //adjust extent to include points slightly outside the view so pan won't affect the outcome Envelope extent2 = new Envelope(extent.XMin - Intensity * res, extent.YMin - Intensity * res, extent.XMax + Intensity * res, extent.YMax + Intensity * res); //get points within the extent and transform them to pixel space foreach (MapPoint p in HeatMapPoints) { if (Map != null && Map.WrapAroundIsActive) { // Note : this should work even if WrapAround is not active but it's probably less performant if (p.Y >= extent2.YMin && p.Y <= extent2.YMax) { Point screenPoint = Map.MapToScreen(p, true); if (!double.IsNaN(width) && Map.FlowDirection == FlowDirection.RightToLeft) screenPoint.X = width - screenPoint.X; if (screenPoint.X >= -Intensity && screenPoint.X <= width + Intensity) { points.Add(new HeatPoint() { X = (int)Math.Round(screenPoint.X), Y = (int)Math.Round(screenPoint.Y) }); } } } else { if (p.X >= extent2.XMin && p.Y >= extent2.YMin && p.X <= extent2.XMax && p.Y <= extent2.YMax) { points.Add(new HeatPoint() { X = (int)Math.Round((p.X - extent.XMin) / res), Y = (int)Math.Round((extent.YMax - p.Y) / res) }); } } } //Start the render thread renderThread.RunWorkerAsync( new object[] { extent, width, height, (int)Math.Round(this.Intensity), stops, points, onComplete }); }