Geospatial Analysis II: buffers, cost surfaces, least cost path
Text files with recode rules, color rules and site locations:
Start GRASS GISIn startup pannel set GRASS GIS Database Directory to path to datasets, for example on MS Windows,
C:\Users\myname\grassdata. For GRASS Location select nc_spm_08_grass7 (North Carolina, State Plane, meters) and for GRASS Mapset create a new mapset (called e.g. HW_buffers_cost) and click Start GRASS session.
Remove MASK in case it was left over from previous assignment (use command
Change working directory:
Settings > GRASS working environment > Change working directory > select/create any directory
cd (stands for change directory) into the GUI
Console and hit Enter:
Download all text files with recode rules, color rules and site locations (see above) to the selected directory. Now you can use the commands from the assignment requiring the text file without the need to specify the full path to the file.
Find developed areas close to lakesSet region, create buffers:
g.region swwake_30m -p r.buffer lakes output=lakes_buff distances=60,120,240,500 d.rast lakes_buff
List categories in land use map to identify category numbers for developed areas. Then run r.mapcalc to extract the developed areas within the buffers and use r.support to assign the labels from the original buffer raster to the new developed buffer raster map (needed for legend):
r.category landuse96_28m r.mapcalc "developed_lake = if(landuse96_28m==1 || landuse96_28m==2, lakes_buff, null())" r.support developed_lake raster=lakes_buff r.category developed_lake
In GUI: switch off previous map, use Add raster, Add vector icons.
d.rast developed_lake d.vect streets_wake color=grey d.rast lakes d.legend -c developed_lake use=2,3,4,5 at=5,25,2,5 d.out.file mylakesbuffmap
Find the total area within buffers and the developed area in ha:
r.report -n lakes_buff units=h r.report -n developed_lake units=h
Find developed areas impacted by noise from highwaysSet region and create buffers along major roads.
Intersect developed areas from landuse map with road buffers.
Transfer the category labels and compute the affected area.
Run r.category from GUI and browse to the txt file, or run r.category command (assuming noise_cats.txt is in your working directory).
g.region raster=landuse96_28m -p r.buffer roadsmajor output=roads_buffers distances=250,500,2500 r.mapcalc "noise = if(landuse96_28m==1 || landuse96_28m==2, roads_buffers, null())" r.colors noise color=ryg r.category noise rules=noise_cats.txt separator=: r.report -n noise units=p,h
Display the results. In GUI switch off previous maps.
d.rast noise d.vect streets_wake d.legend -c noise at=5,25,2,5
Find schools affected by high levels of noiseConvert schools to raster using CORECAPACI attribute (school capacity).
Use map algebra to overlay with noise impact buffers and compute the number of students exposed to noise (see result of r.univar).
v.to.rast schools_wake output=schoolscap_10m use=attr attrcolumn=CORECAPACI type=point r.mapcalc "schools_noise = if(int(schoolscap_10m) && roads_buffers == 2, int(schoolscap_10m), null())" r.univar schools_noise r.to.vect schools_noise output=schools_noise type=point d.vect schools_wake icon=basic/circle size=10 fill_color=blue d.vect schools_noise size=14 fill_color=cyan icon=basic/circle color=black d.out.file mynoisemap
Compute cumulative cost surface to a given accident site based on speed limitsUse 5mi/hr speed limit for off-road areas (nulls).
For legend set the discrete speed limit values in GUI legend dialog:
tab Required > streets_speed, Subset > List of discrete category numbers
g.region swwake_30m -p v.info -c streets_wake v.to.rast streets_wake output=streets_speedtmp use=attr attrcolumn=SPEED type=line r.mapcalc "streets_speed = if(isnull(streets_speedtmp),5,streets_speedtmp)" r.info streets_speed r.colors streets_speed color=gyr d.rast streets_speed d.legend streets_speed at=5,40,2,5 use=5,25,35,45,65 d.out.file myspeedmap
Import the accident point location from GeoJSON file fire_pt.json
Run v.in.ogr from GUI, use file browser to provide full path to the file, or run the command assuming the file is in your working directory.
v.in.ogr input=fire_pt.json output=fire_pt
Assign travel time to cross a 30m grid cell in hours.
Note that cost in GRASS GIS is defined as travel time per cell.
Compute cumulative cost surface to the given point.
Where does the 0.018641 constant come from? You can modify the expression to get time in minutes.
r.mapcalc "streets_travtime = 0.018641/streets_speed" r.cost -k streets_travtime output=streets_cost start_points=fire_pt
Compute isochrones and display the cumulative cost surface map.
r.contour streets_cost output=streets_cost_04 step=0.04 r.colors streets_cost color=elevation d.rast streets_cost d.vect fire_pt color=red icon=basic/marker size=20 d.vect streets_cost_04 d.legend streets_cost at=5,50,2,5 d.out.file mycostmap
Find cost (travel time) from selected firestationsFirst make your own copy of the firestations map and list attributes.
Then query the cumulative cost surface at the firestations location.
The travel time in hours will be stored in the attribute column CVLAG.
g.copy vector=firestations,myfirestations v.info -c myfirestations v.what.rast myfirestations raster=streets_cost column=CVLAG
Add myfirestations to Layer Manager and right click on Show attribute data.
Click on CVLAG to order them and find the lowest cost (shortest time) > 0 (firestations with 0 cost are outside the region).
You should see a table like this.
Export firestations with traveltime less than 0.1 hr:
v.out.ascii input=myfirestations separator=space precision=3 columns=ID,LOCATION,CVLAG where="CVLAG<0.1 AND CVLAG>0"
You should get something like the following:
635775.565 228121.693 19 19 4021 District Dr 0.076 635940.262 225912.796 20 0 5001 Western Blvd 0.037 637386.831 222569.152 21 0 1721 Trailwood Dr 0.071 633178.155 221353.037 52 27 6000 Holly Springs Rd 0.060
To get the computed time, you can also query the cumulative cost raster directly using coordinates (in this example it's Western Blvd firestation), or using GUI query tool by selecting the cost layer and clicking on the map:
r.what map=streets_cost coordinates=635940.262,225912.796 separator=space
Find the least cost path for the two closest stations:
r.drain -n input=streets_cost output=route_20Westernb start_coordinates=635940.3,225912.8 r.drain -n input=streets_cost output=route_52Hollyb start_coordinates=633178.2,221353.0 r.colors route_20Westernb color=grey r.colors route_52Hollyb color=grey
Display the results in GUI.
You already may have some of these maps in GUI layer tree, so just switch them on and off and re-order as needed:
d.erase d.rast streets_cost d.vect fire_pt color=red icon=basic/marker size=20 d.rast route_20Westernb d.rast route_52Hollyb d.out.file mylcpmap
Print the length of the path in cells (multiply by 30m to get approx. m).
You should have the time in hr already from the cost map.
At what average speed [km/hr] needs the truck travel to get there in estimated time? Is the time, speed and distance realistic?
r.describe route_20Westernb r.describe route_52Hollyb
If you would like to display streets_cost surface in 3D as shown in the lecture,
you need to multiply the surface by 1000 using r.mapcalc because the numbers
in hours are very low.
Then switch off all layers except for the streets_cost_1000 and change display to 3D.
Compute accessibility map for help in search for lost personCreate friction map based on land cover.
Reminder: Time to time, you should remove or at least uncheck previously used map layers in the Layer Manager, so the layers are not rendered when you don't need them anymore.
First display land cover classes:
g.region swwake_30m -p r.category landclass96
Recode the landuse map to friction map using the rules in
r.recode landclass96 out=friction rules=friction_rules.txt
Add the streets to friction map - they are missed by the landuse map.
r.mapcalc "friction2 = if(streets_speed > 6, 0.1, friction)" r.colors friction2 rules=friction_color.txt d.erase d.rast friction2 d.legend friction2 at=5,50,2,5
Compute the cost map and generate isochrones:
r.walk -k elevation=elev_ned_30m friction=friction2 output=walkcost start_coordinates=635576,216485 lambda=0.5 max_cost=10000 r.contour walkcost output=walkcost step=1000
To display the input, import coordinates of the point where the lost person was last seen given in the file lostperson.txt.
v.in.ascii input=lostperson.txt output=lostperson separator=comma
Uncheck the friction map and display the results:
d.erase r.colors -e map=walkcost color=viridis d.rast lakes d.rast walkcost d.vect streets_wake d.vect walkcost color=red d.vect walkcost color=red where=level=6000 width=3 d.vect lostperson color=yellow fill_color=yellow icon=basic/marker size=30 d.legend walkcost at=5,50,2,5 d.out.file mywalkcostmap
Cost surfaces to line featuresCompute the shortest distance to a major road.
Set region, convert vector road map to raster:
g.region swwake_30m -p v.to.rast roadsmajor output=roadsmajor use=val type=line
Compute the distance map and cost surface to highways:
r.mapcalc "area_one = 1" r.cost input=area_one output=dist_toroad start_rast=roadsmajor r.mapcalc "dist_meters = dist_toroad * (ewres() + nsres())/2." r.mapcalc "dist_class = int(dist_meters/500)" d.erase d.rast dist_class d.vect roadsmajor d.out.file dist_roadsmaj r.cost -k input=streets_travtime output=cdist_toroadk start_rast=roadsmajor r.colors cdist_toroadk color=bgyr d.rast cdist_toroadk d.vect streets_wake color=black d.vect roadsmajor color=red d.legend cdist_toroadk at=5,50,2,5 d.out.file cost_roadsmaj