A primer on GeoJSON standard and visualization tools
What is GeoJSON ?
Well, the name GeoJSON (Geo+JSON) itself is a giveaway. The GeoJSON is a format for encoding geographical data structures, using the JavaScript Object Notation (JSON). Simply put, GeoJSON gives you an easy format for representing simple geographical features, along with their non-spatial attributes.
As described in the RFC, JSON was designed to be a lightweight, text-based and language-independent data interchange format that is easy for both humans and machines to read and write. And GeoJSON basically uses this design strategy to represent data about geographic features, their properties, and their spatial extents.
Fancy an example ?
Does the structure make sense ? No ? Read on!
So, what all goes inside a GeoJSON object ?
Glad you asked! A GeoJSON object can define the followings:
- Geometric objects in space: for example, a Point, LineString or Polygon etc.
- Features: A feature is a spatially bounded entity.
- List of Features: Also known as a FeatureCollection.
Okay, this terminology might be too much to digest at once. So, let’s look into each part one-by-one.
Geometric Objects
Geometry objects represent points, curves, and surfaces in coordinate space. The GeoJSON RFC defines 7 “types” of a geometric shapes that a GeoJSON object can represent. These are “Point”, “MultiPoint”, “LineString”, “MultiLineString”, “Polygon”, “MultiPolygon”, and “GeometryCollection”.
Point, LineString and Polygon shapes are also known as single type Geometry objects. While MultiPoint, MultiLineString, and MultiPolygon are also called homogeneously typed multipart Geometry objects.
Construct for many of these shapes will become clear once you understand the concept of a Position.
A Position is a fundamental geometric construct. Simply put, it is an array of 2 or three numbers. The first two numbers represent longitude and latitude(in that order). And the third (optional) number represents altitude or elevation. So, a position is basically the array [longitude, latitude, elevation/altitude].
NOTE: Among different geographical tools or libraries, there seems to be no common consent about whether the ordering should be [longitude, latitude] or [latitude, longitude]. For example, Google Maps API and Leaflet.js expect the coordinates to be [latitude, longitude] while GeoJSON, shapefile, D3.js, ArcGIS API expect the coordinates to be in the format [longitude, latitude]. So, always be wary of what order is required for your application. For reference, you could use the below table compiled by Tom MacWright on his blog.
All geometric shapes have two key value pairs defining that shape. You might have also noticed them in the sample GeoJSON object you saw above. The two keys are type and coordinates. “type” must be one of the seven types we saw above and “coordinates” is an array of Position values. The exact structure of the elements in this array is determined by the type of geometry.
Point: As you can guess, if we want to represent a Point geometry, we need to have one position. So, we can define a Point in GeoJSON as:
{ "type": "Point",
"coordinates": [30, 10]
}
MultiPoint: The “coordinates” value would be an array of Position objects for a MultiPoint object.
{ "type": "MultiPoint",
"coordinates": [
[10, 40], [40, 30], [20, 20], [30, 10]
]
}
LineString: For LineString, we need to provide two positions, i.e. the start and end points of the line segment. For example:
{ "type": "LineString",
"coordinates": [
[30, 10], [10, 30], [40, 40]
]
}
MultiLineString: For type “MultiLineString”, the “coordinates” member is an array of LineString coordinate arrays.
{ "type": "MultiLineString",
"coordinates": [
[[10, 10], [20, 20], [10, 40]],
[[40, 40], [30, 30], [40, 20], [30, 10]]
]
}
Polygon
Polygons in GeoJSON standard, are slightly more complex than the other geometric shapes. A Polygon is defined in RFC document as “For type “Polygon”, the “coordinates” member MUST be an array of linear ring coordinate arrays”. So to understand a Polygon definition, we must first have a look at the LinearRing concept.
A LinearRing is a closed LineString with four or more positions. “Closed” simply means that the start and end point of the LinearRing must be the same Position. A Polygon in GeoJSON format is specified in terms of multiple LinearRing shapes. The outer boundary of the Polygon is one LinearRing, and there could be multiple other LinearRing shapes defining the other intricate ring shapes inside that Polygon.
As per the standard, the first LinearRing array inside the “coordinate” array must be the exterior ring and all following LinearRing arrays define the interior rings. RFC 7946 also defined winding order for these rings, which specifies that the exterior rings Position are defined counterclockwise, and interior rings Position values are defined clockwise. This winding order is useful for many drawing APIs.
{ "type": "Polygon",
"coordinates": [
[[35, 10], [45, 45], [15, 40], [10, 20], [35, 10]],
[[20, 30], [35, 35], [30, 20], [20, 30]]
]
}
MultiPolygon
For type “MultiPolygon”, the “coordinates” member is an array of Polygon coordinate arrays.
{ "type": "MultiPolygon",
"coordinates": [
[
[[30, 20], [45, 40], [10, 40], [30, 20]]
],
[
[[15, 5], [40, 10], [10, 20], [5, 10], [15, 5]]
]
]
}
GeometryCollection
A GeometryCollection is a heterogeneous composition of the other geometry types you saw above. A GeometryCollection object has no “coordinates” member, instead it has a member named “geometries”. The value of “geometries” is an array. Each element of this array is a GeoJSON Geometry object. It is possible for this array to be empty.
{ "type": "GeometryCollection",
"geometries": [
{
"type": "Point",
"coordinates": [0, 0]
}, {
"type": "Polygon",
"coordinates": [[[45, 45], [45, -45], [-45, -45], [-45, 45], [45,45]]]
}
]
}
Feature Object
The Geometric shapes that you saw in last section, define shapes that can be plotted on a map. However, our shapes on map should also have some real-world meaning. This meaning is defined by attributes of that shape. For example, a building marked by a Polygon on map could have a name property like “Taj Mahal” and possibly some other parameters further describing the shape. In GeoJSON, an object of type “Feature” defines both the gemoetric shape and attributes for an entity.
The Feature object has a member with name “type” with the value “Feature”. It also has a member with the name “geometry” with value of any geometric shape that we discussed above or a null value. Further, it has a member with the name “properties” whose value is a JSON object (or null value) defining the attributes for that object. It can also have an optional “id” member with a unique string or null value specifying an identifier for the Feature.
As an example of Feature object, take a look at the sample GeoJSON object that you saw at the start of this article.
I hope it makes more sense now.
FeatureCollection Object
A FeatureCollection object is a composition of Feature objects. It is the most common top-level construct you will observe in a GeoJSON file. It has a member “type” with value “FeatureCollection” and another member with name “features” with array of Feature object as value.
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-80.83775386582222, 35.24980190252168]
},
"properties": {
"name": "DOUBLE OAKS CENTER",
"address": "1326 WOODWARD AV"
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-80.83827000459532, 35.25674709224663]
},
"properties": {
"name": "DOUBLE OAKS NEIGHBORHOOD PARK",
"address": "2605 DOUBLE OAKS RD"
}
}
]
}
Miscellaneous: Bounding Box
A GeoJSON object might also contain a bounding box that defines the bounding range for the GeoJSON object. For example, in a 2-dimensional geometry, a bounding box is simply a member with name “bbox” and an array of four numbers as values. These four values define the rectangle that contains the complete GeoJSON object.
{
"type": "FeatureCollection",
"bbox": [100.0, 0.0, 105.0, 1.0],
"features": [
//...
]
}
Cool! So now that you know the basics you need to master GeoJSON data, let’s take a look some of the tools that you can use to visualize the GeoJSON data.
How to visualize GeoJSON data ?
In this section, I will share some of the popular GUI based tools that you may use to quickly visualize the GeoJSON data. Tom MacWright has an exhaustive list of utilities that convert, process, and analyze GeoJSON data on his Github.
For a Python based environment such as a Jupyter Notebook, you might use a module like GeoPandas. Twilio has a nice little tutorial using Shaply and GeoPandas.
Google Developers — GeoJSON appspot
On this web app, you can plot geometric shapes directly on Google Maps and visualize the GeoJSON code side-by-side in two panes. This visualization is really helpful to understand GeoJSON concept. You may also download .geojson file in a single click.
geojson.io is a web-based editor where you can import and export GeoJSON data. It also shows you GeoJSON code and visual output in side-by-side panes.
QGIS is a free, open-source cross-platform software for viewing, editing, and analyzing geospatial data. GeoJSON format is supported by QGIS, along with plethora of other geospatial data standards. You can download and install latest QGIS software from here. As an example, I will use the crime incidents data of Nanaimo city of Canada. This data is available here in GeoJSON format.
- Open “QGIS Browser” on your computer and browse the .geojson file in the left pane. The right pane will show you a quick preview of the data points.
- You may also view attributes by clicking on the Attributes tab next to Preview tab.
In the next article, I will explain how to overlay the GeoJSON data on a raster data layer using QGIS Desktop. I will be using Spacenet satellite imagery dataset available on AWS.
I hope this article was helped you to better understand the GeoJSON standard. Thank you for your time! And I’ll see you in the next one! :)
Edit: The follow up article with SpaceNet dataset is live. In this article, you will learn about the high resolution satellite imagery made available in SpaceNet and how to access and visualize it.