The 4 Most Common Geometries in KML

Keyhole Markup Language (KML) is an XML notation for expressing geographic annotation and visualization within two-dimensional maps and three-dimensional Earth browsers.

In this post, we are going to first quickly introduce KML file structure and <Placemark> element, then focus on the 4 most common geometries that can be used in a <Placemark> in KML.

If you are familiar with the concept of extensions in object-oriented programming, you might find the diagram below helpful to understand the KML elements we are going to cover in this post.

(Partial) class tree for KML elements

This diagram is only a small portion (that we will cover in this post) of all the supported KML elements. If you are interested, please see the whole tree here.

In the tree, you can consider each element as a class in OOP, and an element is an extension of its parent. For example, <Placemark> is a special kind of Feature: a <Placemark> contains all of the attributes that a Feature has, and it adds some attributes that are specific to the <Placemark>.

Further, as you notice, there are two kinds of elements in the tree:

  • abstract element (dashed-border, no-background, italic-text)
  • concrete element (solid-border, blue-background, angle-brackected)

Abstract elements are not actually used in KML files (as you cannot instantiate from an abstract class in OOP), while concrete elements are the ones you will see from a KML file, such as <Placemark>.

KML Basic Syntax

A simple KML would look like this (⚠️ all tags are case-sensitive):

A simple KML
  • An XML header
  • A KML namespace declaration on <kml>

In this example, within the <kml> element, there is a <Placemark> containing one <Point> and some non-geometric information that describes the <Placemark>.

<Placemark>

<Placemark>
<name>Simple placemark</name>
<description>Can use HTML here.</description>
<Point>
<coordinates>-122.08,37.42,0</coordinates>
</Point>
</Placemark>

A <Placemark> contains geometries and the forth-mentioned “non-geometric information.”

Before we talk about geometry part, let’s see what the non-geometric information is. As shown in the above example, they are elements like <name> and <description>.

Nothing too exciting about <name>—it contains plain text which will be displayed as label when the KML is rendered in Earth browsers.

However, <description>, the content of which will be displayed as description balloon in Earth browsers, is more powerful and informative—you can write HTML in it! There are two ways of doing this (since KML is essentially XML):

  • put HTML inside a CDATA tag
  • convert special characters to entity references: e.g. >&gt

Now we can talk about the geometry part. It’s represented in KML as elements such as:

  • <Point>
  • <LineString>
  • <LinearRing>
  • <Polygon>
  • etc.

<Point>

<Point>
<coordinates>-122.08,37.42,0</coordinates>
</Point>

A <Point> contains one element of <coordinates>. <coordinates> is a single tuple consisting of floating point values for:

  • longitude: ≥ −180 and ≤ 180 in decimal degrees, e.g. -122.08
  • latitude: ≥ −90 and ≤ 90 in decimal degrees, e.g. 37.42
  • altitude (optional): in meters above sea level, e.g. 0

⚠️ Do not include spaces between the three values that describe a coordinate.

Here’s a demo rendering a <Point> from a KML.

Render a KML <Point> on map

<Point> is pretty straightforward. Let’s move on to the next dimension.

<LineString>

<LineString>
<extrude>1</extrude>
<tessellate>1</tessellate>
<altitudeMode>relativeToGround</altitudeMode>
<coordinates>-12.2,36.09 -12.27,36.09 -12.25,36.10</coordinates>
</LineString>

While <Point>’s <coordinates> only contains one tuple, the <coordinates> of a <LineString>’s contains two or more tuples, representing two or more points. A space is inserted between the tuples, and no space within a tuple.

As you may notice in the example above, there are only two values in a tuple—the altitude is not required. Then you may wonder, how should an Earth Browser know at what altitude the <LineString> should be displayed?

What an Earch Browser does know about is the terrain. Would it be nice to display the <LineString> following the terrain? You can do this by including <tessellate> element which contains 1 in it, as shown in the example above. The value contained in this element is acutally a boolean and it is represented by 0 or 1.

tessellate: 0 (yellow) vs 1 (red)

In the image above, yellow line is a line string with tessellate turned off and red turned on. The yellow line string can possibly go underground since they are straight line segments between points, while red ones will follow the terrain.

Of course KML will let you include the altitude value, but you probably need to make sure the value is interpreted as what you want by specifying an element called <altitudeMode>. Please see more details about it here.

Here’s a demo rendering a <LineString>:

The other kind of line geometry in KML is <LinearRing>

<LinearRing>

<LinearRing>
<coordinates>
-77.05788457660967,38.87253259892824,100
-77.05465973756702,38.87291016281703,100
-77.05315536854791,38.87053267794386,100
-77.05552622493516,38.868757801256,100
-77.05844056290393,38.86996206506943,100
-77.05788457660967,38.87253259892824,100
</coordinates>
</LinearRing>

Well, it’s just a closed line string. To show the characteristic of this “closedness,” the last tuple is identical with the first one in the <coordinates> element. Plus it’s closed, so the <coordinates> needs at least four tuples to be valid.

<LinearRing> is very useful to define <Polygon> which we are going to talk about next.

<Polygon>

<Polygon>
<extrude>1</extrude>
<altitudeMode>relativeToGround</altitudeMode>
<outerBoundaryIs>
<LinearRing>
<coordinates>
-77.05788457660967,38.87253259892824,100
-77.05465973756702,38.87291016281703,100
-77.05315536854791,38.87053267794386,100
-77.05552622493516,38.868757801256,100
-77.05844056290393,38.86996206506943,100
-77.05788457660967,38.87253259892824,100
</coordinates>
</LinearRing>
</outerBoundaryIs>
<innerBoundaryIs>
<LinearRing>
<coordinates>
-77.05668055019126,38.87154239798456,100
-77.05542625960818,38.87167890344077,100
-77.05485125901024,38.87076535397792,100
-77.05577677433152,38.87008686581446,100
-77.05691162017543,38.87054446963351,100
-77.05668055019126,38.87154239798456,100
</coordinates>
</LinearRing>
</innerBoundaryIs>
</Polygon>

This example could be a little bit long. Just imagine we need to define an area: what would we need to do? We need to describle the boundaries. There are two kinds of boundaries in a <Polygon>:

  • outer boundary <outerBoundaryIs>: a polygon can have 1 and only 1 of it
  • inner boundary <innerBoundaryIs>: a polygon can have 0 or more of it

A boundary is defined by a <LinearRing> that we just talked about above.

Boundaries define an area. In the above example, an area is 100 meters above the ground (as specified by relativeToGround in <altitudeMode>), floating in the air, with a hole in it. What about defining a volume, like a building? Simply extrude the floating-in-the-air area to the ground by turning on the flag of <extrude>.

extrude: 0 vs 1

Here’s a demo rendering the <Polygon>:

The polygons in the screenshots above are styled: they have a specific color and line thickness. Yes, you can style geomeetries in KML, and I hope to cover that topic in another post.

References

The post structure and KML files used in the demo were borrowed from the Google KML tutorial. Some of the KML tutorial/documentation content was rephrased to better serve the purpose of the post.

The demo was implemented using ArcGIS API for JavaScript (https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-KMLLayer.html) on CodeSandbox. Here’s the demo link: https://codesandbox.io/s/load-kml-using-arcgis-js-api-q60lt

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store