On May 28, 2009, at 10:04 PM, Dwight Needels wrote:
I am trying to create a map of hiking trails based on GPS data. If anyone can point me to a tutorial that discusses the techniques and issues involved, I would appreciate it. Meanwhile, a couple of specific questions.
I have a series of GPS tracks that have been brought into GRASS as polylines, and a series of time-averaged waypoints that have been brought into GRASS as points. The lines represent segments of color-blazed trails, and the waypoints represent higher-quality measurements of trail termini and intersections.
My questions were about how to force a vector line to pass exactly through specified points in such a way that they would continue to pass through those points after smoothing.
Thank you Hamish for pointing out several very useful tools for me to concentrate on learning. Also, thank you Moritz for the awk magic required to pipe point coordinates from one vector into the v.edit command operating on a second vector. With your indispensable help I was able to come up with something that does almost exactly what I want. If anybody can see any "gotchas" or better ways to accomplish these steps, I would appreciate the feedback.
Thanks, -Dwight
Starting with a line (track) vector and a point (waypoint) vector, modify the line vector so that it passes exactly through each point. This handles three cases; 1) where a vector line terminus undershoots the defined terminus point, 2) where a vector line terminus overshoots the defined terminus point, and 3) where the vector line passes within the threshold of a point somewhere in the middle of the line (a fork, hard curve or switchback).
Threshold (distance from points) should be chosen to include at least two vertices for each line segment of interest, without including vertices from other line segments.
Line vector: trail
Point vector: trail_nodes
Resulting line vector: trail_clean
Summary:
# Split the line vector at closest spot to each point within a threshold, delete superfluous points (v.net op=connect; v.edit tool=delete)
# Delete added lines and nodes to leave a gap (v.to.points -n; v.edit tool=vertexdel)
# Bridge the gaps, but have each bridge pass through one of the original points (v.distance -a; v.edit tool=copy)
# Remove zero length lines, merge bridges across the gaps in the line vector (v.clean tool=rmline; v.edit tool=merge)
# Add back a node at each of the original points, remove zero length lines (v.net op=connect; v.clean tool=rmline)
# Clean up intermediate vectors (g.remove)
Steps:
v.net trail points=trail_nodes out=trail_net op=connect thresh=100 --o
v.edit tool=delete map=trail_net layer=2 cats=1-9999
v.to.points -n in=trail_net out=trail_net_nodes --o
v.edit trail_net tool=vertexdel coords=`v.to.db -p trail_net_nodes layer=2 option=coor --quiet | awk -F"|" '{printf"%f,%f,",$2,$3} END{printf"\n"}'`
v.distance -p -a from=trail_nodes to=trail_net from_type=point to_type=line output=trail_bridges dmax=100 upload=dist column=dist --overwrite
v.edit map=trail_net tool=copy bgmap=trail_bridges ids=1-9999
v.clean input=trail_net output=trail_net_clean type=line tool=rmline thresh=-1 --o
v.edit tool=merge map=trail_net_clean ids=1-9999
v.net trail_net_clean points=trail_nodes out=trail_plus_nodes op=connect thresh=100 --o
v.clean input=trail_plus_nodes output=trail_clean type=line tool=rmline thresh=-1 --o
g.remove vect=trail_net,trail_net_clean,trail_bridges,trail_net_nodes,trail_plus_nodes
Nodes were added back (the polyline was split at each of the original points) so that the trail could be smoothed while still guaranteeing that the vector will pass through the original points.
# Smooth/straighten (v.generalize, method=snakes)
v.generalize input=trail_clean output=trail_smooth method=snakes alpha=1 beta=1 --o