/// <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)); }
void ISupportsDynamicImageByteRequests.GetImageData(DynamicLayer.ImageParameters properties, OnImageDataReceived onImageDataReceived) { OnImageComplete onImageComplete = (image, props) => { BitmapSource bitmapSource = image as BitmapSource; MemoryStream stream = new MemoryStream(); if (bitmapSource != null) { PngBitmapEncoder encoder = new PngBitmapEncoder(); encoder.Interlace = PngInterlaceOption.Off; encoder.Frames.Add(BitmapFrame.Create(bitmapSource)); encoder.Save(stream); stream.Seek(0, SeekOrigin.Begin); } onImageDataReceived(stream, props); }; GetSource(properties, onImageComplete); }
/// <summary> /// Gets the URL. Override from DynamicMapServiceLayer /// </summary> /// <param name="properties">The image export properties.</param> /// <param name="onComplete">OnUrlComplete delegate.</param> /// <remarks> /// The Map has a private method loadLayerInView which calls Layer.Draw. /// The DynamicMapServiceLayer abstract class overrides the Draw method and calls /// DynamicMapServiceLayer.GetUrl which must be implemented in a subclass. /// The last parameter is the OnUrlComplete delegate, which is used to pass the appropriate values /// (url, width, height, envelope) to the private DynamicMapServiceLayer.getUrlComplete method. /// </remarks> public override void GetUrl(DynamicLayer.ImageParameters properties, DynamicMapServiceLayer.OnUrlComplete onComplete) { Envelope extent = properties.Extent; int width = properties.Width; int height = properties.Height; int extentWKID = (extent.SpatialReference != null) ? extent.SpatialReference.WKID : 0; string baseUrl = MapUrl ?? Url; if (baseUrl == null) { onComplete(null, null); return; } StringBuilder mapURL = new StringBuilder(baseUrl); if (!baseUrl.Contains("?")) { mapURL.Append("?"); } else if (!baseUrl.EndsWith("&")) { mapURL.Append("&"); } mapURL.Append("SERVICE=WMS&REQUEST=GetMap"); mapURL.AppendFormat("&WIDTH={0}", width); mapURL.AppendFormat("&HEIGHT={0}", height); mapURL.AppendFormat("&FORMAT={0}", ImageFormat); mapURL.AppendFormat("&LAYERS={0}", Layers == null ? "" : String.Join(",", Layers)); mapURL.Append("&STYLES="); mapURL.AppendFormat("&BGCOLOR={0}", "0xFFFFFF"); mapURL.AppendFormat("&TRANSPARENT={0}", "TRUE"); mapURL.AppendFormat("&VERSION={0}", GetValidVersionNumber()); //If one of the WebMercator codes, change to a WKID supported by the service if (SupportedSpatialReferenceIDs != null && (extentWKID == 102100 || extentWKID == 102113 || extentWKID == 3857 || extentWKID == 900913)) { if (!SupportedSpatialReferenceIDs.Contains(extentWKID)) { if (SupportedSpatialReferenceIDs.Contains(3857)) { extentWKID = 3857; } else if (SupportedSpatialReferenceIDs.Contains(102100)) { extentWKID = 102100; } else if (SupportedSpatialReferenceIDs.Contains(102113)) { extentWKID = 102113; } else if (SupportedSpatialReferenceIDs.Contains(900913)) { extentWKID = 900913; } } } if (LowerThan13Version()) { mapURL.AppendFormat("&SRS=EPSG:{0}", extentWKID); mapURL.AppendFormat(CultureInfo.InvariantCulture, "&bbox={0},{1},{2},{3}", extent.XMin, extent.YMin, extent.XMax, extent.YMax); } else { mapURL.AppendFormat("&CRS=EPSG:{0}", extentWKID); if (UseLatLon(extentWKID)) { mapURL.AppendFormat(CultureInfo.InvariantCulture, "&BBOX={0},{1},{2},{3}", extent.YMin, extent.XMin, extent.YMax, extent.XMax); } else { mapURL.AppendFormat(CultureInfo.InvariantCulture, "&BBOX={0},{1},{2},{3}", extent.XMin, extent.YMin, extent.XMax, extent.YMax); } } onComplete(Utilities.PrefixProxy(ProxyUrl, mapURL.ToString()).AbsoluteUri, new ImageResult(new ESRI.ArcGIS.Client.Geometry.Envelope() { XMin = extent.XMin, YMin = extent.YMin, XMax = extent.XMax, YMax = extent.YMax })); }
/// <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 }); }
public override void GetUrl(DynamicLayer.ImageParameters properties, DynamicMapServiceLayer.OnUrlComplete onComplete) { throw new NotImplementedException(); }
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 }); }