ComponentOne Maps for ASP.NET Web Forms
Features / Vector Layer / Display Shapes using a KML File
In This Topic
    Display Shapes using a KML File
    In This Topic

    You can also add shapes on the maps using zipped KML files. KML is an XML-based language for geographic visualization and annotation that was originally created for Google Earth. For more information, see https://developers.google.com/kml/documentation/kml_tut.

    KML import is performed by KmlReader class that has static methods that create collection of vector objects from the supplied KML source (string or stream). The collection can then be added to the C1VectorLayer.

    Complete the following steps:

    In the Designer

    1. In Visual Studio, create a new ASP.Net Web Application and add a new Web Form.
    2. Locate the C1Maps control in the toolbox and place it onto the Web Form.
    3. Right click the control and select Properties from the context menu to open the Properties window.
    4. Set the Height and Width as per the requirement.
    5. Set the Source to None.
    6. Set the CssClass to 'c1maps'.

    After completing the above steps, complete the steps given in source view.

    In Source View

    1. Following will be the markup for the C1Maps control after completing the steps in the designer:

      Source View
      Copy Code
      <c1:C1Maps ID="C1Maps1" CssClass="c1maps" runat="server" Height="475px" Width="756px"
        ShowTools="True" Source="None" Zoom="1">
      
    2. Add the following Css style tag between the <head></head> tags:

      Source View
      Copy Code
      <style type="text/css">
          .c1maps
          {
              float: left;
          }
          .legend
          {
              float: left;
              margin-left: 5px;
              margin-top: 15px;
          }
          .legend ul
          {
              list-style: none;
              font-size: 10px;
          }
          .legend .legend-item
          {
              width: 20px;
              height: 20px;
              display: inline-block;
              margin-right: 2px;
          }
      </style>
      

    After completing the above steps, complete the steps in code view.

    In Code

    1. In code, include the following libraries:

      To write code in C#

      C#
      Copy Code
      using System;
      using System.Collections.Generic;
      using System.Globalization;
      using System.IO;
      using System.Linq;
      using System.Runtime.InteropServices;
      using System.Web;
      using System.Web.UI;
      using System.Web.UI.WebControls;
      using C1.Web.Wijmo.Controls.C1Maps;
      using System.Collections.ObjectModel;
      using System.Drawing;
      

      To write code in VB

      VB
      Copy Code
      Imports System.Collections.Generic
      Imports System.Globalization
      Imports System.IO
      Imports System.Linq
      Imports System.Runtime.InteropServices
      Imports System.Web
      Imports System.Web.UI
      Imports System.Web.UI.WebControls
      Imports C1.Web.Wijmo.Controls.C1Maps
      Imports System.Collections.ObjectModel
      Imports System.Drawing
      
    2. Add the following classes to represent countries on the map:

      To write code in C#

      C#
      Copy Code
      public class Country
      {
          private Color _fill = Color.Empty;
          private double _value;
          internal Countries Parent;
          public string Name { get; set; }
          public double Value
          {
              get { return _value; }
              set
              {
                  _value = value;
                  _fill = Color.Empty;
              }
          }
          public Color Fill
          {
              get
              {
                  if (_fill == Color.Empty)
                  {
                      if (Parent != null)
                          _fill = Parent.ValueToColor(Value);
                  }
                  return _fill;
              }
          }
      }
      public class Countries : Collection<Country>
      {
          private readonly Dictionary<string, Country> _dict = new Dictionary<string, Country>();
          public IValueToColor Converter { get; set; }
          public Color ValueToColor(double value)
          {
              if (Converter != null)
                  return Converter.ValueToColor(value);
              return Color.Empty;
          }
          public Country this[string name]
          {
              get
              {
                  if (_dict.ContainsKey(name))
                      return _dict[name];
                  return null;
              }
          }
          public double GetMin()
          {
              double min = double.NaN;
              foreach (Country country in this)
              {
                  if (double.IsNaN(min) || country.Value < min)
                      min = country.Value;
              }
              return min;
          }
          public double GetMax()
          {
              double max = double.NaN;
              foreach (Country country in this)
              {
                  if (double.IsNaN(max) || country.Value > max)
                      max = country.Value;
              }
              return max;
          }
          protected override void InsertItem(int index, Country item)
          {
              base.InsertItem(index, item);
              item.Parent = this;
              _dict.Add(item.Name, item);
          }
          protected override void ClearItems()
          {
              foreach (Country item in this)
                  item.Parent = null;
              base.ClearItems();
              _dict.Clear();
          }
          protected override void RemoveItem(int index)
          {
              Country item = this[index];
              base.RemoveItem(index);
              _dict.Remove(item.Name);
              item.Parent = null;
          }
      }
      

      To write code in VB

      VB
      Copy Code
      Public Class Country
          Private _fill As Color = Color.Empty
          Private _value As Double
          Friend Parent As Countries
          Public Property Name() As String
              Get
                  Return m_Name
              End Get
              Set(value As String)
                  m_Name = value
              End Set
          End Property
          Private m_Name As String
          Public Property Value() As Double
              Get
                  Return _value
              End Get
              Set(value As Double)
                  _value = value
                  _fill = Color.Empty
              End Set
          End Property
          Public ReadOnly Property Fill() As Color
              Get
                  If _fill = Color.Empty Then
                      If Parent IsNot Nothing Then
                          _fill = Parent.ValueToColor(Value)
                      End If
                  End If
                  Return _fill
              End Get
          End Property
      End Class
      Public Class Countries
          Inherits Collection(Of Country)
          Private ReadOnly _dict As New Dictionary(Of String, Country)()
          Public Property Converter() As IValueToColor
              Get
                  Return m_Converter
              End Get
              Set(value As IValueToColor)
                  m_Converter = value
              End Set
          End Property
          Private m_Converter As IValueToColor
          Public Function ValueToColor(value As Double) As Color
              If Converter IsNot Nothing Then
                  Return Converter.ValueToColor(value)
              End If
              Return Color.Empty
          End Function
          Default Public ReadOnly Property Item(name As String) As Country
              Get
                  If _dict.ContainsKey(name) Then
                      Return _dict(name)
                  End If
                  Return Nothing
              End Get
          End Property
          Public Function GetMin() As Double
              Dim min As Double = Double.NaN
              For Each country As Country In Me
                  If Double.IsNaN(min) OrElse country.Value < min Then
                      min = country.Value
                  End If
              Next
              Return min
          End Function
          Public Function GetMax() As Double
              Dim max As Double = Double.NaN
              For Each country As Country In Me
                  If Double.IsNaN(max) OrElse country.Value > max Then
                      max = country.Value
                  End If
              Next
              Return max
          End Function
          Protected Overrides Sub InsertItem(index As Integer, item As Country)
              MyBase.InsertItem(index, item)
              item.Parent = Me
              _dict.Add(item.Name, item)
          End Sub
          Protected Overrides Sub ClearItems()
              For Each item As Country In Me
                  item.Parent = Nothing
              Next
              MyBase.ClearItems()
              _dict.Clear()
          End Sub
          Protected Overrides Sub RemoveItem(index As Integer)
              Dim item As Country = Me(index)
              MyBase.RemoveItem(index)
              _dict.Remove(item.Name)
              item.Parent = Nothing
          End Sub
      End Class
      
    3. Add the following classes to represent different color values for the countries:

      To write code in C#

      C#
      Copy Code
      public class ColorValue
      {
          public Color Color { get; set; }
          public double Value { get; set; }
      }
      public class ColorValues : Collection<ColorValue>, IValueToColor
      {
          public Color ValueToColor(double value)
          {
              Color color = Color.Empty;
              ColorValue greater = null;
              ColorValue less = null;
              foreach (ColorValue cval in this)
              {
                  if (cval.Value < value)
                  {
                      if (less == null || (value - cval.Value < value - less.Value))
                          less = cval;
                  }
                  if (cval.Value > value)
                  {
                      if (greater == null || (value - cval.Value > value - greater.Value))
                          greater = cval;
                  }
              }
              if (less != null && greater != null)
              {
                  Color clr1 = less.Color;
                  Color clr2 = greater.Color;
                  double rval = (value - less.Value) / (greater.Value - less.Value);
                  color = Color.FromArgb(
                      (byte)(clr1.A + rval * (clr2.A - clr1.A)),
                      (byte)(clr1.R + rval * (clr2.R - clr1.R)),
                      (byte)(clr1.G + rval * (clr2.G - clr1.G)),
                      (byte)(clr1.B + rval * (clr2.B - clr1.B)));
              }
              return color;
          }
      }
      public interface IValueToColor
      {
          Color ValueToColor(double value);
      }
      

      To write code in VB

      VB
      Copy Code
      Public Class ColorValue
          Public Property Color() As Color
              Get
                  Return m_Color
              End Get
              Set(value As Color)
                  m_Color = value
              End Set
          End Property
          Private m_Color As Color
          Public Property Value() As Double
              Get
                  Return m_Value
              End Get
              Set(value As Double)
                  m_Value = value
              End Set
          End Property
          Private m_Value As Double
      End Class
      
      Public Class ColorValues
          Inherits Collection(Of ColorValue)
          Implements IValueToColor
          Public Function ValueToColor(value As Double) As Color Implements IValueToColor.ValueToColor
              Dim color1 As Color
              color1 = Color.Empty
              Dim greater As ColorValue
              greater = Nothing
              Dim less As ColorValue
              less = Nothing
              For Each cval As ColorValue In Me
                  If cval.Value < value Then
                      If less Is Nothing OrElse (value - cval.Value < value - less.Value) Then
                          less = cval
                      End If
                  End If
                  If cval.Value > value Then
                      If greater Is Nothing OrElse (value - cval.Value > value - greater.Value) Then
                          greater = cval
                      End If
                  End If
              Next
                If Not less Is Nothing And greater Is Nothing Then
                  Dim clr1 As Color
                  clr1 = less.Color
                  Dim clr2 As Color
                  clr2 = greater.Color
                  Dim rval As Double
                  rval = (value - less.Value) / (greater.Value - less.Value)
                  color1 = Color.FromArgb(
                      CType((clr1.A + rval * (clr2.A - clr1.A)), Int32),
                      CType((clr1.R + rval * (clr2.R - clr1.R)), Int32),
                      CType((clr1.G + rval * (clr2.G - clr1.G)), Int32),
                      CType((clr1.B + rval * (clr2.B - clr1.B)), Int32))
              End If
              Return color1
          End Function
      End Class
      Public Interface IValueToColor
          Function ValueToColor(value As Double) As Color
      End Interface
      
    4. Add the following method to the current class to read the KML file and create countries:

      To write code in C#

      C#
      Copy Code
      private Countries CreateCounties()
      {
          var countries = new Countries();
          var pathGdp = Server.MapPath("Resources/gdp-ppp.txt");
          using (var stream = new FileStream(pathGdp, FileMode.Open, FileAccess.Read))
          {
              using (var sr = new StreamReader(stream))
              {
                  for (; !sr.EndOfStream; )
                  {
                      string s = sr.ReadLine();
                      if (s != null)
                      {
                          string[] ss = s.Split(new[] { '\t' },
                              StringSplitOptions.RemoveEmptyEntries);
                          countries.Add(new Country { Name = ss[1].Trim(), Value = double.Parse(ss[2], CultureInfo.InvariantCulture) });
                      }
                  }
              }
          }
         
          var cvals = new ColorValues
          {
              new ColorValue {Color = Color.FromArgb(255, 241, 244, 255), Value = 0},
              new ColorValue {Color = Color.FromArgb(255, 241, 244, 255), Value = 5000},
              new ColorValue {Color = Color.FromArgb(255, 224, 224, 246), Value = 10000},
              new ColorValue {Color = Color.FromArgb(255, 203, 205, 255), Value = 20000},
              new ColorValue {Color = Color.FromArgb(255, 179, 182, 230), Value = 50000},
              new ColorValue {Color = Color.FromArgb(255, 156, 160, 240), Value = 100000},
              new ColorValue {Color = Color.FromArgb(255, 127, 132, 243), Value = 200000},
              new ColorValue {Color = Color.FromArgb(255, 89, 97, 230), Value = 500000},
              new ColorValue {Color = Color.FromArgb(255, 56, 64, 217), Value = 1000000},
              new ColorValue {Color = Color.FromArgb(255, 19, 26, 148), Value = 2000000},
              new ColorValue {Color = Color.FromArgb(255, 0, 3, 74), Value = 1.001*countries.GetMax()}
          };
          countries.Converter = cvals;
          return countries;
      }
      

      To write code in VB

      VB
      Copy Code
      Private Function CreateCounties() As Countries
          Dim countries = New Countries()
          Dim pathGdp = Server.MapPath("Resources/gdp-ppp.txt")
          Using stream = New FileStream(pathGdp, FileMode.Open, FileAccess.Read)
              Using sr = New StreamReader(stream)
                  While Not sr.EndOfStream
                      Dim s As String = sr.ReadLine()
                      If s IsNot Nothing Then
                          Dim ss As String()
                          ss = s.Split({ControlChars.Tab}, StringSplitOptions.RemoveEmptyEntries)
                          Dim cntry As New Country()
                          cntry.Name = ss(1).Trim()
                          cntry.Value = Double.Parse(ss(2), CultureInfo.InvariantCulture)
                          countries.Add(cntry)
                      End If
                  End While
              End Using
          End Using
      
          Dim cvals As New ColorValues()
          Dim cval1 As New ColorValue()
          cval1.Color = Color.FromArgb(255, 241, 244, 255)
          cval1.Value = 0
          cvals.Add(cval1)
      
          Dim cval2 As New ColorValue()
          cval2.Color = Color.FromArgb(255, 241, 244, 255)
          cval2.Value = 5000
          cvals.Add(cval2)
      
          Dim cval3 As New ColorValue()
          cval3.Color = Color.FromArgb(255, 224, 224, 246)
          cval3.Value = 10000
          cvals.Add(cval3)
      
          Dim cval4 As New ColorValue()
          cval4.Color = Color.FromArgb(255, 203, 205, 255)
          cval4.Value = 20000
          cvals.Add(cval4)
      
          Dim cval5 As New ColorValue()
          cval5.Color = Color.FromArgb(255, 179, 182, 230)
          cval5.Value = 50000
          cvals.Add(cval5)
      
          Dim cval6 As New ColorValue()
          cval6.Color = Color.FromArgb(255, 156, 160, 240)
          cval6.Value = 100000
          cvals.Add(cval6)
      
          Dim cval7 As New ColorValue()
          cval7.Color = Color.FromArgb(255, 127, 132, 243)
          cval7.Value = 200000
          cvals.Add(cval7)
      
          Dim cval8 As New ColorValue()
          cval8.Color = Color.FromArgb(255, 89, 97, 230)
          cval8.Value = 500000
          cvals.Add(cval8)
      
          Dim cval9 As New ColorValue()
          cval9.Color = Color.FromArgb(255, 56, 64, 217)
          cval9.Value = 1000000
          cvals.Add(cval9)
      
          Dim cval10 As New ColorValue()
          cval10.Color = Color.FromArgb(255, 19, 26, 148)
          cval10.Value = 2000000
          cvals.Add(cval10)
      
          Dim cval11 As New ColorValue()
          cval11.Color = Color.FromArgb(255, 0, 3, 74)
          cval11.Value = 1.001 * countries.GetMax()
          cvals.Add(cval11)
      
          countries.Converter = cvals
          Return countries
      End Function
      
    5. Add the following code to the Page_Load event to add a new vector layer and display countries created using the KML file

      To write code in C#

      C#
      Copy Code
      var layer = new C1VectorLayer();
      C1Maps1.Layers.Add(layer);
      layer.DataType = DataType.WijJson;
      var data = new WijJsonData();
      layer.DataWijJson = data;
      var path = Server.MapPath("Resources/WorldMap.kmz");
      using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read))
      {
          var items = KmlReader.ReadVectorItems(stream);
          var countries = CreateCounties();
          foreach (var item in items)
          {
              var country = countries[item.Name];
              if (country != null)
              {
                  item.Fill = country.Fill;
              }
              else
              {
                  item.Fill = Color.Transparent;
              }
              data.Vectors.Add(item);
          }
      }
      

      To write code in VB

      VB
      Copy Code
      Dim layer As New C1VectorLayer()
      C1Maps1.Layers.Add(layer)
      layer.DataType = DataType.WijJson
      Dim data As New WijJsonData()
      layer.DataWijJson = data
      Dim path = Server.MapPath("Resources/WorldMap.kmz")
      Using stream = New FileStream(path, FileMode.Open, FileAccess.Read)
          Dim items = KmlReader.ReadVectorItems(stream)
          Dim countries = CreateCounties()
          For Each item In items
              Dim country = countries(item.Name)
              If country IsNot Nothing Then
                  item.Fill = country.Fill
              Else
                  item.Fill = Color.Transparent
              End If
              data.Vectors.Add(item)
          Next
      End Using
      

    What You've Accomplished

     The following image depicts a C1Maps control displaying all the countries of the world in a black boundary and in different colors, using a KML file.