/// <summary> </summary> /// <param name="left"></param> /// <param name="top"></param> /// <param name="right"></param> /// <param name="bottom"></param> /// <param name="width"></param> /// <param name="height"></param> /// <returns></returns> public Stream GetImageStream(double left, double top, double right, double bottom, int width, int height) { var bitmap = new Bitmap(width, height); var graphics = Graphics.FromImage(bitmap); int symbolRadius = SymbolSize / 2; foreach (var location in Locations) { System.Windows.Point mercatorPoint = GeoTransform.WGSToPtvMercator( new System.Windows.Point(location.Longitude, location.Latitude)); var pixelPoint = new Point( (int)((mercatorPoint.X - left) / (right - left) * width), (int)((mercatorPoint.Y - bottom) / (top - bottom) * height)); if (pixelPoint.X < -symbolRadius || pixelPoint.X > width + symbolRadius || pixelPoint.Y < -symbolRadius || pixelPoint.Y > height + symbolRadius) { continue; } graphics.FillEllipse(new SolidBrush(Color.FromArgb(SymbolColor.A, SymbolColor.R, SymbolColor.G, SymbolColor.B)), pixelPoint.X - symbolRadius, pixelPoint.Y - symbolRadius, SymbolSize, SymbolSize); } var memoryStream = new MemoryStream(); bitmap.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Png); memoryStream.Seek(0, SeekOrigin.Begin); // goto stream begin return(memoryStream); }
/// <summary> Reads the earthquakes from a csv file and adds them to a clusterer. The clusterer then groups /// them to clusters. </summary> /// <returns> Documentation in progress... </returns> public static TileBasedPointClusterer <Post> ReadCSVFile() { var clusterer = new TileBasedPointClusterer <Post>(MapView.LogicalSize, 0, 19); var filePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources\ClusterData") + @"\wikilocations.csv"; using (var reader = new CsvFileReader(filePath, (char)0x09)) { var row = new CsvRow(); while (reader.ReadRow(row)) { if (row.Count < 3) { continue; } double x, y; bool parsed = Double.TryParse(row[2], NumberStyles.Float, CultureInfo.InvariantCulture, out x); x = parsed ? x : Double.NaN; parsed = Double.TryParse(row[1], NumberStyles.Float, CultureInfo.InvariantCulture, out y); y = parsed ? y : Double.NaN; var post = new Post { Title = row[0], Location = new Point(x, y) }; post.TransformedLocation = GeoTransform.WGSToPtvMercator(post.Location); clusterer.AddPoint(post.TransformedLocation.X, post.TransformedLocation.Y, 1, post); } } #region doc:clusterer.Cluster method call clusterer.Cluster(); return(clusterer); #endregion //doc:clusterer.Cluster method call }
private void addSymbol(Point coordinate, Symbol symbol, ScaleTransform adjustTransform) { // create button and set pin template var image = new Image { // create cached bimap Source = createBitmap(symbol), // scale around center RenderTransformOrigin = new Point(.5, .5), // set render transform for scaling RenderTransform = adjustTransform, }; image.Width = image.Height = symbol.Size; // set tool tip information ToolTipService.SetToolTip(image, symbol.Tooltip); // tranform to map coordinates var mercatorPoint = GeoTransform.WGSToPtvMercator(coordinate); // set position and add to canvas (invert y-ordinate) SetLeft(image, mercatorPoint.X - image.Width / 2); SetTop(image, -(mercatorPoint.Y + image.Height / 2)); Children.Add(image); }
/// <summary> Converts a geographic point to a canvas point. </summary> /// <param name="geoPoint"> The geographic point. </param> /// <returns> The canvas point. </returns> public Point GeoToCanvas(Point geoPoint) { return(PtvMercatorToCanvas(GeoTransform.WGSToPtvMercator(geoPoint))); }
/// <summary> Reads the earthquakes from an xml file and adds a pin element for each to the map. </summary> private void ParseAtomUsingLinq() { System.Xml.Linq.XDocument feedXML = System.Xml.Linq.XDocument.Load("http://earthquake.usgs.gov/earthquakes/catalogs/7day-M2.5.xml"); System.Xml.Linq.XNamespace xmlns = "http://www.w3.org/2005/Atom"; //Atom namespace System.Xml.Linq.XNamespace georssns = "http://www.georss.org/georss"; //GeoRSS Namespace // time to learn some LINQ var posts = (from item in feedXML.Descendants(xmlns + "entry") select new { Title = item.Element(xmlns + "title").Value, Published = DateTime.Parse(item.Element(xmlns + "updated").Value), Url = item.Element(xmlns + "link").Attribute("href").Value, Description = item.Element(xmlns + "summary").Value, Location = CoordinateGeoRssPoint(item.Element(georssns + "point")), //Simple GeoRSS <georss:point>X Y</georss.point> }).ToList(); int i = 0; // order posts by latitude, so they overlap nicely on the map foreach (var post in from post in posts orderby post.Location.Y descending select post) { if (!double.IsNaN(post.Location.X) && !double.IsNaN(post.Location.Y)) { // transform wgs to PTVMercator coordinate var mapPoint = GeoTransform.WGSToPtvMercator(post.Location); // create button and set pin template var pin = new Pin { // a bug in SL throws an obscure exception if children share the same name // http://forums.silverlight.net/forums/t/134299.aspx // the name is needed in XAML for data binding, so just create a unique name at runtime Name = "pin" + (i++), // set render transform for power-law scaling RenderTransform = adjustTransform, // scale around lower right RenderTransformOrigin = new System.Windows.Point(1, 1) }; // set size by magnitude double magnitude = MagnitudeFromTitle(post.Title); pin.Height = magnitude * 10; pin.Width = magnitude * 10; // calculate a value between 0 and 1 and use it for a blend color double relativeDanger = Math.Max(0, Math.Min(1, (magnitude - 2.5) / 4)); pin.Color = Colors.Red; pin.Color = ColorBlend.Danger.GetColor((float)relativeDanger); // set tool tip information ToolTipService.SetToolTip(pin, post.Title); // set position and add to canvas (invert y-ordinate) // set lower right (pin-tip) as position SetLeft(pin, mapPoint.X - pin.Width); SetTop(pin, -(mapPoint.Y + pin.Height)); Children.Add(pin); } } }