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 System.Collections.Generic; using System.Collections.ObjectModel; using ThinkGeo.MapSuite.Core; namespace ClusterPointStyle { class ClusterPointStyle : PointStyle { private int cellSize = 100; private TextStyle textSytle = new TextStyle(); // These are all of the constructors from the original point style public ClusterPointStyle() : base() { } public ClusterPointStyle(GeoImage image) : base(image) { } public ClusterPointStyle(GeoFont characterFont, int characterIndex, GeoSolidBrush characterSolidBrush) : base(characterFont, characterIndex, characterSolidBrush) { } public ClusterPointStyle(PointSymbolType symbolType, GeoSolidBrush symbolSolidBrush, int symbolSize) : base(symbolType, symbolSolidBrush, symbolSize) { } public ClusterPointStyle(PointSymbolType symbolType, GeoSolidBrush symbolSolidBrush, GeoPen symbolPen, int symbolSize) : base(symbolType, symbolSolidBrush, symbolPen, symbolSize) { } // The TextStyle will be the label on the cluster. public TextStyle TextStyle { get { return textSytle; } set { textSytle = value; } } // This is in pixels and determines how the screen will be divided. The smaller the slower it runs public int CellSize { get { return cellSize; } set { cellSize = value; } } // Here in the DrawCore we cluster the features protected override void DrawCore(IEnumerable<Feature> features, GeoCanvas canvas, Collection<SimpleCandidate> labelsInThisLayer, Collection<SimpleCandidate> labelsInAllLayers) { // We get the scale to determine the grid. This scale property should really be on the Canvas! double scale = ExtentHelper.GetScale(canvas.CurrentWorldExtent, canvas.Width, canvas.MapUnit); // Setup our grid for clustering the points. This is where we specify our cell size in pixels MapSuiteTileMatrix mapSuiteTileMatrix = new MapSuiteTileMatrix(scale, cellSize, cellSize, canvas.MapUnit); // Pass in the current extent to get our grid cells. All points in these cells will be consolidated IEnumerable<TileMatrixCell> tileMatricCells = mapSuiteTileMatrix.GetContainedCells(canvas.CurrentWorldExtent); // Create an unused features list, as we add them to clusters we will remove them from here // This is just for speed so we don't re-test lots of already associated features Dictionary<string, string> unusedFeatures = new Dictionary<string, string>(); foreach (Feature feature in features) { unusedFeatures.Add(feature.Id, feature.Id); } // Loop through each cell and find the features that fit inside of it foreach (TileMatrixCell cell in tileMatricCells) { int featureCount = 0; MultipointShape multiPointShape = new MultipointShape(); foreach (Feature feature in features) { // Make sure the feature has not been used in another cluster if (unusedFeatures.ContainsKey(feature.Id)) { // Check if the cell contains the feature if (cell.BoundingBox.Contains(feature.GetBoundingBox())) { featureCount++; unusedFeatures.Remove(feature.Id); multiPointShape.Points.Add(feature.GetBoundingBox().GetCenterPoint()); } } } if (featureCount > 0) { // Add the feature count to the new feature we created. The feature will be placed // at the center of gravity of all the clustered features of the cell we created. Dictionary<string, string> featureValues = new Dictionary<string, string>(); featureValues.Add("FeatureCount", featureCount.ToString()); //Draw the point shape base.DrawCore(new Feature[] { new Feature(multiPointShape.GetCenterPoint(), featureValues) }, canvas, labelsInThisLayer, labelsInAllLayers); // Draw the text style to show how many feaures are consolidated in the cluster textSytle.Draw(new Feature[] { new Feature(multiPointShape.GetCenterPoint(), featureValues) }, canvas, labelsInThisLayer, labelsInAllLayers); } } } } }
using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; namespace ClusterPointStyle { static class Program { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new TestForm()); } } }
using System; using System.Drawing; using System.Windows.Forms; using ThinkGeo.MapSuite.Core; namespace ClusterPointStyle { public partial class TestForm : Form { private MapEngine mapEngine = new MapEngine(); private Bitmap bitmap = null; public TestForm() { InitializeComponent(); } private void TestForm_Load(object sender, EventArgs e) { // Set the full extent and the background color mapEngine.CurrentExtent = ExtentHelper.GetDrawingExtent(new RectangleShape(-180,64,-91,14), Map.Width, Map.Height); mapEngine.BackgroundFillBrush = new GeoSolidBrush(GeoColor.GeographicColors.ShallowOcean); // Add the static layers to the MapEngine ShapeFileFeatureLayer worldLayer = new ShapeFileFeatureLayer(@"..\..\Data\Countries02.shp", ShapeFileReadWriteMode.ReadOnly); worldLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.County1; worldLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; mapEngine.StaticLayers.Add("WorldLayer", worldLayer); //Adds the volcano layer representing each feature as a simple triangle symbol. ShapeFileFeatureLayer volcanoesLayer = new ShapeFileFeatureLayer(@"..\..\Data\volcanoes.shp", ShapeFileReadWriteMode.ReadOnly); volcanoesLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Clear(); volcanoesLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = PointStyles.CreateSimpleTriangleStyle(GeoColor.StandardColors.Orange, 8,GeoColor.StandardColors.Black); volcanoesLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; mapEngine.StaticLayers.Add("VolcanoesLayer", volcanoesLayer); //Adds the same volcano layer using the ClusterPointStyle. //It clusters all the features within a cell with a size determined in pixel into one triangle //symbol with the count labeled inside. ClusterPointStyle clusterPointStyle = new ClusterPointStyle(PointSymbolType.Triangle, new GeoSolidBrush(GeoColor.FromArgb(150, GeoColor.StandardColors.Orange)), new GeoPen(GeoColor.StandardColors.Red, 2), 27); clusterPointStyle.TextStyle = new TextStyle("FeatureCount", new GeoFont("Arial", 8), new GeoSolidBrush(GeoColor.StandardColors.Black)); clusterPointStyle.TextStyle.DuplicateRule = LabelDuplicateRule.UnlimitedDuplicateLabels; clusterPointStyle.TextStyle.PointPlacement = PointPlacement.Center; ShapeFileFeatureLayer clusterVolcanoesLayer = new ShapeFileFeatureLayer(@"..\..\Data\volcanoes.shp", ShapeFileReadWriteMode.ReadOnly); clusterVolcanoesLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Clear(); clusterVolcanoesLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(clusterPointStyle); clusterVolcanoesLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; mapEngine.StaticLayers.Add("ClusterVolcanoesLayer", clusterVolcanoesLayer); DrawImage(); } private void DrawImage() { if (bitmap != null) { bitmap.Dispose(); } bitmap = new Bitmap(Map.Width, Map.Height); mapEngine.OpenAllLayers(); mapEngine.DrawStaticLayers(bitmap, GeographyUnit.DecimalDegree); mapEngine.CloseAllLayers(); Map.Image = bitmap; } private void ToolBar_ButtonClick(object sender, ToolBarButtonClickEventArgs e) { switch (e.Button.Tag.ToString()) { case "Zoom In": mapEngine.CurrentExtent.ScaleDown(50); break; case "Zoom Out": mapEngine.CurrentExtent.ScaleUp(50); break; case "Full Extent": mapEngine.CurrentExtent = ExtentHelper.GetDrawingExtent(new RectangleShape(-180.0, 83.0, 180.0, -90.0), Map.Width, Map.Height); break; case "Pan Left": mapEngine.CurrentExtent = ExtentHelper.Pan(mapEngine.CurrentExtent, PanDirection.Left, 20); break; case "Pan Right": mapEngine.CurrentExtent = ExtentHelper.Pan(mapEngine.CurrentExtent, PanDirection.Right, 20); break; case "Pan Up": mapEngine.CurrentExtent = ExtentHelper.Pan(mapEngine.CurrentExtent, PanDirection.Up, 20); break; case "Pan Down": mapEngine.CurrentExtent = ExtentHelper.Pan(mapEngine.CurrentExtent, PanDirection.Down, 20); break; default: break; } DrawImage(); } private void btnClose_Click(object sender, EventArgs e) { this.Close(); } } }