Creating elevation contours

Now, let's look at another way to visualize the elevation better using contours. A contour is an isoline along the same elevation in a dataset. Contours are usually stepped at intervals to create an intuitive way to represent elevation data, both visually and numerically, using a resource-efficient vector dataset.

The input to generate contours is our DEM and the output is a shapefile. The algorithm to generate contours is fairly complex and very difficult to implement using NumPy's linear algebra. So, our solution in this case is to fall back on the GDAL library, which has a contouring method available through the Python API. In fact, the majority of this script is just setting up the OGR library code that is needed to output a shapefile. The actual contouring is a single method call named gdal.ContourGenerate(). Just before this call, there are comments defining the method's arguments. The most important ones are as follows:

  • contourInterval: It is the distance in the dataset units between contours
  • contourBase: It is the starting elevation for the contouring
  • fixedLevelCount: It specifies a fixed number of contours as opposed to distance
  • idField: It is a name for a required shapefile dbf field, usually just called ID
  • elevField: It is a name for a required shapefile dbf field for the elevation value that is useful for the labeling in maps

You should have GDAL and OGR installed from the Installing GDAL section in Chapter 4, Geospatial Python Toolbox. In the following code, we will define the input DEM filename, output shapefile name, create the shapefile data source with OGR, get the OGR layer, open the DEM, and generate contours on the OGR layer:

import gdal
import ogr

# Elevation DEM
source = "dem.asc"
# Output shapefile
target = "contour"

ogr_driver = ogr.GetDriverByName("ESRI Shapefile")
ogr_ds = ogr_driver.CreateDataSource(target + ".shp")
ogr_lyr = ogr_ds.CreateLayer(target, 
# wkbLineString25D is the type code for geometry with a z 
# elevation value.
geom_type=ogr.wkbLineString25D)
field_defn = ogr.FieldDefn("ID" ogr.OFTInteger)
ogr_lyr.CreateField(field_defn)
field_defn = ogr.FieldDefn("ELEV" ogr.OFTReal)
ogr_lyr.CreateField(field_defn)

# gdal.ContourGenerate() arguments
# Band srcBand,
# double contourInterval,
# double contourBase,
# double[] fixedLevelCount,
# int useNoData,
# double noDataValue,
# Layer dstLayer,
# int idField,
# int elevField
ds = gdal.Open(source)
# EPGS:3157
gdal.ContourGenerate(ds.GetRasterBand(1), 400, 10, [], 0, 0, ogr_lyr, 0, 1))
ogr_ds = None

Now, let's draw the contour shapefile that we just created using PNGCanvas, introduced in the PNGCanvas section of Chapter 4, Geospatial Python Toolbox:

import shapefile
import pngcanvas
# Open the contours
r = shapefile.Reader("contour.shp")
# Setup the world to pixels conversion
xdist = r.bbox[2] - r.bbox[0]
ydist = r.bbox[3] - r.bbox[1]
iwidth = 800
iheight = 600
xratio = iwidth/xdist
yratio = iheight/ydist
contours = []
# Loop through all shapes
for shape in r.shapes():
    # Loop through all parts
    for i in range(len(shape.parts)):
        pixels = []
        pt = None
        if i < len(shape.parts) - 1:
            pt = shape.points[shape.parts[i]:shape.parts[i+1]]
        else:
            pt = shape.points[shape.parts[i]:]
        for x, y in pt:
            px = int(iwidth - ((r.bbox[2] - x) * xratio))
            py = int((r.bbox[3] - y) * yratio)
            pixels.append([px, py])
        contours.append(pixels)
# Set up the output canvas
canvas = pngcanvas.PNGCanvas(iwidth, iheight)
# PNGCanvas accepts rgba byte arrays for colors
red = [0xff, 0, 0, 0xff]
canvas.color = red
# Loop through the polygons and draw them
for c in contours:
    canvas.polyline(c)
# Save the image
with open("contours.png", "wb") as f:
    f.write(canvas.dump())

We will end up with the following image:

Creating elevation contours

If we bring our shaded relief ASCIIGRID and the shapefile into a GIS, such as QGIS, we can create a simple topographic map as follows. You can use the elevation (that is ELEV) dbf field that you specified in the script to label the contour lines with the elevation:

Creating elevation contours

The techniques in these NumPy grid examples provide the building blocks for all kinds of elevation products. The USGS has an excellent web page with sample elevation-based data layers, including the examples that we created as well as some more advanced types:

http://edna.usgs.gov/datalayers.asp

Next, we'll work with one of the most complex elevation data types: LIDAR data.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset