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; using System.Configuration; using ThinkGeo.MapSuite.Core; using ThinkGeo.MapSuite.WebEdition; using System.IO; using System.Collections.ObjectModel; namespace KmlExtensionWeb { public partial class TestForm : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPostBack) { Map1.MapBackground.BackgroundBrush = new GeoSolidBrush(GeoColor.FromHtml("#E5E3DF")); Map1.CurrentExtent = new RectangleShape(-122.0874, 37.4245, -122.0804, 37.4201); Map1.MapUnit = GeographyUnit.DecimalDegree; WorldMapKitWmsWebOverlay worldMapKitOverlay = new WorldMapKitWmsWebOverlay(); Map1.CustomOverlays.Add(worldMapKitOverlay); KmlFeatureLayer layer = new KmlFeatureLayer(MapPath("~/App_Data/KML_Samples.kml")); layer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; layer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = new AreaStyle(new GeoPen(GeoColor.SimpleColors.Black), new GeoSolidBrush(GeoColor.SimpleColors.Yellow)); layer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = new LineStyle(new GeoPen(GeoColor.SimpleColors.Blue, 5)); layer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = new PointStyle(PointSymbolType.Circle, new GeoSolidBrush(GeoColor.SimpleColors.Green), 10); LayerOverlay dynamicOverlay = new LayerOverlay("DynamicOverlay"); dynamicOverlay.IsBaseOverlay = false; dynamicOverlay.Layers.Add("KmlLayer", layer); Map1.CustomOverlays.Add(dynamicOverlay); } } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ThinkGeo.MapSuite.Core { public class KmlFeatureLayer : FeatureLayer { protected KmlFeatureLayer() : this(string.Empty) { } public KmlFeatureLayer(string kmlPathFileName) : this(kmlPathFileName, KmlStringType.File) { } public KmlFeatureLayer(string kmlString, KmlStringType stringType) : base() { FeatureSource = new KmlFeatureSource(kmlString, stringType); } public override bool HasBoundingBox { get { return true; } } } }
//KML reference //<styleUrl> //URL of a <Style> or <StyleMap> defined in a Document. If the style is in the same file, use a # reference. //If the style is defined in an external file, use a full URL along with # referencing. Examples are //<styleUrl>#myIconStyleID</styleUrl> //<styleUrl>http://someserver.com/somestylefile.xml#restaurant</styleUrl> //<styleUrl>eateries.kml#my-lunch-spot</styleUrl> //KML reference //<styleUrl> //URL of a <Style> or <StyleMap> defined in a Document. If the style is in the same file, use a # reference. //If the style is defined in an external file, use a full URL along with # referencing. Examples are //<styleUrl>#myIconStyleID</styleUrl> //<styleUrl>http://someserver.com/somestylefile.xml#restaurant</styleUrl> //<styleUrl>eateries.kml#my-lunch-spot</styleUrl> using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections.ObjectModel; using System.Xml; using System.Net; using System.Web; using System.Globalization; namespace ThinkGeo.MapSuite.Core { public class KmlFeatureSource : FeatureSource { private const string presetXml = "<?xml version='1.0' encoding='UTF-8'?><kml xmlns='http://earth.google.com/kml/2.1'></kml>"; private XmlDocument kmlDocument; private InMemoryFeatureLayer inMemoryFeatureLayer; private Collection<Feature> tempFeatures; private Dictionary<string, Dictionary<string, string>> globalStyles; protected KmlFeatureSource() : this(string.Empty) { } public KmlFeatureSource(string kmlPathFileName) : this(kmlPathFileName, KmlStringType.File) { } public KmlFeatureSource(string kmlString, KmlStringType stringType) : base() { switch (stringType) { case KmlStringType.String: kmlDocument = new XmlDocument(); if (string.IsNullOrEmpty(kmlString)) { kmlDocument.LoadXml(presetXml); } else { kmlDocument.LoadXml(kmlString); } break; case KmlStringType.File: default: kmlDocument = new XmlDocument(); kmlDocument.Load(kmlString); break; } this.inMemoryFeatureLayer = new InMemoryFeatureLayer(); inMemoryFeatureLayer.Open(); inMemoryFeatureLayer.Columns.Add(new FeatureSourceColumn("linecolor")); inMemoryFeatureLayer.Columns.Add(new FeatureSourceColumn("linewidth")); inMemoryFeatureLayer.Close(); globalStyles = new Dictionary<string, Dictionary<string, string>>(); } protected override void OpenCore() { if (inMemoryFeatureLayer.InternalFeatures.Count == 0) { tempFeatures = new Collection<Feature>(); XmlNamespaceManager manager = new XmlNamespaceManager(kmlDocument.NameTable); manager.AddNamespace("kk", kmlDocument.DocumentElement.NamespaceURI); if (kmlDocument.DocumentElement.HasChildNodes) { XmlNodeList styleList = kmlDocument.DocumentElement.ChildNodes[0].SelectNodes("kk:Style", manager); foreach (XmlNode item in styleList) { string styleId = item.Attributes["id"].Value; Dictionary<string, string> columnValues = GetColumnValues(item, manager); globalStyles.Add(styleId, columnValues); } XmlNodeList placemarks = kmlDocument.SelectNodes("//kk:Placemark", manager); foreach (XmlNode placemark in placemarks) { ProcessPlacemark(placemark, manager); } // There is no Placemark tag, so it may use NetworkLink if (placemarks.Count == 0) { XmlNodeList networkLinks = kmlDocument.SelectNodes("//kk:NetworkLink", manager); foreach (XmlNode networkLink in networkLinks) { ProcessNetworkLink(networkLink, manager); } } foreach (Feature item in tempFeatures) { WellKnownType wellKnownType = item.GetWellKnownType(); if (wellKnownType == WellKnownType.Polygon || wellKnownType == WellKnownType.Multipolygon) { inMemoryFeatureLayer.InternalFeatures.Add(item); } } foreach (Feature item in tempFeatures) { WellKnownType wellKnownType = item.GetWellKnownType(); if (wellKnownType == WellKnownType.Line || wellKnownType == WellKnownType.Multiline) { inMemoryFeatureLayer.InternalFeatures.Add(item); } } foreach (Feature item in tempFeatures) { WellKnownType wellKnownType = item.GetWellKnownType(); if (wellKnownType == WellKnownType.Point || wellKnownType == WellKnownType.Multipoint) { inMemoryFeatureLayer.InternalFeatures.Add(item); } } } } } private void ProcessNetworkLink(XmlNode networkLink, XmlNamespaceManager manager) { XmlNode hrefNode = networkLink.SelectSingleNode("kk:Url/kk:href", manager); string fileUrl = hrefNode.InnerText; WebRequest request = WebRequest.Create(fileUrl); request.Timeout = 10000; WebResponse response = null; try { response = request.GetResponse(); string disposition = response.Headers["Content-Disposition"]; if (!string.IsNullOrEmpty(disposition)) { string filename = @"C:\temp\" + disposition.Split('=')[1].Trim('\"'); WebClient webClient = new WebClient(); webClient.DownloadFile(fileUrl, filename); if (filename.EndsWith(".kml", StringComparison.InvariantCultureIgnoreCase)) { } else if (filename.EndsWith(".kmz", StringComparison.InvariantCultureIgnoreCase)) { filename = new KmlHelper().ProcessUnZip(filename); } else { return; } KmlFeatureSource source = new KmlFeatureSource(filename); source.Open(); foreach (Feature item in source.inMemoryFeatureLayer.InternalFeatures) { tempFeatures.Add(item); } source.Close(); } } catch { } finally { if (response != null) { response.Close(); } } } private void ProcessPlacemark(XmlNode placemark, XmlNamespaceManager manager) { XmlNode stylesNode = placemark.SelectSingleNode("kk:Style", manager); Dictionary<string, string> columnValues = GetColumnValues(stylesNode, manager); XmlNode descriptionNode = placemark.SelectSingleNode("kk:description", manager); if (descriptionNode != null) { columnValues.Add("popupHTML", descriptionNode.InnerXml); } XmlNodeList linearRingList = placemark.SelectNodes(".//kk:LinearRing", manager); foreach (XmlNode node in linearRingList) { string value = node.SelectSingleNode("kk:coordinates", manager).InnerText.Trim(); //TODO: the document says use " ", not "\r\n" string[] values = value.Split(new string[] { " ", "\r\n" }, StringSplitOptions.RemoveEmptyEntries); Collection<Vertex> Vertices = new Collection<Vertex>(); foreach (string item in values) { string[] items = item.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); Vertex vertex = new Vertex(double.Parse(items[0], CultureInfo.InvariantCulture), double.Parse(items[1], CultureInfo.InvariantCulture)); Vertices.Add(vertex); } RingShape ringShape = new RingShape(Vertices); tempFeatures.Add(new Feature(ringShape, columnValues)); } XmlNodeList lineStringList = placemark.SelectNodes(".//kk:LineString", manager); foreach (XmlNode node in lineStringList) { string value = node.SelectSingleNode("kk:coordinates", manager).InnerText.Trim(); //TODO: the document says use " ", not "\r\n" string[] values = value.Split(new string[] { " ", "\r\n" }, StringSplitOptions.RemoveEmptyEntries); Collection<Vertex> Vertices = new Collection<Vertex>(); foreach (string item in values) { string[] items = item.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); Vertex vertex = new Vertex(double.Parse(items[0], CultureInfo.InvariantCulture), double.Parse(items[1], CultureInfo.InvariantCulture)); Vertices.Add(vertex); } LineShape lineShape = new LineShape(Vertices); if (columnValues.Count == 0 || (columnValues.Count == 1 && columnValues.ContainsKey("popupHTML"))) { columnValues.Add("linecolor", "ffffffff"); columnValues.Add("linewidth", "1"); if (placemark.SelectSingleNode("kk:styleUrl", manager) != null) { string styleUrl = placemark.SelectSingleNode("kk:styleUrl", manager).InnerText; if (styleUrl.StartsWith("#")) { columnValues = globalStyles[styleUrl.TrimStart('#')]; } } } tempFeatures.Add(new Feature(lineShape, columnValues)); } XmlNodeList pointList = placemark.SelectNodes(".//kk:Point", manager); foreach (XmlNode item in pointList) { string value = item.SelectSingleNode("kk:coordinates", manager).InnerText.Trim(); string[] values = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); PointShape point = new PointShape(double.Parse(values[0], CultureInfo.InvariantCulture), double.Parse(values[1], CultureInfo.InvariantCulture)); tempFeatures.Add(new Feature(point, columnValues)); } } private Dictionary<string, string> GetColumnValues(XmlNode stylesNode, XmlNamespaceManager manager) { Dictionary<string, string> columnValues = new Dictionary<string, string>(); if (stylesNode != null) { foreach (XmlNode styleNode in stylesNode.ChildNodes) { if (styleNode.Name == "LineStyle") { string linecolor = "ffffffff"; if (styleNode.SelectSingleNode("kk:color", manager) != null) { linecolor = styleNode.SelectSingleNode("kk:color", manager).InnerText; } string linewidth = "1"; if (styleNode.SelectSingleNode("kk:width", manager) != null) { linewidth = styleNode.SelectSingleNode("kk:width", manager).InnerText; } columnValues.Add("linecolor", linecolor); columnValues.Add("linewidth", linewidth); break; } } } return columnValues; } protected override void CloseCore() { //inMemoryFeatureLayer.InternalFeatures.Clear(); //globalStyles.Clear(); } protected override Collection<Feature> GetAllFeaturesCore(IEnumerable<string> returningColumnNames) { return inMemoryFeatureLayer.InternalFeatures; } } }
using System; using System.Collections.Generic; using System.Linq; using System.Web; using ICSharpCode.SharpZipLib.Zip; using System.IO; namespace ThinkGeo.MapSuite.Core { public class KmlHelper { // Copy this function is from FormIndexBuilder. public string ProcessUnZip(string fileToUpZip) { ZipInputStream s = null; ZipEntry theEntry = null; string fileName = null; FileStream streamWriter = null; try { s = new ZipInputStream(File.OpenRead(fileToUpZip)); //s.Password = Password; while ((theEntry = s.GetNextEntry()) != null) { if (theEntry.Name != String.Empty) { if (theEntry.Name.EndsWith(".kml", StringComparison.InvariantCultureIgnoreCase)) { string folder = Path.GetDirectoryName(fileToUpZip); fileName = Path.Combine(folder, theEntry.Name); fileName = fileName.Replace("/", " "); string directoryName = Path.GetDirectoryName(fileName); if (!Directory.Exists(directoryName)) { Directory.CreateDirectory(directoryName); } streamWriter = File.Create(fileName); int size = 2048; byte[] data = new byte[2048]; while (true) { size = s.Read(data, 0, data.Length); if (size > 0) { streamWriter.Write(data, 0, size); } else { break; } } break; } } } return fileName; } finally { if (streamWriter != null) { streamWriter.Close(); streamWriter = null; } if (theEntry != null) { theEntry = null; } if (s != null) { s.Close(); s = null; } GC.Collect(); GC.Collect(1); } } } }
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace ThinkGeo.MapSuite.Core { public enum KmlStringType { File = 0, String = 1, } }
//Color and opacity (alpha) values are expressed in hexadecimal notation. The range of values for any one color is 0 //to 255 (00 to ff). For alpha, 00 is fully transparent and ff is fully opaque. The order of expression is aabbggrr, //where aa=alpha (00 to ff); bb=blue (00 to ff); gg=green (00 to ff); rr=red (00 to ff). For example, if you want to //apply a blue color with 50 percent opacity to an overlay, you would specify the following: <color>7fff0000</color>, //where alpha=0x7f, blue=0xff, green=0x00, and red=0x00. using System.Collections.Generic; using System.Collections.ObjectModel; using System.Drawing.Imaging; using System.Globalization; using System.IO; namespace ThinkGeo.MapSuite.Core { public class KmlStyle : Style { private GeoImage defaultIcon; public KmlStyle() : base() { Stream stream = new MemoryStream(); //Properties.Resources.GoogleEarthPushpin.Save(stream, ImageFormat.Png); defaultIcon = new GeoImage(stream); } public GeoImage DefaultIcon { get { return defaultIcon; } set { defaultIcon = value; } } protected override void DrawCore(IEnumerable<Feature> features, GeoCanvas canvas, Collection<SimpleCandidate> labelsInThisLayer, System.Collections.ObjectModel.Collection<SimpleCandidate> labelsInAllLayers) { foreach (Feature feature in features) { switch (feature.GetWellKnownType()) { case WellKnownType.Line: case WellKnownType.Multiline: { GeoPen geoPen = GetGeoPen(feature); canvas.DrawLine(feature, geoPen, DrawingLevel.LevelOne); } break; case WellKnownType.Point: case WellKnownType.Multipoint: if (defaultIcon == null) { GeoBrush geoBrush = GetGeoBrush(feature); canvas.DrawEllipse(feature, 8, 8, geoBrush, DrawingLevel.LevelOne); } else { PointShape pointShape = feature.GetShape() as PointShape; canvas.DrawWorldImageWithoutScaling(defaultIcon, pointShape.X, pointShape.Y, DrawingLevel.LevelOne); } break; case WellKnownType.Polygon: case WellKnownType.Multipolygon: { GeoPen geoPen = GetGeoPen(feature); canvas.DrawArea(feature, geoPen, DrawingLevel.LevelOne); } break; } } } private GeoBrush GetGeoBrush(Feature feature) { return new GeoSolidBrush(GeoColor.SimpleColors.Black); } private GeoPen GetGeoPen(Feature feature) { GeoPen geoPen = new GeoPen(GeoColor.SimpleColors.Black); if (feature.ColumnValues.Count >= 2) { string linecolor = feature.ColumnValues["linecolor"]; string linewidth = feature.ColumnValues["linewidth"]; GeoColor geoColor = GetGeoColor(linecolor); int width = int.Parse(linewidth); geoPen.Color = geoColor; geoPen.Width = width; } return geoPen; } private GeoColor GetGeoColor(string linecolor) { GeoColor geoColor = new GeoColor(); if (linecolor.Length == 8) { int alpha = int.Parse(linecolor.Substring(0, 2), NumberStyles.AllowHexSpecifier); int blue = int.Parse(linecolor.Substring(2, 2), NumberStyles.AllowHexSpecifier); int green = int.Parse(linecolor.Substring(4, 2), NumberStyles.AllowHexSpecifier); int red = int.Parse(linecolor.Substring(6, 2), NumberStyles.AllowHexSpecifier); geoColor = new GeoColor(alpha, red, green, blue); } return geoColor; } } }
<%@ Register Assembly="WebEdition" Namespace="ThinkGeo.MapSuite.WebEdition" TagPrefix="cc1" %> <html xmlns="http://www.w3.org/1999/xhtml"> <head id="Head1" runat="server"> <link href="~/theme/default/samplepic/style.css" rel="stylesheet" type="text/css" /> <title>KML Extension</title> </head> <body> <form id="form1" runat="server"> <asp:ScriptManager ID="ScriptManager1" runat="server"> </asp:ScriptManager> <cc1:Map ID="Map1" runat="server" Height="100%" Width="100%"> </cc1:Map> <%-- <description:descriptionpanel ID="DescPanel" runat="server"> This sample displays a google map. Click buttons below to switch between different Google maps. <br /> <br /> <asp:Button CssClass="btn" ID="btnRoad" runat="server" Text="Normal" OnClientClick="Map1.SetCurrentBackgroundMapType(G_NORMAL_MAP); return false;" /> <asp:Button CssClass="btn" ID="btnAerial" runat="server" Text="Hybrid" OnClientClick="Map1.SetCurrentBackgroundMapType(G_HYBRID_MAP); return false;" /><br /> <asp:Button CssClass="btn" ID="btnSatellite" runat="server" Text="Satellite" OnClientClick="Map1.SetCurrentBackgroundMapType(G_SATELLITE_MAP); return false;" /> <asp:Button CssClass="btn" ID="btnPhysical" runat="server" Text="Physical" OnClientClick="Map1.SetCurrentBackgroundMapType(G_PHYSICAL_MAP); return false;" /> </description:descriptionpanel>--%> </form> </body> </html>