[GIS] Extracting or categorizing shared boundaries of polygons QGIS

administrative-boundariesqgisqgis-processing

I would like to recreate the style in this Wikipedia Locator map, where there are three distinct styles for boundaries:

  1. Coastline (thin blue line)
  2. High-level administrative land-border (thick grey line)
  3. Low-level administrative land-border (thin grey line)

Wikipedia style Locator map, from https://en.wikipedia.org/wiki/File:France_location_map.svg

I have high and low level administrative units for my area of interest, as polygons. I have tried to match the style as closely as possible:

enter image description here

However, I have no way to distinguish coast-line from land-border. Adding a new coastline polygon would allow me to add a blue line along the coast, but I would still have the grey lines along the coast.

I think that the next step would be to extract only the land-borders from the polygons, but I'm not sure how to do so, other than manually snipping the line wherever it reaches the coast.

Is there a way to 'detect shared boundaries'? Ideally using Processing Toolbox, GRASS, or a QGIS3 Plugin. I am learning to use PyQGIS so would be able to try with that also.

Edit:
I have just seen this question: Converting polygon to lines without duplicate edges?
It appears what I am trying to do is work with a 'planar graph', which was achieved by using OpenJump.

Best Answer

I assume you have either an ocean polygon layer or a coastline line layer. If not, you can create one by making a large polygon that covers your entire layer of interest, and use the clip tool to cut holes in it where the land is. Substitute the name of this layer in the expressions where they say 'coastline'.

Coastline (thin blue line)

For the coastline, simply apply a thin blue line style to your coastline layer, or a thin blue boundary line to your ocean polygon layer.


Add three rule-based styles to the administrative areas layer. The first two rules will be the boundaries. The third rule will be the polygon fill.

High-level administrative land-border (thick grey line)

Filter the first rule to the high-level administrative areas. Apply a line geometry generator style using this expression:

difference( boundary( $geometry), buffer(collect('coastline'),42))

Substitute a reasonable, small buffer distance where my expression says 42. Buffer distance is in the same units as the layer's CRS. "Reasonable" depends on the scale of your map and how closely your coastline layer lines up with your administrative boundaries layer. The goal is to clip the entire section of the administrative boundary along the coast, without leaving a noticeable gap.

Apply a thick grey line style.

Low-level administrative land-border (thin grey line)

Filter the second rule to the low-level administrative areas. Use the same geometry generator settings and expression. Apply a thin grey line style.

For the third rule, don't apply a filter. Apply a simple fill style, and set the outline pen type to "no pen."


Explanation of the expression difference( boundary( $geometry), buffer('coastline',42))

  • boundary($geometry) converts the current polygon boundary into a line
  • difference(geometry_a,geometry_b) removes the part of geometry_a that intersects with geometry_b
  • collect('coastline') merges the 'coastline' layer into a single feature. This step is needed because the difference() formula requires a single feature input.
  • buffer('coastline', distance) creates a buffer around the coastline layer, just in case the coastline doesn't exactly match up with the admin boundary.
  • If the 'coastline' layer does match the admin boundary exactly, you could omit the buffer function, and just use difference( boundary($geometry), 'coastline')
  • difference( boundary , buffer('coastline') ) subtracts the buffered coastline from the administrative boundary, leaving only the part of the boundary that isn't on the coast

Using a complicated expression like this in the geometry generator can cause slow rendering, because QGIS has to run all the steps of the expression "on the fly". If you have a problem with slow rendering, you can shave some time off the rendering process by performing some of the steps outside the expression. For example, dissolve the coastline layer into a single feature, clip it to your area of interest, and buffer the result. Omit the buffer function from the expression, and just use this layer. Use it in the coalesce('newlayer') function or by extracting the single feature using geometry(get_feature('newlayer','anyattribute',attributevalue). I'm not sure which method will be faster.

Related Question