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.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 Newtonsoft.Json; using ThinkGeo.MapSuite.Core; using ThinkGeo.MapSuite.WebApiEdition; namespace Labeling.Controllers { [RoutePrefix("label")] public class LabelingController : ApiController { [Route("{z}/{x}/{y}")] public HttpResponseMessage GetBaseMapTile(int z, int x, int y) { // Create the LayerOverlay for displaying the map. LayerOverlay layerOverlay = OverlayBuilder.GetOverlayAsBaseMap(); return DrawTileImage(layerOverlay, x, y, z); } [Route("{overlayId}/{z}/{x}/{y}")] public HttpResponseMessage GetDynamicLayerTile(string overlayId, int z, int x, int y) { // Get layerOverlay specified by its id. LayerOverlay layerOverlay = GetLabelingOverlay(overlayId); return DrawTileImage(layerOverlay, x, y, z); } [Route("GetStyle/{overlayId}")] public Dictionary<string, object> GetStyle(string overlayId) { // Get layerOverlay specified by its id. LayerOverlay layerOverlay = GetLabelingOverlay(overlayId); Dictionary<string, object> styles = new Dictionary<string, object>(); switch (overlayId) { case "LabelStyling": styles = OverlayBuilder.GetLabelingStyle(layerOverlay); break; case "LabelingPoints": styles = OverlayBuilder.GetLabelingPointStyle(layerOverlay); break; case "LabelingLines": styles = OverlayBuilder.GetLabelingLineStyle(layerOverlay); break; case "LabelingPolygons": styles = OverlayBuilder.GetLabelingPolygonStyle(layerOverlay); break; case "CustomLabeling": styles = OverlayBuilder.GetCustomLabelingStyle(layerOverlay); break; default: break; } // Return the style defination in JSON saved on server side to client side. return styles; } [Route("Update/{overlayId}")] [HttpPost] public void UpdateTextStyle(string overlayId, [FromBody] string postData) { // Deserialize the style in JSON format passed from client side. Dictionary<string, string> styles = JsonConvert.DeserializeObject<Dictionary<string, string>>(postData); // Get layerOverlay specified by its id. LayerOverlay layerOverlay = GetLabelingOverlay(overlayId); switch (overlayId) { case "LabelStyling": OverlayBuilder.UpdateLabelingStyle(layerOverlay, styles); break; case "LabelingPoints": OverlayBuilder.UpdateLabelingPointStyle(layerOverlay, styles); break; case "LabelingLines": OverlayBuilder.UpdateLabelingLineStyle(layerOverlay, styles); break; case "LabelingPolygons": OverlayBuilder.UpdateLabelingPolygonStyle(layerOverlay, styles); break; case "CustomLabeling": OverlayBuilder.UpdateCustomLabelingStyle(layerOverlay, styles); break; default: break; } } private static HttpResponseMessage DrawTileImage(LayerOverlay layerOverlay, int x, int y, int z) { 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); if (layerOverlay != null) { layerOverlay.Draw(geoCanvas); } geoCanvas.EndDrawing(); MemoryStream memoryStream = new MemoryStream(); bitmap.Save(memoryStream, ImageFormat.Png); HttpResponseMessage message = new HttpResponseMessage(HttpStatusCode.OK); message.Content = new ByteArrayContent(memoryStream.ToArray()); message.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png"); return message; } } private static LayerOverlay GetLabelingOverlay(string id) { IHttpSessionState session = SessionStateUtility.GetHttpSessionStateFromContext(HttpContext.Current); Dictionary<string, LayerOverlay> overlays = session["overlays"] as Dictionary<string, LayerOverlay>; if (overlays == null) { overlays = new Dictionary<string, LayerOverlay>(); overlays.Add("LabelStyling", OverlayBuilder.GetOverlayWithLabelingStyle()); overlays.Add("LabelingPoints", OverlayBuilder.GetOverlayWithLabelingPoint()); overlays.Add("LabelingLines", OverlayBuilder.GetOverlayWithLabelingLine()); overlays.Add("LabelingPolygons", OverlayBuilder.GetOverlayWithLabelingPolygon()); overlays.Add("CustomLabeling", OverlayBuilder.GetOverlayWithCustomLabeling()); session["overlays"] = overlays; } LayerOverlay selectedOverlay = null; if (overlays.ContainsKey(id)) { selectedOverlay = overlays[id]; } return selectedOverlay; } } }
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using ThinkGeo.MapSuite.Core; namespace Labeling { [Serializable] public class CustomTextStyle : TextStyle { private float minFontSize; private float maxFontSize; public CustomTextStyle(string textColumnName, GeoFont textFont, GeoSolidBrush textSolidBrush) : base(textColumnName, textFont, textSolidBrush) { this.minFontSize = 8; this.MaxFontSize = 25; } public float MinFontSize { get { return minFontSize; } set { minFontSize = value; } } public float MaxFontSize { get { return maxFontSize; } set { maxFontSize = value; } } protected override void DrawCore(IEnumerable<Feature> features, GeoCanvas canvas, Collection<SimpleCandidate> labelsInThisLayer, Collection<SimpleCandidate> labelsInAllLayers) { TextStyle clonedStyle = new TextStyle(this.TextColumnName, this.Font, this.TextSolidBrush); clonedStyle.HaloPen = this.HaloPen; clonedStyle.Mask = this.Mask; clonedStyle.GridSize = this.GridSize; clonedStyle.OverlappingRule = this.OverlappingRule; clonedStyle.DuplicateRule = this.DuplicateRule; float fontSize = Convert.ToInt32(50000 / canvas.CurrentScale); if (fontSize < minFontSize) { fontSize = minFontSize; } else if (fontSize > maxFontSize) { fontSize = maxFontSize; } clonedStyle.Font = new GeoFont(clonedStyle.Font.FontName, fontSize, clonedStyle.Font.Style); clonedStyle.Draw(features, canvas, labelsInThisLayer, labelsInAllLayers); } } }
using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using ThinkGeo.MapSuite.Core; using ThinkGeo.MapSuite.WebApiEdition; namespace Labeling { public static class OverlayBuilder { // Initialize the grid size for filtering the labels. private static Dictionary<string, int> gridSizeConfigurations = new Dictionary<string, int>() { { "Small", 100 }, { "Medium", 500 }, { "Large", 1000 } }; /// <summary> /// Gets an overlay used as base map. /// </summary> public static LayerOverlay GetOverlayAsBaseMap() { // Create the LayerOverlay for displaying the map. LayerOverlay labelingStyleOverlay = new LayerOverlay(); // Create the parcels layer. ShapeFileFeatureLayer parcelLayer = new ShapeFileFeatureLayer(string.Format(@"{0}\{1}", GetBaseDirectory(), "Parcels.shp")); parcelLayer.ZoomLevelSet.ZoomLevel10.DefaultAreaStyle = new AreaStyle(new GeoPen(GeoColor.FromHtml("#d6d5d4"), 2), new GeoSolidBrush(GeoColor.FromHtml("#faf7f3")), PenBrushDrawingOrder.PenFirst); parcelLayer.ZoomLevelSet.ZoomLevel10.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; labelingStyleOverlay.Layers.Add("parcel", parcelLayer); // Create the pois layer. ShapeFileFeatureLayer restaurantsLayer = new ShapeFileFeatureLayer(string.Format(@"{0}\{1}", GetBaseDirectory(), "Pois.shp")); restaurantsLayer.ZoomLevelSet.ZoomLevel10.DefaultPointStyle = new PointStyle(PointSymbolType.Circle, new GeoSolidBrush(GeoColor.FromHtml("#99cc33")), new GeoPen(GeoColor.FromHtml("#666666"), 1), 3); restaurantsLayer.ZoomLevelSet.ZoomLevel10.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; // Set DrawingMarginPercentage to a proper value to avoid some labels are cut-off restaurantsLayer.DrawingMarginPercentage = 300; labelingStyleOverlay.Layers.Add("street", restaurantsLayer); // Create the streets layer. ShapeFileFeatureLayer streetLayer = new ShapeFileFeatureLayer(string.Format(@"{0}\{1}", GetBaseDirectory(), "Street.shp")); // Add a copy of road stype to make sure the end of line shape is round cap. ClassBreakStyle roadStyleCopy = new ClassBreakStyle("Type"); ClassBreak localRoadBreak = new ClassBreak(); localRoadBreak.Value = 6.9; localRoadBreak.DefaultLineStyle = new LineStyle(new GeoPen(GeoColor.FromHtml("#d6d5d4"), 8f), new GeoPen(GeoColor.FromHtml("#ffffff"), 6f)); localRoadBreak.DefaultLineStyle.CenterPen.EndCap = DrawingLineCap.Round; localRoadBreak.DefaultLineStyle.OuterPen.EndCap = DrawingLineCap.Round; roadStyleCopy.ClassBreaks.Add(localRoadBreak); streetLayer.ZoomLevelSet.ZoomLevel10.CustomStyles.Add(roadStyleCopy); // Define the style of streets based on its type. ClassBreakStyle roadStyle = new ClassBreakStyle("Type"); roadStyle.BreakValueInclusion = BreakValueInclusion.ExcludeValue; ClassBreak highwayBreak = new ClassBreak(); highwayBreak.Value = 0.9; highwayBreak.DefaultLineStyle = new LineStyle(new GeoPen(GeoColor.FromHtml("#a2a09c"), 12f), new GeoPen(GeoColor.FromHtml("#f7c67f"), 10f)); highwayBreak.DefaultLineStyle.CenterPen.EndCap = DrawingLineCap.Round; highwayBreak.DefaultLineStyle.OuterPen.EndCap = DrawingLineCap.Round; roadStyle.ClassBreaks.Add(highwayBreak); ClassBreak majorRoadBreak = new ClassBreak(); majorRoadBreak.Value = 3.8; majorRoadBreak.DefaultLineStyle = new LineStyle(new GeoPen(GeoColor.FromHtml("#d6d5d4"), 10f), new GeoPen(GeoColor.FromHtml("#f5e8cb"), 8f)); majorRoadBreak.DefaultLineStyle.CenterPen.EndCap = DrawingLineCap.Round; majorRoadBreak.DefaultLineStyle.OuterPen.EndCap = DrawingLineCap.Round; roadStyle.ClassBreaks.Add(majorRoadBreak); ClassBreak minorRoadBreak = new ClassBreak(); minorRoadBreak.Value = 6.9; minorRoadBreak.DefaultLineStyle = new LineStyle(new GeoPen(GeoColor.SimpleColors.Transparent), new GeoPen(GeoColor.SimpleColors.Transparent)); roadStyle.ClassBreaks.Add(minorRoadBreak); streetLayer.ZoomLevelSet.ZoomLevel10.CustomStyles.Add(roadStyle); streetLayer.ZoomLevelSet.ZoomLevel10.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; streetLayer.DrawingMarginPercentage = 200; labelingStyleOverlay.Layers.Add("poi", streetLayer); return labelingStyleOverlay; } /// <summary> /// Gets an overlay applied with customized labeling style. /// </summary> public static LayerOverlay GetOverlayWithCustomLabeling() { LayerOverlay customLabelingOverlay = new LayerOverlay(); ShapeFileFeatureLayer poiLayer = new ShapeFileFeatureLayer(string.Format(@"{0}\{1}", GetBaseDirectory(), "Pois.shp")); customLabelingOverlay.Layers.Add("customLabeling_Label", poiLayer); poiLayer.ZoomLevelSet.ZoomLevel10.DefaultPointStyle = new PointStyle(PointSymbolType.Circle, new GeoSolidBrush(GeoColor.FromHtml("#99cc33")), new GeoPen(GeoColor.FromHtml("#666666"), 1), 7); poiLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle = new CustomTextStyle("Name", new GeoFont("Arail", 9, DrawingFontStyles.Bold), new GeoSolidBrush(GeoColor.SimpleColors.Black)); poiLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.HaloPen = new GeoPen(GeoColor.StandardColors.White, 1); poiLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.Mask = new AreaStyle(); poiLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.XOffsetInPixel = 10; poiLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.YOffsetInPixel = 10; poiLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.PointPlacement = PointPlacement.Center; poiLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.OverlappingRule = LabelOverlappingRule.NoOverlapping; poiLayer.ZoomLevelSet.ZoomLevel10.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; // Set DrawingMarginPercentage to a proper value to avoid some labels are cut-off poiLayer.DrawingMarginPercentage = 600; return customLabelingOverlay; } /// <summary> /// Gets the labeling style applied to a specified overlay with customized labeling style. /// </summary> public static Dictionary<string, object> GetCustomLabelingStyle(LayerOverlay overlay) { Dictionary<string, object> styles = new Dictionary<string, object>(); ShapeFileFeatureLayer layer = overlay.Layers[0] as ShapeFileFeatureLayer; CustomTextStyle customLabelStyle = layer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle as CustomTextStyle; if (customLabelStyle != null) { styles.Add("minSize", customLabelStyle.MinFontSize.ToString()); styles.Add("maxSize", customLabelStyle.MaxFontSize.ToString()); } return styles; } /// <summary> /// Updates the specified style to a specified overlay. /// </summary> public static void UpdateCustomLabelingStyle(LayerOverlay overlay, Dictionary<string, string> styles) { float minSize = 0, maxSize = 0; if (float.TryParse(styles["minSize"], out minSize) && float.TryParse(styles["maxSize"], out maxSize)) { foreach (ShapeFileFeatureLayer item in overlay.Layers) { CustomTextStyle customLabelStyle = item.ZoomLevelSet.ZoomLevel10.DefaultTextStyle as CustomTextStyle; customLabelStyle.MinFontSize = minSize; customLabelStyle.MaxFontSize = maxSize; } } } /// <summary> /// Gets an overlay for showing streets. /// </summary> public static LayerOverlay GetOverlayWithLabelingLine() { LayerOverlay labelingLinesOverlay = new LayerOverlay(); ShapeFileFeatureLayer streetLayer = new ShapeFileFeatureLayer(string.Format(@"{0}\{1}", GetBaseDirectory(), "Street.shp")); labelingLinesOverlay.Layers.Add("street_Label", streetLayer); // Create a classBreakStyle for different type of roads ClassBreakStyle roadStyle = new ClassBreakStyle("Type"); roadStyle.BreakValueInclusion = BreakValueInclusion.ExcludeValue; ClassBreak break1 = new ClassBreak(); break1.Value = 0.9; break1.DefaultTextStyle = new TextStyle("ROAD_NAME", new GeoFont("Arial", 12, DrawingFontStyles.Regular), new GeoSolidBrush(GeoColor.FromHtml("#666666"))); break1.DefaultTextStyle.HaloPen = new GeoPen(GeoColor.SimpleColors.White, 2); break1.DefaultTextStyle.SplineType = SplineType.ForceSplining; break1.DefaultTextStyle.Mask = new AreaStyle(); roadStyle.ClassBreaks.Add(break1); ClassBreak break2 = new ClassBreak(); break2.Value = 3.8; break2.DefaultTextStyle = new TextStyle("ROAD_NAME", new GeoFont("Arial", 8, DrawingFontStyles.Bold), new GeoSolidBrush(GeoColor.FromHtml("#666666"))); break2.DefaultTextStyle.HaloPen = new GeoPen(GeoColor.SimpleColors.White, 1); break2.DefaultTextStyle.SplineType = SplineType.ForceSplining; break2.DefaultTextStyle.Mask = new AreaStyle(); roadStyle.ClassBreaks.Add(break2); ClassBreak break3 = new ClassBreak(); break3.Value = 7; break3.DefaultTextStyle = new TextStyle("ROAD_NAME", new GeoFont("Arial", 6, DrawingFontStyles.Regular), new GeoSolidBrush(GeoColor.FromHtml("#666666"))); break3.DefaultTextStyle.Mask = new AreaStyle(); break3.DefaultTextStyle.SplineType = SplineType.ForceSplining; roadStyle.ClassBreaks.Add(break3); streetLayer.ZoomLevelSet.ZoomLevel10.CustomStyles.Add(roadStyle); streetLayer.ZoomLevelSet.ZoomLevel10.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; // Set DrawingMarginPercentage to a proper value to avoid some labels are cut-off streetLayer.DrawingMarginPercentage = 200; return labelingLinesOverlay; } /// <summary> /// Gets the labeling style applied to streets. /// </summary> public static Dictionary<string, object> GetLabelingLineStyle(LayerOverlay overlay) { ShapeFileFeatureLayer layer = overlay.Layers[0] as ShapeFileFeatureLayer; ClassBreakStyle classBreakStyle = layer.ZoomLevelSet.ZoomLevel10.CustomStyles[0] as ClassBreakStyle; Dictionary<string, object> styles = new Dictionary<string, object>(); if (classBreakStyle != null && classBreakStyle.ClassBreaks.Count > 0) { styles.Add("spline", classBreakStyle.ClassBreaks[0].DefaultTextStyle.SplineType.ToString()); styles.Add("lineSegmentRatio", classBreakStyle.ClassBreaks[0].DefaultTextStyle.TextLineSegmentRatio.ToString()); } return styles; } /// <summary> /// Updates the specified style to a specified overlay. /// </summary> public static void UpdateLabelingLineStyle(LayerOverlay overlay, Dictionary<string, string> styles) { SplineType splineType = SplineType.Default; double lineSegmentRatio = 0; if (Enum.TryParse<SplineType>(styles["spline"], out splineType) && double.TryParse(styles["lineSegmentRatio"], out lineSegmentRatio)) { foreach (string layerId in overlay.Layers.GetKeys()) { ShapeFileFeatureLayer featureLayer = overlay.Layers[layerId] as ShapeFileFeatureLayer; ClassBreakStyle classBreakStyle = featureLayer.ZoomLevelSet.ZoomLevel10.CustomStyles[0] as ClassBreakStyle; foreach (var classBreak in classBreakStyle.ClassBreaks) { classBreak.DefaultTextStyle.SplineType = splineType; classBreak.DefaultTextStyle.TextLineSegmentRatio = lineSegmentRatio; } } } } /// <summary> /// Gets an overlay for showing points. /// </summary> public static LayerOverlay GetOverlayWithLabelingPoint() { LayerOverlay labelingPointsOverlay = new LayerOverlay(); ShapeFileFeatureLayer poiLayer = new ShapeFileFeatureLayer(string.Format(CultureInfo.InvariantCulture, @"{0}\{1}", GetBaseDirectory(), "Pois.shp")); labelingPointsOverlay.Layers.Add("poi_Label", poiLayer); poiLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle = new TextStyle("Name", new GeoFont("Arail", 9, DrawingFontStyles.Bold), new GeoSolidBrush(GeoColor.SimpleColors.Black)); poiLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.HaloPen = new GeoPen(GeoColor.StandardColors.White, 2); poiLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.Mask = new AreaStyle(new GeoPen(GeoColor.FromHtml("#999999"), 1), new GeoSolidBrush(new GeoColor(100, GeoColor.FromHtml("#cccc99"))), PenBrushDrawingOrder.PenFirst); poiLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.XOffsetInPixel = 0; poiLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.YOffsetInPixel = 8; poiLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.PointPlacement = PointPlacement.UpperCenter; poiLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.OverlappingRule = LabelOverlappingRule.NoOverlapping; poiLayer.ZoomLevelSet.ZoomLevel10.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; // Set DrawingMarginPercentage to a proper value to avoid some labels are cut-off poiLayer.DrawingMarginPercentage = 100; return labelingPointsOverlay; } /// <summary> /// Gets the labeling style applied to streets. /// </summary> public static Dictionary<string, object> GetLabelingPointStyle(LayerOverlay overlay) { Dictionary<string, object> styles = new Dictionary<string, object>(); ShapeFileFeatureLayer layer = overlay.Layers[0] as ShapeFileFeatureLayer; styles.Add("placement", layer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.PointPlacement.ToString()); styles.Add("xoffset", layer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.XOffsetInPixel.ToString()); styles.Add("yoffset", layer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.YOffsetInPixel.ToString()); return styles; } /// <summary> /// Updates the specified style to a specified overlay. /// </summary> public static void UpdateLabelingPointStyle(LayerOverlay overlay, Dictionary<string, string> styles) { PointPlacement placement = PointPlacement.Center; float xOffset = 0f; float yOffset = 0f; if (Enum.TryParse<PointPlacement>(styles["placement"], out placement) && float.TryParse(styles["xoffset"], out xOffset) && float.TryParse(styles["yoffset"], out yOffset)) { foreach (string layerId in overlay.Layers.GetKeys()) { ShapeFileFeatureLayer featureLayer = overlay.Layers[layerId] as ShapeFileFeatureLayer; featureLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.PointPlacement = placement; featureLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.XOffsetInPixel = xOffset; featureLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.YOffsetInPixel = yOffset; } } } /// <summary> /// Gets an overlay for showing polygons(Parcel). /// </summary> public static LayerOverlay GetOverlayWithLabelingPolygon() { LayerOverlay labelingPolygonsOverlay = new LayerOverlay(); ShapeFileFeatureLayer subdivisionsLayer = new ShapeFileFeatureLayer(string.Format(@"{0}\{1}", GetBaseDirectory(), "Subdivisions.shp")); labelingPolygonsOverlay.Layers.Add("subdivision_Label", subdivisionsLayer); subdivisionsLayer.ZoomLevelSet.ZoomLevel10.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.StandardColors.White, GeoColor.FromHtml("#9C9C9C"), 1); subdivisionsLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle = new TextStyle("NAME_COMMO", new GeoFont("Arail", 9, DrawingFontStyles.Bold), new GeoSolidBrush(GeoColor.SimpleColors.Black)); subdivisionsLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.HaloPen = new GeoPen(GeoColor.StandardColors.White, 1); subdivisionsLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.Mask = new AreaStyle(); subdivisionsLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.BestPlacement = true; subdivisionsLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.GridSize = 100; subdivisionsLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.OverlappingRule = LabelOverlappingRule.NoOverlapping; subdivisionsLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.DuplicateRule = LabelDuplicateRule.NoDuplicateLabels; subdivisionsLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.SuppressPartialLabels = true; subdivisionsLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.FittingPolygon = true; subdivisionsLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.FittingPolygonFactor = 18; subdivisionsLayer.ZoomLevelSet.ZoomLevel10.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; return labelingPolygonsOverlay; } /// <summary> /// Gets the labeling style applied to streets. /// </summary> public static Dictionary<string, object> GetLabelingPolygonStyle(LayerOverlay overlay) { Dictionary<string, object> styles = new Dictionary<string, object>(); ShapeFileFeatureLayer layer = overlay.Layers[0] as ShapeFileFeatureLayer; styles.Add("fittingFactors", layer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.FittingPolygonFactor > 1.0); styles.Add("labelAllPolygonParts", layer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.LabelAllPolygonParts); return styles; } /// <summary> /// Updates the specified style to a specified overlay. /// </summary> public static void UpdateLabelingPolygonStyle(LayerOverlay overlay, Dictionary<string, string> styles) { bool fittingFactors = true; bool labelAllPolygonParts = true; if (bool.TryParse(styles["fittingFactors"], out fittingFactors) && bool.TryParse(styles["labelAllPolygonParts"], out labelAllPolygonParts)) { foreach (string layerId in overlay.Layers.GetKeys()) { ShapeFileFeatureLayer featureLayer = overlay.Layers[layerId] as ShapeFileFeatureLayer; featureLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.FittingPolygonFactor = fittingFactors ? 18.0 : 1.0; featureLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.LabelAllPolygonParts = labelAllPolygonParts; } } } /// <summary> /// Gets an overlay of displaying kinds of labels. /// </summary> public static LayerOverlay GetOverlayWithLabelingStyle() { LayerOverlay labelingStyleOverlay = new LayerOverlay(); /*Load Frisco Parcel Layer*/ ShapeFileFeatureLayer parcelLayer = GetLabelingStyleParcelLayer(); labelingStyleOverlay.Layers.Add("parcel_Label", parcelLayer); /*Load Frisco Street Layer*/ ShapeFileFeatureLayer streetLabelingLayer = GetLabelingStreetLayer(); labelingStyleOverlay.Layers.Add("street_Label", streetLabelingLayer); /*Load Frisco Pois Layer*/ ShapeFileFeatureLayer poisLayer = GetLabelingStylePoisLayer(); labelingStyleOverlay.Layers.Add("poi_Label", poisLayer); return labelingStyleOverlay; } /// <summary> /// Gets the labeling style applied to a specified overlay. /// </summary> public static Dictionary<string, object> GetLabelingStyle(LayerOverlay overlay) { Dictionary<string, object> styles = new Dictionary<string, object>(); TextStyle textStyle = ((ShapeFileFeatureLayer)overlay.Layers[0]).ZoomLevelSet.ZoomLevel10.DefaultTextStyle; styles["haloPen"] = textStyle.HaloPen.Color.AlphaComponent != 0; styles["mask"] = textStyle.Mask.IsActive; styles["overlapping"] = textStyle.OverlappingRule == LabelOverlappingRule.AllowOverlapping; styles["duplicate"] = textStyle.DuplicateRule.ToString(); styles["drawingMargin"] = ((ShapeFileFeatureLayer)overlay.Layers[0]).DrawingMarginPercentage.ToString(); styles["gridSize"] = "Small"; foreach (var item in gridSizeConfigurations) { if (item.Value == textStyle.GridSize) { styles["gridSize"] = item.Key; break; } } return styles; } /// <summary> /// Updates the specified style to a specified overlay. /// </summary> public static void UpdateLabelingStyle(LayerOverlay overlay, Dictionary<string, string> styles) { string haloPen = styles["haloPen"]; string mask = styles["mask"]; string overlapping = styles["overlapping"]; string duplicateRule = styles["duplicate"]; string gridSize = styles["gridSize"]; string drawingMargin = styles["drawingMargin"]; if (overlay.Layers.Count > 0) { bool useHalopen = false; bool useMask = false; bool allowOverlapping = false; LabelDuplicateRule labelDuplicateRule = LabelDuplicateRule.OneDuplicateLabelPerQuadrant; double drawingMarginPercentage = 0; if (bool.TryParse(haloPen, out useHalopen) && bool.TryParse(mask, out useMask) && bool.TryParse(overlapping, out allowOverlapping) && Enum.TryParse<LabelDuplicateRule>(duplicateRule, out labelDuplicateRule) && double.TryParse(drawingMargin, out drawingMarginPercentage) && gridSizeConfigurations.ContainsKey(gridSize)) { int gridSizeValue = gridSizeConfigurations[gridSize]; foreach (string layerId in overlay.Layers.GetKeys()) { ShapeFileFeatureLayer featureLayer = overlay.Layers[layerId] as ShapeFileFeatureLayer; List<TextStyle> textStyles = new List<TextStyle>(); if (featureLayer.ZoomLevelSet.ZoomLevel10.CustomStyles.Count > 0) { ClassBreakStyle classBreakStyle = featureLayer.ZoomLevelSet.ZoomLevel10.CustomStyles[0] as ClassBreakStyle; textStyles = classBreakStyle.ClassBreaks.Select(c => c.DefaultTextStyle).ToList(); } else { textStyles.Add(featureLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle); } foreach (var textStyle in textStyles) { int red = textStyle.HaloPen.Color.RedComponent; int green = textStyle.HaloPen.Color.GreenComponent; int blue = textStyle.HaloPen.Color.BlueComponent; int alpha = useHalopen ? 255 : 0; textStyle.HaloPen = new GeoPen(GeoColor.FromArgb(alpha, red, green, blue), textStyle.HaloPen.Width); textStyle.Mask.IsActive = useMask; textStyle.OverlappingRule = allowOverlapping ? LabelOverlappingRule.AllowOverlapping : LabelOverlappingRule.NoOverlapping; textStyle.DuplicateRule = labelDuplicateRule; textStyle.GridSize = gridSizeValue; featureLayer.DrawingMarginPercentage = drawingMarginPercentage; } } } } } private static ShapeFileFeatureLayer GetLabelingStyleParcelLayer() { ShapeFileFeatureLayer parcelLayer = new ShapeFileFeatureLayer(string.Format(@"{0}\{1}", GetBaseDirectory(), "Parcels.shp")); // Here shows how to apply text style to a layer /// We can use predefined style using the code like: //parcelLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle = TextStyles.Park1("X_REF"); // Or creating a simple one using the code like: //parcelLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle = TextStyles.CreateSimpleTextStyle("X_REF", "Arial", 9, DrawingFontStyles.Regular, GeoColor.FromHtml("#d9ccbe")); // Or create a new one by ourselves parcelLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle = new TextStyle("X_REF", new GeoFont("Arail", 6, DrawingFontStyles.Regular), new GeoSolidBrush(GeoColor.FromHtml("#7b7b78"))); parcelLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.DuplicateRule = LabelDuplicateRule.NoDuplicateLabels; parcelLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.GridSize = 1000; parcelLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.HaloPen = new GeoPen(GeoColor.SimpleColors.White, 1); parcelLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.Mask = new AreaStyle(); parcelLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.OverlappingRule = LabelOverlappingRule.NoOverlapping; parcelLayer.ZoomLevelSet.ZoomLevel10.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; // Set DrawingMarginPercentage to a proper value to avoid some labels are cut-off parcelLayer.DrawingMarginPercentage = 300; return parcelLayer; } private static ShapeFileFeatureLayer GetLabelingStylePoisLayer() { ShapeFileFeatureLayer restaurantsLayer = new ShapeFileFeatureLayer(string.Format(@"{0}\{1}", GetBaseDirectory(), "Pois.shp")); restaurantsLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle = new TextStyle("Name", new GeoFont("Arail", 8, DrawingFontStyles.Bold), new GeoSolidBrush(GeoColor.FromHtml("#666666"))); restaurantsLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.HaloPen = new GeoPen(GeoColor.SimpleColors.White, 1); restaurantsLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.XOffsetInPixel = 5; restaurantsLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.Mask = new AreaStyle(new GeoPen(GeoColor.FromHtml("#999999"), 1), new GeoSolidBrush(new GeoColor(100, GeoColor.FromHtml("#eeeeee"))), PenBrushDrawingOrder.PenFirst); restaurantsLayer.ZoomLevelSet.ZoomLevel10.DefaultTextStyle.OverlappingRule = LabelOverlappingRule.NoOverlapping; restaurantsLayer.ZoomLevelSet.ZoomLevel10.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; // Set DrawingMarginPercentage to a proper value to avoid some labels are cut-off restaurantsLayer.DrawingMarginPercentage = 300; return restaurantsLayer; } private static ShapeFileFeatureLayer GetLabelingStreetLayer() { ShapeFileFeatureLayer streetLayer = new ShapeFileFeatureLayer(string.Format(@"{0}\{1}", GetBaseDirectory(), "Street.shp")); // Create a classBreakStyle for different type of roads ClassBreakStyle roadStyle = new ClassBreakStyle("Type"); roadStyle.BreakValueInclusion = BreakValueInclusion.ExcludeValue; ClassBreak break1 = new ClassBreak(); break1.Value = 0.9; break1.DefaultTextStyle = new TextStyle("ROAD_NAME", new GeoFont("Arial", 12, DrawingFontStyles.Regular), new GeoSolidBrush(GeoColor.FromHtml("#666666"))); break1.DefaultTextStyle.HaloPen = new GeoPen(GeoColor.SimpleColors.White, 2); break1.DefaultTextStyle.Mask = new AreaStyle(); roadStyle.ClassBreaks.Add(break1); ClassBreak break2 = new ClassBreak(); break2.Value = 3.8; break2.DefaultTextStyle = new TextStyle("ROAD_NAME", new GeoFont("Arial", 8, DrawingFontStyles.Bold), new GeoSolidBrush(GeoColor.FromHtml("#666666"))); break2.DefaultTextStyle.HaloPen = new GeoPen(GeoColor.SimpleColors.White, 1); break2.DefaultTextStyle.Mask = new AreaStyle(); roadStyle.ClassBreaks.Add(break2); ClassBreak break3 = new ClassBreak(); break3.Value = 7; break3.DefaultTextStyle = new TextStyle("ROAD_NAME", new GeoFont("Arial", 6, DrawingFontStyles.Regular), new GeoSolidBrush(GeoColor.FromHtml("#666666"))); break3.DefaultTextStyle.Mask = new AreaStyle(); roadStyle.ClassBreaks.Add(break3); streetLayer.ZoomLevelSet.ZoomLevel10.CustomStyles.Add(roadStyle); streetLayer.ZoomLevelSet.ZoomLevel10.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; // Set DrawingMarginPercentage to a proper value to avoid some labels are cut-off streetLayer.DrawingMarginPercentage = 200; return streetLayer; } private static string GetBaseDirectory() { Uri uri = new Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase); string rootDirectory = Path.GetDirectoryName(Path.GetDirectoryName(uri.LocalPath)); return Path.Combine(rootDirectory, "App_Data"); ; } } }
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Labeling</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="Labeling" /> <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="left-panel"> <div class="panel-header" title="Close"> <span class="title">Layer List</span> </div> <div class="panel-content"> <ul id="layer-options"> <li> <div id="layer-styling" title="LabelStyling" class="selected"> <span>Label Styling</span> </div> </li> <li> <div id="layer-point" title="LabelingPoints" class="unselected"> <span>Labeling Points</span> </div> </li> <li> <div id="layer-line" title="LabelingLines" class="unselected"> <span>Labeling Lines</span> </div> </li> <li> <div id="layer-area" title="LabelingPolygons" class="unselected"> <span>Labeling Polygons</span> </div> </li> <li> <div id="layer-custom" title="CustomLabeling" class="unselected"> <span>Custom Labeling – Auto Scaling</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"> <!--please put the dialog here--> </div> <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> <script src="Scripts/jquery-1.11.1.min.js"></script> <script src="Scripts/leaflet.js"></script> <script src="thinkgeo.leaflet.js"></script> <script> var selectedLayer = 'LabelStyling'; $(function () { // add map var map = L.map('map').setView([33.1010,|-96.8134], 17); // add base street layer without any label from the web API controller of this Project var streetLayer = L.tileLayer(L.Util.getRootPath() + '/label/{z}/{x}/{y}').addTo(map); // add dynamic tile layer to map from the web API controller of this Project var tileLayer = L.dynamicLayer(L.Util.getRootPath() + '/label/LabelStyling/{z}/{x}/{y}').addTo(map); // add image buttons for layers, settings, help etc. L.imageButtons({ imgs: [ | { src: 'Images/layers.png', id: 'lyrOptions', title: 'Show layers', callback: function () { $('#left-panel').animate({ 'left': '0px' }); } }, { src: 'Images/gear.png', id: 'btnConfig', title: 'Show style settings', callback: function () { showStyleDlg(); loadStyleDlg(); } }, { src: 'Images/info.png', id: 'btnInfo', title: 'Show help', callback: function () { window.open('http://wiki.thinkgeo.com', '_blank'); } } ] }).addTo(map); var loadStyleDlg = function () { var pageUrl = 'labelingStyleEdit.html'; switch (selectedLayer) { case 'LabelingPoints': pageUrl = 'LabelingPointsEdit.html'; break; case 'LabelingLines': pageUrl = 'LabelingLinesEdit.html'; break; case 'LabelingPolygons': pageUrl = 'LabelingPolygonsEdit.html'; break; case 'CustomLabeling': pageUrl = 'CustomLabelingEdit.html'; break; case 'LabelStyling': default: break; } // load style editing page dynamically from the web API controller of this Project $('#labelingStyleEdit').load('EditPages/' + pageUrl, function () { var url = L.Util.getRootPath() + '/label/GetStyle/' + selectedLayer; $.get(url, function (data) { switch (selectedLayer) { case 'LabelStyling': $('#applyHalo').prop('checked', data.haloPen); $('#applyMask').prop('checked', data.mask); $('#isOverlap').prop('checked', data.overlapping); $('#gridSize').val(data.gridSize); $('#duplicateRule').val(data.duplicate); $('#drawingMargin').val(data.drawingMargin); break; case 'LabelingPoints': $('#applyPlace').val(data.placement), $('#xOffset').val(data.xoffset), $('#yOffset').val(data.yoffset) break; case 'LabelingLines': $('#applySpline').val(data.spline), $('#applyLineSegmentRatio').val(data.lineSegmentRatio) break; case 'LabelingPolygons': $('#applyFittingFactors').prop('checked', data.fittingFactors), $('#applyLabelAllPolygonParts').prop('checked', data.labelAllPolygonParts) break; case 'CustomLabeling': $('#applyMinFontSize').val(data.minSize), $('#applyMaxFontSize').val(data.maxSize) break; default: break; } }); }); }; // save the style modified $('#btnSave').click(function (e) { var changes = null; switch (selectedLayer) { case 'LabelStyling': changes = { haloPen: $('#applyHalo').is(':checked'), mask: $('#applyMask').is(':checked'), overlapping: $('#isOverlap').is(':checked'), gridSize: $('#gridSize option:selected').text(), duplicate: $('#duplicateRule option:selected').text(), drawingMargin: $('#drawingMargin').val() }; break; case 'LabelingPoints': changes = { placement: $('#applyPlace option:selected').text(), xoffset: $('#xOffset').val(), yoffset: $('#yOffset').val() }; break; case 'LabelingLines': changes = { placement: $('#applyPlace option:selected').text(), spline: $('#applySpline option:selected').text(), lineSegmentRatio: $('#applyLineSegmentRatio').val() }; break; case 'LabelingPolygons': changes = { placement: $('#applyPlace option:selected').text(), fittingFactors: $('#applyFittingFactors').is(':checked'), labelAllPolygonParts: $('#applyLabelAllPolygonParts').is(':checked') }; break; case 'CustomLabeling': changes = { minSize: $('#applyMinFontSize').val(), maxSize: $('#applyMaxFontSize').val() }; break; default: break; } // Here we post back to the web API controller of this Project $.post(L.Util.getRootPath() + '/label/update/' + selectedLayer, { //: JSON.stringify(changes) }, function (e) { tileLayer.redraw(); hideStyleDlg(); }); }); $('#btnCancel').click(function (e) { hideStyleDlg(); }); // select a style from options $("#layer-options div").bind("click", function () { var layers = $("#layer-options div"); for (var i = 0; i < layers.length; i++) { $(layers[i]).attr("class", "unselected"); } $(this).attr("class", "selected"); // redraw the map selectedLayer = $(this).attr("title"); tileLayer.setUrl(L.Util.getRootPath() + '/label/' + selectedLayer + '/{z}/{x}/{y}'); tileLayer.redraw(); if (selectedLayer === 'LabelingPolygons') { streetLayer.setOpacity(0); map.setView([33.1010,|-96.8134], 16); } else if (selectedLayer === 'LabelingLines') { streetLayer.setOpacity(1); map.setView([33.098772,|-96.82198], 17); } else { streetLayer.setOpacity(1); map.setView([33.1010,|-96.8134], 17); } }); // show model-dialog function showStyleDlg() { this.bgmask = L.DomUtil.create('div', 'bg-mask'); $('body').append(this.bgmask); $('#edit-panel').slideToggle("fast"); } function hideStyleDlg() { $('.bg-mask').remove(); $('#edit-panel').slideToggle("fast"); } // do the layers panel animation $("html").click(function () { $('#left-panel').animate({ 'left': -$('#left-panel').width() + 'px' }); }); }); </script> </body> </html>
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Labeling</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="Labeling" /> <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/Site.css" rel="stylesheet" /> <link href="Content/thinkgeo.openlayers.css" rel="stylesheet" /> </head> <body> <div id="map"> </div> <div id="bg-mask"> </div> <div id="left-panel"> <div class="panel-header" title="Close"> <span class="title">Layer List</span> </div> <div class="panel-content"> <ul id="layer-options"> <li> <div id="layer-styling" title="LabelStyling" class="selected"> <span>Label Styling</span> </div> </li> <li> <div id="layer-point" title="LabelingPoints" class="unselected"> <span>Labeling Points</span> </div> </li> <li> <div id="layer-line" title="LabelingLines" class="unselected"> <span>Labeling Lines</span> </div> </li> <li> <div id="layer-area" title="LabelingPolygons" class="unselected"> <span>Labeling Polygons</span> </div> </li> <li> <div id="layer-custom" title="CustomLabeling" class="unselected"> <span>Custom Labeling – Auto Scaling</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"> <!--please put the dialog here--> </div> <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> <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 = 'LabelStyling'; // add map //var map = L.map('map').setView([33.1010, -96.8134], 17); var map = new ol.Map({ target: 'map', view: new ol.View({ center: [-10777218.3900, 3908717.7103], zoom: 17 }) }); // add base street layer without any label from the web API controller of this Project var streetSource = new ol.source.XYZ({ url: getRootPath() + '/label/{z}/{x}/{y}', maxZoom: 19 }); streetSource.tileLoadFunction = function (imageTile, src) { imageTile.getImage().src = src + '?t=' + new Date().getTime();; }; var streetLayer = new ol.layer.Tile({ source: streetSource }); map.addLayer(streetLayer); // add dynamic tile layer to map from the web API controller of this Project var tileSource = new ol.source.XYZ({ url: getRootPath() + '/label/LabelStyling/{z}/{x}/{y}', maxZoom: 19 }); tileSource.tileLoadFunction = function (imageTile, src) { imageTile.getImage().src = src + '?t=' + new Date().getTime();; }; var tileLayer = new ol.layer.Tile({ source: tileSource }); map.addLayer(tileLayer); // add image buttons for layers, settings, help etc. var imgControls = new app.ImagesControl({ imgs: [ { src: 'Images/layers.png', id: 'lyrOptions', title: 'Show layers', callback: function () { $('#left-panel').animate({ 'left': '0px' }); } }, { src: 'Images/gear.png', id: 'btnConfig', title: 'Show style settings', callback: function () { showStyleDlg(); loadStyleDlg(); } }, { src: 'Images/info.png', id: 'btnInfo', title: 'Show help', callback: function () { window.open('http://wiki.thinkgeo.com', '_blank'); } } ] }); map.addControl(imgControls); map.on("click", function () { $('#left-panel').animate({ 'left': -$('#left-panel').width() + 'px' }); }); var loadStyleDlg = function () { var pageUrl = 'labelingStyleEdit.html'; switch (selectedLayer) { case 'LabelingPoints': pageUrl = 'LabelingPointsEdit.html'; break; case 'LabelingLines': pageUrl = 'LabelingLinesEdit.html'; break; case 'LabelingPolygons': pageUrl = 'LabelingPolygons