Calculating minimum river width for a route within the river in PostGIS/Python

distancemulti-polygonpostgispythonrivers

I have a complex ancient river system containing islands and multiple channels. I also have line segments defining a vessel's path along the river:

Screenshot of river system and an example line (between points R3 and R4)

I use PostGIS to hold the data, the river system is saved both as a multipolygon and a set of multilinestrings (for the outlines). The paths are simple lines.

For each given route (the points are sure to be in the river, but they are not in the middle of the river), I would like to calculate (or estimate) the minimum river width. I have been looking for approaches to this problem, but are unsure on what the best approach would be:

  • My naive approach would be to take each point along the line and check the closest shapes.
  • For each given point, I would have to find the shortest line that connects to the nearest shores. I have found some hints on this topic in the math section of StackExchange, but I have a multipolygon and that makes things complicated.
    *If I had this shortest line for each point, it would be trivial to calculate the minimum river width along this section.

How would I be able to do this in either PostGis and/or Python?

  • I have thought about cutting the river into smaller segments somehow, mabye this would help.
  • I might also try to create a buffered shape (using ST_buffer) on the line. Unfortunately, my line is not in the middle of the river, so this only helps partially. On the other hand, I might be able to identify shapes that touch/cut this new polygon and use this to simplify my problem…
  • I guess, I could separate islands from the river itself (all shapes contained by another one are islands) – this might simplify things a bit – or not?

Any hints?

Best Answer

Difficult question, the holes are tricky.

One idea would be to start by getting the lines of the polygon. The difficulty is that you need to separate them to be sure to don't have both sides in the same line. For example on your image you can take a buffer big enough around the line between your two points to be sure to have what you need but not big enough to have the line on the bottom and the line on the top to be in the same linestring.

You would do something like ST_Intersection(ST_Boundary(poly), ST_Buffer(line, big_distance).

Then once you have your different linestrings of riverside, you can check the distance between the 2 closest lines, and they should be your two closest riverside. Once you have their id, you can get the distance between the 2 linestrings of riverside directly.

It can be a bit difficult notably if your buffer is not big enough to always have the line of a riverside completly inside, in that case both your closests could be from the same side... Also you could select the size of another branch of the river without knowing.

Another option would be, once you have all the riverside lines, not only check the distance between them, but also get the ST_Closest_Point for each line from each other, and make a line between both points to see if it cross your travel line. That way you can select the branch that you actually have crossed, and you also have in bonus the cross section where your river is the narrowest.

Anyway I think the first step you should take is to properly select the linestring for all the riversides, and distinguish between them.

Finally, you can also take a look at the ST_StraightSkeleton function, maybe there is something to do with it.

Related Question