ThinkGeo Cloud
ThinkGeo UI Controls
ThinkGeo Open Source
Help and Support
External Resources
ThinkGeo Cloud
ThinkGeo UI Controls
ThinkGeo Open Source
Help and Support
External Resources
using DynamicMarkerOverlay.NaFacilityService; using System; using System.Collections.ObjectModel; using System.Drawing; using System.Drawing.Imaging; using System.Globalization; using System.IO; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Forms; using System.Windows.Input; using System.Windows.Media.Imaging; using ThinkGeo.MapSuite.Core; using ThinkGeo.MapSuite.WpfDesktopEdition; using ZedGraph; namespace DynamicMarkerOverlay { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); // Create a timer which is used to retrive the data from a webservice to update the warehouses. Timer dataRetriveTimer = new Timer() { Enabled = true, Interval = 5000 // By default, it will refresh data per hour }; dataRetriveTimer.Tick += (sender, e) => { using (var client = new DataServiceClient("defaultDataService")) { // Retrive the data from service FacilityModel[] facilities = client.GetFacilities(); // Apply the retrived data to InMemoryFeatureSource which is for warehouses. foreach (FacilityModel model in facilities) { FeatureSourceMarkerOverlay facilitiesOverlay = Map1.Overlays["FacilitiesOverlay"] as FeatureSourceMarkerOverlay; InMemoryFeatureSource factilityFeatureSource = facilitiesOverlay.FeatureSource as InMemoryFeatureSource; Feature feature = factilityFeatureSource.InternalFeatures.Where(v => v.ColumnValues["Airport Code"] == model.AirportCode).FirstOrDefault(); feature.ColumnValues["Packages"] = model.Packages.ToString(CultureInfo.InvariantCulture); feature.ColumnValues["AverageP"] = model.PackageAverage.ToString(CultureInfo.InvariantCulture); } } Dispatcher.BeginInvoke(new Action(() => Map1.Refresh())); }; } private void Map1_Loaded(object sender, RoutedEventArgs e) { Map1.MapUnit = GeographyUnit.DecimalDegree; // Load ThinkGeo Map Suite World Map Kit as base map. WorldMapKitWmsWpfOverlay worldOverlay = new WorldMapKitWmsWpfOverlay(); Map1.Overlays.Add("WMK", worldOverlay); // Import the data into a InMemoryFeatureLayer with limited data, becuase we need to update its column value on the fly. ShapeFileFeatureSource shapeFileFeatureSource = new ShapeFileFeatureSource(@"..\..\App_Data\Facilities.shp"); shapeFileFeatureSource.Open(); InMemoryFeatureSource facilitiesFeatureSource = new InMemoryFeatureSource(shapeFileFeatureSource.GetColumns(), shapeFileFeatureSource.GetAllFeatures(ReturningColumnsType.AllColumns)); shapeFileFeatureSource.Close(); // Create a FeatureSourceMarkerOverlay to display Na-Factilities from InMemoryFeatureSource, which // is created from a shape file "Facilities.shp", it is converted from the "NA-Facitlities.xlsx". // The data convert can be managed by following steps: // 1. Save the *.xlsx as *.csv with Microsoft Office. // 2. Load *.csv into Map Suite GisEditor, and then export it to *.shp. ClickableFeatureSourceMarkerOverlay facilitiesOverlay = new ClickableFeatureSourceMarkerOverlay(); facilitiesOverlay.MarkerMouseClick += FacilitiesOverlay_MarkerMouseClick; facilitiesOverlay.FeatureSource = facilitiesFeatureSource; // Create the classbreak style with different colors based on the packages. ClassBreakMarkerStyle facilitiesStyle = new ClassBreakMarkerStyle("Packages"); MarkerClassBreak lessBreak = new MarkerClassBreak(0, new PointMarkerStyle(new BitmapImage(new Uri(@"pack://application:,,,/image/Green_warehouse.png")))); facilitiesStyle.ClassBreaks.Add(lessBreak); MarkerClassBreak greaterBreak = new MarkerClassBreak(10000, new PointMarkerStyle(new BitmapImage(new Uri(@"pack://application:,,,/image/Red_warehouse.png")))); facilitiesStyle.ClassBreaks.Add(greaterBreak); facilitiesOverlay.ZoomLevelSet.ZoomLevel01.CustomMarkerStyle = facilitiesStyle; facilitiesOverlay.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; Map1.Overlays.Add("FacilitiesOverlay", facilitiesOverlay); // Create a popup for showing message. PopupOverlay popupOverlay = new PopupOverlay(); Map1.Overlays.Add("MessagePopup", popupOverlay); // Set the map zoom to the extent of all the facilities at the startup. facilitiesOverlay.FeatureSource.Open(); Map1.CurrentExtent = facilitiesOverlay.FeatureSource.GetBoundingBox(); facilitiesOverlay.FeatureSource.Close(); Map1.Refresh(); } private void FacilitiesOverlay_MarkerMouseClick(object sender, MouseButtonEventArgs e) { Marker marker = sender as Marker; FeatureSourceMarkerOverlay facilitiesOverlay = Map1.Overlays["FacilitiesOverlay"] as FeatureSourceMarkerOverlay; facilitiesOverlay.FeatureSource.Open(); Collection<Feature> selectedFeatures = facilitiesOverlay.FeatureSource.GetFeaturesNearestTo(new PointShape(marker.Position.X, marker.Position.Y), Map1.MapUnit, 1, ReturningColumnsType.AllColumns); facilitiesOverlay.FeatureSource.Close(); if (selectedFeatures.Count > 0) { PopupOverlay popupOverlay = (PopupOverlay)Map1.Overlays["MessagePopup"]; Popup popup = new Popup(marker.Position); Feature feature = selectedFeatures[0]; popup.Content = CreatePopup(selectedFeatures[0]); popup.FontSize = 12d; popupOverlay.Popups.Clear(); popupOverlay.Popups.Add(popup); popupOverlay.Refresh(); } } private ContentControl CreatePopup(Feature feature) { ContentControl content = new ContentControl(); Grid panel = new Grid(); panel.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(120)}); panel.ColumnDefinitions.Add(new ColumnDefinition()); content.Content = panel; System.Windows.Controls.Image image = new System.Windows.Controls.Image() { Width = 120, Height = 100 }; panel.Children.Add(image); Grid.SetColumn(image, 0); using (Stream ms = CreateImageStream(feature)) { BitmapImage bitmap = new BitmapImage(); bitmap.BeginInit(); bitmap.CacheOption = BitmapCacheOption.OnLoad; bitmap.StreamSource = ms; bitmap.EndInit(); bitmap.Freeze(); image.Source = bitmap; } TextBlock desc = new TextBlock() { TextWrapping = TextWrapping.WrapWithOverflow}; panel.Children.Add(desc); Grid.SetColumn(desc, 1); StringBuilder info = new StringBuilder(); info.AppendLine(String.Format(CultureInfo.InvariantCulture, "Airport Code:\t{0}", feature.ColumnValues["Airport Code"].Trim())); info.AppendLine(String.Format(CultureInfo.InvariantCulture, "Address:\t{0}, {1}\t", feature.ColumnValues["Address1"].Trim(), feature.ColumnValues["Description"].Trim())); info.AppendLine(String.Format(CultureInfo.InvariantCulture, "Packages:\t{0}", feature.ColumnValues["Packages"].Trim())); info.AppendLine(String.Format(CultureInfo.InvariantCulture, "AveragePackages:\t{0}", feature.ColumnValues["AverageP"].Trim())); desc.Text = info.ToString(); return content; } /// <summary> /// Create the Chart using ZedGraph based on feature's columns. /// </summary> /// <param name="feature"></param> /// <returns></returns> private Stream CreateImageStream(Feature feature) { MemoryStream ms = new MemoryStream(); ZedGraphControl grapControl = new ZedGraphControl(); GraphPane myPane = grapControl.GraphPane; myPane.YAxis.Title.Text = "Account"; string[] labels = { "Packages", "AveragePackages" }; double[] y = { Convert.ToInt32(feature.ColumnValues["Packages"], CultureInfo.InvariantCulture), Convert.ToInt32(feature.ColumnValues["AverageP"], CultureInfo.InvariantCulture) }; BarItem myBar = myPane.AddBar("", null, y, Color.Green); myBar.Bar.Fill = new Fill(Color.Green, Color.Green, Color.Green); myPane.XAxis.Scale.TextLabels = labels; myPane.XAxis.Type = AxisType.Text; myPane.AxisChange(); System.Drawing.Image image = grapControl.GetImage(); image.Save(ms, ImageFormat.Png); return ms; } } }
using System.Windows.Input; using ThinkGeo.MapSuite.Core; using ThinkGeo.MapSuite.WpfDesktopEdition; namespace DynamicMarkerOverlay { public class ClickableFeatureSourceMarkerOverlay : FeatureSourceMarkerOverlay { public event MouseButtonEventHandler MarkerMouseDown; public event MouseButtonEventHandler MarkerMouseUp; public event MouseButtonEventHandler MarkerMouseClick; public event MouseEventHandler MarkerMouseMove; protected override GeoCollection<Marker> GetMarkersForDrawingCore(RectangleShape boundingBox) { GeoCollection<Marker> markers = base.GetMarkersForDrawingCore(boundingBox); foreach(Marker marker in markers) { marker.MarkerMouseClick -= MarkerMouseClick; marker.MarkerMouseClick += MarkerMouseClick; marker.MarkerMouseDown -= MarkerMouseDown; marker.MarkerMouseDown += MarkerMouseDown; marker.MarkerMouseUp -= MarkerMouseUp; marker.MarkerMouseUp += MarkerMouseUp; marker.MarkerMouseMove -= MarkerMouseMove; marker.MarkerMouseMove += MarkerMouseMove; } return markers; } protected virtual void OnMarkerMouseDown(MouseButtonEventArgs e) { MouseButtonEventHandler handler = MarkerMouseDown; if (handler != null) handler(this, e); } protected virtual void OnMarkerMouseUp(MouseButtonEventArgs e) { MouseButtonEventHandler handler = MarkerMouseUp; if (handler != null) handler(this, e); } protected virtual void OnMarkerMouseClick(MouseButtonEventArgs e) { MouseButtonEventHandler handler = MarkerMouseClick; if (handler != null) handler(this, e); } protected virtual void OnMarkerMouseMove(MouseEventArgs e) { MouseEventHandler handler = MarkerMouseMove; if (handler != null) handler(this, e); } } }
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Globalization; using System.Windows.Input; using ThinkGeo.MapSuite.Core; using ThinkGeo.MapSuite.WpfDesktopEdition; namespace DynamicMarkerOverlay { public class ClassBreakMarkerStyle : MarkerStyle { private string columnName; private BreakValueInclusion breakValueInclusion; private Collection<MarkerClassBreak> classBreaks; public ClassBreakMarkerStyle() : this(String.Empty, BreakValueInclusion.IncludeValue, new Collection<MarkerClassBreak>()) { } public ClassBreakMarkerStyle(string columnName) : this(columnName, BreakValueInclusion.IncludeValue, new Collection<MarkerClassBreak>()) { } public ClassBreakMarkerStyle(string columnName, BreakValueInclusion breakValueInclusion) : this(columnName, breakValueInclusion, new Collection<MarkerClassBreak>()) { } public ClassBreakMarkerStyle(string columnName, BreakValueInclusion breakValueInclusion, Collection<MarkerClassBreak> classBreaks) : base() { this.columnName = columnName; this.breakValueInclusion = breakValueInclusion; this.classBreaks = classBreaks; } public string ColumnName { get { return columnName; } set { columnName = value; } } public BreakValueInclusion BreakValueInclusion { get { return breakValueInclusion; } set { breakValueInclusion = value; } } public Collection<MarkerClassBreak> ClassBreaks { get { return classBreaks; } } public override GeoCollection<Marker> GetMarkers(IEnumerable<Feature> features) { GeoCollection<Marker> returnMarkers = new GeoCollection<Marker>(); foreach (Feature feature in features) { double columnValue = double.Parse(feature.ColumnValues[ColumnName].Trim(), CultureInfo.InvariantCulture); MarkerClassBreak classBreak = GetClassBreak(columnValue); if (classBreak != null) { Collection<Marker> tempMarkers = classBreak.DefaultMarkerStyle.GetMarkers(new Collection<Feature>() { feature }); foreach (Marker marker in tempMarkers) { // To make sure the cursor is pointer when move mouse to marker, use the events as following to change cursor marker.Cursor = Cursors.Hand; returnMarkers.Add(marker); } } } return returnMarkers; } private MarkerClassBreak GetClassBreak(double breakValue) { MarkerClassBreak result = classBreaks[classBreaks.Count - 1]; if (breakValueInclusion == BreakValueInclusion.IncludeValue) { if (breakValue < classBreaks[0].Value) { return null; } for (int i = 1; i < classBreaks.Count; i++) { if (breakValue < classBreaks[i].Value) { result = classBreaks[i - 1]; break; } else if (breakValue == classBreaks[i].Value) { result = classBreaks[i]; break; } } } else { if (breakValue <= classBreaks[0].Value) { return null; } for (int i = 1; i < classBreaks.Count; i++) { if (breakValue < classBreaks[i].Value) { result = classBreaks[i - 1]; break; } } } return result; } } }
using System; using ThinkGeo.MapSuite.WpfDesktopEdition; namespace DynamicMarkerOverlay { public class MarkerClassBreak { private double breakValue; private PointMarkerStyle defaultMarkerStyle; public MarkerClassBreak() : this(Double.MinValue, new PointMarkerStyle()) { } public MarkerClassBreak(double value, PointMarkerStyle markerStyle) { this.breakValue = value; this.DefaultMarkerStyle = markerStyle; } public double Value { get { return breakValue; } set { breakValue = value; } } public PointMarkerStyle DefaultMarkerStyle { get { if (defaultMarkerStyle == null) { defaultMarkerStyle = new PointMarkerStyle(); } return defaultMarkerStyle; } set { defaultMarkerStyle = value; } } } }