Snap lines to polygon verticies at interscetion

I'm trying to figure out a way to snap lines to a polygon layer, but only at the intersecting point. Here is a sample picture of what I'm working with. I have a layer of polygons and a line string layer.

My goal is to create a topology from the polygons, thin the verticies, and then snap the line layer to polygon verticies within some threshold (i.e. 20 meters). However, I haven't figured out a way to do this using any of my available software, which is QGIS, Grass 7, and PostGIS. Ultimately I would like to be able to make changes to say the polygon layer, and have those changes affect the line string layer, but still be able to differentiate the layers and all their attributes. I have tried various tools in GRASS to no avail, and have only just begun to learn and investigate PostGIS.

Does anyone have suggestions on ways to accomplish this task using these open source tools? Even multi-step, more complex solutions would be welcome, as I hope to eventually script this work flow as much as possible.

• check out the postgis function st_snaptogrid – ziggy Jun 9 '17 at 20:22

1. First add two columns to the streams vector: end_x and end_y, then use the `v.to.db` module, with `option=end` to get the current (wrong) coordinates of each reach endpoint.
2. Export these two columns with `v.out.ascii` and pipe back into `v.in.ascii` to get a points vector of the current endpoints.
3. Again add two columns to this new endpoints vector `snap_x, snap_y`. Then run the module v.distance with the option `upload=to_x,to_y` and the `to=` parameter will be the basins layer. This will add to the endpoints vector the x,y coordinates at the nearest vertex in the basins polygons.
4. Next, another `v.out.ascii ... | v.in.ascii` to create a second points vector of the correct drainage points that should lie on the basins boundary. Be sure to specify correctly the x,y columns in the v.in.ascii part to get the snap_x and snap_y columns.
5. Finally `v.distance` from streams to the new points vector, where you specify `output=connectors` . And `v.patch` to merge the streams with the connectors. This should leave you with streams line vector that includes a small line segment from the (incorrect) end of each reach to the actual basin drain points. You can then try `v.generalize` or `v.clean tool=snap` to join these small segments to the rest of the stream reach.