====== Source Code OsmWorldMapKitExplorer.zip ====== ====Explorer.xaml.cs==== using System; using System.Collections.ObjectModel; using System.ComponentModel; using System.Configuration; using System.Globalization; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using ThinkGeo.MapSuite.Core; using ThinkGeo.MapSuite.WpfDesktopEdition; namespace OsmWorldMapKitExplorer { public partial class Explorer : Window { ObservableCollection layerRenderStats = new ObservableCollection(); GridViewColumnHeader lastHeaderClicked = null; ListSortDirection lastSortDirection = ListSortDirection.Ascending; public Explorer() { InitializeComponent(); } private void LayoutRoot_Loaded(object sender, RoutedEventArgs e) { // Create our new OsmWorldMapKit Layer OsmWorldMapKitLayer osmWorldMapKitLayer = GetLayerByDatabaseType(); osmWorldMapKitLayer.Open(); // Setup the overlay LayerOverlay layerOverlay = new LayerOverlay(); layerOverlay.TileType = TileType.SingleTile; layerOverlay.LockLayerMode = LockLayerMode.DoNotLock; layerOverlay.Layers.Add(osmWorldMapKitLayer); // Setup the map Map1.MapUnit = GeographyUnit.Meter; Map1.CurrentExtent = RectangleShape.ScaleDown(osmWorldMapKitLayer.Layers["osm_road_linestring"].GetBoundingBox(),50).GetBoundingBox(); Map1.MapTools.ScaleLine.IsEnabled = true; Map1.BackgroundOverlay.BackgroundBrush = new GeoSolidBrush(GeoColor.FromArgb(255, 172, 205, 226)); // Add the overlay to the map Map1.Overlays.Add("worldmapkit", layerOverlay); // Setup the layer stats grid layerStatsList.Items.Clear(); layerStatsList.ItemsSource = layerRenderStats; Map1.Refresh(); } private void Map1_OverlayDrawn(object sender, OverlayDrawnWpfMapEventArgs e) { if (e.Overlay.GetType() == typeof(LayerOverlay)) { LayerOverlay layerOverlay = (LayerOverlay)e.Overlay; OsmWorldMapKitLayer osmWorldMapKitLayer = (OsmWorldMapKitLayer)layerOverlay.Layers[0]; // Get the stats from each layer that rendered for the grid LayerStats totalLayerStats = new LayerStats(); layerRenderStats.Clear(); foreach (FeatureLayer layer in osmWorldMapKitLayer.Layers) { // Update the stats for one layer LayerStats layerStats = new LayerStats() { LayerName = layer.Name, DrawingTime = Math.Round(layer.DrawingTime.TotalSeconds, 2), FetchTime = Math.Round(((SqliteFeatureSource)layer.FeatureSource).FetchTime / 1000, 2), TotalBytes = ((SqliteFeatureSource)layer.FeatureSource).TotalBytesDrawn, TotalFeatures = ((SqliteFeatureSource)layer.FeatureSource).DrawnFeatureCount, TotalBytesFormatted = BytesToString(((SqliteFeatureSource)layer.FeatureSource).TotalBytesDrawn), TotalFeaturesFormatted = ((SqliteFeatureSource)layer.FeatureSource).DrawnFeatureCount.ToString("n0", CultureInfo.InvariantCulture) }; if (layerStats.DrawingTime != 0) { layerRenderStats.Add(layerStats); // Add to total stats for the statusbar totalLayerStats.DrawingTime += layerStats.DrawingTime; totalLayerStats.FetchTime += layerStats.FetchTime; totalLayerStats.TotalBytes += layerStats.TotalBytes; totalLayerStats.TotalFeatures += layerStats.TotalFeatures; } } // Update the statusbar StatusBar.Items[0] = "Total Render Time: " + Math.Round(totalLayerStats.DrawingTime, 2).ToString(); StatusBar.Items[2] = "Total Fetch Time: " + Math.Round(totalLayerStats.FetchTime, 2).ToString(); StatusBar.Items[4] = "Total Features: " + totalLayerStats.TotalFeatures.ToString("n0", CultureInfo.InvariantCulture); StatusBar.Items[6] = "Total Bytes: " + BytesToString(totalLayerStats.TotalBytes); // Update the zoom level box for (int i = 0; i < Map1.ZoomLevelSet.GetZoomLevels().Count; i++) { if (Map1.CurrentScale == Map1.ZoomLevelSet.GetZoomLevels()[i].Scale) { GoToZoomLevel.Value = i + 1; } } } } private void btnGo_Click(object sender, RoutedEventArgs e) { int zoomLevelValue = (int)GoToZoomLevel.Value; Map1.ZoomToScale(Map1.ZoomLevelSet.GetZoomLevels()[zoomLevelValue|- 1].Scale); } private void btnAdd_Click(object sender, RoutedEventArgs e) { Map1.ZoomIn(); } private void btnSub_Click(object sender, RoutedEventArgs e) { Map1.ZoomOut(); } private void btnDallas_Click(object sender, RoutedEventArgs e) { Map1.CurrentExtent = new RectangleShape(-12541720.9791664, 5306835.34485512, -9009727.61128801, 2425472.3342175); Map1.Refresh(); } private void btnLondon_Click(object sender, RoutedEventArgs e) { Map1.CurrentExtent = new RectangleShape(-1785915.62939165, 8154571.52149373, 1746077.73848672, 5273208.51085611); Map1.Refresh(); } private void btnShanghai_Click(object sender, RoutedEventArgs e) { Map1.CurrentExtent = new RectangleShape(11778565.4791326, 5104283.10089011, 15310558.847011, 2222920.09025249); Map1.Refresh(); } private void chkSingleTileMode_Checked(object sender, RoutedEventArgs e) { if (Map1.Overlays.Count > 0) { LayerOverlay layerOverlay = (LayerOverlay)Map1.Overlays["worldmapkit"]; if (layerOverlay.TileType == TileType.MultipleTile) { layerOverlay.TileType = TileType.SingleTile; Map1.Refresh(); } } } private void chkSingleTileMode_Unchecked(object sender, RoutedEventArgs e) { LayerOverlay layerOverlay = (LayerOverlay)Map1.Overlays["worldmapkit"]; if (layerOverlay.TileType == TileType.SingleTile) { layerOverlay.TileType = TileType.MultipleTile; Map1.Refresh(); } } private void Rdo_DecimalDegrees_Checked(object sender, RoutedEventArgs e) { if (Map1.MapUnit != GeographyUnit.DecimalDegree) { Proj4Projection proj = new Proj4Projection(3857, 4326); proj.Open(); RectangleShape newExtent = proj.ConvertToExternalProjection(Map1.CurrentExtent); proj.Close(); LayerOverlay layerOverlay = (LayerOverlay)Map1.Overlays["worldmapkit"]; OsmWorldMapKitLayer osmWorldMapKitLayer = (OsmWorldMapKitLayer)layerOverlay.Layers[0]; foreach (FeatureLayer layer in osmWorldMapKitLayer.Layers) { Proj4Projection layerProj = new Proj4Projection(3857, 4326); layer.FeatureSource.Projection = layerProj; layer.FeatureSource.Projection.Open(); } Map1.MapUnit = GeographyUnit.DecimalDegree; Map1.CurrentExtent = newExtent; Map1.Refresh(); } } private void Rdo_SphericalMercator_Checked(object sender, RoutedEventArgs e) { if (Map1.MapUnit != GeographyUnit.Meter) { Proj4Projection proj = new Proj4Projection(4326, 3857); proj.Open(); RectangleShape tempExtent = proj.ConvertToExternalProjection(Map1.CurrentExtent); proj.Close(); LayerOverlay layerOverlay = (LayerOverlay)Map1.Overlays["worldmapkit"]; OsmWorldMapKitLayer osmWorldMapKitLayer = (OsmWorldMapKitLayer)layerOverlay.Layers[0]; foreach (FeatureLayer layer in osmWorldMapKitLayer.Layers) { Proj4Projection layerProj = new Proj4Projection(3857, 3857); layer.FeatureSource.Projection = layerProj; layer.FeatureSource.Projection.Open(); } Map1.MapUnit = GeographyUnit.Meter; Map1.CurrentExtent = tempExtent; Map1.Refresh(); } } void GridViewColumnHeaderClickedHandler(object sender, RoutedEventArgs e) { GridViewColumnHeader headerClicked = e.OriginalSource as GridViewColumnHeader; ListSortDirection direction; if (headerClicked != null) { if (headerClicked.Role != GridViewColumnHeaderRole.Padding) { if (headerClicked != lastHeaderClicked) direction = ListSortDirection.Ascending; else { if (lastSortDirection == ListSortDirection.Ascending) direction = ListSortDirection.Descending; else direction = ListSortDirection.Ascending; } string header = headerClicked.Column.Header as string; // Sort ICollectionView dataView = CollectionViewSource.GetDefaultView(layerStatsList.ItemsSource); dataView.SortDescriptions.Clear(); SortDescription sd = new SortDescription(header.Replace("Formatted", ""), direction); dataView.SortDescriptions.Add(sd); dataView.Refresh(); if (direction == ListSortDirection.Ascending) { headerClicked.Column.HeaderTemplate = Resources["HeaderTemplateArrowUp"] as DataTemplate; } else { headerClicked.Column.HeaderTemplate = Resources["HeaderTemplateArrowDown"] as DataTemplate; } // Remove arrow from previously sorted header if (lastHeaderClicked != null && lastHeaderClicked != headerClicked) { lastHeaderClicked.Column.HeaderTemplate = null; } lastHeaderClicked = headerClicked; lastSortDirection = direction; } } } private static OsmWorldMapKitLayer GetLayerByDatabaseType() { OsmWorldMapKitLayer result = null; if (ConfigurationManager.AppSettings["DatabaseType"] == "sqlite") { result = new OsmWorldMapKitLayer(ConfigurationManager.AppSettings["SqliteConnectionString"], OsmWorldMapKitDatabaseType.Sqlite); } else if (ConfigurationManager.AppSettings["DatabaseType"] == "postgres") { result = new OsmWorldMapKitLayer(ConfigurationManager.AppSettings["PostgresConnectionString"], OsmWorldMapKitDatabaseType.Postgres); } else { throw new Exception("Invalid DatabaseType in app.config"); } return result; } private String BytesToString(long byteCount) { string[] suf = { "B", "KB", "MB", "GB", "TB", "PB", "EB" }; if (byteCount == 0) return "0" + suf[0]; long bytes = Math.Abs(byteCount); int place = Convert.ToInt32(Math.Floor(Math.Log(bytes, 1024))); double num = Math.Round(bytes / Math.Pow(1024, place), 1); return (Math.Sign(byteCount) * num).ToString() + suf[place]; } } } ====LayerStates.cs==== namespace OsmWorldMapKitExplorer { public class LayerStats { public double FetchTime { get; set; } public double DrawingTime { get; set; } public string LayerName { get; set; } public string StyleName { get; set; } public string TotalBytesFormatted { get; set; } public string TotalFeaturesFormatted { get; set; } public long TotalBytes { get; set; } public double TotalFeatures { get; set; } } }