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 Newtonsoft.Json; using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Web; using System.Web.Http; using System.Web.SessionState; using ThinkGeo.MapSuite.Core; using ThinkGeo.MapSuite.WebApiEdition; namespace Visualization.Controllers { [RoutePrefix("tile")] public class VisualizationController : ApiController { // Initialize the overlays for drawing, which is cached for whole website. private static Dictionary<string, LayerOverlay> cachedOverlays = new Dictionary<string, LayerOverlay>() { {"HeatStyle", OverlayBuilder.GetOverlayWithHeatStyle()}, {"ClassBreakStyle", OverlayBuilder.GetOverlayWithClassBreakStyle()}, {"DotDensityStyle", OverlayBuilder.GetOverlayWithDotDensityStyle()}, {"IsolineStyle", OverlayBuilder.GetOverlayWithIsoLineStyle()}, {"ClusterStyle", OverlayBuilder.GetOverlayWithClusterPointStyle()}, {"ZedGraphStyle", OverlayBuilder.GetOverlayWithZedGraphStyle()}, {"IconStyle", OverlayBuilder.GetOverlayWithIconStyle()}, {"CustomStyle", OverlayBuilder.GetOverlayWithCustomeStyle()} }; // Initialize the filter expression. private static Dictionary<string, Tuple<string, string>> filterExpressions = new Dictionary<string, Tuple<string, string>>() { {"GreaterThanOrEqualTo", new Tuple<string, string>(">=", string.Empty)}, {"GreaterThan", new Tuple<string, string>(">", string.Empty)}, {"LessThanOrEqualTo", new Tuple<string, string>("<=", string.Empty)}, {"LessThan", new Tuple<string, string>("<", string.Empty)}, {"Equal", new Tuple<string, string>("^", "$")}, {"DoesNotEqual", new Tuple<string, string>("^(?!", ").*?$")} }; [Route("{layerId}/{z}/{x}/{y}")] public HttpResponseMessage GetTile(string layerId, int z, int x, int y) { // Create the LayerOverlay for displaying the map. LayerOverlay layerOverlay = GetDrawingOverlay(layerId); // Draw the map and return the image back to client in an HttpResponseMessage. using (Bitmap bitmap = new Bitmap(256, 256)) { GdiPlusGeoCanvas geoCanvas = new GdiPlusGeoCanvas(); RectangleShape boundingBox = WebApiExtentHelper.GetBoundingBoxForXyz(x, y, z, GeographyUnit.Meter); geoCanvas.BeginDrawing(bitmap, boundingBox, GeographyUnit.Meter); layerOverlay.Draw(geoCanvas); geoCanvas.EndDrawing(); MemoryStream memoryStream = new MemoryStream(); bitmap.Save(memoryStream, ImageFormat.Png); HttpResponseMessage responseMessage = new HttpResponseMessage(HttpStatusCode.OK); responseMessage.Content = new ByteArrayContent(memoryStream.ToArray()); responseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png"); return responseMessage; } } [Route("UpdateFilterStyle/")] [HttpPost] public bool UpdateFilterStyle([FromBody] string postData) { // Parse the post data from client side in JSON format. // There are 2 parameters included in the "postData", one is the filterExpression and another one is the value for filter. Dictionary<string, string> parameters = JsonConvert.DeserializeObject<Dictionary<string, string>>(postData); string filterExpression = parameters["filterExpression"]; string filterValue = parameters["filterValue"]; bool updateResult = false; LayerOverlay layerOverlay = GetDrawingOverlay("FilterStyle"); if (filterExpressions.ContainsKey(filterExpression) && layerOverlay.Layers.Count > 0) { // Get the filter style applied to the drawing Overlay. FilterStyle filterStyle = ((FeatureLayer)layerOverlay.Layers[0]).ZoomLevelSet.ZoomLevel01.CustomStyles[0] as FilterStyle; if (filterStyle != null) { filterStyle.Conditions.Clear(); // Create the filter expression based on the values from client side. string expression = string.Format("{0}{1}{2}", filterExpressions[filterExpression].Item1, filterValue, filterExpressions[filterExpression].Item2); FilterCondition filterCondition = new FilterCondition("Population", expression); filterStyle.Conditions.Add(filterCondition); } updateResult = true; } return updateResult; } private static LayerOverlay GetDrawingOverlay(string id) { // For FilterStyle, it's cached for a specific Session. LayerOverlay layerOverlay = null; if (id == "FilterStyle") { IHttpSessionState session = SessionStateUtility.GetHttpSessionStateFromContext(HttpContext.Current); layerOverlay = session[id] as LayerOverlay; if (layerOverlay == null || session == null) { layerOverlay = OverlayBuilder.GetOverlayWithFilterStyle(); session[id] = layerOverlay; } } else { layerOverlay = cachedOverlays[id]; } return layerOverlay; } } }
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using ThinkGeo.MapSuite.Core; using ThinkGeo.MapSuite.WebApiEdition; namespace Visualization { public static class OverlayBuilder { /// <summary> /// Gets an overlay applied with ClassBreak style. /// </summary> public static LayerOverlay GetOverlayWithClassBreakStyle() { // Get the file path name from its relative path. string shpFilePathName = GetFullPath(@"app_data\usStatesCensus2010.shp"); ShapeFileFeatureLayer shapeFileFeatureLayer = new ShapeFileFeatureLayer(shpFilePathName); shapeFileFeatureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; shapeFileFeatureLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(GetClassBreakStyle()); // Apply projection to the shape file which is used for display. shapeFileFeatureLayer.FeatureSource.Projection = GetProjection(); LayerOverlay layerOverlay = new LayerOverlay(); layerOverlay.Layers.Add(shapeFileFeatureLayer); return layerOverlay; } /// <summary> /// Gets an overlay applied with ClusterPoint style. /// </summary> public static LayerOverlay GetOverlayWithClusterPointStyle() { // Get the file path name from its relative path. string shpFilePathName = GetFullPath(@"app_data\usEarthquake.shp"); ShapeFileFeatureLayer shapeFileFeatureLayer = new ShapeFileFeatureLayer(shpFilePathName); shapeFileFeatureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; shapeFileFeatureLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(GetClusterPointStyle()); // Apply projection to the shape file which is used for display. shapeFileFeatureLayer.FeatureSource.Projection = GetProjection(); LayerOverlay layerOverlay = new LayerOverlay(); layerOverlay.Layers.Add(shapeFileFeatureLayer); return layerOverlay; } /// <summary> /// Gets an overlay applied with a weather custmized style. /// </summary> public static LayerOverlay GetOverlayWithCustomeStyle() { // Get the layers which have been applied the customized style. Collection<FeatureLayer> styleLayers = GetCustomStyleLayers(); LayerOverlay layerOverlay = new LayerOverlay(); for (int i = 0; i < styleLayers.Count; i++) { string styleId = string.Format(CultureInfo.InvariantCulture, "CustomStyle{0}", i.ToString(CultureInfo.InvariantCulture)); layerOverlay.Layers.Add(styleId, styleLayers[i]); } return layerOverlay; } /// <summary> /// Gets an overlay applied with DotDensity style. /// </summary> public static LayerOverlay GetOverlayWithDotDensityStyle() { // Get the file path name from its relative path. string shpFilePathName = GetFullPath(@"app_data\usStatesCensus2010.shp"); ShapeFileFeatureLayer shapeFileFeatureLayer = new ShapeFileFeatureLayer(shpFilePathName); shapeFileFeatureLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(20, GeoColor.FromHtml("#00e6fe")), GeoColor.StandardColors.Gray)); // Create the DotDensityStyle DotDensityStyle dotDensityStyle = new DotDensityStyle("Population", 0.0000094778167166538189, PointStyles.CreateSimpleCircleStyle(GeoColor.StandardColors.Black, 7)); dotDensityStyle.CustomPointStyle = PointStyles.CreateSimpleCircleStyle(GeoColor.FromHtml("#a57431"), 5); shapeFileFeatureLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(dotDensityStyle); shapeFileFeatureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; // Apply projection to the shape file which is used for display. shapeFileFeatureLayer.FeatureSource.Projection = GetProjection(); LayerOverlay layerOverlay = new LayerOverlay(); layerOverlay.Layers.Add(shapeFileFeatureLayer); return layerOverlay; } /// <summary> /// Gets an overlay applied with IsoLine style. /// </summary> public static LayerOverlay GetOverlayWithIsoLineStyle() { LayerOverlay layerOverlay = new LayerOverlay(); layerOverlay.Layers.Add(GetDynamicIsoLineLayer()); return layerOverlay; } /// <summary> /// Gets an overlay applied with Filter style. /// </summary> public static LayerOverlay GetOverlayWithFilterStyle() { // Get the file path name from its relative path. string shpFilePathName = GetFullPath(@"app_data\usStatesCensus2010.shp"); ShapeFileFeatureLayer shapeFileFeatureLayer = new ShapeFileFeatureLayer(shpFilePathName); shapeFileFeatureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; // Create the FilterStyle. FilterStyle filterStyle = new FilterStyle(); filterStyle.Conditions.Add(new FilterCondition("Population", ">2967297")); filterStyle.Styles.Add(AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(130, GeoColor.FromHtml("#ffb74c")), GeoColor.FromHtml("#333333"))); shapeFileFeatureLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(filterStyle); // Apply projection to the shape file which is used for display shapeFileFeatureLayer.FeatureSource.Projection = GetProjection(); LayerOverlay layerOverlay = new LayerOverlay(); layerOverlay.Layers.Add(shapeFileFeatureLayer); return layerOverlay; } /// <summary> /// Gets an overlay applied with heatmap style. /// </summary> public static LayerOverlay GetOverlayWithHeatStyle() { // Get the file path name from its relative path. string shpFilePathName = GetFullPath(@"app_data\usEarthquake.shp"); ShapeFileFeatureLayer shapeFileFeatureLayer = new ShapeFileFeatureLayer(shpFilePathName); shapeFileFeatureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; shapeFileFeatureLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(new HeatStyle(10, 150, "MAGNITUDE", 0, 12, 100, DistanceUnit.Kilometer)); shapeFileFeatureLayer.DrawingMarginPercentage = 300; // Apply projection to the shape file which is used for display shapeFileFeatureLayer.FeatureSource.Projection = GetProjection(); LayerOverlay layerOverlay = new LayerOverlay(); layerOverlay.Layers.Add(shapeFileFeatureLayer); return layerOverlay; } /// <summary> /// Gets an overlay applied with icon style. /// </summary> public static LayerOverlay GetOverlayWithIconStyle() { // Get the file path name from its relative path. string shpFilePathName = GetFullPath(@"app_data\Vehicles.shp"); ShapeFileFeatureLayer shapeFileFeatureLayer = new ShapeFileFeatureLayer(shpFilePathName); shapeFileFeatureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; shapeFileFeatureLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(GetIconStyle()); // Apply projection to the shape file which is used for display. shapeFileFeatureLayer.FeatureSource.Projection = GetProjection(); LayerOverlay layerOverlay = new LayerOverlay(); layerOverlay.Layers.Add(shapeFileFeatureLayer); return layerOverlay; } /// <summary> /// Gets an overlay applied with ZedGraph style. /// </summary> public static LayerOverlay GetOverlayWithZedGraphStyle() { // Get the file path name from its relative path. string shpFilePathName = GetFullPath(@"app_data\MajorCities.shp"); ShapeFileFeatureLayer shapeFileFeatureLayer = new ShapeFileFeatureLayer(shpFilePathName); shapeFileFeatureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; TextStyle textStyle = TextStyles.CreateSimpleTextStyle("AREANAME", "Arial", 10, DrawingFontStyles.Regular, GeoColor.StandardColors.Black, GeoColor.SimpleColors.White, 2, -20, 40); shapeFileFeatureLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(new PieChartStyle()); shapeFileFeatureLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(textStyle); shapeFileFeatureLayer.DrawingMarginPercentage = 100; // Apply projection to the shape file which is used for display. ManagedProj4Projection managedProj4Projection = new ManagedProj4Projection(); managedProj4Projection.InternalProjectionParametersString = Proj4Projection.GetWgs84ParametersString(); managedProj4Projection.ExternalProjectionParametersString = Proj4Projection.GetSphericalMercatorParametersString(); shapeFileFeatureLayer.FeatureSource.Projection = managedProj4Projection; LayerOverlay layerOverlay = new LayerOverlay(); layerOverlay.Layers.Add(shapeFileFeatureLayer); return layerOverlay; } private static ClassBreakStyle GetClassBreakStyle() { // Define the values which are used as the class breaks. double[] classBreakValues = new double[] { 0, 814180.0, 1328361.0, 2059179.0, 2967297.0, 4339367.0, 5303925.0, 6392017.0, 8791894.0 }; // Create a color family for displying the features. Collection<GeoColor> familyColors = GeoColor.GetColorsInQualityFamily(GeoColor.FromArgb(255, 116, 160, 255), GeoColor.FromArgb(255, 220, 52, 56), 10, ColorWheelDirection.CounterClockwise); ClassBreakStyle classBreakStyle = new ClassBreakStyle("Population", BreakValueInclusion.IncludeValue); for (int i = 0; i < classBreakValues.Length; i++) { classBreakStyle.ClassBreaks.Add(new ClassBreak(classBreakValues[i], AreaStyles.CreateSimpleAreaStyle(new GeoColor(150, familyColors[i]), GeoColor.FromHtml("#f05133"), 1))); } return classBreakStyle; } private static ClassBreakClusterPointStyle GetClusterPointStyle() { ClassBreakClusterPointStyle clusterPointStyle = new ClassBreakClusterPointStyle(); clusterPointStyle.CellSize = 65; // Create the PointStyle for different class breaks. PointStyle pointStyle1 = new PointStyle(PointSymbolType.Circle, new GeoSolidBrush(GeoColor.FromArgb(250, 222, 226, 153)), new GeoPen(GeoColor.FromArgb(100, 222, 226, 153), 5), 8); clusterPointStyle.ClassBreakPoints.Add(1, pointStyle1); PointStyle pointStyle2 = new PointStyle(PointSymbolType.Circle, new GeoSolidBrush(GeoColor.FromArgb(250, 222, 226, 153)), new GeoPen(GeoColor.FromArgb(100, 222, 226, 153), 8), 15); clusterPointStyle.ClassBreakPoints.Add(2, pointStyle2); PointStyle pointStyle3 = new PointStyle(PointSymbolType.Circle, new GeoSolidBrush(GeoColor.FromArgb(250, 255, 183, 76)), new GeoPen(GeoColor.FromArgb(100, 255, 183, 76), 10), 25); clusterPointStyle.ClassBreakPoints.Add(50, pointStyle3); PointStyle pointStyle4 = new PointStyle(PointSymbolType.Circle, new GeoSolidBrush(GeoColor.FromArgb(250, 243, 193, 26)), new GeoPen(GeoColor.FromArgb(100, 243, 193, 26), 15), 35); clusterPointStyle.ClassBreakPoints.Add(150, pointStyle4); PointStyle pointStyle5 = new PointStyle(PointSymbolType.Circle, new GeoSolidBrush(GeoColor.FromArgb(250, 245, 7, 10)), new GeoPen(GeoColor.FromArgb(100, 245, 7, 10), 15), 40); clusterPointStyle.ClassBreakPoints.Add(350, pointStyle5); PointStyle pointStyle6 = new PointStyle(PointSymbolType.Circle, new GeoSolidBrush(GeoColor.FromArgb(250, 245, 7, 10)), new GeoPen(GeoColor.FromArgb(100, 245, 7, 10), 20), 50); clusterPointStyle.ClassBreakPoints.Add(500, pointStyle6); clusterPointStyle.TextStyle = TextStyles.CreateSimpleTextStyle("FeatureCount", "Arail", 10, DrawingFontStyles.Regular, GeoColor.SimpleColors.Black); clusterPointStyle.TextStyle.PointPlacement = PointPlacement.Center; return clusterPointStyle; } private static Collection<FeatureLayer> GetCustomStyleLayers() { Collection<FeatureLayer> featureLayers = new Collection<FeatureLayer>(); // Create the weather line style. LineStyle lineStyle = LineStyles.CreateSimpleLineStyle(GeoColor.FromArgb(255, 50, 0, 249), 4, false); InMemoryFeatureLayer inMemoryFeatureLayerColdFront = new InMemoryFeatureLayer(); // Cold Front Icon Style. string[] temperatureIcons = new string[] { GetFullPath(@"App_Data/CustomStyles/offset_circle_red_bl.png"), GetFullPath(@"App_Data/CustomStyles/offset_triangle_blue_revert.png") }; CustomGeoImageLineStyle coldFrontLineStyle = new CustomGeoImageLineStyle(lineStyle, temperatureIcons.Select(p => new GeoImage(p)), 19, ImageDirection.Right); inMemoryFeatureLayerColdFront.ZoomLevelSet.ZoomLevel05.CustomStyles.Add(coldFrontLineStyle); inMemoryFeatureLayerColdFront.ZoomLevelSet.ZoomLevel05.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; featureLayers.Add(inMemoryFeatureLayerColdFront); // Add features which present the cold points. inMemoryFeatureLayerColdFront.InternalFeatures.Add(new Feature(File.ReadAllText(GetFullPath(@"App_Data/CustomStyles/ColdFront2.txt")))); inMemoryFeatureLayerColdFront.InternalFeatures.Add(new Feature(File.ReadAllText(GetFullPath(@"App_Data/CustomStyles/ColdFront3.txt")))); InMemoryFeatureLayer inMemoryFeatureLayerWarmFront = new InMemoryFeatureLayer(); // Warm Front Icon Style. CustomGeoImageLineStyle warmFrontLineStyle = new CustomGeoImageLineStyle(lineStyle, new GeoImage(GetFullPath(@"App_Data/CustomStyles/offset_circle_blue.png")), 30, ImageDirection.Right); inMemoryFeatureLayerWarmFront.ZoomLevelSet.ZoomLevel05.CustomStyles.Add(warmFrontLineStyle); inMemoryFeatureLayerWarmFront.ZoomLevelSet.ZoomLevel05.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; featureLayers.Add(inMemoryFeatureLayerWarmFront); // Add features which present the warm points. LineShape lineShape5 = new LineShape(File.ReadAllText(GetFullPath(@"App_Data/CustomStyles/WarmFront5.txt")).Trim()); inMemoryFeatureLayerWarmFront.InternalFeatures.Add(new Feature(lineShape5)); LineShape lineShape6 = new LineShape(File.ReadAllText(GetFullPath(@"App_Data/CustomStyles/WarmFront6.txt")).Trim()); inMemoryFeatureLayerWarmFront.InternalFeatures.Add(new Feature(lineShape6)); LineShape lineShape7 = new LineShape(File.ReadAllText(GetFullPath(@"App_Data/CustomStyles/WarmFront7.txt")).Trim()); inMemoryFeatureLayerWarmFront.InternalFeatures.Add(new Feature(lineShape7)); LineShape lineShape8 = new LineShape(File.ReadAllText(GetFullPath(@"App_Data/CustomStyles/WarmFront8.txt")).Trim()); inMemoryFeatureLayerWarmFront.InternalFeatures.Add(new Feature(lineShape8)); // Occluded Front Icon Style. InMemoryFeatureLayer inMemoryFeatureLayerOccludedFront = new InMemoryFeatureLayer(); CustomGeoImageLineStyle occludedFrontLineStyle = new CustomGeoImageLineStyle(lineStyle, new[] { new GeoImage(GetFullPath(@"App_Data/CustomStyles/offset_triangle_and_circle_blue.png")), new GeoImage(GetFullPath(@"App_Data/CustomStyles/offset_triangle_and_circle_red.png")) }, 45, ImageDirection.Right); inMemoryFeatureLayerOccludedFront.ZoomLevelSet.ZoomLevel05.CustomStyles.Add(occludedFrontLineStyle); inMemoryFeatureLayerOccludedFront.ZoomLevelSet.ZoomLevel05.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; featureLayers.Add(inMemoryFeatureLayerOccludedFront); // Add features which present the occluded points. LineShape lineShape9 = new LineShape(File.ReadAllText(GetFullPath(@"App_Data/CustomStyles/OccludedFront9.txt")).Trim()); inMemoryFeatureLayerOccludedFront.InternalFeatures.Add(new Feature(lineShape9)); LineShape lineShape10 = new LineShape(File.ReadAllText(GetFullPath(@"App_Data/CustomStyles/OccludedFront10.txt")).Trim()); inMemoryFeatureLayerOccludedFront.InternalFeatures.Add(new Feature(lineShape10)); LineShape lineShape11 = new LineShape(File.ReadAllText(GetFullPath(@"App_Data/CustomStyles/OccludedFront11.txt")).Trim()); inMemoryFeatureLayerOccludedFront.InternalFeatures.Add(new Feature(lineShape11)); // Create the style for "Pressure" values. PressureValueStyle pressureValueStyle = new PressureValueStyle(); pressureValueStyle.ColumnName = "Pressure"; InMemoryFeatureLayer pressureFeatureLayer = new InMemoryFeatureLayer(); pressureFeatureLayer.Open(); pressureFeatureLayer.Columns.Add(new FeatureSourceColumn("Pressure")); pressureFeatureLayer.ZoomLevelSet.ZoomLevel05.CustomStyles.Add(pressureValueStyle); pressureFeatureLayer.ZoomLevelSet.ZoomLevel05.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; featureLayers.Add(pressureFeatureLayer); // Add features which present the "Pressure" points. string[] pressurePointStr = File.ReadAllLines(GetFullPath(@"App_Data/Pressure.txt")); foreach (string pointStr in pressurePointStr) { string[] parts = pointStr.Split(','); Feature pressurePoint = new Feature(double.Parse(parts[0]), double.Parse(parts[1])); pressurePoint.ColumnValues["Pressure"] = parts[2]; pressureFeatureLayer.InternalFeatures.Add(pressurePoint); } // Create the style for "wind". ClassBreakStyle windClassBreakStyle = new ClassBreakStyle("TEXT"); WindPointStyle windStyle1 = new WindPointStyle("TEXT", "LEVEL", "ANGLE", GeoColor.FromHtml("#0AF8F8")); windClassBreakStyle.ClassBreaks.Add(new ClassBreak(50, new Collection<Style> { windStyle1 })); WindPointStyle windStyle2 = new WindPointStyle("TEXT", "LEVEL", "ANGLE", GeoColor.FromHtml("#0FF5B0")); windClassBreakStyle.ClassBreaks.Add(new ClassBreak(60, new Collection<Style> { windStyle2 })); WindPointStyle windStyle3 = new WindPointStyle("TEXT", "LEVEL", "ANGLE", GeoColor.FromHtml("#F7F70D")); windClassBreakStyle.ClassBreaks.Add(new ClassBreak(70, new Collection<Style> { windStyle3 })); WindPointStyle windStyle4 = new WindPointStyle("TEXT", "LEVEL", "ANGLE", GeoColor.FromHtml("#FBE306")); windClassBreakStyle.ClassBreaks.Add(new ClassBreak(80, new Collection<Style> { windStyle4 })); InMemoryFeatureLayer windFeatureLayer = new InMemoryFeatureLayer(); windFeatureLayer.Open(); windFeatureLayer.Columns.Add(new FeatureSourceColumn("TEXT")); windFeatureLayer.Columns.Add(new FeatureSourceColumn("ANGLE")); windFeatureLayer.Columns.Add(new FeatureSourceColumn("LEVEL")); windFeatureLayer.ZoomLevelSet.ZoomLevel05.CustomStyles.Add(windClassBreakStyle); windFeatureLayer.ZoomLevelSet.ZoomLevel05.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; featureLayers.Add(windFeatureLayer); // Add features which present the "wind" points. Random random = new Random(); for (int i = 0; i < 8; i++) { Feature windFeature = new Feature(random.Next(-13886070, -8906057), random.Next(3382985, 6660597)); windFeature.ColumnValues["TEXT"] = random.Next(55, 99).ToString(); windFeature.ColumnValues["ANGLE"] = random.Next(0, 360).ToString(); windFeature.ColumnValues["LEVEL"] = random.Next(0, 5).ToString(); windFeatureLayer.InternalFeatures.Add(windFeature); } return featureLayers; } private static DynamicIsoLineLayer GetDynamicIsoLineLayer() { // Define the colors for different earthquake magnitude. Collection<GeoColor> colorsOfMagnitude = new Collection<GeoColor>() { GeoColor.FromHtml("#FFFFBE"), GeoColor.FromHtml("#FDFF9E"), GeoColor.FromHtml("#FDFF37"), GeoColor.FromHtml("#FDDA04"), GeoColor.FromHtml("#FFA701"), GeoColor.FromHtml("#FF6F02"), GeoColor.FromHtml("#EC0000"), GeoColor.FromHtml("#B90000"), GeoColor.FromHtml("#850100"), GeoColor.FromHtml("#620001"), GeoColor.FromHtml("#450005"), GeoColor.FromHtml("#2B0804") }; // Get the file path name from its relative path. string shpFilePathName = GetFullPath(@"app_data\usEarthquake.shp"); // Create the layer for IsoLine. ShapeFileFeatureSource featureSource = new ShapeFileFeatureSource(shpFilePathName); Dictionary<PointShape, double> dataPoints = GetDataPoints(featureSource); GridInterpolationModel interpolationModel = new InverseDistanceWeightedGridInterpolationModel(3, double.MaxValue); DynamicIsoLineLayer isoLineLayer = new DynamicIsoLineLayer(dataPoints, GetClassBreakValues(dataPoints.Values, 12), interpolationModel, IsoLineType.ClosedLinesAsPolygons); // Create the style for different level of earthquake magnitude. ClassBreakStyle earthquakeMagnitudeBreakStyle = new ClassBreakStyle(isoLineLayer.DataValueColumnName); earthquakeMagnitudeBreakStyle.ClassBreaks.Add(new ClassBreak(double.MinValue, new AreaStyle(new GeoPen(GeoColor.FromHtml("#FE6B06"), 1), new GeoSolidBrush(new GeoColor(100, colorsOfMagnitude[0]))))); for (int i = 0; i < isoLineLayer.IsoLineLevels.Count - 1; i++) { earthquakeMagnitudeBreakStyle.ClassBreaks.Add(new ClassBreak(isoLineLayer.IsoLineLevels[i|+ 1], new AreaStyle(new GeoPen(GeoColor.FromHtml("#FE6B06"), 1), new GeoSolidBrush(new GeoColor(100, colorsOfMagnitude[i|+ 1]))))); } isoLineLayer.CustomStyles.Add(earthquakeMagnitudeBreakStyle); TextStyle textStyle = TextStyles.CreateSimpleTextStyle(isoLineLayer.DataValueColumnName, "Arial", 8, DrawingFontStyles.Bold, GeoColor.StandardColors.Black, 0, 0); textStyle.HaloPen = new GeoPen(GeoColor.StandardColors.White, 2); textStyle.OverlappingRule = LabelOverlappingRule.NoOverlapping; textStyle.SplineType = SplineType.StandardSplining; textStyle.DuplicateRule = LabelDuplicateRule.UnlimitedDuplicateLabels; textStyle.TextLineSegmentRatio = 9999999; textStyle.FittingLineInScreen = true; textStyle.SuppressPartialLabels = true; textStyle.NumericFormat = "{0:0.00}"; isoLineLayer.CustomStyles.Add(textStyle); return isoLineLayer; } private static Dictionary<PointShape, double> GetDataPoints(FeatureSource featureSource) { featureSource.Open(); Dictionary<PointShape, double> features = (from feature in featureSource.GetAllFeatures(new string[] { "LONGITUDE", "LATITIUDE", "MAGNITUDE" }) where double.Parse(feature.ColumnValues["MAGNITUDE"]) > 0 select new PointShape { X = double.Parse(feature.ColumnValues["LONGITUDE"], CultureInfo.InvariantCulture), Y = double.Parse(feature.ColumnValues["LATITIUDE"], CultureInfo.InvariantCulture), Z = double.Parse(feature.ColumnValues["MAGNITUDE"], CultureInfo.InvariantCulture) }).ToDictionary(point => point, point => point.Z); return features; } private static IEnumerable<double> GetClassBreakValues(IEnumerable<double> values, int count) { // Take an average value for creating class breaks. Collection<double> result = new Collection<double>(); double[] sortedValues = values.OrderBy(v => v).ToArray(); int classCount = sortedValues.Length / count; for (int i = 1; i < count; i++) { result.Add(sortedValues[i|* classCount]); } return result; } private static ValueStyle GetIconStyle() { // Get the file path name from its relative path. string imagePath = GetFullPath(@"Images\vehicle"); ValueStyle valueStyle = new ValueStyle() { ColumnName = "TYPE" }; // Create the icon style for different type of vehicles. for (int i = 1; i <= 7; i++) { IconStyle iconStyle = new IconStyle(string.Format("{0}{1}.png", imagePath, i.ToString(CultureInfo.InvariantCulture), ".png"), "Type", new GeoFont("Arial", 12, DrawingFontStyles.Bold), new GeoSolidBrush(GeoColor.StandardColors.Black)); iconStyle.HaloPen = new GeoPen(GeoColor.SimpleColors.White); ValueItem valueItem = new ValueItem(i.ToString(CultureInfo.InvariantCulture), iconStyle); valueStyle.ValueItems.Add(valueItem); } return valueStyle; } private static ManagedProj4Projection GetProjection() { ManagedProj4Projection managedProj4Projection = new ManagedProj4Projection(); managedProj4Projection.InternalProjectionParametersString = Proj4Projection.GetWgs84ParametersString(); managedProj4Projection.ExternalProjectionParametersString = Proj4Projection.GetSphericalMercatorParametersString(); return managedProj4Projection; } private static string GetFullPath(string relativePath) { Uri uri = new Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase); string folderPath = Path.GetDirectoryName(Path.GetDirectoryName(uri.LocalPath)); return Path.Combine(folderPath, relativePath); } } }
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using ThinkGeo.MapSuite.Core; namespace Visualization { public class CustomGeoImageLineStyle : LineStyle { private LineStyle lineStyle; private int imageSpacing; private Collection<GeoImage> images; private ImageDirection imageDirection; private CustomGeoImageLineStyle() { } public CustomGeoImageLineStyle(LineStyle lineStyle, GeoImage geoImage, int imageSpacing, ImageDirection imageDirection) : this(lineStyle, new Collection<GeoImage> { geoImage }, imageSpacing, imageDirection) { } public CustomGeoImageLineStyle(LineStyle lineStyle, IEnumerable<GeoImage> geoImages, int imageSpacing, ImageDirection imageDirection) { this.imageDirection = imageDirection; this.imageSpacing = imageSpacing; this.lineStyle = lineStyle; this.images = new Collection<GeoImage>(); foreach (var geoImage in geoImages) { this.images.Add(geoImage); } } /// <summary> /// Gets or sets the line style of the weather front end. /// </summary> public LineStyle LineStyle { get { return lineStyle; } set { lineStyle = value; } } /// <summary> /// Gets a collection of images for temperature display. /// </summary> public Collection<GeoImage> Images { get { return images; } } /// <summary> /// Gets or sets the image spacing in screen coordinate between each GeoImage on the line. /// </summary> public int ImageSpacing { get { return imageSpacing; } set { imageSpacing = value; } } /// <summary> /// Gets or sets the direction where the image display according to the weather front end line. /// </summary> public ImageDirection Direction { get { return imageDirection; } set { imageDirection = value; } } protected override void DrawCore(IEnumerable<Feature> features, GeoCanvas canvas, Collection<SimpleCandidate> labelsInThisLayer, Collection<SimpleCandidate> labelsInAllLayers) { PointStyle[] pointStyles = images.Select(geoImage => { return new PointStyle(geoImage) { DrawingLevel = DrawingLevel.LevelThree }; }).ToArray(); // Loop the features for display. foreach (Feature feature in features) { LineShape lineShape = (LineShape)feature.GetShape(); lineStyle.Draw(new BaseShape[] { lineShape }, canvas, labelsInThisLayer, labelsInAllLayers); int index = 0; double totalDistance = 0; for (int i = 0; i < lineShape.Vertices.Count - 1; i++) { PointShape pointShape1 = new PointShape(lineShape.Vertices[i]); PointShape pointShape2 = new PointShape(lineShape.Vertices[i|+ 1]); LineShape tempLineShape = new LineShape(); tempLineShape.Vertices.Add(lineShape.Vertices[i]); tempLineShape.Vertices.Add(lineShape.Vertices[i|+ 1]); double angle = WeatherLineStyle.GetAngleFromTwoVertices(lineShape.Vertices[i], lineShape.Vertices[i|+ 1]); // Left side if (imageDirection == ImageDirection.Left) { if (angle >= 270) { angle = angle - 180; } } // Right side else { if (angle <= 90) { angle = angle + 180; } } foreach (var pointStyle in pointStyles) { pointStyle.RotationAngle = (float)angle; } float screenDistance = ExtentHelper.GetScreenDistanceBetweenTwoWorldPoints(canvas.CurrentWorldExtent, pointShape1, pointShape2, canvas.Width, canvas.Height); double currentDistance = Math.Round(pointShape1.GetDistanceTo(pointShape2, canvas.MapUnit, DistanceUnit.Meter), 2); double worldInterval = (currentDistance * imageSpacing) / screenDistance; while (totalDistance <= currentDistance) { PointStyle pointStyle = pointStyles[index|% pointStyles.Length]; PointShape tempPointShape = tempLineShape.GetPointOnALine(StartingPoint.FirstPoint, totalDistance, canvas.MapUnit, DistanceUnit.Meter); pointStyle.Draw(new BaseShape[] { tempPointShape }, canvas, labelsInThisLayer, labelsInAllLayers); totalDistance = totalDistance + worldInterval; index++; } totalDistance = totalDistance - currentDistance; } } } } }
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using ThinkGeo.MapSuite.Core; namespace Visualization { public class PressureValueStyle : ValueStyle { private ValueItem lowPressureValueItem; private ValueItem highPressureValueItem; public PressureValueStyle() { SquareTextPointStyle highPressurePointStyle = new SquareTextPointStyle(); highPressurePointStyle.Text = "L"; highPressurePointStyle.SymbolSolidBrush = new GeoSolidBrush(GeoColor.FromArgb(255, 39, 39, 245)); highPressureValueItem = new ValueItem("H", highPressurePointStyle); ValueItems.Add(highPressureValueItem); SquareTextPointStyle lowPressurePointStyle = new SquareTextPointStyle(); lowPressurePointStyle.Text = "H"; lowPressurePointStyle.SymbolSolidBrush = new GeoSolidBrush(GeoColor.StandardColors.Red); lowPressureValueItem = new ValueItem("L", lowPressurePointStyle); ValueItems.Add(lowPressureValueItem); } protected override void DrawCore(IEnumerable<Feature> features, GeoCanvas canvas, Collection<SimpleCandidate> labelsInThisLayer, Collection<SimpleCandidate> labelsInAllLayers) { base.DrawCore(features, canvas, labelsInThisLayer, labelsInAllLayers); } public class SquareTextPointStyle : PointStyle { private string text; private GeoFont font; private GeoBrush textBrush; public SquareTextPointStyle() { SymbolType = PointSymbolType.Square; SymbolSize = 30; PointType = PointType.Symbol; font = new GeoFont("Verdana", 14); textBrush = new GeoSolidBrush(GeoColor.StandardColors.White); SymbolPen = new GeoPen(GeoColor.StandardColors.White, 1); } public string Text { get { return text; } set { text = value; } } protected override void DrawCore(IEnumerable<Feature> features, GeoCanvas canvas, Collection<SimpleCandidate> labelsInThisLayer, Collection<SimpleCandidate> labelsInAllLayers) { base.DrawCore(features, canvas, labelsInThisLayer, labelsInAllLayers); double resolution = Math.Max(canvas.CurrentWorldExtent.Width / canvas.Width, canvas.CurrentWorldExtent.Height / canvas.Height); foreach (Feature feature in features) { PointShape pointShape = feature.GetShape() as PointShape; if (pointShape != null) { float screenOffsetX = (float)((pointShape.X - canvas.CurrentWorldExtent.UpperLeftPoint.X) / resolution); float screenOffsetY = (float)((canvas.CurrentWorldExtent.UpperLeftPoint.Y - pointShape.Y) / resolution); canvas.DrawTextWithScreenCoordinate(Text, font, textBrush, screenOffsetX, screenOffsetY, ThinkGeo.MapSuite.Core.DrawingLevel.LabelLevel); } } } } } }
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using ThinkGeo.MapSuite.Core; namespace Visualization { public class WeatherLineStyle : LineStyle { private GeoImage geoImage; private int imageSpacing; private LineStyle lineStyle; private ImageDirection imageDirection; private WeatherLineStyle() { } public WeatherLineStyle(LineStyle lineStyle, GeoImage GeoImage, int imageSpacing, ImageDirection imageDirection) { this.lineStyle = lineStyle; this.geoImage = GeoImage; this.imageSpacing = imageSpacing; this.imageDirection = imageDirection; } /// <summary> /// Gets or sets the line style of the weather front end. /// </summary> public LineStyle LineStyle { get { return lineStyle; } set { lineStyle = value; } } /// <summary> /// Gets the image for temperature display. /// </summary> public GeoImage GeoImage { get { return geoImage; } set { geoImage = value; } } /// <summary> /// Gets or sets the image spacing in screen coordinate between each GeoImage on the line. /// </summary> public int ImageSpacing { get { return imageSpacing; } set { imageSpacing = value; } } /// <summary> /// Gets or sets the direction where the image display according to the weather front end line. /// </summary> public ImageDirection Direction { get { return imageDirection; } set { imageDirection = value; } } protected override void DrawCore(IEnumerable<Feature> features, GeoCanvas canvas, Collection<SimpleCandidate> labelsInThisLayer, Collection<SimpleCandidate> labelsInAllLayers) { PointStyle pointStyle = new PointStyle(geoImage); foreach (Feature feature in features) { MultilineShape lineShape = (MultilineShape)feature.GetShape(); lineStyle.Draw(new BaseShape[] { lineShape }, canvas, labelsInThisLayer, labelsInAllLayers); List<Vertex> allVertices = lineShape.Lines.SelectMany(l => l.Vertices).ToList(); double totalDistance = 0; for (int i = 0; i < allVertices.Count - 1; i++) { PointShape pointShape1 = new PointShape(allVertices[i]); PointShape pointShape2 = new PointShape(allVertices[i|+ 1]); LineShape tempLineShape = new LineShape(); tempLineShape.Vertices.Add(allVertices[i]); tempLineShape.Vertices.Add(allVertices[i|+ 1]); double angle = GetAngleFromTwoVertices(allVertices[i], allVertices[i|+ 1]); // Left side if (imageDirection == ImageDirection.Left) { if (angle >= 270) { angle -= 180; } } // Right side else { if (angle <= 90) { angle += 180; } } pointStyle.RotationAngle = (float)angle; float screenDistance = ExtentHelper.GetScreenDistanceBetweenTwoWorldPoints(canvas.CurrentWorldExtent, pointShape1, pointShape2, canvas.Width, canvas.Height); double currentDistance = Math.Round(pointShape1.GetDistanceTo(pointShape2, canvas.MapUnit, DistanceUnit.Meter), 2); double worldInterval = (currentDistance * imageSpacing) / screenDistance; while (totalDistance <= currentDistance) { PointShape tempPointShape = tempLineShape.GetPointOnALine(StartingPoint.FirstPoint, totalDistance, canvas.MapUnit, DistanceUnit.Meter); pointStyle.Draw(new BaseShape[] { tempPointShape }, canvas, labelsInThisLayer, labelsInAllLayers); totalDistance = totalDistance + worldInterval; } totalDistance = totalDistance - currentDistance; } } } public static double GetAngleFromTwoVertices(Vertex firstVertex, Vertex secondVertex) { double tangentAlpha = (secondVertex.Y - firstVertex.Y) / (secondVertex.X - firstVertex.X); double Peta = Math.Atan(tangentAlpha); double alpha = 0; if (secondVertex.X > firstVertex.X) { alpha = 90 + (Peta * (180 / Math.PI)); } else if (secondVertex.X < firstVertex.X) { alpha = 270 + (Peta * (180 / Math.PI)); } else { if (secondVertex.Y > firstVertex.Y) alpha = 0; if (secondVertex.Y < firstVertex.Y) alpha = 180; } double offset = -90; if (firstVertex.X > secondVertex.X) { offset = 90; } return alpha + offset; } } }
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using ThinkGeo.MapSuite.Core; namespace Visualization { public class WindPointStyle : Style { private string textColumn; private string angleColumn; private string windLevelColumn; private GeoFont font; private GeoBrush textBrush; private GeoSolidBrush fillBrush; private GeoSolidBrush blackBrush; private float directionLineLength1; private float directionLineLength2; private GeoPen outlinePen; private GeoPen innerlinePen; public WindPointStyle() : this(string.Empty, string.Empty, string.Empty, GeoColor.StandardColors.Orange) { } public WindPointStyle(string textColumn, string levelColumn, string angleColumn, GeoColor fillColor) { this.directionLineLength1 = 40; this.directionLineLength2 = 10; this.blackBrush = new GeoSolidBrush(GeoColor.SimpleColors.Black); this.font = new GeoFont("Verdana", 10); this.textBrush = new GeoSolidBrush(GeoColor.StandardColors.Black); this.fillBrush = new GeoSolidBrush(fillColor); this.outlinePen = new GeoPen(GeoColor.StandardColors.Black, 4); this.innerlinePen = new GeoPen(fillBrush, 2); this.textColumn = textColumn; this.windLevelColumn = levelColumn; this.angleColumn = angleColumn; } public string TextColumn { get { return textColumn; } set { textColumn = value; } } public string AngleColumn { get { return angleColumn; } set { angleColumn = value; } } public string WindLevelColumn { get { return windLevelColumn; } set { windLevelColumn = value; } } protected override Collection<string> GetRequiredColumnNamesCore() { return new Collection<string> { TextColumn, AngleColumn, WindLevelColumn }; } protected override void DrawCore(IEnumerable<Feature> features, GeoCanvas canvas, Collection<SimpleCandidate> labelsInThisLayer, Collection<SimpleCandidate> labelsInAllLayers) { double resolution = Math.Max(canvas.CurrentWorldExtent.Width / canvas.Width, canvas.CurrentWorldExtent.Height / canvas.Height); foreach (var feature in features) { PointShape pointShape = feature.GetShape() as PointShape; if (pointShape != null) { float screenOffsetX = (float)((pointShape.X - canvas.CurrentWorldExtent.UpperLeftPoint.X) / resolution); float screenOffsetY = (float)((canvas.CurrentWorldExtent.UpperLeftPoint.Y - pointShape.Y) / resolution); string angle = feature.ColumnValues[AngleColumn]; string level = feature.ColumnValues[WindLevelColumn]; int windLevel = int.Parse(level); ScreenPointF[] directionLine = null; ScreenPointF[] levelLine1 = null; ScreenPointF[] levelLine2 = null; if (!string.IsNullOrEmpty(angle)) { double radian1 = double.Parse(angle) * Math.PI / 180; float x1 = (float)(directionLineLength1 * Math.Cos(radian1)); float y1 = (float)(directionLineLength1 * Math.Sin(radian1)); double radian2 = (double.Parse(angle) - 90) * Math.PI / 180; float x2 = (float)(directionLineLength2 * Math.Cos(radian2)); float y2 = (float)(directionLineLength2 * Math.Sin(radian2)); float x3 = (float)((directionLineLength1 - 8) * Math.Cos(radian1)); float y3 = (float)((directionLineLength1 - 8) * Math.Sin(radian1)); float x4 = (float)(directionLineLength2 * Math.Cos(radian2)); float y4 = (float)(directionLineLength2 * Math.Sin(radian2)); if (windLevel >= 1) { directionLine = new ScreenPointF[2]; directionLine[0] = new ScreenPointF(screenOffsetX, screenOffsetY); directionLine[1] = new ScreenPointF(screenOffsetX + x1, screenOffsetY + y1); } if (windLevel >= 2) { levelLine1 = new ScreenPointF[2]; levelLine1[0] = new ScreenPointF(screenOffsetX + x1, screenOffsetY + y1); levelLine1[1] = new ScreenPointF(screenOffsetX + x1 + x2, screenOffsetY + y1 + y2); } if (windLevel >= 3) { levelLine2 = new ScreenPointF[2]; levelLine2[0] = new ScreenPointF(screenOffsetX + x3, screenOffsetY + y3); levelLine2[1] = new ScreenPointF(screenOffsetX + x3 + x4, screenOffsetY + y3 + y4); } } // draw back canvas.DrawEllipse(feature, 26, 26, blackBrush, ThinkGeo.MapSuite.Core.DrawingLevel.LevelOne); if (directionLine != null) { canvas.DrawLine(directionLine, outlinePen, DrawingLevel.LevelOne, 0, 0); } if (levelLine1 != null) { canvas.DrawLine(levelLine1, outlinePen, DrawingLevel.LevelOne, 0, 0); } if (levelLine2 != null) { canvas.DrawLine(levelLine2, outlinePen, DrawingLevel.LevelOne, 0, 0); } //draw fore canvas.DrawEllipse(feature, 24, 24, fillBrush, ThinkGeo.MapSuite.Core.DrawingLevel.LevelTwo); if (directionLine != null) { canvas.DrawLine(directionLine, innerlinePen, DrawingLevel.LevelTwo, 0, 0); } if (levelLine1 != null) { canvas.DrawLine(levelLine1, innerlinePen, DrawingLevel.LevelTwo, 0, 0); } if (levelLine2 != null) { canvas.DrawLine(levelLine2, innerlinePen, DrawingLevel.LevelTwo, 0, 0); } string text = feature.ColumnValues[TextColumn]; if (!string.IsNullOrEmpty(text)) { canvas.DrawTextWithScreenCoordinate(text, font, textBrush, screenOffsetX, screenOffsetY, DrawingLevel.LabelLevel); } } } } } }
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Globalization; using System.Linq; using System.Reflection; namespace ThinkGeo.MapSuite.Core { [Serializable] public class ClassBreakClusterPointStyle : Style { [Obfuscation(Exclude|= true)] private int cellSize; [Obfuscation(Exclude|= true)] private TextStyle textSytle; [Obfuscation(Exclude|= true)] private Dictionary<int, PointStyle> classBreakPoints; public ClassBreakClusterPointStyle() : base() { cellSize = 100; textSytle = new TextStyle(); classBreakPoints = new Dictionary<int, PointStyle>(); } public Dictionary<int, PointStyle> ClassBreakPoints { get { return classBreakPoints; } } /// <summary> /// Gets or sets a TextStyle for display the label on the cluster. /// </summary> public TextStyle TextStyle { get { return textSytle; } set { textSytle = value; } } /// <summary> /// Gets or sets a value in pixel which determines how devide the screen. The smaller the slower it runs. /// </summary> public int CellSize { get { return cellSize; } set { cellSize = value; } } /// <summary> /// Here in the DrawCore we cluster the features /// </summary> 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) { if (feature.GetWellKnownType() != WellKnownType.Point && feature.GetWellKnownType() != WellKnownType.Multipoint) { continue; } 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 tempMultiPointShape = 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); if (feature.GetWellKnownType() == WellKnownType.Multipoint) { MultipointShape multipointShape = feature.GetShape() as MultipointShape; foreach (var item in multipointShape.Points) { tempMultiPointShape.Points.Add(item); } } else { tempMultiPointShape.Points.Add(feature.GetShape() as PointShape); } } } } 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(CultureInfo.InvariantCulture)); bool isMatch = false; for (int i = 0; i < classBreakPoints.Count - 1; i++) { var startItem = classBreakPoints.ElementAt(i); var endItem = classBreakPoints.ElementAt(i + 1); if (featureCount >= startItem.Key && featureCount < endItem.Key) { // Draw the point shape startItem.Value.Draw(new Feature[] { new Feature(tempMultiPointShape.GetCenterPoint(), featureValues) }, canvas, labelsInThisLayer, labelsInAllLayers); isMatch = true; break; } } if (!isMatch && featureCount >= classBreakPoints.LastOrDefault().Key) { classBreakPoints.LastOrDefault().Value.Draw(new Feature[] { new Feature(tempMultiPointShape.GetCenterPoint(), featureValues) }, canvas, labelsInThisLayer, labelsInAllLayers); } if (featureCount != 1) { // Draw the text style to show how many feaures are consolidated in the cluster textSytle.Draw(new Feature[] { new Feature(tempMultiPointShape.GetCenterPoint(), featureValues) }, canvas, labelsInThisLayer, labelsInAllLayers); } } } } } }
using System; using System.Drawing; using System.Globalization; using ThinkGeo.MapSuite.Core; using ZedGraph; namespace Visualization { public class PieChartStyle : ZedGraphStyle { public PieChartStyle() { this.ZedGraphDrawing += new EventHandler<ZedGraphDrawingEventArgs>(zedGraphStyle_ZedGraphDrawing); this.RequiredColumnNames.Add("WHITE"); this.RequiredColumnNames.Add("ASIAN"); this.RequiredColumnNames.Add("Black"); this.RequiredColumnNames.Add("Other"); this.RequiredColumnNames.Add("AREANAME"); } private void zedGraphStyle_ZedGraphDrawing(object sender, ZedGraphDrawingEventArgs e) { ZedGraphControl zedGraph = new ZedGraphControl() { Size = new Size(100, 100) }; zedGraph.GraphPane.Fill.Type = FillType.None; zedGraph.GraphPane.Chart.Fill.Type = FillType.None; zedGraph.GraphPane.Border.IsVisible = false; zedGraph.GraphPane.Chart.Border.IsVisible = false; zedGraph.GraphPane.XAxis.IsVisible = false; zedGraph.GraphPane.YAxis.IsVisible = false; zedGraph.GraphPane.Legend.IsVisible = false; zedGraph.GraphPane.Title.IsVisible = false; PieItem pieItem1 = zedGraph.GraphPane.AddPieSlice(Convert.ToDouble(e.Feature.ColumnValues["WHITE"], CultureInfo.InvariantCulture), GetColorFromGeoColor(GeoColor.FromHtml("#93fc8f")), 0.08f, "White"); pieItem1.LabelDetail.IsVisible = false; PieItem pieItem2 = zedGraph.GraphPane.AddPieSlice(Convert.ToDouble(e.Feature.ColumnValues["ASIAN"], CultureInfo.InvariantCulture), GetColorFromGeoColor(GeoColor.FromHtml("#8ffbe8")), 0.08f, "Asian"); pieItem2.LabelDetail.IsVisible = false; PieItem pieItem3 = zedGraph.GraphPane.AddPieSlice(Convert.ToDouble(e.Feature.ColumnValues["Black"], CultureInfo.InvariantCulture), GetColorFromGeoColor(GeoColor.FromHtml("#cc8efa")), 0.08f, "Black"); pieItem3.LabelDetail.IsVisible = false; PieItem pieItem4 = zedGraph.GraphPane.AddPieSlice(Convert.ToDouble(e.Feature.ColumnValues["Other"], CultureInfo.InvariantCulture), GetColorFromGeoColor(GeoColor.FromHtml("#fcab8d")), 0.08f, "Other"); pieItem4.LabelDetail.IsVisible = false; zedGraph.AxisChange(); e.Bitmap = zedGraph.GraphPane.GetImage(); } private static Color GetColorFromGeoColor(GeoColor geoColor) { return Color.FromArgb(geoColor.AlphaComponent, geoColor.RedComponent, geoColor.GreenComponent, geoColor.BlueComponent); } } }
namespace Visualization { public enum ImageDirection { Right = 0, Left = 1 } }
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>Visualization</title> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <meta name="author" content="ThinkGeo" /> <link rel="apple-touch-icon" href="desktop.png"> <meta name="apple-mobile-web-app-title" content="Visualization" /> <link href="favicon.ico" rel="shortcut icon" type="Images/x-icon" /> <link href="Content/bootstrap.min.css" rel="stylesheet" /> <link href="Content/leaflet.css" rel="stylesheet" /> <link href="Content/Site.css" rel="stylesheet" /> </head> <body> <div id="map"> </div> <div id="loadingImage"> <img src="Images/ajax-loader.gif" /> </div> <div id="zedgraph-legend"> <img src="Images/zedgraph_lengend.png" /> </div> <div id="styles-panel"> <div id="styles-header" title="Close"> <span class="title">Style list</span> </div> <div class="panel-content"> <ul id="style-options"> <li> <div id="FilterStyle" title="FilterStyle" class="selected"> <span>Filter Style – US Population</span> </div> </li> <li> <div id="ClusterStyle" title="ClusterStyle" class="unselected"> <span>Cluster Style - US Earthquake</span> </div> </li> <li> <div id="CustomStyle" title="CustomStyle" class="unselected"> <span>Custom Style - Weather</span> </div> </li> <li> <div id="ZedGraphStyle" title="ZedGraphStyle" class="unselected"> <span>ZedGraph – US Demographic</span> </div> </li> <li> <div id="ClassBreakStyle" title="ClassBreakStyle" class="unselected"> <span>Class Break Style - US Population</span> </div> </li> <li> <div id="DotDensityStyle" title="DotDensityStyle" class="unselected"> <span>Dot Density – US Population</span> </div> </li> <li> <div id="IsolineStyle" title="IsolineStyle" class="unselected"> <span>Isoline Style - US Earthquake</span> </div> </li> <li> <div id="IconStyle" title="IconStyle" class="unselected"> <span>Icon Style – Vehicles</span> </div> </li> <li> <div id="HeatStyle" title="HeatStyle" class="unselected"> <span>Heat Style - US Earthquake</span> </div> </li> </ul> </div> </div> <div class="centroid"> <div id="edit-panel"> <div class="edit-panel-header"> <span id="settingTitle">LabelStyling Settings</span> </div> <div id="labelingStyleEdit" class="edit-content"> <ul> <li> <span class="edit-title">Column</span> <input type="text" readonly="true" value="Population" class="edit-item" /> </li> <li> <span class="edit-item-title">Condition</span> <select id="filterCondition" class="edit-item"> <option>GreaterThanOrEqualTo</option> <option>GreaterThan</option> <option>LessThanOrEqualTo</option> <option>LessThan</option> <option>Equal</option> <option>DoesNotEqual</option> </select> </li> <li> <span class="edit-title">Value</span> <input id="filterMatchValue" type="text" class="edit-item" value="3000000" /> </li> </ul> <div class="edit-foot"> <a id="btnCancel" href="#" class="btn btn-default" role="button">Cancel</a> <a id="btnSave" href="#" class="btn btn-primary" role="button">Save</a> </div> </div> </div> </div> <script src="Scripts/jquery-1.11.1.min.js"></script> <script src="Scripts/leaflet.js"></script> <script src="thinkgeo.leaflet.js"></script> <script> // create the map var map = L.map('map', { zoomAnimation: false }).setView([39.6948,|-96.8150], 4); // add thinkgeo map L.tileLayer.wms('http://{s}.thinkgeo.com/CachedWMSServer/WmsServer.axd', { subdomains: ['worldmapkit1',|'worldmapkit2', 'worldmapkit3', 'worldmapkit4', 'worldmapkit5', 'worldmapkit6'], layers: 'OSMWorldMapKitLayer', format: 'image/png', styles: 'WorldMapKitDefaultStyle', version: '1.1.1', attribution: '<a href="http://thinkgeo.com/map-suite-developer-gis/world-map-kit-sdk/">ThinkGeo</a> | © <a href="http://osm.org/copyright">OpenStreetMap</a> contributors ' }).addTo(map); // add dynamic tile layer to map var shapeLayer = L.dynamicLayer(L.Util.getRootPath() + '/tile/FilterStyle/{z}/{x}/{y}', { unloadInvisibleTiles: true, reuseTiles: true }).addTo(map); shapeLayer.on('loading', function () { $('#loadingImage').show(); }) shapeLayer.on('load', function () { $('#loadingImage').hide(); }) // add image buttons for layers, edit, help etc. L.imageButtons({ imgs: [ | { src: 'Images/layers.png', id: 'lyrOptions', title: 'Show layers', callback: function () { $('#styles-panel').animate({ 'left': '0px' }); } }, { src: 'Images/gear.png', id: 'btnConfig', title: 'Show style settings', css: 'active', callback: function () { showDlg(); } }, { src: 'Images/info.png', id: 'btnInfo', title: 'Show help', callback: function () { window.open('http://wiki.thinkgeo.com', '_blank'); } } ] }).addTo(map); // apply 'select' style after clicking on a style item on left-panel $('#style-options div').click(function () { var layers = $("#style-options div"); for (var i = 0; i < layers.length; i++) { $(layers[i]).attr("class", "unselected"); } $(this).attr("class", "selected"); // disable edit toolbar button var selectedLayer = $(this).attr('id'); $('#btnConfig').removeClass('active'); $('#btnConfig').removeClass('deactive'); if (selectedLayer == 'FilterStyle') { $('#btnConfig').addClass('active'); } else { $('#btnConfig').addClass('deactive'); } if (selectedLayer == 'ZedGraphStyle') { $('#zedgraph-legend').show(); } else { $('#zedgraph-legend').hide(); } // redraw the map redrawLayer(selectedLayer); }); function redrawLayer(layerId) { switch (layerId) { case 'IconStyle': map.setView([33.16342102407101,|-96.75676345825195], 13); break; case 'ZedGraphStyle': default: map.setView([39.6948,|-96.8150], 4); break; } shapeLayer.setUrl(L.Util.getRootPath() + '/tile/' + layerId + '/{z}/{x}/{y}'); shapeLayer.redraw(); } // click event for save button in edit dialog $('#btnSave').click(function () { var url = L.Util.getRootPath() + '/tile/UpdateStyle/' + $('#filterCondition option:selected').text() + '/' + $('#filterMatchValue').val(); $.get(url, function (data) { if (data) { hideDlg(); shapeLayer.redraw(); } else { alert('Update failed.'); } }); }); $('#btnCancel').click(function (e) { hideDlg(); }); // show/hide edit dialog in model mode function showDlg() { if ($('#btnConfig').hasClass('active')) { this.bgmask = L.DomUtil.create('div', 'bg-mask'); $('body').append(this.bgmask); $('#edit-panel').slideToggle("fast"); } } function hideDlg() { $('.bg-mask').remove(); $('#edit-panel').slideToggle("fast"); } // do the layers panel animation $("html").click(function () { $('#styles-panel').animate({ 'left': -$('#styles-panel').width() + 'px' }); }); </script> </body> </html>
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>Visualization</title> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <meta name="author" content="ThinkGeo" /> <link rel="apple-touch-icon" href="desktop.png"> <meta name="apple-mobile-web-app-title" content="Visualization" /> <link href="favicon.ico" rel="shortcut icon" type="Images/x-icon" /> <link href="Content/bootstrap.min.css" rel="stylesheet" /> <link href="Content/ol.css" rel="stylesheet" /> <link href="Content/thinkgeo.openlayers.css" rel="stylesheet" /> <link href="Content/Site.css" rel="stylesheet" /> </head> <body> <div id="map"> </div> <div id="loadingImage"> <img src="Images/ajax-loader.gif" /> </div> <div id="bg-mask" class="bg-mask"></div> <div id="zedgraph-legend"> <img src="Images/zedgraph_lengend.png" /> </div> <div id="styles-panel"> <div id="styles-header" title="Close"> <span class="title">Style list</span> </div> <div class="panel-content"> <ul id="style-options"> <li> <div id="FilterStyle" title="FilterStyle" class="selected"> <span>Filter Style – US Population</span> </div> </li> <li> <div id="ClusterStyle" title="ClusterStyle" class="unselected"> <span>Cluster Style - US Earthquake</span> </div> </li> <li> <div id="CustomStyle" title="CustomStyle" class="unselected"> <span>Custom Style - Weather</span> </div> </li> <li> <div id="ZedGraphStyle" title="ZedGraphStyle" class="unselected"> <span>ZedGraph – US Demographic</span> </div> </li> <li> <div id="ClassBreakStyle" title="ClassBreakStyle" class="unselected"> <span>Class Break Style - US Population</span> </div> </li> <li> <div id="DotDensityStyle" title="DotDensityStyle" class="unselected"> <span>Dot Density – US Population</span> </div> </li> <li> <div id="IsolineStyle" title="IsolineStyle" class="unselected"> <span>Isoline Style - US Earthquake</span> </div> </li> <li> <div id="IconStyle" title="IconStyle" class="unselected"> <span>Icon Style – Vehicles</span> </div> </li> <li> <div id="HeatStyle" title="HeatStyle" class="unselected"> <span>Heat Style - US Earthquake</span> </div> </li> </ul> </div> </div> <div class="centroid"> <div id="edit-panel"> <div class="edit-panel-header"> <span id="settingTitle">LabelStyling Settings</span> </div> <div id="labelingStyleEdit" class="edit-content"> <ul> <li> <span class="edit-title">Column</span> <input type="text" readonly="true" value="Population" class="edit-item" /> </li> <li> <span class="edit-item-title">Condition</span> <select id="filterCondition" class="edit-item"> <option>GreaterThanOrEqualTo</option> <option>GreaterThan</option> <option>LessThanOrEqualTo</option> <option>LessThan</option> <option>Equal</option> <option>DoesNotEqual</option> </select> </li> <li> <span class="edit-title">Value</span> <input id="filterMatchValue" type="text" class="edit-item" value="3000000" /> </li> </ul> <div class="edit-foot"> <a id="btnCancel" href="#" class="btn btn-default" role="button">Cancel</a> <a id="btnSave" href="#" class="btn btn-primary" role="button">Save</a> </div> </div> </div> </div> <script src="Scripts/jquery-1.11.1.min.js"></script> <script src="Scripts/ol.js"></script> <script src="thinkgeo.openlayers.js"></script> <script> var selectedLayer = 'FilterStyle'; // create the map var map = new ol.Map({ target: 'map', controls: ol.control.defaults({ attribution: false }).extend( [new|ol.control.Attribution({ collapsible: false })]), view: new ol.View({ center: [-10777396.499651,|4821690.0604384], zoom: 4 }) }); var worldmapkitlayer = new ol.layer.Tile({ source: new ol.source.TileWMS(({ urls: ['http://worldmapkit1.thinkgeo.com/CachedWMSServer/WmsServer.axd', | 'http://worldmapkit2.thinkgeo.com/CachedWMSServer/WmsServer.axd', 'http://worldmapkit3.thinkgeo.com/CachedWMSServer/WmsServer.axd', 'http://worldmapkit4.thinkgeo.com/CachedWMSServer/WmsServer.axd', 'http://worldmapkit5.thinkgeo.com/CachedWMSServer/WmsServer.axd', 'http://worldmapkit6.thinkgeo.com/CachedWMSServer/WmsServer.axd'], params: { 'LAYERS': 'OSMWorldMapKitLayer', 'VERSION': '1.1.1', 'STYLE': 'WorldMapKitDefaultStyle' }, attributions: [new|ol.Attribution({ html: '<a href="http://thinkgeo.com/map-suite-developer-gis/world-map-kit-sdk/">ThinkGeo</a> | © <a href="http://osm.org/copyright">OpenStreetMap</a> contributors <a href="http://www.openstreetmap.org/copyright">ODbL</a>' })] })) }); map.addLayer(worldmapkitlayer); var xyzSource = new ol.source.XYZ({ url: getRootPath() + '/tile/FilterStyle/{z}/{x}/{y}', maxZoom: 19 }); xyzSource.tileLoadFunction = function (imageTile, src) { imageTile.getImage().src = src + '?t=' + new Date().getTime();; }; map.addLayer(new ol.layer.Tile({ source: xyzSource })); var imgControls = new app.ImagesControl({ imgs: [ | { id: 'lyrOptions', src: 'Images/layers.png', title: 'Show layers', callback: function () { $('#styles-panel').animate({ 'left': '0px' }); } }, { id: 'btnConfig', src: 'Images/gear.png', title: 'Show style settings', css: 'active', callback: function () { showDlg(); } }, { id: 'btnInfo', src: 'Images/info.png', title: 'Show help', callback: function () { window.open('http://wiki.thinkgeo.com', '_blank'); } } ] }); map.addControl(imgControls); map.on("click", function () { $('#styles-panel').animate({ 'left': -$('#styles-panel').width() + 'px' }); }); // apply 'select' style after clicking on a style item on left-panel $('#style-options div').click(function () { var layers = $("#style-options div"); for (var i = 0; i < layers.length; i++) { $(layers[i]).attr("class", "unselected"); } $(this).attr("class", "selected"); // disable edit toolbar button selectedLayer = $(this).attr('id'); $('#btnConfig').removeClass('active'); $('#btnConfig').removeClass('deactive'); if (selectedLayer == 'FilterStyle') { $('#btnConfig').addClass('active'); } else { $('#btnConfig').addClass('deactive'); } if (selectedLayer == 'ZedGraphStyle') { $('#zedgraph-legend').show(); } else { $('#zedgraph-legend').hide(); } // redraw the map redrawLayer(); }); // click event for save button in edit dialog $('#btnSave').click(function () { var url = getRootPath() + '/tile/UpdateStyle/' + $('#filterCondition option:selected').text() + '/' + $('#filterMatchValue').val(); $.get(url, function (data) { if (data) { hideDlg(); redrawLayer(); } else { alert('Update failed.'); } }); }); $('#btnCancel').click(function (e) { hideDlg(); }); function redrawLayer() { switch (selectedLayer) { case 'IconStyle': map.setView(new ol.View({ center: [-10770913.637479,|3917015.5139286], zoom: 13 })); break; case 'ZedGraphStyle': default: map.setView(new ol.View({ center: [-10777396.499651,|4821690.0604384], zoom: 4 })); break; } xyzSource.setUrl(getRootPath() + '/tile/' + selectedLayer + '/{z}/{x}/{y}'); } // show/hide edit dialog in model mode function showDlg() { if ($('#btnConfig').hasClass('active')) { $('#bg-mask').show(); $('#edit-panel').slideToggle("fast"); } } function hideDlg() { $('#bg-mask').hide(); $('#edit-panel').slideToggle("fast"); } // do the layers panel animation $("html").click(function () { $('#styles-panel').animate({ 'left': -$('#styles-panel').width() + 'px' }); }); </script> </body> </html>