[GRASSLIST:854] contour->dem - nice new tool + questions

William Kyngesburye woklist at kyngchaos.com
Mon Apr 24 18:32:24 EDT 2006


I found this mentioned in a bug report for r.contour (#4248).  I  
expanded a bit on it and added more details.  Until (if) the nnbathy  
tool gets added to GRASS, the process is a bit lengthy.  But the  
results are better for contour data than r.surf.contour or  
v.surf.rst.  Thanks to Maciek for the original outline of this process.

The main idea behind my expansion of his outline is that I wanted to  
include extra help for the plain contours:

- any spot elevations - either peaks or just extra points in flat areas

- lake polygons of known elevation - the contour can help.  And if  
you like, you can patch in the area afterwards for a flat fill.

It uses the Natural Neighbors algorythm.  Software is here:

http://www.marine.csiro.au/~sakov/

You must get the nnbathy program - binaries for Windows and some  
flavor of linux, or build it from source.

Also, I worked this out using OGR tools.  This should work with GRASS  
6.0.  The current 6.1 CVS has an improved v.patch that could speed  
things up a bit.


Start with 1-3 vectors, lines minimum: all should have the same  
attribute for elevation (elev in this example), and just that  
attribute, though the OGR method will take care of extra attributes  
for you, but the elevation field still must be the same.  I didn't  
take the time to figure out how do this in GRASS.

1. hypsol - At least your contours - all lines, and they don't have  
to be continuous, you can have supplemental contour segments in flat  
areas.

2. hypsox - Spot elevations are helpful - a point vector, can be  
peaks, low points, or anywhere in between

3. hypsop - Lake polygons - area vector.  the boundary will be used  
as another contour, and the area will be used as a mask and a flat-fill


### merge all the layer together as points
# skip steps referring to lake polys and/or spot points if you don't  
have those
# if you have neither, just lines, there is no need to export, merge  
and import
#   and you can skip to the prepaing for nnbathy steps, and use  
hypsox as the point
#   vector as if it were the merged point vector

# spot elevs are ready to go as is
v.out.ogr in=hypsox dsn=. olay=hypsox typ=point

# turn contour lines into lots of points and export them
#   use a dmax = desired dem cell size, but there may be a better choice
v.to.points in=hypsol out=hypsolx dmax=0.000833
v.out.ogr in=hypsolx dsn=. olay=hypsolx typ=point

# rasterize poly fills with elevation to use as mask for  
interpolation grid
v.to.rast in=hypsop out=hypsofills col=elev
# invert nulls/values - this is the grid for the values we want in  
the end,
#   and we don't need to waste time interpolating the lakes
r.mapcalc hypsointerp="if(isnull(hypsofills),1,null())"
r.stats -g -n hypsointerp > hypsointerp1.asc
# remove extra dummy elev column
cat hypsointerp1.asc | sed 's/ 1$//g' > hypsointerp.asc

# also export boundaries of polys as extra contours
#   don't want the whole fill since that would ruin the slope of the  
shore into the lake
v.category in=hypsop out=hypsopc op=add typ=boundary
# same as for lines, pick dmax = cell size
v.to.points in=hypsopc out=hypsopx type=boundary dmax=0.000833
v.out.ogr in=hypsopx dsn=. olay=hypsopx typ=point

# cleanup and merge points, lines and boundaries
#   if there are extra attributes, this takes care of ignoring those
ogr2ogr -select elev . . hypsolx -nln hypsopt
ogr2ogr -update -append -select elev . . hypsopx -nln hypsopt
ogr2ogr -update -append -select elev . . hypsox -nln hypsopt

v.in.ogr dsn=. lay=hypsopt out=hypsopt

## alt merging in GRASS, instead of all the above: CVS only, all  
columns must be exact same
v.patch -e out=hypsopt in=hypsolx,hypsopx,hypsox
##

### prepare for nnbathy

# need coords in attributes
v.db.addcol map=hypso col="x double,y double"
# ! v.to.db really slow !  there must be a better way (or maybe it's  
the dbf)
v.to.db map=hypso op=coor col=x,y
v.db.select -c hypso column=x,y,elev fs=" " > hypsopoints.asc

### finally, interpolate the grid.  at this point, this step goes  
much faster than r.surf.contour of v.surf.rst
nnbathy -i hypsopoints.asc -o hypsointerp.asc > dem.grd

# a few random cells it just can't interpolate, tidy it up for GRASS
cat dem.grd | sed 's/nan/999999.0/g' > dem.grd.nonan

### bring it back in and cleanup

v.in.ascii -t -z in=dem.grd.nonan out=dem_vect fs=space z=3
v.to.rast in=dem_vect out=dem1 use=z
r.null dem1 set=999999.0

# merge in lake polys
r.patch out=dem in=dem1,hypsofills

# you could run r.fillnulls on this to fill in those last stray cells


You can delete all the inbetween stuff now.  The merging step would  
probably be much faster with the v.patch method, but if the vector  
attributes don't match it won't work.  You can't drop or rename  
columns in a dbf, but with sqlite attrib storage it might be  
possible, certainly with postgres.  Just a couple db.execute's to  
alter tables.


If some industrious programmer adds nnbathy to GRASS as a C module  
(or script I guess, it would just be much slower, and require the  
nnbathy binary), it would be nice to have all threee line, point and  
poly source options, or at least line and point.  To make it easier  
to deal with attribute disparities, all sources should have a way to  
set the elevation column (or to use the z value).


QUESTION:

The output looks great - a coworker said it looks a lot like Arc's  
topogridtool output without any stream input.  So, is there some way  
to enforce stream drainage patterns (if one has the digitized stream  
vectors) in generated DEMs with GRASS commands?  Could it be done  
after the above DEM interpolation, or would it only work as a part of  
the interpolation (assuming someone could add that to the program code)?

-----
William Kyngesburye <kyngchaos at kyngchaos.com>
http://www.kyngchaos.com/

All generalizations are dangerous, even this one.




More information about the grass-user mailing list