Main Content

Export KML Files for Viewing in Earth Browsers

Keyhole Markup Language (KML) is an XML dialect for formatting 2-D and 3-D geodata for display in "Earth browsers," such as Google Earth™ mapping service, Google Maps™ mapping service, Google Mobile™ wireless service, and NASA WorldWind. Other Web browser applications, such as Yahoo!® Pipes, also support KML either by rendering or generating files. A KML file specifies a set of features (placemarks, images, polygons, 3-D models, textual descriptions, etc.) and how they are to be displayed in browsers and applications.

Each place must at least have an address or a longitude and a latitude. Places can also have textual descriptions, including hyperlinks. KML files can also specify display styles for markers, lines and polygons, and "camera view" parameters such as tilt, heading, and altitude. You can generate placemarks in KML files for individual points and sets of points that include attributes in table form. You can include HTML markups in these tables, with or without hyperlinks, but you cannot currently control the camera view of a placemark. (However, the users of an Earth browser can generally control their views of it).

Generate a Single Placemark Using kmlwritepoint

This example shows how to generate a placemark using kmlwritepoint by specifying the latitude and longitude that identifies a location. This example also specifies the icon used for the placemark and the text that appears in the balloon associated with the placemark.

lat =  42.299827;
lon = -71.350273;
description = sprintf('%s<br>%s</b><br>%s</b>', ...
    '3 Apple Hill Drive', 'Natick, MA. 01760', ...
    'https://www.mathworks.com');
name = 'The MathWorks, Inc.';
iconFilename = ...
    'https://www.mathworks.com/products/product_listing/images/ml_icon.gif';
iconScale = 1.0;
filename = 'MathWorks.kml';
kmlwritepoint(filename, lat, lon, ...
    'Description', description, 'Name', name, ...
    'Icon', iconFilename, 'IconScale', iconScale);

This code produces the following KML file.

<?xml version="1.0" encoding="utf-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
   <Document>
      <name>MathWorks</name>
      <Placemark>
         <Snippet maxLines="0"> </Snippet>
         <description>3 Apple Hill Drive<br>Natick, MA. 01760</b>;
                      <br>https://www.mathworks.com</b>;
         </description>
         <name>The MathWorks, Inc.</name>
         <Style>
            <IconStyle>
               <Icon>
                 <href>
                   https://www.mathworks.com/products/product_listing/images/ml_icon.gif
                 </href>
               </Icon>
               <scale>1</scale>
            </IconStyle>
         </Style>
         <Point>
            <coordinates>-71.350273,42.299827,0.0</coordinates>
         </Point>
      </Placemark>
   </Document>
</kml>
If you view this in an Earth Browser, notice that the text inside the placemark, "https://www.mathworks.com," was automatically rendered as a hyperlink. The Google Earth service also adds a link called "Directions". kmlwritepoint does not include location coordinates in placemarks. This is because it is easy for users to read out where a placemark is by mousing over it or by viewing its Properties dialog box.

Generate Placemarks from Addresses

This example shows how to generate a placemark using street addresses or more general addresses such as postal codes, city, state, or country names, instead of latitude and longitude information. If the viewing application is capable of looking up addresses, such placemarks can be displayed in appropriate, although possibly imprecise, locations. (Note that the Google Maps service does not support address-based placemarks.)

When you use addresses, kmlwrite creates an <address> element for each placemark rather than <point> elements containing <coordinates> elements. For example, here is code for kmlwrite that generates address-based placemarks for three cities in Australia from a cell array:

  address = {'Perth, Australia', ...
             'Melbourne, Australia', ...
             'Sydney, Australia'};
  filename = 'Australian_Cities.kml';
  kmlwrite(filename, address, 'Name', address);
The generated KML file has the following structure and content:
<?xml version="1.0" encoding="utf-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
   <Document>
      <name>Australian_Cities</name>
      <Placemark>
         <Snippet maxLines="0"> </Snippet>
         <description> </description>
         <name>Perth, Australia</name>
         <address>Perth, Australia</address>
      </Placemark>
      <Placemark>
         <Snippet maxLines="0"> </Snippet>
         <description> </description>
         <name>Melbourne, Australia</name>
         <address>Melbourne, Australia</address>
      </Placemark>
      <Placemark>
         <Snippet maxLines="0"> </Snippet>
         <description> </description>
         <name>Sydney, Australia</name>
         <address>Sydney, Australia</address>
      </Placemark>
   </Document>
</kml>

Export Point Geostructs to Placemarks

This example shows how to read data from shapefiles and generate a KML file that identifies all or selected attributes, which you can then view in an earth browser such as Google Earth. It also shows how to customize placemark icons and vary them according to attribute values.

The Mapping Toolbox™ tsunamis shapefiles contain a database of 162 tsunami (tidal wave) events reported between 1950 and 2006, described as point locations with 21 variables (including 18 attributes). You can type out the metadata file tsunamis.txt to see the definitions of all the data fields. The steps below select some of these from the shapefiles and display them as tables in exported KML placemarks.

  1. Read the tsunami shapefiles, selecting certain attributes.

    There are several ways to select attributes from shapefiles. One is to pass shaperead a cell array of attribute names in the Attributes parameter. For example, you might just want to map the maximum wave height, the suspected cause, and also show the year, location and country for each event. Set up a cell array with the corresponding attribute field names as follows, remembering that field names are case-sensitive.

    attrs = {'Max_Height','Cause','Year','Location','Country'};
    

    Since the data file uses latitude and longitude coordinates, you need to specify 'UseGeoCoords',true to ensure that shaperead returns a geostruct (having Lat and Lon fields).

    tsunamis = shaperead('tsunamis.shp','useGeoCoords',true,...
                         'Attributes',attrs);
    

    Look at the first record in the tsunamis geostruct returned by shaperead.

    tsunamis(1)
    
               Geometry: 'Point'
               Lon: 128.3000
               Lat: -3.8000
        Max_Height: 2.8000
             Cause: 'Earthquake'
              Year: 1950
          Location: 'JAVA TRENCH, INDONESIA'
           Country: 'INDONESIA'

  2. Export the tsunami data to a KML file with kmlwrite

    By default, kmlwrite outputs all attribute data in a geostruct to a KML formatted file as an HTML table containing unstyled text. When you view it, the Google Earth program supplies a default marker.

    kmlfilename = 'tsunami1.kml';
    kmlwritepoint(kmlfilename,tsunamis(1).Lat,tsunamis(1).Lon);
    

  3. View the placemarks in an earth browser. For example, you can view KML files with the Google Earth browser, which must be installed on your computer.

    For Windows, use the winopen function:

    winopen(filename)
    

    For Linux, if the file name is a partial path, use the following commands:

    cmd = 'googleearth ';
    fullfilename = fullfile(pwd, filename);   
    system([cmd fullfilename])
    

    For Mac, if the file name is a partial path, use the following commands:

    cmd = 'open -a Google\ Earth '
    fullfilename = fullfile(pwd, filename);   
    system([cmd fullfilename])
    
  4. Customize the placemark contents

    To customize the HTML table in the placemark, use the makeattribspec function. Create an attribute spec for the tsunamis geostruct and inspect it.

    attribspec = makeattribspec(tsunamis)
    
    attribspec = 
        Max_Height: [1x1 struct]
             Cause: [1x1 struct]
              Year: [1x1 struct]
          Location: [1x1 struct]
           Country: [1x1 struct]
    Format the label for Max_Height as bold text, give units information about Max_Height, and also set the other attribute labels in bold.
    attribspec.Max_Height.AttributeLabel = '<b>Maximum Height</b>';
    attribspec.Max_Height.Format = '%.1f Meters';
    attribspec.Cause.AttributeLabel = '<b>Cause</b>';
    attribspec.Year.AttributeLabel = '<b>Year</b>';
    attribspec.Year.Format = '%.0f';
    attribspec.Location.AttributeLabel = '<b>Location</b>';
    attribspec.Country.AttributeLabel = '<b>Country</b>';
    
    When you use the attribute spec, all the attributes it lists are included in the placemarks generated by kmlwrite unless you remove them from the spec manually (e.g., with rmfield).

  5. Customize the placemark icon

    You can specify your own icon using kmlwrite to use instead of the default pushpin symbol. The black-and-white bullseye icon used here is specified as URL for an icon in the Google KML library.

    iconname = ...
      'http://maps.google.com/mapfiles/kml/shapes/placemark_circle.png';
    kmlwritepoint(kmlfilename,tsunamis(1).Lat,tsunamis(1).Lon, ...
      'Description',attribspec,'Name',{tsunamis(1).Location}, ...
      'Icon',iconname,'IconScale',2);
    

  6. Vary placemark size by tsunami height

    To vary the size of placemark icons, specify an icon file and a scaling factor for every observation as vectors of names (all the same) and scale factors (all computed individually) when writing a KML file. Scale the width and height of the markers to the log of Max_Height. Scaling factors for point icons are data-dependent and can take some experimenting with to get right.

    % Create vector with log2 exponents of |Max_Height| values
    [loghgtx loghgte] = log2([tsunamis.Max_Height]);
    % Create a vector replicating the icon URL
    iconnames = cellstr(repmat(iconname,numel(tsunamis),1));
    kmlwritepoint(kmlfilename,tsunamis(1).Lat,tsunamis(1).Lon,
        'Description',attribspec,...
        'Name',{tsunamis(1).Location},'Icon',iconname,...
        'IconScale',loghgte);