Convert S-57 Electronic Nautical Charts (ENCs) to GeoJSON using Python

Jordan Taylor
Shipping Intel
Published in
5 min readJul 22, 2024

Electronic nautical charts (ENCs) are charts that are produced by government authorities and used by onboard electronic chart display and information systems (ECDIS). In this article I explain how to unpack and read these files using Python.

Source: NOAA.

Introduction

Professional mariners use electronic display and information systems (ECDIS) on the bridge of vessels when underway for the purpose of safety of navigation. An ECDIS will allow a mariner to obtain their position in real time and simultaneously be able to see a chart as well as objects around the vessel that aid in navigation. Electronic nautical charts (ENCs) are produced by government authorities and disseminated through various sources such as the National Oceanic and Atmospheric Administration (NOAA).

The data structure that ENCs follow is the International Hydrographic Organization (IHO) S-57 Standard, and is strictly adhered to and vetted by professional cartographers and data analysts worldwide when producing electronic charts. Within artificial intelligence, the data contained in electronic charts is considered grounded truth, as the primary purpose of government-sourced ENCs is safety of navigation (IMO, 2016).

My original purpose for unpacking these files is to collect the wealth of information hidden in these datasets. Specifically, there are objects that impact commercial terms, such as passing a sea buoy or anchorage demarcations. However there is a great deal of valuable data contained in these charts that have technical and operational applicability as well.

Method

Step 1: Obtain an ENC

Within the United States, ENCs can be obtained for free using a chart location tool through NOAA. In the example that follows I will upload the entrance chart to San Francisco.

Source: NOAA.

When the ENC is loaded up, you will receive a ZIP file or directory, typically called ENC_ROOT. Within the chart name directory (i.e. US4CA11M) there is a file with the extension “.000” which contains ENC objects that exhibit geospatiality. In other words, the file contains labels, points, lines, and polygons associated with aids to navigation.

Step 2: Import GDAL

The GDAL (Geospatial Data Abstraction Library) in Python is a translator library for vector geospatial data formats. It provides tools for reading data in a variety of geospatial formats.

A javascript object notation library (JSON) will need to be imported as well.

Terminal:

pip install GDAL
pip install JSON

Step 3: Unpack the Electronic Nautical Chart

Within the GDAL library you will need to import OpenGIS Simple Features Reference Implementation (OGR). Python IDE:

from osgeo import ogr
import json

Within OGR import the S-57 driver:

driver = ogr.GetDriverByName('S57')

Using the loaded driver, it tries to open the dataset located at the given file path. Ensure you replace file_path below with the path to the file with the “.000” extension.

dataset = driver.Open(file_path)

The last step is to iterate over the geospacial layers and obtain the geographical elements within the dataset.

    features = []
for layer_index in range(dataset.GetLayerCount()):
layer = dataset.GetLayerByIndex(layer_index)
print("Inspecting layer:", layer.GetName(), "with", layer.GetFeatureCount(), "features")

for feature in layer:
geometry = feature.GetGeometryRef()
if geometry is None:
print("Feature with ID", feature.GetFID(), "in layer", layer.GetName(), "has no geometry")
continue

geom_type = geometry.GetGeometryType()
if geom_type == ogr.wkbPoint:
point = geometry.GetPoint()
features.append(('point', point, layer.GetName()))
elif geom_type == ogr.wkbLineString:
line = geometry.GetPoints()
features.append(('line', line, layer.GetName()))
elif geom_type == ogr.wkbPolygon:
polygon = geometry.GetGeometryRef(0).GetPoints()
features.append(('polygon', polygon, layer.GetName()))

When unpacked and applied to folium:

Source: Folium.

Full Code Example

Note that you will need to replace the path with the path to the ENC chart you wish to unpack. The below function then iterates through each layer in the dataset. For each geospatial layer, it collects the layer name and geometry (point, line, polygon) and outputs as JSON.

from osgeo import ogr
import json

# Define a function to read ENC file and extract features from all layers
def read_enc(file_path):
driver = ogr.GetDriverByName('S57')
if not driver:
print("Driver not found for 'S57'")
return []

dataset = driver.Open(file_path)
if not dataset:
print("Failed to open file:", file_path)
return []

features = []
for layer_index in range(dataset.GetLayerCount()):
layer = dataset.GetLayerByIndex(layer_index)
print("Inspecting layer:", layer.GetName(), "with", layer.GetFeatureCount(), "features")

for feature in layer:
geometry = feature.GetGeometryRef()
if geometry is None:
print("Feature with ID", feature.GetFID(), "in layer", layer.GetName(), "has no geometry")
continue

geom_type = geometry.GetGeometryType()
if geom_type == ogr.wkbPoint:
point = geometry.GetPoint()
features.append(('point', point, layer.GetName()))
elif geom_type == ogr.wkbLineString:
line = geometry.GetPoints()
features.append(('line', line, layer.GetName()))
elif geom_type == ogr.wkbPolygon:
polygon = geometry.GetGeometryRef(0).GetPoints()
features.append(('polygon', polygon, layer.GetName()))

return features

# Read ENC file and extract features
file_path = '[REPLACE WITH PATH]'
features = read_enc(file_path)
print("Extracted features:", features)

# Save features to a JSON file
with open('[YOUR FILE NAME].json', 'w') as f:
json.dump(features, f)

Conclusion

One of the primary missions of the International Maritime Organization is digitization in the pursuit of sustainability. Electronic charts support navigational safety, reduce risk of collisions, and aid in route optimization. Furthermore, the information within ENCs is considered grounded truth and has been described as such since the 1990s (IMO, 1996).

Therefore, when we discuss digitization, and particularly digitization in the context of artificial intelligence, it is the author’s opinion that ENCs must be a part of foundational domain-specific models. In other words, the AI must be able to know if a vessel is within an anchorage, or transiting a traffic separation scheme, as these objects will have direct impact on sustainability models.

Shipping Intel

To learn more about how Shipping Intel could help in your maritime tech journey contact info@shippingintel or visit shippingintel.com. Alternatively, you are welcome to contact me directly through LinkedIn.

References

(n.d.). International Maritime Organization (IMO). Retrieved July 22, 2024, from https://www.imo.org/

General information — GDAL documentation. (n.d.). GDAL. Retrieved July 22, 2024, from https://gdal.org/api/python_bindings.html

IHO S-57 (ENC) — GDAL documentation. (n.d.). GDAL. Retrieved July 22, 2024, from https://gdal.org/drivers/vector/s57.html

IHO TRANSFER STANDARD for DIGITAL HYDROGRAPHIC DATA. (2000, November 1). International Hydrographic Organization. Retrieved July 22, 2024, from https://iho.int/uploads/user/pubs/standards/s-57/31Main.pdf

RESOLUTION MSC.530(106) (adopted on 7 November 2022) PERFORMANCE STANDARDS FOR ELECTRONIC CHART DISPLAY AND INFORMATION SYSTEMS (ECDIS). (2022, November 7). International Maritime Organization. Retrieved July 22, 2024, from https://wwwcdn.imo.org/localresources/en/KnowledgeCentre/IndexofIMOResolutions/MSCResolutions/MSC.530(106).pdf

Shipping Intel. (2024). Shipping Intelligence. Retrieved from https://www.shippingintel.com/

--

--

Jordan Taylor
Shipping Intel

Merchant marine officer with a B.S. in Marine Transportation and a M.S. in Transportation Management.